Compare commits

...

60 Commits

Author SHA1 Message Date
Lorexia d7eb8262ed Add updates to community list projects 2023-08-01 10:49:20 +02:00
pierre 5964f104c5 fix(nc-desktop): typo 2023-07-27 15:54:45 +02:00
pierre 0bfc1be1d5 ci: fix release strapi actions 2023-07-27 11:42:02 +02:00
pierre aedacf6c65 ci: fix release strapi actions 2023-07-27 11:12:42 +02:00
Tommy Verrall f6e20c8201 Merge branch 'release/v1.1.25' into develop 2023-07-26 17:39:34 +02:00
pierre 1da6ee2058 fix workflows (try) 2023-07-26 17:37:54 +02:00
pierre 109fb96fca fix workflows 2023-07-26 17:37:54 +02:00
benedetta davico 557bfa7b34 Update CHANGELOG.md 2023-07-26 17:37:25 +02:00
Tommy Verrall 4c9727b1ef Update nym-connect-publish-ubuntu.yml (#3706)
* Update nym-connect-publish-ubuntu.yml

* Update nym-connect-publish-ubuntu.yml

* Update nym-connect-publish-macos.yml

* Update nym-connect-publish-windows10.yml
2023-07-26 17:37:25 +02:00
Tommy Verrall a0408b74dc Update nym-connect-publish-macos.yml (#3705)
* Update nym-connect-publish-macos.yml

install wasm and build

* Update nym-connect-publish-macos.yml

use the correct download
2023-07-26 17:37:25 +02:00
Tommy Verrall 8a1ed12f58 bump versions for NC 2023-07-26 17:37:25 +02:00
mfahampshire c38c5c2f0d fixed clippy warning 2023-07-26 17:37:25 +02:00
pierre 03300a859e build(nc-desktop): sentry dsn as env var 2023-07-26 17:37:22 +02:00
mfahampshire 2fe5401a38 ran fmt 2023-07-26 17:37:22 +02:00
mfahampshire d8a44cd9c1 added reply with surbs example to rust sdk examples dir 2023-07-26 17:37:22 +02:00
mfahampshire a0b41db22d added rust sdk surb example 2023-07-26 17:37:22 +02:00
Pierre Dommerc 7d6d8669b0 feat(nc-desktop): add sentry to backend (#3652) 2023-07-26 17:37:18 +02:00
mfahampshire a1a2f37fce included url 2023-07-26 17:23:20 +02:00
mfahampshire 91341733c1 updated NR guide with list explainer + info on comments in local allow list 2023-07-26 17:23:20 +02:00
mfahampshire 93cd8821c3 version update 2023-07-26 17:23:20 +02:00
mfahampshire b79ec60381 * added serinko + alexia to book authors
* version bumps for next release
2023-07-26 17:23:20 +02:00
mfahampshire 2c2dd54028 updated sdk documentation with surb example 2023-07-26 17:23:20 +02:00
mfahampshire 4306cec49c version bumps 2023-07-26 17:23:14 +02:00
mfahampshire 5781d3043f removed command information from mix node + gateway guide 2023-07-26 17:23:14 +02:00
⚡️2FakTor⚡️ d843407ba7 Update network-requester-setup.md 2023-07-26 17:23:14 +02:00
⚡️2FakTor⚡️ 053e047cca Update network-requester-setup.md 2023-07-26 17:23:14 +02:00
Jędrzej Stuczyński 516561dcf9 Feature/wasm nyxd client (#3708)
* separated signing and nyxd-client features

* updated cosmrs to the most recent version

* using tendermint_rpc directly for the Client trait

* fixed rest of the codebase

* removed nyxd-client feature

* export more types

* clippy that seems to have been skipped in makefile
2023-07-26 15:49:45 +01:00
Jon Häggblad 290dbc1a03 client-core: make latency based gateway selection concurrent (#3709) 2023-07-26 13:08:06 +02:00
Jon Häggblad 524863aae7 Uncouple gateways and network-requester in nym-connect (#3639)
* Split fetching network-requesters from gateways

* Tidy names

* Select gateway independenty in frontend

* Fix threshold value

* Fix gateway type

* Fix naming for setGateway and setServiceProvider

* Unshadow variable

* Naming conventions

* Missing semicolon

* Explicit types in invoke calls

* Dedup random function

* Inline some functions

* Silence handlebars in log

* Emojis in healthcheck log statements

* Remove gateway from service provider type

* Remove unneeded type cast

* fix linting

* Remove gateway field from harbour master response type

---------

Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>
2023-07-25 13:51:27 +02:00
Tommy Verrall 61ad336b18 Merge pull request #3598 from nymtech/bug-fix/balanceVSfeeWarning
TX warning when fee > balance
2023-07-25 09:55:34 +02:00
pierre 867b745a38 fix(nc-android): http requests 2023-07-25 08:53:34 +02:00
fmtabbara 78e54287da include tx amount when checking balance 2023-07-24 16:57:28 +01:00
fmtabbara 96c29b974b add warning for more txs 2023-07-24 16:57:28 +01:00
fmtabbara eadd116ae4 add warning modal for more txs 2023-07-24 16:57:28 +01:00
fmtabbara f1175280cf add warning to tx modals when fee exceeds balance 2023-07-24 16:57:28 +01:00
pierre 34a47a9449 build(nc-desktop): sentry dsn as env var 2023-07-21 15:56:08 +02:00
Bogdan-Ștefan Neacşu dff11df2bd Add DKG resharing benchmark (#3692)
* Add DKG resharing benchmark

* Fix clippy
2023-07-21 11:25:14 +01:00
benedettadavico feb888a154 updating sandbox .env 2023-07-20 17:20:00 +02:00
Pierre Dommerc 415fe4605c feat(nc-desktop): add sentry to backend (#3652) 2023-07-20 13:17:49 +02:00
Pierre Dommerc 70e6539298 refactor(nc-desktop): add privacy level user settings (#3664) 2023-07-19 15:56:00 +02:00
pierre fe76ba68a0 ci: fix connect-desktop-ci workflow 2023-07-19 15:41:00 +02:00
pierre 863580a6f2 ci: fix workflow for strapi data publish 2023-07-18 19:23:31 +02:00
pierre 4c558db08e add alephium to supported wallets 2023-07-18 17:08:20 +02:00
Mark Sinclair 9d5b582908 SDK - fix unsubscribe function for events (#3659)
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-07-18 14:12:00 +01:00
Fouad c12b20f1d6 Feature/sdk browser extension examples (#3673)
* New TypeScript SDK example: Google Chrome

Example of a simple manifest v3 extension to load a Nym client within  a
popup view.

* Firefox Extension example for Nym TypeScript SDK

* Fix typo

* Add basic install script

* fix up html files

* remove unnecessary background page

* bundle extensions with webpack

* use icons from shared assets

* ignore sdk index file

* import sdk lib

* create new build script for non-inline workers

* import workers and build as separate files using webpack

* update html titles

* create react app node tester example

* add readme file

* update readme for FF extension

* code formatting

---------

Co-authored-by: Nadim Kobeissi <nadim@symbolic.software>
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
2023-07-18 14:09:40 +01:00
farbanas edeb8369df Merge branch 'master' into develop 2023-07-18 14:22:46 +02:00
farbanas 22b2405aa2 Merge branch 'release/v1.1.24' 2023-07-18 13:43:47 +02:00
Bogdan-Ștefan Neacşu 41e1009095 Upgrade cosmwasm (#3678)
* Upgrade cosmwasm

* Remove serde annotation for Denom too

* Fix clippy after rustup update
2023-07-18 12:15:20 +03:00
Bogdan-Ștefan Neacşu 6d79b6f600 Apply clippy fix (#3670) 2023-07-13 11:40:40 +03:00
mfahampshire 34de42fe7a updated validator docs: upgrade to 0.32.0 instructions 2023-07-11 15:51:02 +02:00
pierre 766261f774 sync gh actions for s with normal ones 2023-07-11 09:56:54 +02:00
serinko 6e2eaf29e7 edited NC-Matrix user manual
- changed setup for Mac
- fixed typo
2023-07-10 15:32:23 +02:00
Bogdan-Ștefan Neacşu c99309dd79 Use NYXD env in api (#3654) 2023-07-10 15:14:16 +03:00
Pierre Dommerc 37c875d8ee build(nym-connect-desktop): speedy mode (#3636) 2023-07-10 13:18:46 +02:00
Jędrzej Stuczyński b2b0a1478b exposed methods for sending replies in rust-sdk (#3658) 2023-07-10 09:49:32 +01:00
Raphaël Walther aa67e183a6 Github Actions: fix daily audit workflow notification 2023-07-07 18:00:41 +02:00
Fouad b27fa51092 Feature/nym browser extension (#3637)
* Chore/browser extension bootstrap (#3257)

* init package

* set up TS and Webpack

* add eslint config

* add prettier config

* add react and mui theme

* add CI

* update mui theme version number

* Chore/browser extension routes (#3327)

* start routes

* create layouts

* add initial app routes

* add initial app pages

* add global types

* create reuseable components

* move password and mnemonic fields to shared react components package

* refactor register routes

* move client address component to shared package

* move components to ui folder

* create menu and appbar components

* adjust layout components

* add readme

* use memory router

* Feature/nym browser extension login and send (#3373)

* init package

* set up TS and Webpack

* add eslint config

* add prettier config

* add react and mui theme

* add CI

* update mui theme version number

* Chore/browser extension routes (#3327)

* start routes

* create layouts

* add initial app routes

* add initial app pages

* add global types

* create reuseable components

* move password and mnemonic fields to shared react components package

* refactor register routes

* move client address component to shared package

* move components to ui folder

* create menu and appbar components

* adjust layout components

* add readme

* use memory router

* add extension to mono-repo config

* fix webpack build

* util functions

* add TX type

* refactor routes

* refactor pages + add send page

* add page layout for app pages

* set up app context

* app components

* set up connection config

* fix lint errors

* Chore/browser extension bootstrap (#3257)

* init package

* set up TS and Webpack

* add eslint config

* add prettier config

* add react and mui theme

* add CI

* update mui theme version number

* Chore/browser extension routes (#3327)

* start routes

* create layouts

* add initial app routes

* add initial app pages

* add global types

* create reuseable components

* move password and mnemonic fields to shared react components package

* refactor register routes

* move client address component to shared package

* move components to ui folder

* create menu and appbar components

* adjust layout components

* add readme

* use memory router

* add extension to mono-repo config

* util functions

* add TX type

* refactor routes

* refactor pages + add send page

* add page layout for app pages

* set up app context

* app components

* set up connection config

* use fee simulation when sending tokens

* use object argument for simulate send api

* login validation + fee refinements

* use components from shared components lib

* add receive modal (#3408)

* account storage via wasm

* method to get all storage keys

* Feature/nym browser extension password encryption (single account) (#3442)

* build wasm

* reuse components and state for password pages

* refactor registration pages

* use login with password

* import storage as local package

* add yarn preinstall script to ts lint gh action

* install wasm-pack for CI

* use @nym scope for ext storage package

* introduced a call to check if database was already initialised (#3465)

* introduced a call to check if database was already initialised

* use extension storage method to check for db existance

---------

Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>

* introduced mnemonic key existence check (#3462)

* Browser extension - Multi-accounts +  view mnemonic action (#3488)

* add UI for multi-accounts + add view mnemonic for accounts

* refactor routes

* set up import account

* add account to existing wallet

* check if account name exists before creating new one

* handle password errors

* add token to currency conversion

* fixed ClientStorageError import path

* fix CI

* fix CI

---------

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
2023-07-07 11:02:05 +01:00
Mark Sinclair d01b6a12d6 Add needs-triage to new issues for project workflow automation 2023-07-07 09:34:41 +00:00
Jędrzej Stuczyński a133457722 chore: applied fmt for let-else statements (#3649) 2023-07-06 10:08:39 +01:00
Fouad ad995b1934 Node Tester SDK examples (#3641)
* create parcel example

* update plain html example

* move chat examples into own dir

* add examples to workspace

* update tsconfig path

* move webpack base to parent dir
2023-07-05 16:14:21 +01:00
480 changed files with 13742 additions and 4675 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
name: 'Documentation' name: 'Documentation'
about: Suggest a fix or enhancement to the documentation or developer portal content about: Suggest a fix or enhancement to the documentation or developer portal content
title: "[DOCS]" title: "[DOCS]"
labels: documentation labels: documentation, needs-triage
assignees: mfahampshire assignees: mfahampshire
--- ---
+1 -1
View File
@@ -2,7 +2,7 @@
name: Feature request name: Feature request
about: Suggest an enhancement to the product about: Suggest an enhancement to the product
title: "[Feature Request]" title: "[Feature Request]"
labels: enhancement labels: enhancement, needs-triage
assignees: '' assignees: ''
--- ---
+1 -1
View File
@@ -2,7 +2,7 @@
name: Report name: Report
about: To help identify and reproduce issues about: To help identify and reproduce issues
title: "[Issue]" title: "[Issue]"
labels: bug, bug-needs-triage, qa labels: bug, bug-needs-triage, qa, needs-triage
assignees: tommyv1987 assignees: tommyv1987
--- ---
+6 -1
View File
@@ -23,7 +23,12 @@ jobs:
node-version: 18 node-version: 18
- name: Install Yarn - name: Install Yarn
run: npm install -g yarn run: npm install -g yarn
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install project dependencies - name: Install project dependencies
run: cd ../.. && yarn --network-timeout 100000 run: cd ../.. && yarn --network-timeout 100000
@@ -31,10 +31,20 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Install Rust stable - name: Install Rust stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: stable toolchain: stable
target: wasm32-unknown-unknown
- name: Install wasm-pack
run: |
export WASM_PACK_VERSION="v0.12.1"
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
- name: Install the Apple developer certificate for code signing - name: Install the Apple developer certificate for code signing
env: env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
@@ -78,6 +88,8 @@ jobs:
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn && yarn build run: yarn && yarn build
- name: Upload Artifact - name: Upload Artifact
@@ -103,9 +115,10 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}" ref=${{ github.ref_name }}
echo "version=$semver" >> "$GITHUB_OUTPUT" semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "filename=nym-connect_$version_x64.dmg" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_x64.dmg " >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/dmg/nym-connect_*_x64.dmg') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/dmg/nym-connect_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -61,6 +61,8 @@ jobs:
env: env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@@ -80,9 +82,10 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}" ref=${{ github.ref_name }}
echo "version=$semver" >> "$GITHUB_OUTPUT" semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "filename=nym-connect_$version_amd64.AppImage" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/appimage/nym-connect_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/appimage/nym-connect_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -79,6 +79,8 @@ jobs:
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
run: yarn build run: yarn build
- name: Upload Artifact - name: Upload Artifact
@@ -99,9 +101,10 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}" ref=${{ github.ref_name }}
echo "version=$semver" >> "$GITHUB_OUTPUT" semver="${ref##nym-connect-}" && semver="${semver##v}"
echo "filename=nym-connect_$version_x64_en-US.msi" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-connect_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/msi/nym-connect_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-connect/desktop/target/release/bundle/msi/nym-connect_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -106,7 +106,7 @@ jobs:
ref=${{ github.ref_name }} ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}" semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${version}_x64.dmg" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${semver}_x64.dmg" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/dmg/nym-wallet_*_x64.dmg') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/dmg/nym-wallet_*_x64.dmg') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -83,7 +83,7 @@ jobs:
ref=${{ github.ref_name }} ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}" semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${version}_amd64.AppImage" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/appimage/nym-wallet_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/appimage/nym-wallet_*_amd64.AppImage') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -103,7 +103,7 @@ jobs:
ref=${{ github.ref_name }} ref=${{ github.ref_name }}
semver="${ref##nym-wallet-}" && semver="${semver##v}" semver="${ref##nym-wallet-}" && semver="${semver##v}"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "version=${semver}" >> "$GITHUB_OUTPUT"
echo "filename=nym-wallet_${version}_x64_en-US.msi" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT"
echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/msi/nym-wallet_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT" echo "file_hash=${{ hashFiles('nym-wallet/target/release/bundle/msi/nym-wallet_*_x64_en-US.msi') }}" >> "$GITHUB_OUTPUT"
push-release-data: push-release-data:
@@ -10,7 +10,7 @@ async function addToContextAndValidate(context) {
async function getMessageBody(context) { async function getMessageBody(context) {
try { try {
const source = fs const source = fs
.readFileSync("deny.message").toString(); .readFileSync("./notifications/deny.message").toString();
return source; return source;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
+60 -54
View File
@@ -3,64 +3,70 @@ name: CI for linting Typescript
on: on:
push: push:
paths: paths:
- 'ts-packages/**' - "ts-packages/**"
- 'sdk/typescript/**' - "sdk/typescript/**"
- 'nym-connect/desktop/src/**' - "nym-connect/desktop/src/**"
- 'nym-connect/desktop/package.json' - "nym-connect/desktop/package.json"
- 'nym-connect/mobile/src/**' - "nym-connect/mobile/src/**"
- 'nym-connect/mobile/package.json' - "nym-connect/mobile/package.json"
- 'nym-wallet/src/**' - "nym-wallet/src/**"
- 'nym-wallet/package.json' - "nym-wallet/package.json"
- 'explorer/**' - "explorer/**"
pull_request: pull_request:
paths: paths:
- 'ts-packages/**' - "ts-packages/**"
- 'sdk/typescript/**' - "sdk/typescript/**"
- 'nym-connect/desktop/src/**' - "nym-connect/desktop/src/**"
- 'nym-connect/desktop/package.json' - "nym-connect/desktop/package.json"
- 'nym-connect/mobile/src/**' - "nym-connect/mobile/src/**"
- 'nym-connect/mobile/package.json' - "nym-connect/mobile/package.json"
- 'nym-wallet/src/**' - "nym-wallet/src/**"
- 'nym-wallet/package.json' - "nym-wallet/package.json"
- 'explorer/**' - "explorer/**"
jobs: jobs:
build: build:
runs-on: custom-runner-linux runs-on: custom-runner-linux
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install rsync - name: Install rsync
run: sudo apt-get install rsync run: sudo apt-get install rsync
continue-on-error: true continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
- name: Setup yarn - name: Install Rust stable
run: npm install -g yarn uses: actions-rs/toolchain@v1
- name: Install with:
run: yarn toolchain: stable
- name: Build packages - name: Install wasm-pack
run: yarn build run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Lint - name: Setup yarn
run: yarn lint && yarn tsc run: npm install -g yarn
- name: Matrix - Node Install - name: Install
run: npm install run: yarn
working-directory: .github/workflows/support-files - name: Build packages
- name: Matrix - Send Notification run: yarn build
env: - name: Lint
NYM_NOTIFICATION_KIND: ts-packages run: yarn lint && yarn tsc
NYM_PROJECT_NAME: "ts-packages" - name: Matrix - Node Install
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}" run: npm install
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}" working-directory: .github/workflows/support-files
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" - name: Matrix - Send Notification
GIT_BRANCH: "${GITHUB_REF##*/}" env:
IS_SUCCESS: "${{ job.status == 'success' }}" NYM_NOTIFICATION_KIND: ts-packages
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}" NYM_PROJECT_NAME: "ts-packages"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}" NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}" NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}" GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}" GIT_BRANCH: "${GITHUB_REF##*/}"
uses: docker://keybaseio/client:stable-node IS_SUCCESS: "${{ job.status == 'success' }}"
with: MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
args: .github/workflows/support-files/notifications/entry_point.sh MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node
with:
args: .github/workflows/support-files/notifications/entry_point.sh
Generated
+450 -212
View File
File diff suppressed because it is too large Load Diff
+16 -12
View File
@@ -102,7 +102,7 @@ default-members = [
"explorer-api", "explorer-api",
] ]
exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"] exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-browser-extension/storage", "cpu-cycles"]
[workspace.package] [workspace.package]
authors = ["Nym Technologies SA"] authors = ["Nym Technologies SA"]
@@ -117,19 +117,23 @@ anyhow = "1.0.71"
async-trait = "0.1.64" async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] } bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0" cfg-if = "1.0.0"
cosmwasm-derive = "=1.0.0" cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.0.0" cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.0.0" cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.0.0" cosmwasm-storage = "=1.2.5"
cw-controllers = "=0.13.4" cosmrs = "=0.14.0"
cw-storage-plus = "=0.13.4" # same version as used by cosmrs
cw-utils = "=0.13.4" tendermint-rpc = "=0.32"
cw2 = { version = "=0.13.4" } cw-utils = "=1.0.1"
cw3 = { version = "=0.13.4" } cw-storage-plus = "=1.0.1"
cw3-fixed-multisig = { version = "=0.13.4" } cw2 = { version = "=1.0.1" }
cw4 = { version = "=0.13.4" } cw3 = { version = "=1.0.1" }
cw3-fixed-multisig = { version = "=1.0.1" }
cw4 = { version = "=1.0.1" }
cw-controllers = { version = "=1.0.1" }
dotenvy = "0.15.6" dotenvy = "0.15.6"
generic-array = "0.14.7" generic-array = "0.14.7"
k256 = "0.13"
getrandom = "0.2.10" getrandom = "0.2.10"
lazy_static = "1.4.0" lazy_static = "1.4.0"
log = "0.4" log = "0.4"
+53
View File
@@ -0,0 +1,53 @@
<svg
width="100%"
height="100%"
viewBox="0 0 80 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_421_13045)">
<path
d="M40 80C62.0914 80 80 62.0914 80 40C80 17.9086 62.0914 0 40 0C17.9086 0 0 17.9086 0 40C0 62.0914 17.9086 80 40 80Z"
fill="black"
/>
<path
d="M40 77.2636C60.5801 77.2636 77.2636 60.5801 77.2636 40C77.2636 19.4199 60.5801 2.73645 40 2.73645C19.4199 2.73645 2.73645 19.4199 2.73645 40C2.73645 60.5801 19.4199 77.2636 40 77.2636Z"
fill="white"
/>
<path
d="M24.0224 32.471H23.9776V32.5084V45.5775L18.4673 32.4934L18.4598 32.471H18.4299H15.3047H11.7981H11.7607V32.5084V47.4916V47.529H11.7981H15.3047H15.3421V47.4916V34.4L20.8748 47.5065L20.8822 47.529H20.9121H24.0224H27.5215H27.5589V47.4916V32.5084V32.471H27.5215H24.0224Z"
fill="black"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M23.8965 32.39H27.64V47.6101H20.8238L20.7989 47.5352L15.4232 34.8006V47.6101H11.6797V32.39H18.5183L18.5432 32.4649L23.8965 45.1761V32.39ZM23.9776 45.5776L18.4673 32.4935L18.4598 32.471H11.7608V47.529H15.3421V34.4L20.8748 47.5065L20.8823 47.529H27.5589V32.471H23.9776V45.5776Z"
fill="black"
/>
<path
d="M68.2019 32.471H61.5178H61.4804L61.4729 32.5009L58.0486 45.6374L54.6169 32.5009L54.6094 32.471H54.5795H47.8804H47.8355V32.5084V47.4916V47.529H47.8804H51.3795H51.4169V47.4916V34.5047L54.8038 47.499L54.8112 47.529H54.8486H61.2337H61.2636L61.2711 47.499L64.658 34.5047V47.4916V47.529H64.6954H68.2019H68.2393V47.4916V32.5084V32.471H68.2019Z"
fill="black"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M61.4171 32.39H68.3204V47.6101H64.5769V35.1372L61.3497 47.5187L61.3495 47.5195L61.3269 47.6101H54.7479L54.7253 47.5195L54.7251 47.5187L51.4979 35.1372V47.6101H47.7545V32.39H54.6727L54.6953 32.4804L54.6955 32.4813L58.0485 45.3163L61.3943 32.4813L61.3945 32.4805L61.4171 32.39ZM58.0486 45.6374L54.6168 32.5009L54.6094 32.471H47.8355V47.529H51.4168V34.5047L54.8038 47.4991L54.8112 47.529H61.2636L61.2711 47.4991L64.658 34.5047V47.529H68.2393V32.471H61.4804L61.4729 32.5009L58.0486 45.6374Z"
fill="black"
/>
<path
d="M42.0711 32.471H42.0486L42.0412 32.486L37.7869 39.8804L33.5103 32.486L33.5028 32.471H33.4804H29.4355H29.3608L29.3982 32.5308L35.9851 43.9402V47.4916V47.529H36.0225H39.529H39.5664V47.4916V43.9402L46.1533 32.5308L46.1907 32.471H46.1159H42.0711Z"
fill="black"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M41.9985 32.39H46.337L46.2228 32.5726L39.6475 43.9619V47.6101H35.904V43.9619L29.3286 32.5726L29.2145 32.39H33.5529L33.5817 32.4475L37.7868 39.7181L41.9697 32.4476L41.9985 32.39ZM42.0411 32.486L37.7869 39.8804L33.5103 32.486L33.5028 32.471H29.3608L29.3981 32.5308L35.9851 43.9402V47.529H39.5664V43.9402L46.1533 32.5308L46.1907 32.471H42.0486L42.0411 32.486Z"
fill="black"
/>
</g>
<defs>
<clipPath id="clip0_421_13045">
<rect width="80" height="80" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

+1 -1
View File
@@ -21,5 +21,5 @@ nym-credential-storage = { path = "../../common/credential-storage" }
nym-bin-common = { path = "../../common/bin-common"} nym-bin-common = { path = "../../common/bin-common"}
nym-network-defaults = { path = "../../common/network-defaults" } nym-network-defaults = { path = "../../common/network-defaults" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } nym-validator-client = { path = "../../common/client-libs/validator-client" }
+1 -1
View File
@@ -48,7 +48,7 @@ nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" } nym-pemstore = { path = "../../common/pemstore" }
nym-task = { path = "../../common/task" } nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" } nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
nym-client-websocket-requests = { path = "websocket-requests" } nym-client-websocket-requests = { path = "websocket-requests" }
[dev-dependencies] [dev-dependencies]
+6 -5
View File
@@ -117,10 +117,11 @@ impl Handler {
let Ok(base_length) = self let Ok(base_length) = self
.lane_queue_lengths .lane_queue_lengths
.lock() .lock()
.map(|guard| guard.get(&conn_lane).unwrap_or_default()) else { .map(|guard| guard.get(&conn_lane).unwrap_or_default())
else {
// I'd argue we should panic here as this error it not recoverable // I'd argue we should panic here as this error it not recoverable
error!("The lane queue length lock is poisoned!!"); error!("The lane queue length lock is poisoned!!");
return None return None;
}; };
// get the number of pending replies waiting for reply surbs // get the number of pending replies waiting for reply surbs
@@ -174,7 +175,7 @@ impl Handler {
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let TransmissionLane::ConnectionId(connection_id) = lane else {
return None return None;
}; };
self.get_lane_queue_length(connection_id).await self.get_lane_queue_length(connection_id).await
@@ -206,7 +207,7 @@ impl Handler {
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let TransmissionLane::ConnectionId(connection_id) = lane else {
return None return None;
}; };
self.get_lane_queue_length(connection_id).await self.get_lane_queue_length(connection_id).await
@@ -233,7 +234,7 @@ impl Handler {
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let TransmissionLane::ConnectionId(connection_id) = lane else {
return None return None;
}; };
self.get_lane_queue_length(connection_id).await self.get_lane_queue_length(connection_id).await
+19 -18
View File
@@ -3,11 +3,11 @@
"version": "0.19.0", "version": "0.19.0",
"description": "A TypeScript client for interacting with smart contracts in Nym validators", "description": "A TypeScript client for interacting with smart contracts in Nym validators",
"repository": "https://github.com/nymtech/nym", "repository": "https://github.com/nymtech/nym",
"main": "./dist/index.js", "main": "dist/index.js",
"types": "./dist/index.d.ts", "types": "dist/index.d.ts",
"scripts": { "scripts": {
"build": "rollup -c ./rollup.config.mjs", "build": "rollup -c ./rollup.config.mjs",
"build:types": "rollup-type-bundler --dist ./dist/nym-validator-client", "build:types": "rollup-type-bundler --dist ./dist",
"build:prod": "sh ./scripts/build-prod.sh", "build:prod": "sh ./scripts/build-prod.sh",
"test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts", "test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts",
"testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts", "testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts",
@@ -29,16 +29,23 @@
], ],
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@cosmjs/cosmwasm-stargate": "^0.29.5",
"@cosmjs/crypto": "^0.29.5",
"@cosmjs/math": "^0.29.5",
"@cosmjs/proto-signing": "^0.29.5",
"@cosmjs/stargate": "^0.29.5",
"@cosmjs/tendermint-rpc": "^0.29.5",
"@favware/rollup-type-bundler": "^2.0.0", "@favware/rollup-type-bundler": "^2.0.0",
"@nymproject/types": "^1.0.0", "@nymproject/types": "^1.0.0",
"@rollup/plugin-commonjs": "^24.0.1", "@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^6.0.0", "@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-typescript": "^11.0.0",
"@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-node-resolve": "^15.0.1",
"rollup": "^3.17.2", "@rollup/plugin-typescript": "^11.0.0",
"rollup-plugin-dts": "^5.2.0",
"@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0", "@typescript-eslint/parser": "^5.7.0",
"axios": "^1.3.3",
"cosmjs-types": "^0.4.1",
"dotenv": "^16.0.3",
"eslint": "^7.18.0", "eslint": "^7.18.0",
"eslint-config-airbnb": "^19.0.2", "eslint-config-airbnb": "^19.0.2",
"eslint-config-airbnb-typescript": "^16.1.0", "eslint-config-airbnb-typescript": "^16.1.0",
@@ -47,21 +54,15 @@
"eslint-plugin-import": "^2.25.4", "eslint-plugin-import": "^2.25.4",
"eslint-plugin-mocha": "^10.0.3", "eslint-plugin-mocha": "^10.0.3",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"expect": "^28.1.3",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"moq.ts": "^7.3.4",
"prettier": "^2.8.7", "prettier": "^2.8.7",
"rollup": "^3.17.2",
"rollup-plugin-dts": "^5.2.0",
"rollup-plugin-node-polyfills": "^0.2.1",
"ts-mocha": "^10.0.0", "ts-mocha": "^10.0.0",
"typedoc": "^0.22.13", "typedoc": "^0.22.13",
"typescript": "^4.6.2", "typescript": "^4.6.2"
"cosmjs-types": "^0.4.1",
"dotenv": "^16.0.3",
"expect": "^28.1.3",
"moq.ts": "^7.3.4",
"@cosmjs/cosmwasm-stargate": "^0.29.5",
"@cosmjs/crypto": "^0.29.5",
"@cosmjs/math": "^0.29.5",
"@cosmjs/proto-signing": "^0.29.5",
"@cosmjs/stargate": "^0.29.5",
"@cosmjs/tendermint-rpc": "^0.29.5",
"axios": "^1.3.3"
} }
} }
+4 -4
View File
@@ -1,15 +1,15 @@
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve'; import nodePolyfills from 'rollup-plugin-node-polyfills';
import json from '@rollup/plugin-json'; import json from '@rollup/plugin-json';
import commonjs from '@rollup/plugin-commonjs'; import commonjs from '@rollup/plugin-commonjs';
export default [ export default [
{ {
input: './src/index.ts', input: 'src/index.ts',
output: { output: {
dir: 'dist/nym-validator-client', dir: 'dist',
format: 'cjs', format: 'cjs',
}, },
plugins: [resolve(), typescript(), commonjs(), json()], plugins: [nodePolyfills(), typescript(), commonjs(), json()],
}, },
]; ];
+1 -1
View File
@@ -21,7 +21,7 @@ node ./scripts/buildPackageJson.mjs
# Copy README # Copy README
cp README.md dist/nym-validator-client cp README.md dist/
# move the output outside of the yarn/npm workspaces # move the output outside of the yarn/npm workspaces
@@ -17,4 +17,4 @@ const packageJson = {
types, types,
}; };
fs.writeFileSync('./dist/nym-validator-client/package.json', JSON.stringify(packageJson, null, 2)); fs.writeFileSync('./dist/package.json', JSON.stringify(packageJson, null, 2));
+12 -3
View File
@@ -45,7 +45,6 @@ import {
} from '@nymproject/types'; } from '@nymproject/types';
import QueryClient from './query-client'; import QueryClient from './query-client';
import SigningClient, { ISigningClient } from './signing-client'; import SigningClient, { ISigningClient } from './signing-client';
// import { DelegationBlock } from './types/shared';
export interface INymClient { export interface INymClient {
readonly mixnetContract: string; readonly mixnetContract: string;
@@ -626,7 +625,17 @@ export default class ValidatorClient implements INymClient {
// SIMULATE // SIMULATE
public async simulateSend(signingAddress: string, from: string, to: string, amount: Coin[]) { public async simulateSend({
return (this.client as SigningClient).simulateSend(signingAddress, from, to, amount); signingAddress,
from,
to,
amount,
}: {
signingAddress: string;
from: string;
to: string;
amount: Coin[];
}) {
return (this.client as ISigningClient).simulateSend(signingAddress, from, to, amount);
} }
} }
@@ -22,9 +22,12 @@ describe('Simualtions', () => {
}); });
it('can simulate sending tokens', async () => { it('can simulate sending tokens', async () => {
const res = await client.simulateSend(client.address, client.address, client.address, [ const res = await client.simulateSend({
{ amount: '400000', denom: 'unym' }, signingAddress: client.address,
]); from: client.address,
to: client.address,
amount: [{ amount: '400000', denom: 'unym' }],
});
expect(typeof res).toBe('number'); expect(typeof res).toBe('number');
}).timeout(10000); }).timeout(10000);
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"outDir": "./dist/nym-validator-client", "outDir": "dist",
"module": "ES2020", "module": "ES2020",
"target": "es2021", "target": "es2021",
"allowJs": false, "allowJs": false,
+434 -164
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -4,7 +4,7 @@
// due to expansion of #[wasm_bindgen] macro on `Debug` Config struct // due to expansion of #[wasm_bindgen] macro on `Debug` Config struct
#![allow(clippy::drop_non_drop)] #![allow(clippy::drop_non_drop)]
// another issue due to #[wasm_bindgen] and `Copy` trait // another issue due to #[wasm_bindgen] and `Copy` trait
#![allow(clippy::drop_copy)] #![allow(dropping_copy_types)]
use nym_client_core::config::{ use nym_client_core::config::{
Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig, Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig,
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::storage::errors::ClientStorageError; use crate::storage::error::ClientStorageError;
use crate::topology::WasmTopologyError; use crate::topology::WasmTopologyError;
use js_sys::Promise; use js_sys::Promise;
use nym_client_core::config::GatewayEndpointConfig; use nym_client_core::config::GatewayEndpointConfig;
+2 -2
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config; use crate::client::config::Config;
use crate::storage::errors::ClientStorageError; use crate::storage::error::ClientStorageError;
use js_sys::Promise; use js_sys::Promise;
use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails; use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails;
use nym_crypto::asymmetric::{encryption, identity}; use nym_crypto::asymmetric::{encryption, identity};
@@ -15,7 +15,7 @@ use wasm_utils::storage::{IdbVersionChangeEvent, WasmStorage};
use wasm_utils::PromisableResult; use wasm_utils::PromisableResult;
use zeroize::Zeroizing; use zeroize::Zeroizing;
pub(crate) mod errors; pub(crate) mod error;
pub(crate) mod traits; pub(crate) mod traits;
const STORAGE_NAME_PREFIX: &str = "wasm-client-storage"; const STORAGE_NAME_PREFIX: &str = "wasm-client-storage";
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::storage::errors::ClientStorageError; use crate::storage::error::ClientStorageError;
use crate::storage::ClientStorage; use crate::storage::ClientStorage;
use async_trait::async_trait; use async_trait::async_trait;
use nym_client_core::client::base_client::storage::gateway_details::{ use nym_client_core::client::base_client::storage::gateway_details::{
+1 -1
View File
@@ -101,7 +101,7 @@ impl AsyncFileWatcher {
} }
let Some(filters) = &self.filters else { let Some(filters) = &self.filters else {
return true return true;
}; };
for filter in filters { for filter in filters {
+1 -2
View File
@@ -18,7 +18,6 @@ nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric"
nym-network-defaults = { path = "../network-defaults" } nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false } nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client" path = "../client-libs/validator-client"
features = ["nyxd-client"] features = ["signing"]
@@ -10,8 +10,8 @@ use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO; use nym_network_defaults::VOUCHER_INFO;
use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient; use nym_validator_client::nyxd::traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::traits::DkgQueryClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
use nym_validator_client::nyxd::tx::Hash;
use nym_validator_client::nyxd::Coin; use nym_validator_client::nyxd::Coin;
use nym_validator_client::nyxd::Hash;
use nym_validator_client::CoconutApiClient; use nym_validator_client::CoconutApiClient;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use state::{KeyPair, State}; use state::{KeyPair, State};
+1 -1
View File
@@ -45,7 +45,7 @@ nym-network-defaults = { path = "../network-defaults" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.nym-validator-client]
path = "../client-libs/validator-client" path = "../client-libs/validator-client"
features = ["nyxd-client"] features = ["signing", "http-client"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.11" version = "0.1.11"
@@ -153,7 +153,7 @@ impl LoopCoverTrafficStream<OsRng> {
fn loop_cover_message_size(&mut self) -> PacketSize { fn loop_cover_message_size(&mut self) -> PacketSize {
let Some(secondary_packet_size) = self.secondary_packet_size else { let Some(secondary_packet_size) = self.secondary_packet_size else {
return self.primary_packet_size return self.primary_packet_size;
}; };
let use_primary = self let use_primary = self
@@ -224,7 +224,7 @@ where
// if secondary packet was never set, then it's obvious we have to use the primary packet // if secondary packet was never set, then it's obvious we have to use the primary packet
let Some(secondary_packet) = self.config.secondary_packet_size else { let Some(secondary_packet) = self.config.secondary_packet_size else {
trace!("only primary packet size is available"); trace!("only primary packet size is available");
return self.config.primary_packet_size return self.config.primary_packet_size;
}; };
let primary_count = let primary_count =
@@ -200,7 +200,7 @@ where
fn loop_cover_message_size(&mut self) -> PacketSize { fn loop_cover_message_size(&mut self) -> PacketSize {
let Some(secondary_packet_size) = self.config.traffic.secondary_packet_size else { let Some(secondary_packet_size) = self.config.traffic.secondary_packet_size else {
return self.config.traffic.primary_packet_size return self.config.traffic.primary_packet_size;
}; };
let use_primary = self let use_primary = self
@@ -727,7 +727,11 @@ where
continue; continue;
} }
let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else { let Some(last_received) = self
.full_reply_storage
.surbs_storage_ref()
.surbs_last_received_at(pending_reply_target)
else {
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size()); error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size());
to_remove.push(*pending_reply_target); to_remove.push(*pending_reply_target);
continue; continue;
@@ -811,7 +815,8 @@ where
// this should never ever happen (famous last words, eh?), but in case it DOES happen eventually // this should never ever happen (famous last words, eh?), but in case it DOES happen eventually
// purge that malformed data // purge that malformed data
let Ok(sent_at) = OffsetDateTime::from_unix_timestamp(reply_key.sent_at_timestamp) else { let Ok(sent_at) = OffsetDateTime::from_unix_timestamp(reply_key.sent_at_timestamp)
else {
error!("somehow our stored timestamp ({}) for one of our reply key is corrupted!. Going to remove all the entry", reply_key.sent_at_timestamp); error!("somehow our stored timestamp ({}) for one of our reply key is corrupted!. Going to remove all the entry", reply_key.sent_at_timestamp);
to_remove_keys.push(*digest); to_remove_keys.push(*digest);
continue; continue;
@@ -180,7 +180,7 @@ impl<T> TransmissionBuffer<T> {
while items.len() < n { while items.len() < n {
let Some(next) = self.pop_next_message_at_random(rng) else { let Some(next) = self.pop_next_message_at_random(rng) else {
break break;
}; };
items.push(next) items.push(next)
} }
+22 -15
View File
@@ -38,6 +38,7 @@ use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
type WsConn = JSWebsocket; type WsConn = JSWebsocket;
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
const MEASUREMENTS: usize = 3; const MEASUREMENTS: usize = 3;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@@ -158,23 +159,29 @@ pub(super) async fn choose_gateway_by_latency<R: Rng>(
rng: &mut R, rng: &mut R,
gateways: &[gateway::Node], gateways: &[gateway::Node],
) -> Result<gateway::Node, ClientCoreError> { ) -> Result<gateway::Node, ClientCoreError> {
info!("choosing gateway by latency..."); info!(
"choosing gateway by latency, pinging {} gateways ...",
gateways.len()
);
let mut gateways_with_latency = Vec::new(); let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new()));
for gateway in gateways { futures::stream::iter(gateways)
let id = *gateway.identity(); .for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async {
trace!("measuring latency to {id}..."); let id = *gateway.identity();
let with_latency = match measure_latency(gateway).await { trace!("measuring latency to {id}...");
Ok(res) => res, match measure_latency(gateway).await {
Err(err) => { Ok(with_latency) => {
warn!("failed to measure {id}: {err}"); debug!("{id}: {:?}", with_latency.latency);
continue; gateways_with_latency.lock().await.push(with_latency);
} }
}; Err(err) => {
debug!("{id}: {:?}", with_latency.latency); warn!("failed to measure {id}: {err}");
gateways_with_latency.push(with_latency) }
} };
})
.await;
let gateways_with_latency = gateways_with_latency.lock().await;
let chosen = gateways_with_latency let chosen = gateways_with_latency
.choose_weighted(rng, |item| 1. / item.latency.as_secs_f32()) .choose_weighted(rng, |item| 1. / item.latency.as_secs_f32())
.expect("invalid selection weight!"); .expect("invalid selection weight!");
+23 -32
View File
@@ -35,27 +35,30 @@ nym-coconut-interface = { path = "../../coconut-interface" }
nym-network-defaults = { path = "../../network-defaults" } nym-network-defaults = { path = "../../network-defaults" }
nym-api-requests = { path = "../../../nym-api/nym-api-requests" } nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
# required for nyxd-client async-trait = { workspace = true }
# at some point it might be possible to make it wasm-compatible
# perhaps after https://github.com/cosmos/cosmos-rust/pull/97 is resolved (and tendermint-rs is updated)
async-trait = { workspace = true, optional = true }
bip39 = { workspace = true, features = ["rand"], optional = true } bip39 = { workspace = true, features = ["rand"], optional = true }
nym-config = { path = "../../config", optional = true } nym-config = { path = "../../config" }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true } cosmrs = { workspace = true, features = ["bip32", "cosmwasm"] }
#cosmrs = { workspace = true, features = ["bip32", "rpc", "cosmwasm"], optional = true }
# note that this has the same version as used by cosmrs # note that this has the same version as used by cosmrs
# import it just for the `Client` trait
tendermint-rpc = { workspace = true }
eyre = { version = "0.6", optional = true } eyre = { version = "0.6", optional = true }
cw3 = { workspace = true, optional = true } cw3 = { workspace = true }
cw4 = { workspace = true, optional = true } cw4 = { workspace = true }
prost = { version = "0.10", default-features = false, optional = true } prost = { version = "0.11", default-features = false }
flate2 = { version = "1.0.20", optional = true } flate2 = { version = "1.0.20" }
sha2 = { version = "0.9.5", optional = true } sha2 = { version = "0.9.5" }
itertools = { version = "0.10", optional = true } itertools = { version = "0.10" }
zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] } zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true, optional = true } cosmwasm-std = { workspace = true }
[dev-dependencies] [dev-dependencies]
bip39 = { workspace = true } bip39 = { workspace = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32"] } #cosmrs = { workspace = true, features = ["rpc", "bip32"] }
cosmrs = { workspace = true, features = ["bip32"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
ts-rs = "6.1.2" ts-rs = "6.1.2"
@@ -64,35 +67,23 @@ name = "offline_signing"
# it should only really require the "signing" feature, # it should only really require the "signing" feature,
# but that would require another round of refactoring to make it possible # but that would require another round of refactoring to make it possible
# (traits would need to be moved around and refactored themselves) # (traits would need to be moved around and refactored themselves)
required-features = ["nyxd-client"] required-features = ["http-client", "signing"]
[[example]] [[example]]
name = "query_service_provider_directory" name = "query_service_provider_directory"
required-features = ["nyxd-client"] # TODO: validate the requirements
required-features = ["http-client", "signing"]
[[example]] [[example]]
name = "query_name_service" name = "query_name_service"
required-features = ["nyxd-client"] # TODO: validate the requirements
required-features = ["http-client", "signing"]
[features] [features]
nyxd-client = [ http-client = ["cosmrs/rpc", "openssl"]
"async-trait",
"cosmrs",
"cosmwasm-std",
"cw3",
"cw4",
"flate2",
"itertools",
"openssl",
"prost",
"sha2",
"signing"
]
signing = [ signing = [
"bip39", "bip39",
"cosmrs",
"eyre", "eyre",
"nym-config",
"zeroize" "zeroize"
] ]
generate-ts = [] generate-ts = []
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use cosmrs::bank::MsgSend; use cosmrs::bank::MsgSend;
use cosmrs::rpc::{self, HttpClient}; use cosmrs::rpc::HttpClient;
use cosmrs::tx::Msg; use cosmrs::tx::Msg;
use cosmrs::{tx, AccountId, Coin, Denom}; use cosmrs::{tx, AccountId, Coin, Denom};
use nym_validator_client::nyxd::CosmWasmClient; use nym_validator_client::nyxd::CosmWasmClient;
@@ -54,7 +54,7 @@ async fn main() {
denom, denom,
amount: 2500u32.into(), amount: 2500u32.into(),
}, },
100000, 100000u32,
); );
let tx_raw = tx_signer let tx_raw = tx_signer
@@ -70,7 +70,7 @@ async fn main() {
.unwrap(); .unwrap();
// broadcast the tx // broadcast the tx
let res = rpc::Client::broadcast_tx_commit(&broadcaster, tx_bytes.into()) let res = tendermint_rpc::client::Client::broadcast_tx_commit(&broadcaster, tx_bytes)
.await .await
.unwrap(); .unwrap();
@@ -16,37 +16,35 @@ pub use nym_mixnet_contract_common::{
}; };
use url::Url; use url::Url;
#[cfg(feature = "nyxd-client")]
use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient}; use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient};
#[cfg(feature = "nyxd-client")] #[cfg(feature = "http-client")]
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient}; use crate::nyxd::QueryNyxdClient;
#[cfg(feature = "nyxd-client")] use crate::nyxd::{self, CosmWasmClient, NyxdClient};
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
#[cfg(feature = "nyxd-client")]
use nym_api_requests::models::MixNodeBondAnnotated; use nym_api_requests::models::MixNodeBondAnnotated;
#[cfg(feature = "nyxd-client")]
use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare}; use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare};
#[cfg(feature = "nyxd-client")]
use nym_coconut_interface::Base58; use nym_coconut_interface::Base58;
#[cfg(feature = "nyxd-client")]
use nym_mixnet_contract_common::{ use nym_mixnet_contract_common::{
families::{Family, FamilyHead}, families::{Family, FamilyHead},
mixnode::MixNodeBond, mixnode::MixNodeBond,
pending_events::{PendingEpochEvent, PendingIntervalEvent}, pending_events::{PendingEpochEvent, PendingIntervalEvent},
Delegation, RewardedSetNodeStatus, UnbondedMixnode, Delegation, RewardedSetNodeStatus, UnbondedMixnode,
}; };
#[cfg(feature = "nyxd-client")]
use nym_network_defaults::NymNetworkDetails; use nym_network_defaults::NymNetworkDetails;
#[cfg(feature = "nyxd-client")]
use std::str::FromStr; use std::str::FromStr;
#[cfg(feature = "nyxd-client")] #[cfg(all(feature = "signing", feature = "http-client"))]
use crate::nyxd::SigningNyxdClient;
#[cfg(all(feature = "signing", feature = "http-client"))]
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
#[must_use] #[must_use]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Config { pub struct Config {
api_url: Url, api_url: Url,
nyxd_url: Url, nyxd_url: Url,
// TODO: until refactored, this is a dead field under some features
#[allow(dead_code)]
nyxd_config: nyxd::Config, nyxd_config: nyxd::Config,
mixnode_page_limit: Option<u32>, mixnode_page_limit: Option<u32>,
@@ -55,7 +53,6 @@ pub struct Config {
rewarded_set_page_limit: Option<u32>, rewarded_set_page_limit: Option<u32>,
} }
#[cfg(feature = "nyxd-client")]
impl Config { impl Config {
pub fn try_from_nym_network_details( pub fn try_from_nym_network_details(
details: &NymNetworkDetails, details: &NymNetworkDetails,
@@ -119,7 +116,6 @@ impl Config {
} }
} }
#[cfg(feature = "nyxd-client")]
pub struct Client<C> { pub struct Client<C> {
mixnode_page_limit: Option<u32>, mixnode_page_limit: Option<u32>,
gateway_page_limit: Option<u32>, gateway_page_limit: Option<u32>,
@@ -131,7 +127,7 @@ pub struct Client<C> {
pub nyxd: NyxdClient<C>, pub nyxd: NyxdClient<C>,
} }
#[cfg(feature = "nyxd-client")] #[cfg(all(feature = "signing", feature = "http-client"))]
impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> { impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
pub fn new_signing( pub fn new_signing(
config: Config, config: Config,
@@ -165,7 +161,7 @@ impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
} }
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "http-client")]
impl Client<QueryNyxdClient> { impl Client<QueryNyxdClient> {
pub fn new_query(config: Config) -> Result<Client<QueryNyxdClient>, ValidatorClientError> { pub fn new_query(config: Config) -> Result<Client<QueryNyxdClient>, ValidatorClientError> {
let nym_api_client = nym_api::Client::new(config.api_url.clone()); let nym_api_client = nym_api::Client::new(config.api_url.clone());
@@ -189,7 +185,6 @@ impl Client<QueryNyxdClient> {
} }
// nyxd wrappers // nyxd wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C> { impl<C> Client<C> {
// use case: somebody initialised client without a contract in order to upload and initialise one // use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client // and now they want to actually use it without making new client
@@ -572,7 +567,6 @@ impl<C> Client<C> {
} }
// validator-api wrappers // validator-api wrappers
#[cfg(feature = "nyxd-client")]
impl<C> Client<C> { impl<C> Client<C> {
pub fn change_nym_api(&mut self, new_endpoint: Url) { pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api.change_url(new_endpoint) self.nym_api.change_url(new_endpoint)
@@ -635,11 +629,9 @@ pub struct CoconutApiClient {
pub api_client: NymApiClient, pub api_client: NymApiClient,
pub verification_key: VerificationKey, pub verification_key: VerificationKey,
pub node_id: NodeIndex, pub node_id: NodeIndex,
#[cfg(feature = "nyxd-client")]
pub cosmos_address: cosmrs::AccountId, pub cosmos_address: cosmrs::AccountId,
} }
#[cfg(feature = "nyxd-client")]
impl CoconutApiClient { impl CoconutApiClient {
pub async fn all_coconut_api_clients<C>( pub async fn all_coconut_api_clients<C>(
client: &C, client: &C,
@@ -120,7 +120,7 @@ async fn test_nyxd_connection(
) )
.await .await
{ {
Ok(Err(NyxdError::TendermintError(e))) => { Ok(Err(NyxdError::TendermintErrorRpc(e))) => {
// If we get a tendermint-rpc error, we classify the node as not contactable // If we get a tendermint-rpc error, we classify the node as not contactable
log::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e); log::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
false false
@@ -15,7 +15,6 @@ pub enum ValidatorClientError {
#[error("One of the provided URLs was malformed - {0}")] #[error("One of the provided URLs was malformed - {0}")]
MalformedUrlProvided(#[from] url::ParseError), MalformedUrlProvided(#[from] url::ParseError),
#[cfg(feature = "nyxd-client")]
#[error("nyxd request failed - {0}")] #[error("nyxd request failed - {0}")]
NyxdError(#[from] crate::nyxd::error::NyxdError), NyxdError(#[from] crate::nyxd::error::NyxdError),
@@ -2,11 +2,10 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod client; pub mod client;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "http-client")]
pub mod connection_tester; pub mod connection_tester;
pub mod error; pub mod error;
pub mod nym_api; pub mod nym_api;
#[cfg(feature = "nyxd-client")]
pub mod nyxd; pub mod nyxd;
#[cfg(feature = "signing")] #[cfg(feature = "signing")]
@@ -16,5 +15,4 @@ pub use crate::error::ValidatorClientError;
pub use client::NymApiClient; pub use client::NymApiClient;
pub use nym_api_requests::*; pub use nym_api_requests::*;
#[cfg(feature = "nyxd-client")]
pub use client::{Client, CoconutApiClient, Config}; pub use client::{Client, CoconutApiClient, Config};
@@ -52,7 +52,6 @@ impl<'a> Div<GasPrice> for &'a Coin {
} else { } else {
implicit_gas_limit.u128() as u64 implicit_gas_limit.u128() as u64
} }
.into()
} }
} }
@@ -191,32 +190,32 @@ mod tests {
let amount = Coin::new(3938, "unym"); let amount = Coin::new(3938, "unym");
let gas_price = "0.025unym".parse().unwrap(); let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(157520, res.value()); assert_eq!(157520, res);
let amount = Coin::new(1234567890, "unym"); let amount = Coin::new(1234567890, "unym");
let gas_price = "0.025unym".parse().unwrap(); let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(49382715600, res.value()); assert_eq!(49382715600, res);
let amount = Coin::new(1, "unym"); let amount = Coin::new(1, "unym");
let gas_price = "0.025unym".parse().unwrap(); let gas_price = "0.025unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(40, res.value()); assert_eq!(40, res);
let amount = Coin::new(150_000_000, "unym"); let amount = Coin::new(150_000_000, "unym");
let gas_price = "0.001234unym".parse().unwrap(); let gas_price = "0.001234unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(121555915721, res.value()); assert_eq!(121555915721, res);
let amount = Coin::new(150_000_000, "unym"); let amount = Coin::new(150_000_000, "unym");
let gas_price = "1unym".parse().unwrap(); let gas_price = "1unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(150_000_000, res.value()); assert_eq!(150_000_000, res);
let amount = Coin::new(150_000_000, "unym"); let amount = Coin::new(150_000_000, "unym");
let gas_price = "1234.56unym".parse().unwrap(); let gas_price = "1234.56unym".parse().unwrap();
let res = amount / gas_price; let res = amount / gas_price;
assert_eq!(121500, res.value()); assert_eq!(121500, res);
} }
#[test] #[test]
@@ -1,15 +1,16 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::nyxd; use crate::nyxd;
use crate::nyxd::coin::Coin; use crate::nyxd::coin::Coin;
use crate::nyxd::cosmwasm_client::helpers::{create_pagination, next_page_key}; use crate::nyxd::cosmwasm_client::helpers::{create_pagination, next_page_key};
use crate::nyxd::cosmwasm_client::types::{ use crate::nyxd::cosmwasm_client::types::{
Account, Code, CodeDetails, Contract, ContractCodeHistoryEntry, ContractCodeId, Account, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse,
SequenceResponse, SimulateResponse,
}; };
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use crate::nyxd::TendermintClient;
use async_trait::async_trait; use async_trait::async_trait;
use cosmrs::cosmwasm::{CodeInfoResponse, ContractCodeHistoryEntry};
use cosmrs::proto::cosmos::auth::v1beta1::{QueryAccountRequest, QueryAccountResponse}; use cosmrs::proto::cosmos::auth::v1beta1::{QueryAccountRequest, QueryAccountResponse};
use cosmrs::proto::cosmos::bank::v1beta1::{ use cosmrs::proto::cosmos::bank::v1beta1::{
QueryAllBalancesRequest, QueryAllBalancesResponse, QueryBalanceRequest, QueryBalanceResponse, QueryAllBalancesRequest, QueryAllBalancesResponse, QueryBalanceRequest, QueryBalanceResponse,
@@ -18,22 +19,28 @@ use cosmrs::proto::cosmos::bank::v1beta1::{
use cosmrs::proto::cosmos::tx::v1beta1::{ use cosmrs::proto::cosmos::tx::v1beta1::{
SimulateRequest, SimulateResponse as ProtoSimulateResponse, SimulateRequest, SimulateResponse as ProtoSimulateResponse,
}; };
use cosmrs::proto::cosmwasm::wasm::v1::*; use cosmrs::proto::cosmwasm::wasm::v1::{
use cosmrs::rpc::endpoint::block::Response as BlockResponse; QueryCodeRequest, QueryCodeResponse, QueryCodesRequest, QueryCodesResponse,
use cosmrs::rpc::endpoint::broadcast; QueryContractHistoryRequest, QueryContractHistoryResponse, QueryContractInfoRequest,
use cosmrs::rpc::endpoint::tx::Response as TxResponse; QueryContractInfoResponse, QueryContractsByCodeRequest, QueryContractsByCodeResponse,
use cosmrs::rpc::query::Query; QueryRawContractStateRequest, QueryRawContractStateResponse, QuerySmartContractStateRequest,
use cosmrs::rpc::{self, HttpClient, Order}; QuerySmartContractStateResponse,
use cosmrs::tendermint::abci::Transaction; };
use cosmrs::tendermint::{abci, block, chain}; use cosmrs::tendermint::{block, chain, Hash};
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx}; use cosmrs::{AccountId, Coin as CosmosCoin, Tx};
use prost::Message; use prost::Message;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto}; use std::convert::TryFrom;
use std::time::Duration; use std::time::Duration;
use tendermint_rpc::{
endpoint::{block::Response as BlockResponse, broadcast, tx::Response as TxResponse},
query::Query,
Order,
};
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl CosmWasmClient for HttpClient { impl CosmWasmClient for cosmrs::rpc::HttpClient {
fn broadcast_polling_rate(&self) -> Duration { fn broadcast_polling_rate(&self) -> Duration {
Duration::from_secs(4) Duration::from_secs(4)
} }
@@ -44,7 +51,7 @@ impl CosmWasmClient for HttpClient {
} }
#[async_trait] #[async_trait]
pub trait CosmWasmClient: rpc::Client { pub trait CosmWasmClient: TendermintClient {
// this should probably get redesigned, but I'm leaving those like that temporarily to fix // this should probably get redesigned, but I'm leaving those like that temporarily to fix
// the underlying issue more quickly // the underlying issue more quickly
fn broadcast_polling_rate(&self) -> Duration; fn broadcast_polling_rate(&self) -> Duration;
@@ -55,7 +62,7 @@ pub trait CosmWasmClient: rpc::Client {
// require proof? // require proof?
async fn make_abci_query<Req, Res>( async fn make_abci_query<Req, Res>(
&self, &self,
path: Option<abci::Path>, path: Option<String>,
req: Req, req: Req,
) -> Result<Res, NyxdError> ) -> Result<Res, NyxdError>
where where
@@ -81,7 +88,7 @@ pub trait CosmWasmClient: rpc::Client {
// TODO: the return type should probably be changed to a non-proto, type-safe Account alternative // TODO: the return type should probably be changed to a non-proto, type-safe Account alternative
async fn get_account(&self, address: &AccountId) -> Result<Option<Account>, NyxdError> { async fn get_account(&self, address: &AccountId) -> Result<Option<Account>, NyxdError> {
let path = Some("/cosmos.auth.v1beta1.Query/Account".parse().unwrap()); let path = Some("/cosmos.auth.v1beta1.Query/Account".to_owned());
let req = QueryAccountRequest { let req = QueryAccountRequest {
address: address.to_string(), address: address.to_string(),
@@ -119,7 +126,7 @@ pub trait CosmWasmClient: rpc::Client {
address: &AccountId, address: &AccountId,
search_denom: String, search_denom: String,
) -> Result<Option<Coin>, NyxdError> { ) -> Result<Option<Coin>, NyxdError> {
let path = Some("/cosmos.bank.v1beta1.Query/Balance".parse().unwrap()); let path = Some("/cosmos.bank.v1beta1.Query/Balance".to_owned());
let req = QueryBalanceRequest { let req = QueryBalanceRequest {
address: address.to_string(), address: address.to_string(),
@@ -137,7 +144,7 @@ pub trait CosmWasmClient: rpc::Client {
} }
async fn get_all_balances(&self, address: &AccountId) -> Result<Vec<Coin>, NyxdError> { async fn get_all_balances(&self, address: &AccountId) -> Result<Vec<Coin>, NyxdError> {
let path = Some("/cosmos.bank.v1beta1.Query/AllBalances".parse().unwrap()); let path = Some("/cosmos.bank.v1beta1.Query/AllBalances".to_owned());
let mut raw_balances = Vec::new(); let mut raw_balances = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -168,7 +175,7 @@ pub trait CosmWasmClient: rpc::Client {
} }
async fn get_total_supply(&self) -> Result<Vec<Coin>, NyxdError> { async fn get_total_supply(&self) -> Result<Vec<Coin>, NyxdError> {
let path = Some("/cosmos.bank.v1beta1.Query/TotalSupply".parse().unwrap()); let path = Some("/cosmos.bank.v1beta1.Query/TotalSupply".to_owned());
let mut supply = Vec::new(); let mut supply = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -195,7 +202,7 @@ pub trait CosmWasmClient: rpc::Client {
.map_err(|_| NyxdError::SerializationError("Coins".to_owned())) .map_err(|_| NyxdError::SerializationError("Coins".to_owned()))
} }
async fn get_tx(&self, id: tx::Hash) -> Result<TxResponse, NyxdError> { async fn get_tx(&self, id: Hash) -> Result<TxResponse, NyxdError> {
Ok(self.tx(id, false).await?) Ok(self.tx(id, false).await?)
} }
@@ -231,30 +238,36 @@ pub trait CosmWasmClient: rpc::Client {
} }
/// Broadcast a transaction, returning immediately. /// Broadcast a transaction, returning immediately.
async fn broadcast_tx_async( async fn broadcast_tx_async<T>(&self, tx: T) -> Result<broadcast::tx_async::Response, NyxdError>
&self, where
tx: Transaction, T: Into<Vec<u8>> + Send,
) -> Result<broadcast::tx_async::Response, NyxdError> { {
Ok(rpc::Client::broadcast_tx_async(self, tx).await?) Ok(tendermint_rpc::client::Client::broadcast_tx_async(self, tx).await?)
} }
/// Broadcast a transaction, returning the response from `CheckTx`. /// Broadcast a transaction, returning the response from `CheckTx`.
async fn broadcast_tx_sync( async fn broadcast_tx_sync<T>(&self, tx: T) -> Result<broadcast::tx_sync::Response, NyxdError>
&self, where
tx: Transaction, T: Into<Vec<u8>> + Send,
) -> Result<broadcast::tx_sync::Response, NyxdError> { {
Ok(rpc::Client::broadcast_tx_sync(self, tx).await?) Ok(tendermint_rpc::client::Client::broadcast_tx_sync(self, tx).await?)
} }
/// Broadcast a transaction, returning the response from `DeliverTx`. /// Broadcast a transaction, returning the response from `DeliverTx`.
async fn broadcast_tx_commit( async fn broadcast_tx_commit<T>(
&self, &self,
tx: Transaction, tx: T,
) -> Result<broadcast::tx_commit::Response, NyxdError> { ) -> Result<broadcast::tx_commit::Response, NyxdError>
Ok(rpc::Client::broadcast_tx_commit(self, tx).await?) where
T: Into<Vec<u8>> + Send,
{
Ok(tendermint_rpc::client::Client::broadcast_tx_commit(self, tx).await?)
} }
async fn broadcast_tx(&self, tx: Transaction) -> Result<TxResponse, NyxdError> { async fn broadcast_tx<T>(&self, tx: T) -> Result<TxResponse, NyxdError>
where
T: Into<Vec<u8>> + Send,
{
let broadcasted = CosmWasmClient::broadcast_tx_sync(self, tx).await?; let broadcasted = CosmWasmClient::broadcast_tx_sync(self, tx).await?;
if broadcasted.code.is_err() { if broadcasted.code.is_err() {
@@ -290,8 +303,8 @@ pub trait CosmWasmClient: rpc::Client {
} }
} }
async fn get_codes(&self) -> Result<Vec<Code>, NyxdError> { async fn get_codes(&self) -> Result<Vec<CodeInfoResponse>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/Codes".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/Codes".to_owned());
let mut raw_codes = Vec::new(); let mut raw_codes = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -311,14 +324,14 @@ pub trait CosmWasmClient: rpc::Client {
} }
} }
raw_codes Ok(raw_codes
.into_iter() .into_iter()
.map(TryFrom::try_from) .map(TryFrom::try_from)
.collect::<Result<_, _>>() .collect::<Result<_, _>>()?)
} }
async fn get_code_details(&self, code_id: ContractCodeId) -> Result<CodeDetails, NyxdError> { async fn get_code_details(&self, code_id: ContractCodeId) -> Result<CodeDetails, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/Code".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/Code".to_owned());
let req = QueryCodeRequest { code_id }; let req = QueryCodeRequest { code_id };
@@ -333,7 +346,7 @@ pub trait CosmWasmClient: rpc::Client {
} }
} }
async fn get_contracts(&self, code_id: ContractCodeId) -> Result<Vec<AccountId>, NyxdError> { async fn get_contracts(&self, code_id: ContractCodeId) -> Result<Vec<AccountId>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/ContractsByCode".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/ContractsByCode".to_owned());
let mut raw_contracts = Vec::new(); let mut raw_contracts = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -364,7 +377,7 @@ pub trait CosmWasmClient: rpc::Client {
} }
async fn get_contract(&self, address: &AccountId) -> Result<Contract, NyxdError> { async fn get_contract(&self, address: &AccountId) -> Result<Contract, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/ContractInfo".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/ContractInfo".to_owned());
let req = QueryContractInfoRequest { let req = QueryContractInfoRequest {
address: address.to_string(), address: address.to_string(),
@@ -389,7 +402,7 @@ pub trait CosmWasmClient: rpc::Client {
&self, &self,
address: &AccountId, address: &AccountId,
) -> Result<Vec<ContractCodeHistoryEntry>, NyxdError> { ) -> Result<Vec<ContractCodeHistoryEntry>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/ContractHistory".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/ContractHistory".to_owned());
let mut raw_entries = Vec::new(); let mut raw_entries = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -412,10 +425,10 @@ pub trait CosmWasmClient: rpc::Client {
} }
} }
raw_entries Ok(raw_entries
.into_iter() .into_iter()
.map(TryFrom::try_from) .map(TryFrom::try_from)
.collect::<Result<_, _>>() .collect::<Result<_, _>>()?)
} }
async fn query_contract_raw( async fn query_contract_raw(
@@ -423,7 +436,7 @@ pub trait CosmWasmClient: rpc::Client {
address: &AccountId, address: &AccountId,
query_data: Vec<u8>, query_data: Vec<u8>,
) -> Result<Vec<u8>, NyxdError> { ) -> Result<Vec<u8>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/RawContractState".parse().unwrap()); let path = Some("/cosmwasm.wasm.v1.Query/RawContractState".to_owned());
let req = QueryRawContractStateRequest { let req = QueryRawContractStateRequest {
address: address.to_string(), address: address.to_string(),
@@ -479,7 +492,7 @@ pub trait CosmWasmClient: rpc::Client {
tx: Option<Tx>, tx: Option<Tx>,
tx_bytes: Vec<u8>, tx_bytes: Vec<u8>,
) -> Result<SimulateResponse, NyxdError> { ) -> Result<SimulateResponse, NyxdError> {
let path = Some("/cosmos.tx.v1beta1.Service/Simulate".parse().unwrap()); let path = Some("/cosmos.tx.v1beta1.Service/Simulate".to_owned());
let req = SimulateRequest { let req = SimulateRequest {
tx: tx.map(Into::into), tx: tx.map(Into::into),
@@ -3,12 +3,7 @@
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use cosmrs::proto::cosmos::base::query::v1beta1::{PageRequest, PageResponse}; use cosmrs::proto::cosmos::base::query::v1beta1::{PageRequest, PageResponse};
use cosmrs::proto::cosmos::base::v1beta1::Coin as ProtoCoin; use tendermint_rpc::endpoint::broadcast;
use cosmrs::rpc::endpoint::broadcast;
use cosmrs::Coin;
use flate2::write::GzEncoder;
use flate2::Compression;
use std::io::Write;
pub(crate) trait CheckResponse: Sized { pub(crate) trait CheckResponse: Sized {
fn check_response(self) -> Result<Self, NyxdError>; fn check_response(self) -> Result<Self, NyxdError>;
@@ -21,7 +16,7 @@ impl CheckResponse for broadcast::tx_commit::Response {
hash: self.hash, hash: self.hash,
height: Some(self.height), height: Some(self.height),
code: self.check_tx.code.value(), code: self.check_tx.code.value(),
raw_log: self.check_tx.log.value().to_owned(), raw_log: self.check_tx.log,
}); });
} }
@@ -30,7 +25,7 @@ impl CheckResponse for broadcast::tx_commit::Response {
hash: self.hash, hash: self.hash,
height: Some(self.height), height: Some(self.height),
code: self.deliver_tx.code.value(), code: self.deliver_tx.code.value(),
raw_log: self.deliver_tx.log.value().to_owned(), raw_log: self.deliver_tx.log,
}); });
} }
@@ -45,7 +40,7 @@ impl CheckResponse for crate::nyxd::TxResponse {
hash: self.hash, hash: self.hash,
height: Some(self.height), height: Some(self.height),
code: self.tx_result.code.value(), code: self.tx_result.code.value(),
raw_log: self.tx_result.log.value().to_owned(), raw_log: self.tx_result.log,
}); });
} }
@@ -53,7 +48,12 @@ impl CheckResponse for crate::nyxd::TxResponse {
} }
} }
#[cfg(feature = "signing")]
pub(crate) fn compress_wasm_code(code: &[u8]) -> Result<Vec<u8>, NyxdError> { pub(crate) fn compress_wasm_code(code: &[u8]) -> Result<Vec<u8>, NyxdError> {
use flate2::write::GzEncoder;
use flate2::Compression;
use std::io::Write;
// using compression level 9, same as cosmjs, that optimises for size // using compression level 9, same as cosmjs, that optimises for size
let mut encoder = GzEncoder::new(Vec::new(), Compression::best()); let mut encoder = GzEncoder::new(Vec::new(), Compression::best());
encoder encoder
@@ -83,14 +83,3 @@ pub(crate) fn next_page_key(pagination_info: Option<PageResponse>) -> Option<Vec
None None
} }
pub(crate) fn parse_proto_coin_vec(value: Vec<ProtoCoin>) -> Result<Vec<Coin>, NyxdError> {
value
.into_iter()
.map(|proto_coin| {
Coin::try_from(&proto_coin).map_err(|_| NyxdError::MalformedCoin {
coin_representation: format!("{:?}", proto_coin),
})
})
.collect()
}
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use cosmrs::tendermint::abci;
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -49,7 +48,7 @@ fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
Ok(logs) Ok(logs)
} }
pub fn parse_raw_logs(raw: abci::Log) -> Result<Vec<Log>, NyxdError> { pub fn parse_raw_logs(raw: String) -> Result<Vec<Log>, NyxdError> {
parse_raw_str_logs(raw.as_ref()) parse_raw_str_logs(raw.as_ref())
} }
@@ -1,17 +1,22 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "http-client")]
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use crate::nyxd::GasPrice; #[cfg(feature = "http-client")]
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl}; use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl};
#[cfg(feature = "http-client")]
use std::convert::TryInto; use std::convert::TryInto;
pub mod client; pub mod client;
mod helpers; mod helpers;
pub mod logs; pub mod logs;
pub mod signing_client;
pub mod types; pub mod types;
#[cfg(feature = "signing")]
pub mod signing_client;
#[cfg(feature = "http-client")]
pub fn connect<U>(endpoint: U) -> Result<HttpClient, NyxdError> pub fn connect<U>(endpoint: U) -> Result<HttpClient, NyxdError>
where where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>, U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
@@ -19,10 +24,11 @@ where
Ok(HttpClient::new(endpoint)?) Ok(HttpClient::new(endpoint)?)
} }
#[cfg(all(feature = "signing", feature = "http-client"))]
pub fn connect_with_signer<S, U: Clone>( pub fn connect_with_signer<S, U: Clone>(
endpoint: U, endpoint: U,
signer: S, signer: S,
gas_price: GasPrice, gas_price: crate::nyxd::GasPrice,
) -> Result<signing_client::Client<S>, NyxdError> ) -> Result<signing_client::Client<S>, NyxdError>
where where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>, U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
@@ -9,29 +9,37 @@ use crate::nyxd::error::NyxdError;
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER}; use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
use crate::nyxd::{Coin, GasAdjustable, GasPrice, TxResponse}; use crate::nyxd::{Coin, GasAdjustable, GasPrice, TxResponse};
use crate::signing::signer::OfflineSigner; use crate::signing::signer::OfflineSigner;
use crate::signing::tx_signer::TxSigner;
use crate::signing::SignerData; use crate::signing::SignerData;
use async_trait::async_trait; use async_trait::async_trait;
use cosmrs::abci::GasInfo;
use cosmrs::bank::MsgSend; use cosmrs::bank::MsgSend;
use cosmrs::distribution::MsgWithdrawDelegatorReward; use cosmrs::distribution::MsgWithdrawDelegatorReward;
use cosmrs::feegrant::{ use cosmrs::feegrant::{
AllowedMsgAllowance, BasicAllowance, MsgGrantAllowance, MsgRevokeAllowance, AllowedMsgAllowance, BasicAllowance, MsgGrantAllowance, MsgRevokeAllowance,
}; };
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode; use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
use cosmrs::rpc::endpoint::broadcast;
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl, SimpleRequest};
use cosmrs::staking::{MsgDelegate, MsgUndelegate}; use cosmrs::staking::{MsgDelegate, MsgUndelegate};
use cosmrs::tx::{self, Msg, Raw}; use cosmrs::tx::{self, Msg};
use cosmrs::{cosmwasm, rpc, AccountId, Any, Tx}; use cosmrs::{cosmwasm, AccountId, Any, Tx};
use log::debug; use log::debug;
use serde::Serialize; use serde::Serialize;
use sha2::Digest; use sha2::Digest;
use sha2::Sha256; use sha2::Sha256;
use std::convert::TryInto; use std::convert::TryInto;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use tendermint_rpc::endpoint::broadcast;
const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4); #[cfg(feature = "http-client")]
const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60); use crate::signing::tx_signer::TxSigner;
#[cfg(feature = "http-client")]
use tendermint_rpc::{Error as TendermintRpcError, SimpleRequest};
#[cfg(feature = "http-client")]
use cosmrs::rpc::{HttpClient, HttpClientUrl};
pub const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
pub const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
fn empty_fee() -> tx::Fee { fn empty_fee() -> tx::Fee {
tx::Fee { tx::Fee {
@@ -123,7 +131,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.check_response()?; .check_response()?;
let logs = parse_raw_logs(tx_res.tx_result.log)?; let logs = parse_raw_logs(tx_res.tx_result.log)?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
// TODO: should those strings be extracted into some constants? // TODO: should those strings be extracted into some constants?
// the reason I think unwrap here is fine is that if the transaction succeeded and those // the reason I think unwrap here is fine is that if the transaction succeeded and those
@@ -184,8 +195,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.check_response()?; .check_response()?;
let logs = parse_raw_logs(tx_res.tx_result.log)?; let logs = parse_raw_logs(tx_res.tx_result.log)?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
// TODO: should those strings be extracted into some constants? // TODO: should those strings be extracted into some constants?
// the reason I think unwrap here is fine is that if the transaction succeeded and those // the reason I think unwrap here is fine is that if the transaction succeeded and those
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected // fields do not exist or address is malformed, there's no way we can recover, we're probably connected
@@ -212,7 +225,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
fee: Fee, fee: Fee,
memo: impl Into<String> + Send + 'static, memo: impl Into<String> + Send + 'static,
) -> Result<ChangeAdminResult, NyxdError> { ) -> Result<ChangeAdminResult, NyxdError> {
let change_admin_msg = cosmwasm::MsgUpdateAdmin { let change_admin_msg = sealed::cosmwasm::MsgUpdateAdmin {
sender: sender_address.clone(), sender: sender_address.clone(),
new_admin: new_admin.clone(), new_admin: new_admin.clone(),
contract: contract_address.clone(), contract: contract_address.clone(),
@@ -225,8 +238,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
Ok(ChangeAdminResult { Ok(ChangeAdminResult {
logs: parse_raw_logs(tx_res.tx_result.log)?, logs: parse_raw_logs(tx_res.tx_result.log)?,
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
@@ -241,7 +256,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
fee: Fee, fee: Fee,
memo: impl Into<String> + Send + 'static, memo: impl Into<String> + Send + 'static,
) -> Result<ChangeAdminResult, NyxdError> { ) -> Result<ChangeAdminResult, NyxdError> {
let change_admin_msg = cosmwasm::MsgClearAdmin { let change_admin_msg = sealed::cosmwasm::MsgClearAdmin {
sender: sender_address.clone(), sender: sender_address.clone(),
contract: contract_address.clone(), contract: contract_address.clone(),
} }
@@ -253,8 +268,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
Ok(ChangeAdminResult { Ok(ChangeAdminResult {
logs: parse_raw_logs(tx_res.tx_result.log)?, logs: parse_raw_logs(tx_res.tx_result.log)?,
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
@@ -288,8 +305,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
Ok(MigrateResult { Ok(MigrateResult {
logs: parse_raw_logs(tx_res.tx_result.log)?, logs: parse_raw_logs(tx_res.tx_result.log)?,
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
@@ -323,11 +342,13 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
Ok(ExecuteResult { Ok(ExecuteResult {
logs: parse_raw_logs(tx_res.tx_result.log)?, logs: parse_raw_logs(tx_res.tx_result.log)?,
data: tx_res.tx_result.data, data: tx_res.tx_result.data.into(),
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
gas_info, gas_info,
}) })
@@ -364,11 +385,13 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used); let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
};
Ok(ExecuteResult { Ok(ExecuteResult {
logs: parse_raw_logs(tx_res.tx_result.log)?, logs: parse_raw_logs(tx_res.tx_result.log)?,
data: tx_res.tx_result.data, data: tx_res.tx_result.data.into(),
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
gas_info, gas_info,
}) })
@@ -602,7 +625,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.to_bytes() .to_bytes()
.map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?; .map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?;
CosmWasmClient::broadcast_tx_async(self, tx_bytes.into()).await CosmWasmClient::broadcast_tx_async(self, tx_bytes).await
} }
/// Broadcast a transaction, returning the response from `CheckTx`. /// Broadcast a transaction, returning the response from `CheckTx`.
@@ -622,7 +645,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.to_bytes() .to_bytes()
.map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?; .map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?;
CosmWasmClient::broadcast_tx_sync(self, tx_bytes.into()).await CosmWasmClient::broadcast_tx_sync(self, tx_bytes).await
} }
/// Broadcast a transaction, returning the response from `DeliverTx`. /// Broadcast a transaction, returning the response from `DeliverTx`.
@@ -643,7 +666,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.to_bytes() .to_bytes()
.map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?; .map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?;
CosmWasmClient::broadcast_tx_commit(self, tx_bytes.into()).await CosmWasmClient::broadcast_tx_commit(self, tx_bytes).await
} }
/// Broadcast a transaction to the network and monitors its inclusion in a block. /// Broadcast a transaction to the network and monitors its inclusion in a block.
@@ -664,7 +687,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.to_bytes() .to_bytes()
.map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?; .map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?;
self.broadcast_tx(tx_bytes.into()).await self.broadcast_tx(tx_bytes).await
} }
async fn sign( async fn sign(
@@ -709,6 +732,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
) -> Result<tx::Raw, NyxdError>; ) -> Result<tx::Raw, NyxdError>;
} }
#[cfg(feature = "http-client")]
#[derive(Debug)] #[derive(Debug)]
pub struct Client<S> { pub struct Client<S> {
// TODO: somehow nicely hide this guy if we decide to use our client in offline mode, // TODO: somehow nicely hide this guy if we decide to use our client in offline mode,
@@ -722,6 +746,7 @@ pub struct Client<S> {
broadcast_timeout: Duration, broadcast_timeout: Duration,
} }
#[cfg(feature = "http-client")]
impl<S> Client<S> { impl<S> Client<S> {
pub fn connect_with_signer<U: Clone>( pub fn connect_with_signer<U: Clone>(
endpoint: U, endpoint: U,
@@ -770,12 +795,13 @@ impl<S> Client<S> {
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> rpc::Client for Client<S> impl<S> tendermint_rpc::client::Client for Client<S>
where where
S: Send + Sync, S: Send + Sync,
{ {
async fn perform<R>(&self, request: R) -> Result<R::Response, rpc::Error> async fn perform<R>(&self, request: R) -> Result<R::Output, tendermint_rpc::Error>
where where
R: SimpleRequest, R: SimpleRequest,
{ {
@@ -783,6 +809,7 @@ where
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> CosmWasmClient for Client<S> impl<S> CosmWasmClient for Client<S>
where where
@@ -797,6 +824,7 @@ where
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> SigningCosmWasmClient for Client<S> impl<S> SigningCosmWasmClient for Client<S>
where where
@@ -820,7 +848,7 @@ where
fee: tx::Fee, fee: tx::Fee,
memo: impl Into<String> + Send + 'static, memo: impl Into<String> + Send + 'static,
signer_data: SignerData, signer_data: SignerData,
) -> Result<Raw, NyxdError> { ) -> Result<tx::Raw, NyxdError> {
Ok(self Ok(self
.tx_signer .tx_signer
.sign_amino(signer_address, messages, fee, memo, signer_data)?) .sign_amino(signer_address, messages, fee, memo, signer_data)?)
@@ -833,9 +861,173 @@ where
fee: tx::Fee, fee: tx::Fee,
memo: impl Into<String> + Send + 'static, memo: impl Into<String> + Send + 'static,
signer_data: SignerData, signer_data: SignerData,
) -> Result<Raw, NyxdError> { ) -> Result<tx::Raw, NyxdError> {
Ok(self Ok(self
.tx_signer .tx_signer
.sign_direct(signer_address, messages, fee, memo, signer_data)?) .sign_direct(signer_address, messages, fee, memo, signer_data)?)
} }
} }
// a temporary bypass until https://github.com/cosmos/cosmos-rust/pull/419 is merged
mod sealed {
pub mod cosmwasm {
use cosmrs::{proto, tx::Msg, AccountId, ErrorReport, Result};
/// MsgUpdateAdmin sets a new admin for a smart contract
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MsgUpdateAdmin {
/// Sender is the that actor that signed the messages
pub sender: AccountId,
/// NewAdmin address to be set
pub new_admin: AccountId,
/// Contract is the address of the smart contract
pub contract: AccountId,
}
impl Msg for MsgUpdateAdmin {
type Proto = proto::cosmwasm::wasm::v1::MsgUpdateAdmin;
}
impl TryFrom<proto::cosmwasm::wasm::v1::MsgUpdateAdmin> for MsgUpdateAdmin {
type Error = ErrorReport;
fn try_from(
proto: proto::cosmwasm::wasm::v1::MsgUpdateAdmin,
) -> Result<MsgUpdateAdmin> {
MsgUpdateAdmin::try_from(&proto)
}
}
impl TryFrom<&proto::cosmwasm::wasm::v1::MsgUpdateAdmin> for MsgUpdateAdmin {
type Error = ErrorReport;
fn try_from(
proto: &proto::cosmwasm::wasm::v1::MsgUpdateAdmin,
) -> Result<MsgUpdateAdmin> {
Ok(MsgUpdateAdmin {
sender: proto.sender.parse()?,
new_admin: proto.new_admin.parse()?,
contract: proto.contract.parse()?,
})
}
}
impl From<MsgUpdateAdmin> for proto::cosmwasm::wasm::v1::MsgUpdateAdmin {
fn from(msg: MsgUpdateAdmin) -> proto::cosmwasm::wasm::v1::MsgUpdateAdmin {
proto::cosmwasm::wasm::v1::MsgUpdateAdmin::from(&msg)
}
}
impl From<&MsgUpdateAdmin> for proto::cosmwasm::wasm::v1::MsgUpdateAdmin {
fn from(msg: &MsgUpdateAdmin) -> proto::cosmwasm::wasm::v1::MsgUpdateAdmin {
proto::cosmwasm::wasm::v1::MsgUpdateAdmin {
sender: msg.sender.to_string(),
new_admin: msg.new_admin.to_string(),
contract: msg.contract.to_string(),
}
}
}
/// MsgUpdateAdminResponse returns empty data
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MsgUpdateAdminResponse {}
impl Msg for MsgUpdateAdminResponse {
type Proto = proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse;
}
impl TryFrom<proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse> for MsgUpdateAdminResponse {
type Error = ErrorReport;
fn try_from(
_proto: proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse,
) -> Result<MsgUpdateAdminResponse> {
Ok(MsgUpdateAdminResponse {})
}
}
impl From<MsgUpdateAdminResponse> for proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse {
fn from(
_msg: MsgUpdateAdminResponse,
) -> proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse {
proto::cosmwasm::wasm::v1::MsgUpdateAdminResponse {}
}
}
/// MsgClearAdmin removes any admin stored for a smart contract
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MsgClearAdmin {
/// Sender is the that actor that signed the messages
pub sender: AccountId,
/// Contract is the address of the smart contract
pub contract: AccountId,
}
impl Msg for MsgClearAdmin {
type Proto = proto::cosmwasm::wasm::v1::MsgClearAdmin;
}
impl TryFrom<proto::cosmwasm::wasm::v1::MsgClearAdmin> for MsgClearAdmin {
type Error = ErrorReport;
fn try_from(proto: proto::cosmwasm::wasm::v1::MsgClearAdmin) -> Result<MsgClearAdmin> {
MsgClearAdmin::try_from(&proto)
}
}
impl TryFrom<&proto::cosmwasm::wasm::v1::MsgClearAdmin> for MsgClearAdmin {
type Error = ErrorReport;
fn try_from(proto: &proto::cosmwasm::wasm::v1::MsgClearAdmin) -> Result<MsgClearAdmin> {
Ok(MsgClearAdmin {
sender: proto.sender.parse()?,
contract: proto.contract.parse()?,
})
}
}
impl From<MsgClearAdmin> for proto::cosmwasm::wasm::v1::MsgClearAdmin {
fn from(msg: MsgClearAdmin) -> proto::cosmwasm::wasm::v1::MsgClearAdmin {
proto::cosmwasm::wasm::v1::MsgClearAdmin::from(&msg)
}
}
impl From<&MsgClearAdmin> for proto::cosmwasm::wasm::v1::MsgClearAdmin {
fn from(msg: &MsgClearAdmin) -> proto::cosmwasm::wasm::v1::MsgClearAdmin {
proto::cosmwasm::wasm::v1::MsgClearAdmin {
sender: msg.sender.to_string(),
contract: msg.contract.to_string(),
}
}
}
/// MsgClearAdminResponse returns empty data
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MsgClearAdminResponse {}
impl Msg for MsgClearAdminResponse {
type Proto = proto::cosmwasm::wasm::v1::MsgClearAdminResponse;
}
impl TryFrom<proto::cosmwasm::wasm::v1::MsgClearAdminResponse> for MsgClearAdminResponse {
type Error = ErrorReport;
fn try_from(
_proto: proto::cosmwasm::wasm::v1::MsgClearAdminResponse,
) -> Result<MsgClearAdminResponse> {
Ok(MsgClearAdminResponse {})
}
}
impl From<MsgClearAdminResponse> for proto::cosmwasm::wasm::v1::MsgClearAdminResponse {
fn from(
_msg: MsgClearAdminResponse,
) -> proto::cosmwasm::wasm::v1::MsgClearAdminResponse {
proto::cosmwasm::wasm::v1::MsgClearAdminResponse {}
}
}
}
}
@@ -3,36 +3,35 @@
// TODO: There's a significant argument to pull those out of the package and make a PR on https://github.com/cosmos/cosmos-rust/ // TODO: There's a significant argument to pull those out of the package and make a PR on https://github.com/cosmos/cosmos-rust/
use crate::nyxd::cosmwasm_client::helpers::parse_proto_coin_vec;
use crate::nyxd::cosmwasm_client::logs::Log; use crate::nyxd::cosmwasm_client::logs::Log;
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use cosmrs::crypto::PublicKey; use cosmrs::auth::{BaseAccount, ModuleAccount};
use cosmrs::cosmwasm::{CodeInfoResponse, ContractInfo};
use cosmrs::proto::cosmos::auth::v1beta1::{ use cosmrs::proto::cosmos::auth::v1beta1::{
BaseAccount as ProtoBaseAccount, ModuleAccount as ProtoModuleAccount, BaseAccount as ProtoBaseAccount, ModuleAccount as ProtoModuleAccount,
}; };
use cosmrs::proto::cosmos::base::abci::v1beta1::{ use cosmrs::proto::cosmos::base::abci::v1beta1::Result as ProtoAbciResult;
GasInfo as ProtoGasInfo, Result as ProtoAbciResult,
};
use cosmrs::proto::cosmos::tx::v1beta1::SimulateResponse as ProtoSimulateResponse; use cosmrs::proto::cosmos::tx::v1beta1::SimulateResponse as ProtoSimulateResponse;
use cosmrs::proto::cosmos::vesting::v1beta1::{ use cosmrs::proto::cosmos::vesting::v1beta1::{
BaseVestingAccount as ProtoBaseVestingAccount, BaseVestingAccount as ProtoBaseVestingAccount,
ContinuousVestingAccount as ProtoContinuousVestingAccount, ContinuousVestingAccount as ProtoContinuousVestingAccount,
DelayedVestingAccount as ProtoDelayedVestingAccount, Period as ProtoPeriod, DelayedVestingAccount as ProtoDelayedVestingAccount,
PeriodicVestingAccount as ProtoPeriodicVestingAccount, PeriodicVestingAccount as ProtoPeriodicVestingAccount,
PermanentLockedAccount as ProtoPermanentLockedAccount, PermanentLockedAccount as ProtoPermanentLockedAccount,
}; };
use cosmrs::proto::cosmwasm::wasm::v1::{ use cosmrs::tendermint::{abci, Hash};
CodeInfoResponse, ContractCodeHistoryEntry as ProtoContractCodeHistoryEntry, use cosmrs::tx::{AccountNumber, SequenceNumber};
ContractCodeHistoryOperationType, ContractInfo as ProtoContractInfo, use cosmrs::vesting::{
BaseVestingAccount, ContinuousVestingAccount, DelayedVestingAccount, PeriodicVestingAccount,
PermanentLockedAccount,
}; };
use cosmrs::tendermint::abci; use cosmrs::{AccountId, Any, Coin as CosmosCoin};
use cosmrs::tendermint::abci::Data;
use cosmrs::tx::{AccountNumber, Gas, SequenceNumber};
use cosmrs::{tx, AccountId, Any, Coin as CosmosCoin};
use prost::Message; use prost::Message;
use serde::Serialize; use serde::Serialize;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
pub use cosmrs::abci::GasInfo;
pub type ContractCodeId = u64; pub type ContractCodeId = u64;
#[derive(Serialize)] #[derive(Serialize)]
@@ -44,215 +43,6 @@ pub struct SequenceResponse {
pub sequence: SequenceNumber, pub sequence: SequenceNumber,
} }
/// BaseAccount defines a base account type. It contains all the necessary fields
/// for basic account functionality. Any custom account type should extend this
/// type for additional functionality (e.g. vesting).
#[derive(Debug)]
pub struct BaseAccount {
/// Bech32 account address
pub address: AccountId,
pub pubkey: Option<PublicKey>,
pub account_number: AccountNumber,
pub sequence: SequenceNumber,
}
impl TryFrom<ProtoBaseAccount> for BaseAccount {
type Error = NyxdError;
fn try_from(value: ProtoBaseAccount) -> Result<Self, Self::Error> {
let address: AccountId = value
.address
.parse()
.map_err(|_| NyxdError::MalformedAccountAddress(value.address.clone()))?;
let pubkey = value
.pub_key
.map(PublicKey::try_from)
.transpose()
.map_err(|_| NyxdError::InvalidPublicKey(address.clone()))?;
Ok(BaseAccount {
address,
pubkey,
account_number: value.account_number,
sequence: value.sequence,
})
}
}
/// ModuleAccount defines an account for modules that holds coins on a pool.
#[derive(Debug)]
pub struct ModuleAccount {
pub base_account: Option<BaseAccount>,
pub name: String,
pub permissions: Vec<String>,
}
impl TryFrom<ProtoModuleAccount> for ModuleAccount {
type Error = NyxdError;
fn try_from(value: ProtoModuleAccount) -> Result<Self, Self::Error> {
let base_account = value.base_account.map(TryFrom::try_from).transpose()?;
Ok(ModuleAccount {
base_account,
name: value.name,
permissions: value.permissions,
})
}
}
/// BaseVestingAccount implements the VestingAccount interface. It contains all
/// the necessary fields needed for any vesting account implementation.
#[derive(Debug)]
pub struct BaseVestingAccount {
pub base_account: Option<BaseAccount>,
pub original_vesting: Vec<CosmosCoin>,
pub delegated_free: Vec<CosmosCoin>,
pub delegated_vesting: Vec<CosmosCoin>,
pub end_time: i64,
}
impl TryFrom<ProtoBaseVestingAccount> for BaseVestingAccount {
type Error = NyxdError;
fn try_from(value: ProtoBaseVestingAccount) -> Result<Self, Self::Error> {
let base_account = value.base_account.map(TryFrom::try_from).transpose()?;
let original_vesting = parse_proto_coin_vec(value.original_vesting)?;
let delegated_free = parse_proto_coin_vec(value.delegated_free)?;
let delegated_vesting = parse_proto_coin_vec(value.delegated_vesting)?;
Ok(BaseVestingAccount {
base_account,
original_vesting,
delegated_free,
delegated_vesting,
end_time: value.end_time,
})
}
}
/// ContinuousVestingAccount implements the VestingAccount interface. It
/// continuously vests by unlocking coins linearly with respect to time.
#[derive(Debug)]
pub struct ContinuousVestingAccount {
pub base_vesting_account: Option<BaseVestingAccount>,
pub start_time: i64,
}
impl TryFrom<ProtoContinuousVestingAccount> for ContinuousVestingAccount {
type Error = NyxdError;
fn try_from(value: ProtoContinuousVestingAccount) -> Result<Self, Self::Error> {
let base_vesting_account = value
.base_vesting_account
.map(TryFrom::try_from)
.transpose()?;
Ok(ContinuousVestingAccount {
base_vesting_account,
start_time: value.start_time,
})
}
}
/// DelayedVestingAccount implements the VestingAccount interface. It vests all
/// coins after a specific time, but non prior. In other words, it keeps them
/// locked until a specified time.
#[derive(Debug)]
pub struct DelayedVestingAccount {
pub base_vesting_account: Option<BaseVestingAccount>,
}
impl TryFrom<ProtoDelayedVestingAccount> for DelayedVestingAccount {
type Error = NyxdError;
fn try_from(value: ProtoDelayedVestingAccount) -> Result<Self, Self::Error> {
let base_vesting_account = value
.base_vesting_account
.map(TryFrom::try_from)
.transpose()?;
Ok(DelayedVestingAccount {
base_vesting_account,
})
}
}
/// Period defines a length of time and amount of coins that will vest.
#[derive(Debug)]
pub struct Period {
pub length: i64,
pub amount: Vec<CosmosCoin>,
}
impl TryFrom<ProtoPeriod> for Period {
type Error = NyxdError;
fn try_from(value: ProtoPeriod) -> Result<Self, Self::Error> {
Ok(Period {
length: value.length,
amount: parse_proto_coin_vec(value.amount)?,
})
}
}
/// PeriodicVestingAccount implements the VestingAccount interface. It
/// periodically vests by unlocking coins during each specified period.
#[derive(Debug)]
pub struct PeriodicVestingAccount {
pub base_vesting_account: Option<BaseVestingAccount>,
pub start_time: i64,
pub vesting_periods: Vec<Period>,
}
impl TryFrom<ProtoPeriodicVestingAccount> for PeriodicVestingAccount {
type Error = NyxdError;
fn try_from(value: ProtoPeriodicVestingAccount) -> Result<Self, Self::Error> {
let base_vesting_account = value
.base_vesting_account
.map(TryFrom::try_from)
.transpose()?;
let vesting_periods = value
.vesting_periods
.into_iter()
.map(TryFrom::try_from)
.collect::<Result<_, _>>()?;
Ok(PeriodicVestingAccount {
base_vesting_account,
start_time: value.start_time,
vesting_periods,
})
}
}
/// PermanentLockedAccount implements the VestingAccount interface. It does
/// not ever release coins, locking them indefinitely. Coins in this account can
/// still be used for delegating and for governance votes even while locked.
#[derive(Debug)]
pub struct PermanentLockedAccount {
pub base_vesting_account: Option<BaseVestingAccount>,
}
impl TryFrom<ProtoPermanentLockedAccount> for PermanentLockedAccount {
type Error = NyxdError;
fn try_from(value: ProtoPermanentLockedAccount) -> Result<Self, Self::Error> {
let base_vesting_account = value
.base_vesting_account
.map(TryFrom::try_from)
.transpose()?;
Ok(PermanentLockedAccount {
base_vesting_account,
})
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum Account { pub enum Account {
Base(BaseAccount), Base(BaseAccount),
@@ -335,183 +125,32 @@ impl TryFrom<Any> for Account {
} }
} }
#[derive(Debug)]
pub struct Code {
pub code_id: ContractCodeId,
/// Bech32 account address
pub creator: AccountId,
/// sha256 hash of the code stored
pub data_hash: Vec<u8>,
}
impl TryFrom<CodeInfoResponse> for Code {
type Error = NyxdError;
fn try_from(value: CodeInfoResponse) -> Result<Self, Self::Error> {
let CodeInfoResponse {
code_id,
creator,
data_hash,
} = value;
let creator = creator
.parse()
.map_err(|_| NyxdError::MalformedAccountAddress(creator))?;
Ok(Code {
code_id,
creator,
data_hash,
})
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct CodeDetails { pub struct CodeDetails {
pub code_info: Code, pub code_info: CodeInfoResponse,
/// The original wasm bytes /// The original wasm bytes
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl CodeDetails { impl CodeDetails {
pub fn new(code_info: Code, data: Vec<u8>) -> Self { pub fn new(code_info: CodeInfoResponse, data: Vec<u8>) -> Self {
CodeDetails { code_info, data } CodeDetails { code_info, data }
} }
} }
#[derive(Debug)]
pub(crate) struct ContractInfo {
code_id: ContractCodeId,
creator: AccountId,
admin: Option<AccountId>,
label: String,
}
impl TryFrom<ProtoContractInfo> for ContractInfo {
type Error = NyxdError;
fn try_from(value: ProtoContractInfo) -> Result<Self, Self::Error> {
let ProtoContractInfo {
code_id,
creator,
admin,
label,
..
} = value;
let admin = if admin.is_empty() {
None
} else {
Some(
admin
.parse()
.map_err(|_| NyxdError::MalformedAccountAddress(admin))?,
)
};
Ok(ContractInfo {
code_id,
creator: creator
.parse()
.map_err(|_| NyxdError::MalformedAccountAddress(creator))?,
admin,
label,
})
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Contract { pub struct Contract {
pub address: AccountId, pub address: AccountId,
pub code_id: ContractCodeId, pub contract_info: ContractInfo,
/// Bech32 account address
pub creator: AccountId,
/// Bech32-encoded admin address
pub admin: Option<AccountId>,
pub label: String,
} }
impl Contract { impl Contract {
pub(crate) fn new(address: AccountId, contract_info: ContractInfo) -> Self { pub(crate) fn new(address: AccountId, contract_info: ContractInfo) -> Self {
Contract { Contract {
address, address,
code_id: contract_info.code_id, contract_info,
creator: contract_info.creator,
admin: contract_info.admin,
label: contract_info.label,
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum ContractCodeHistoryEntryOperation {
Init,
Genesis,
Migrate,
}
#[derive(Debug)]
pub struct ContractCodeHistoryEntry {
/// The source of this history entry
pub operation: ContractCodeHistoryEntryOperation,
pub code_id: ContractCodeId,
pub msg_json: String,
}
impl TryFrom<ProtoContractCodeHistoryEntry> for ContractCodeHistoryEntry {
type Error = NyxdError;
fn try_from(value: ProtoContractCodeHistoryEntry) -> Result<Self, Self::Error> {
let operation = match ContractCodeHistoryOperationType::from_i32(value.operation)
.ok_or(NyxdError::InvalidContractHistoryOperation)?
{
ContractCodeHistoryOperationType::Unspecified => {
return Err(NyxdError::InvalidContractHistoryOperation)
}
ContractCodeHistoryOperationType::Init => ContractCodeHistoryEntryOperation::Init,
ContractCodeHistoryOperationType::Genesis => ContractCodeHistoryEntryOperation::Genesis,
ContractCodeHistoryOperationType::Migrate => ContractCodeHistoryEntryOperation::Migrate,
};
Ok(ContractCodeHistoryEntry {
operation,
code_id: value.code_id,
msg_json: String::from_utf8(value.msg)
.map_err(|_| NyxdError::DeserializationError("Contract history msg".to_owned()))?,
})
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize)]
pub struct GasInfo {
/// GasWanted is the maximum units of work we allow this tx to perform.
pub gas_wanted: Gas,
/// GasUsed is the amount of gas actually consumed.
pub gas_used: Gas,
}
impl From<ProtoGasInfo> for GasInfo {
fn from(value: ProtoGasInfo) -> Self {
GasInfo {
gas_wanted: value.gas_wanted.into(),
gas_used: value.gas_used.into(),
}
}
}
impl GasInfo {
pub fn new(gas_wanted: Gas, gas_used: Gas) -> Self {
GasInfo {
gas_wanted,
gas_used,
} }
} }
} }
@@ -535,31 +174,15 @@ impl TryFrom<ProtoAbciResult> for AbciResult {
type Error = NyxdError; type Error = NyxdError;
fn try_from(value: ProtoAbciResult) -> Result<Self, Self::Error> { fn try_from(value: ProtoAbciResult) -> Result<Self, Self::Error> {
let mut events = Vec::with_capacity(value.events.len()); let events = value
.events
for proto_event in value.events.into_iter() { .into_iter()
let type_str = proto_event.r#type; .map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()?;
let mut attributes = Vec::with_capacity(proto_event.attributes.len());
for proto_attribute in proto_event.attributes.into_iter() {
let stringified_ked = String::from_utf8(proto_attribute.key)
.map_err(|_| NyxdError::DeserializationError("EventAttributeKey".to_owned()))?;
let stringified_value = String::from_utf8(proto_attribute.value)
.map_err(|_| NyxdError::DeserializationError("EventAttributeKey".to_owned()))?;
attributes.push(abci::tag::Tag {
key: stringified_ked.parse().unwrap(),
value: stringified_value.parse().unwrap(),
})
}
events.push(abci::Event {
type_str,
attributes,
})
}
#[allow(deprecated)]
Ok(AbciResult { Ok(AbciResult {
// TODO: make sure this actually works since technically we're converting from 0.37 protobuf definition as opposed to 0.34...
data: value.data, data: value.data,
log: value.log, log: value.log,
events, events,
@@ -578,7 +201,10 @@ impl TryFrom<ProtoSimulateResponse> for SimulateResponse {
fn try_from(value: ProtoSimulateResponse) -> Result<Self, Self::Error> { fn try_from(value: ProtoSimulateResponse) -> Result<Self, Self::Error> {
Ok(SimulateResponse { Ok(SimulateResponse {
gas_info: value.gas_info.map(|gas_info| gas_info.into()), gas_info: value
.gas_info
.map(|gas_info| gas_info.try_into())
.transpose()?,
result: value.result.map(|result| result.try_into()).transpose()?, result: value.result.map(|result| result.try_into()).transpose()?,
}) })
} }
@@ -608,7 +234,7 @@ pub struct UploadResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: tx::Hash, pub transaction_hash: Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -645,7 +271,7 @@ pub struct InstantiateResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: tx::Hash, pub transaction_hash: Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -655,7 +281,7 @@ pub struct ChangeAdminResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: tx::Hash, pub transaction_hash: Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -665,7 +291,7 @@ pub struct MigrateResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: tx::Hash, pub transaction_hash: Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -674,10 +300,10 @@ pub struct MigrateResult {
pub struct ExecuteResult { pub struct ExecuteResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
pub data: Data, pub data: Vec<u8>,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: tx::Hash, pub transaction_hash: Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -2,34 +2,39 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::types::ContractCodeId; use crate::nyxd::cosmwasm_client::types::ContractCodeId;
use cosmrs::tendermint::Hash;
use cosmrs::{ use cosmrs::{
rpc::endpoint::abci_query::AbciQuery, tendermint::{abci::Code as AbciCode, block},
tendermint::{ AccountId,
abci::{self, Code as AbciCode},
block,
},
tx, AccountId,
}; };
use std::{io, time::Duration};
use tendermint_rpc::endpoint::abci_query::AbciQuery;
use thiserror::Error; use thiserror::Error;
#[cfg(feature = "signing")]
use crate::signing::direct_wallet::DirectSecp256k1HdWalletError; use crate::signing::direct_wallet::DirectSecp256k1HdWalletError;
pub use cosmrs::rpc::{
pub use cosmrs::tendermint::error::Error as TendermintError;
pub use tendermint_rpc::{
error::{Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail}, error::{Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail},
response_error::{Code, ResponseError}, response_error::{Code, ResponseError},
}; };
use std::{io, time::Duration};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum NyxdError { pub enum NyxdError {
#[error("No contract address is available to perform the call: {0}")] #[error("No contract address is available to perform the call: {0}")]
NoContractAddressAvailable(String), NoContractAddressAvailable(String),
#[cfg(feature = "signing")]
#[error(transparent)] #[error(transparent)]
WalletError(#[from] DirectSecp256k1HdWalletError), WalletError(#[from] DirectSecp256k1HdWalletError),
#[error("There was an issue on the cosmrs side - {0}")] #[error("There was an issue on the cosmrs side: {0}")]
CosmrsError(#[from] cosmrs::Error), CosmrsError(#[from] cosmrs::Error),
#[error("There was an issue on the cosmrs side: {0}")]
CosmrsErrorReport(#[from] cosmrs::ErrorReport),
#[error("Failed to derive account address")] #[error("Failed to derive account address")]
AccountDerivationError, AccountDerivationError,
@@ -43,7 +48,10 @@ pub enum NyxdError {
InvalidTxHash(String), InvalidTxHash(String),
#[error("Tendermint RPC request failed - {0}")] #[error("Tendermint RPC request failed - {0}")]
TendermintError(#[from] TendermintRpcError), TendermintErrorRpc(#[from] TendermintRpcError),
#[error("tendermint library failure: {0}")]
TendermintError(#[from] TendermintError),
#[error("Failed when attempting to serialize data ({0})")] #[error("Failed when attempting to serialize data ({0})")]
SerializationError(String), SerializationError(String),
@@ -91,7 +99,7 @@ pub enum NyxdError {
"Error when broadcasting tx {hash} at height {height:?}. Error occurred during CheckTx phase. Code: {code}; Raw log: {raw_log}" "Error when broadcasting tx {hash} at height {height:?}. Error occurred during CheckTx phase. Code: {code}; Raw log: {raw_log}"
)] )]
BroadcastTxErrorCheckTx { BroadcastTxErrorCheckTx {
hash: tx::Hash, hash: Hash,
height: Option<block::Height>, height: Option<block::Height>,
code: u32, code: u32,
raw_log: String, raw_log: String,
@@ -101,7 +109,7 @@ pub enum NyxdError {
"Error when broadcasting tx {hash} at height {height:?}. Error occurred during DeliverTx phase. Code: {code}; Raw log: {raw_log}" "Error when broadcasting tx {hash} at height {height:?}. Error occurred during DeliverTx phase. Code: {code}; Raw log: {raw_log}"
)] )]
BroadcastTxErrorDeliverTx { BroadcastTxErrorDeliverTx {
hash: tx::Hash, hash: Hash,
height: Option<block::Height>, height: Option<block::Height>,
code: u32, code: u32,
raw_log: String, raw_log: String,
@@ -116,7 +124,7 @@ pub enum NyxdError {
#[error("Abci query failed with code {code} - {log}")] #[error("Abci query failed with code {code} - {log}")]
AbciError { AbciError {
code: u32, code: u32,
log: abci::Log, log: String,
pretty_log: Option<String>, pretty_log: Option<String>,
}, },
@@ -130,7 +138,7 @@ pub enum NyxdError {
NoBaseAccountInformationAvailable, NoBaseAccountInformationAvailable,
#[error("Transaction with ID {hash} has been submitted but not yet found on the chain. You might want to check for it later. There was a total wait of {} seconds", .timeout.as_secs())] #[error("Transaction with ID {hash} has been submitted but not yet found on the chain. You might want to check for it later. There was a total wait of {} seconds", .timeout.as_secs())]
BroadcastTimeout { hash: tx::Hash, timeout: Duration }, BroadcastTimeout { hash: Hash, timeout: Duration },
#[error("Cosmwasm std error: {0}")] #[error("Cosmwasm std error: {0}")]
CosmwasmStdError(#[from] cosmwasm_std::StdError), CosmwasmStdError(#[from] cosmwasm_std::StdError),
@@ -148,7 +156,7 @@ pub fn parse_abci_query_result(query_result: AbciQuery) -> Result<AbciQuery, Nyx
match query_result.code { match query_result.code {
AbciCode::Ok => Ok(query_result), AbciCode::Ok => Ok(query_result),
AbciCode::Err(code) => Err(NyxdError::AbciError { AbciCode::Err(code) => Err(NyxdError::AbciError {
code, code: code.into(),
log: query_result.log.clone(), log: query_result.log.clone(),
pretty_log: try_parse_abci_log(&query_result.log), pretty_log: try_parse_abci_log(&query_result.log),
}), }),
@@ -157,11 +165,8 @@ pub fn parse_abci_query_result(query_result: AbciQuery) -> Result<AbciQuery, Nyx
// Some of the error strings returned by the query are a bit too technical to present to the // Some of the error strings returned by the query are a bit too technical to present to the
// enduser. So we special case some commonly encountered errors. // enduser. So we special case some commonly encountered errors.
fn try_parse_abci_log(log: &abci::Log) -> Option<String> { fn try_parse_abci_log(log: &str) -> Option<String> {
if log if log.contains("Maximum amount of locked coins has already been pledged") {
.value()
.contains("Maximum amount of locked coins has already been pledged")
{
Some("Maximum amount of locked tokens has already been used. You can only use up to 10% of your locked tokens for bonding and delegating.".to_string()) Some("Maximum amount of locked tokens has already been used. You can only use up to 10% of your locked tokens for bonding and delegating.".to_string())
} else { } else {
None None
@@ -171,7 +176,7 @@ fn try_parse_abci_log(log: &abci::Log) -> Option<String> {
impl NyxdError { impl NyxdError {
pub fn is_tendermint_response_timeout(&self) -> bool { pub fn is_tendermint_response_timeout(&self) -> bool {
match &self { match &self {
NyxdError::TendermintError(TendermintRpcError( NyxdError::TendermintErrorRpc(TendermintRpcError(
TendermintRpcErrorDetail::Response(err), TendermintRpcErrorDetail::Response(err),
_, _,
)) => { )) => {
@@ -198,7 +203,7 @@ impl NyxdError {
pub fn is_tendermint_response_duplicate(&self) -> bool { pub fn is_tendermint_response_duplicate(&self) -> bool {
match &self { match &self {
NyxdError::TendermintError(TendermintRpcError( NyxdError::TendermintErrorRpc(TendermintRpcError(
TendermintRpcErrorDetail::Response(err), TendermintRpcErrorDetail::Response(err),
_, _,
)) => { )) => {
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use cosmrs::tx::Gas;
use cosmrs::Coin; use cosmrs::Coin;
use cosmrs::Gas;
use cosmwasm_std::{Decimal, Fraction, Uint128}; use cosmwasm_std::{Decimal, Fraction, Uint128};
use nym_config::defaults; use nym_config::defaults;
use std::ops::Mul; use std::ops::Mul;
@@ -25,7 +25,7 @@ impl<'a> Mul<Gas> for &'a GasPrice {
type Output = Coin; type Output = Coin;
fn mul(self, gas_limit: Gas) -> Self::Output { fn mul(self, gas_limit: Gas) -> Self::Output {
let limit_uint128 = Uint128::from(gas_limit.value()); let limit_uint128 = Uint128::from(gas_limit);
let mut amount = self.amount * limit_uint128; let mut amount = self.amount * limit_uint128;
let gas_price_numerator = self.amount.numerator(); let gas_price_numerator = self.amount.numerator();
@@ -122,7 +122,7 @@ mod tests {
fn gas_limit_multiplication() { fn gas_limit_multiplication() {
// real world example that caused an issue when the result was rounded down // real world example that caused an issue when the result was rounded down
let gas_price: GasPrice = "0.025upunk".parse().unwrap(); let gas_price: GasPrice = "0.025upunk".parse().unwrap();
let gas_limit: Gas = 157500u64.into(); let gas_limit: Gas = 157500u64;
let fee = &gas_price * gas_limit; let fee = &gas_price * gas_limit;
// the failing behaviour was result value of 3937 // the failing behaviour was result value of 3937
@@ -116,8 +116,8 @@ impl GasAdjustable for Gas {
if adjustment == 1.0 { if adjustment == 1.0 {
*self *self
} else { } else {
let adjusted = (self.value() as f32 * adjustment).ceil(); let adjusted = (*self as f32 * adjustment).ceil();
(adjusted as u64).into() adjusted as u64
} }
} }
} }
@@ -125,48 +125,15 @@ impl GasAdjustable for Gas {
// a workaround to provide serde implementation for tx::Fee. We don't want to ever expose any of those // a workaround to provide serde implementation for tx::Fee. We don't want to ever expose any of those
// types to the public and ideally they will get replaced by proper implementation inside comrs // types to the public and ideally they will get replaced by proper implementation inside comrs
mod sealed { mod sealed {
use cosmrs::tx::{self, Gas}; use cosmrs::tx::{self};
use cosmrs::Coin as CosmosCoin; use cosmrs::{AccountId, Denom as CosmosDenom};
use cosmrs::{AccountId, Decimal as CosmosDecimal, Denom as CosmosDenom}; use cosmrs::{Coin as CosmosCoin, Gas};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
fn cosmos_denom_inner_getter(val: &CosmosDenom) -> String {
val.as_ref().to_string()
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDenom")]
struct Denom(#[serde(getter = "cosmos_denom_inner_getter")] String);
impl From<Denom> for CosmosDenom {
fn from(val: Denom) -> Self {
val.0.parse().unwrap()
}
}
fn cosmos_decimal_inner_getter(val: &CosmosDecimal) -> u64 {
// haha, this code is so disgusting. I'll make a PR on cosmrs to slightly alleviate those issues...
// note: unwrap here is fine as the to_string is just returning a stringified u64 which, well, is a valid u64
val.to_string().parse().unwrap()
}
// at the time of writing it the current cosmrs' Decimal is extremely limited...
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDecimal")]
struct Decimal(#[serde(getter = "cosmos_decimal_inner_getter")] u64);
impl From<Decimal> for CosmosDecimal {
fn from(val: Decimal) -> Self {
val.0.into()
}
}
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
struct Coin { struct Coin {
#[serde(with = "Denom")]
denom: CosmosDenom, denom: CosmosDenom,
#[serde(with = "Decimal")] amount: u128,
amount: CosmosDecimal,
} }
impl From<Coin> for CosmosCoin { impl From<Coin> for CosmosCoin {
@@ -1,51 +1,67 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::signing_client; use crate::nyxd::cosmwasm_client::types::Account;
use crate::nyxd::cosmwasm_client::types::{
Account, ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions,
InstantiateResult, MigrateResult, SequenceResponse, SimulateResponse, UploadResult,
};
use crate::nyxd::error::NyxdError; use crate::nyxd::error::NyxdError;
use crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
use crate::signing::signer::OfflineSigner;
use cosmrs::cosmwasm;
use cosmrs::rpc::endpoint::block::Response as BlockResponse;
use cosmrs::rpc::query::Query;
use cosmrs::rpc::Error as TendermintRpcError;
use cosmrs::rpc::HttpClientUrl;
use cosmrs::tx::Msg;
use log::{debug, trace}; use log::{debug, trace};
use nym_network_defaults::{ChainDetails, NymNetworkDetails}; use nym_network_defaults::{ChainDetails, NymNetworkDetails};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryInto; use tendermint_rpc::{endpoint::block::Response as BlockResponse, query::Query};
use std::time::SystemTime;
#[cfg(feature = "http-client")]
use tendermint_rpc::Error as TendermintRpcError;
pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient; pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
pub use crate::nyxd::cosmwasm_client::signing_client::SigningCosmWasmClient;
pub use crate::nyxd::fee::Fee; pub use crate::nyxd::fee::Fee;
pub use coin::Coin; pub use coin::Coin;
pub use cosmrs::bank::MsgSend; pub use cosmrs::bank::MsgSend;
pub use cosmrs::rpc::endpoint::tx::Response as TxResponse; pub use cosmrs::tendermint::abci::{response::DeliverTx, Event, EventAttribute};
pub use cosmrs::rpc::endpoint::validators::Response as ValidatorResponse;
pub use cosmrs::rpc::HttpClient as QueryNyxdClient;
pub use cosmrs::rpc::Paging;
pub use cosmrs::tendermint::abci::responses::{DeliverTx, Event};
pub use cosmrs::tendermint::abci::tag::Tag;
pub use cosmrs::tendermint::block::Height; pub use cosmrs::tendermint::block::Height;
pub use cosmrs::tendermint::hash; pub use cosmrs::tendermint::hash::{self, Algorithm, Hash};
pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo; pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
pub use cosmrs::tendermint::Time as TendermintTime; pub use cosmrs::tendermint::Time as TendermintTime;
pub use cosmrs::tx::{self, Gas}; pub use cosmrs::tx::{self};
pub use cosmrs::Coin as CosmosCoin; pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{bip32, AccountId, Decimal, Denom}; pub use cosmrs::Gas;
use cosmwasm_std::Addr; pub use cosmrs::{bip32, AccountId, Denom};
pub use cosmwasm_std::Coin as CosmWasmCoin; pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment}; pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
pub use signing_client::Client as SigningNyxdClient; pub use tendermint_rpc::{client::Client as TendermintClient, Request, Response, SimpleRequest};
pub use traits::{VestingQueryClient, VestingSigningClient}; pub use tendermint_rpc::{
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
Paging,
};
#[cfg(feature = "http-client")]
pub use cosmrs::rpc::{HttpClient as QueryNyxdClient, HttpClientUrl};
#[cfg(all(feature = "signing", feature = "http-client"))]
use crate::nyxd::cosmwasm_client::signing_client;
#[cfg(feature = "signing")]
use crate::nyxd::cosmwasm_client::types::{
ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions, InstantiateResult,
MigrateResult, SequenceResponse, SimulateResponse, UploadResult,
};
#[cfg(all(feature = "signing", feature = "http-client"))]
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
#[cfg(all(feature = "signing", feature = "http-client"))]
use crate::signing::signer::OfflineSigner;
#[cfg(feature = "signing")]
use cosmrs::cosmwasm;
#[cfg(feature = "signing")]
use cosmrs::tx::Msg;
#[cfg(feature = "signing")]
use cosmwasm_std::Addr;
#[cfg(feature = "signing")]
use std::time::SystemTime;
#[cfg(feature = "signing")]
pub use crate::nyxd::cosmwasm_client::signing_client::SigningCosmWasmClient;
#[cfg(all(feature = "signing", feature = "http-client"))]
pub use signing_client::Client as SigningNyxdClient;
#[cfg(all(feature = "signing", feature = "http-client"))]
pub type DirectSigningNyxdClient = SigningNyxdClient<DirectSecp256k1HdWallet>; pub type DirectSigningNyxdClient = SigningNyxdClient<DirectSecp256k1HdWallet>;
pub mod coin; pub mod coin;
@@ -152,10 +168,13 @@ impl Config {
pub struct NyxdClient<C> { pub struct NyxdClient<C> {
client: C, client: C,
config: Config, config: Config,
// TODO: refactor because that field is only really used for signing
#[allow(dead_code)]
client_address: Option<Vec<AccountId>>, client_address: Option<Vec<AccountId>>,
simulated_gas_multiplier: f32, simulated_gas_multiplier: f32,
} }
#[cfg(feature = "http-client")]
impl NyxdClient<QueryNyxdClient> { impl NyxdClient<QueryNyxdClient> {
pub fn connect<U>(config: Config, endpoint: U) -> Result<NyxdClient<QueryNyxdClient>, NyxdError> pub fn connect<U>(config: Config, endpoint: U) -> Result<NyxdClient<QueryNyxdClient>, NyxdError>
where where
@@ -165,11 +184,12 @@ impl NyxdClient<QueryNyxdClient> {
client: QueryNyxdClient::new(endpoint)?, client: QueryNyxdClient::new(endpoint)?,
config, config,
client_address: None, client_address: None,
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER, simulated_gas_multiplier: crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER,
}) })
} }
} }
#[cfg(all(feature = "signing", feature = "http-client"))]
impl NyxdClient<SigningNyxdClient<DirectSecp256k1HdWallet>> { impl NyxdClient<SigningNyxdClient<DirectSecp256k1HdWallet>> {
// TODO: rename this one // TODO: rename this one
pub fn connect_with_mnemonic<U: Clone>( pub fn connect_with_mnemonic<U: Clone>(
@@ -187,12 +207,14 @@ impl NyxdClient<SigningNyxdClient<DirectSecp256k1HdWallet>> {
} }
} }
#[cfg(all(feature = "signing", feature = "http-client"))]
impl<S> NyxdClient<SigningNyxdClient<S>> impl<S> NyxdClient<SigningNyxdClient<S>>
where where
S: OfflineSigner, S: OfflineSigner,
// I have no idea why S::Error: Into<NyxdError> bound wouldn't do the trick // I have no idea why S::Error: Into<NyxdError> bound wouldn't do the trick
NyxdError: From<S::Error>, NyxdError: From<S::Error>,
{ {
#[cfg(feature = "http-client")]
pub fn connect_with_signer<U: Clone>( pub fn connect_with_signer<U: Clone>(
config: Config, config: Config,
endpoint: U, endpoint: U,
@@ -214,10 +236,11 @@ where
client: SigningNyxdClient::connect_with_signer(endpoint, signer, gas_price)?, client: SigningNyxdClient::connect_with_signer(endpoint, signer, gas_price)?,
config, config,
client_address: Some(client_address), client_address: Some(client_address),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER, simulated_gas_multiplier: crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER,
}) })
} }
#[cfg(feature = "http-client")]
pub fn change_endpoint<U>(&mut self, new_endpoint: U) -> Result<(), NyxdError> pub fn change_endpoint<U>(&mut self, new_endpoint: U) -> Result<(), NyxdError>
where where
U: TryInto<HttpClientUrl, Error = TendermintRpcError>, U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
@@ -230,133 +253,47 @@ where
} }
} }
impl<C> NyxdClient<C> { #[cfg(feature = "signing")]
pub fn current_config(&self) -> &Config { impl<C> NyxdClient<C>
&self.config where
} C: SigningCosmWasmClient + Sync,
{
pub fn current_chain_details(&self) -> &ChainDetails { pub fn address(&self) -> &AccountId
&self.config.chain_details
}
pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
self.config.mixnet_contract_address = Some(address);
}
pub fn set_vesting_contract_address(&mut self, address: AccountId) {
self.config.vesting_contract_address = Some(address);
}
pub fn set_bandwidth_claim_contract_address(&mut self, address: AccountId) {
self.config.bandwidth_claim_contract_address = Some(address);
}
pub fn set_coconut_bandwidth_contract_address(&mut self, address: AccountId) {
self.config.coconut_bandwidth_contract_address = Some(address);
}
pub fn set_multisig_contract_address(&mut self, address: AccountId) {
self.config.multisig_contract_address = Some(address);
}
pub fn set_service_provider_contract_address(&mut self, address: AccountId) {
self.config.service_provider_contract_address = Some(address);
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn mixnet_contract_address(&self) -> &AccountId {
self.config.mixnet_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn vesting_contract_address(&self) -> &AccountId {
self.config.vesting_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn bandwidth_claim_contract_address(&self) -> &AccountId {
self.config
.bandwidth_claim_contract_address
.as_ref()
.unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn coconut_bandwidth_contract_address(&self) -> &AccountId {
self.config
.coconut_bandwidth_contract_address
.as_ref()
.unwrap()
}
pub fn group_contract_address(&self) -> &AccountId {
self.config.group_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn multisig_contract_address(&self) -> &AccountId {
self.config.multisig_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn coconut_dkg_contract_address(&self) -> &AccountId {
self.config.coconut_dkg_contract_address.as_ref().unwrap()
}
// The service provider directory contract is optional, so we return an Option not a Result
pub fn service_provider_contract_address(&self) -> Option<&AccountId> {
self.config.service_provider_contract_address.as_ref()
}
// The name service contract is optional, so we return an Option not a Result
pub fn name_service_contract_address(&self) -> Option<&AccountId> {
self.config.name_service_contract_address.as_ref()
}
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
self.simulated_gas_multiplier = multiplier;
}
pub async fn query_contract_smart<M, T>(
&self,
contract: &AccountId,
query_msg: &M,
) -> Result<T, NyxdError>
where where
C: CosmWasmClient + Sync, C: SigningCosmWasmClient,
M: ?Sized + Serialize + Sync,
for<'a> T: Deserialize<'a>,
{ {
self.client.query_contract_smart(contract, query_msg).await // if this is a signing client (as required by the trait bound), it must have the address set
&self.client_address.as_ref().unwrap()[0]
} }
pub async fn query_contract_raw( pub fn cw_address(&self) -> Addr
&self,
contract: &AccountId,
query_data: Vec<u8>,
) -> Result<Vec<u8>, NyxdError>
where where
C: CosmWasmClient + Sync, C: SigningCosmWasmClient,
{ {
self.client.query_contract_raw(contract, query_data).await // the call to unchecked is fine here as we're converting directly from `AccountId`
// which must have been a valid bech32 address
Addr::unchecked(self.address().as_ref())
}
pub async fn account_sequence(&self) -> Result<SequenceResponse, NyxdError>
where
C: SigningCosmWasmClient + Sync,
{
self.client.get_sequence(self.address()).await
}
pub fn signer(&self) -> &<C as SigningCosmWasmClient>::Signer
where
C: SigningCosmWasmClient,
{
self.client.signer()
}
pub fn gas_price(&self) -> &GasPrice
where
C: SigningCosmWasmClient,
{
self.client.gas_price()
} }
pub fn wrap_contract_execute_message<M>( pub fn wrap_contract_execute_message<M>(
@@ -377,175 +314,6 @@ impl<C> NyxdClient<C> {
}) })
} }
pub fn address(&self) -> &AccountId
where
C: SigningCosmWasmClient,
{
// if this is a signing client (as required by the trait bound), it must have the address set
&self.client_address.as_ref().unwrap()[0]
}
pub fn cw_address(&self) -> Addr
where
C: SigningCosmWasmClient,
{
// the call to unchecked is fine here as we're converting directly from `AccountId`
// which must have been a valid bech32 address
Addr::unchecked(self.address().as_ref())
}
pub fn signer(&self) -> &<C as SigningCosmWasmClient>::Signer
where
C: SigningCosmWasmClient,
{
self.client.signer()
}
pub fn gas_price(&self) -> &GasPrice
where
C: SigningCosmWasmClient,
{
self.client.gas_price()
}
pub fn gas_adjustment(&self) -> GasAdjustment {
self.simulated_gas_multiplier
}
// =============
// CHAIN RELATED
// =============
// CHAIN QUERIES
pub async fn account_sequence(&self) -> Result<SequenceResponse, NyxdError>
where
C: SigningCosmWasmClient + Sync,
{
self.client.get_sequence(self.address()).await
}
pub async fn get_account_details(
&self,
address: &AccountId,
) -> Result<Option<Account>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_account(address).await
}
pub async fn get_account_public_key(
&self,
address: &AccountId,
) -> Result<Option<cosmrs::crypto::PublicKey>, NyxdError>
where
C: CosmWasmClient + Sync,
{
if let Some(account) = self.client.get_account(address).await? {
let base_account = account.try_get_base_account()?;
return Ok(base_account.pubkey);
}
Ok(None)
}
pub async fn get_current_block_timestamp(&self) -> Result<TendermintTime, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.get_block_timestamp(None).await
}
pub async fn get_block_timestamp(
&self,
height: Option<u32>,
) -> Result<TendermintTime, NyxdError>
where
C: CosmWasmClient + Sync,
{
Ok(self.client.get_block(height).await?.block.header.time)
}
pub async fn get_block(&self, height: Option<u32>) -> Result<BlockResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_block(height).await
}
pub async fn get_current_block_height(&self) -> Result<Height, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_height().await
}
/// Obtains the hash of a block specified by the provided height.
///
/// # Arguments
///
/// * `height`: height of the block for which we want to obtain the hash.
pub async fn get_block_hash(&self, height: u32) -> Result<hash::Hash, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client
.get_block(Some(height))
.await
.map(|block| block.block_id.hash)
}
pub async fn get_validators(
&self,
height: u64,
paging: Paging,
) -> Result<ValidatorResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
Ok(self.client.validators(height as u32, paging).await?)
}
pub async fn get_balance(
&self,
address: &AccountId,
denom: String,
) -> Result<Option<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_balance(address, denom).await
}
pub async fn get_all_balances(&self, address: &AccountId) -> Result<Vec<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_all_balances(address).await
}
pub async fn get_tx(&self, id: tx::Hash) -> Result<TxResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_tx(id).await
}
pub async fn search_tx(&self, query: Query) -> Result<Vec<TxResponse>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.search_tx(query).await
}
pub async fn get_total_supply(&self) -> Result<Vec<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_total_supply().await
}
pub async fn simulate<I, M>(&self, messages: I) -> Result<SimulateResponse, NyxdError> pub async fn simulate<I, M>(&self, messages: I) -> Result<SimulateResponse, NyxdError>
where where
C: SigningCosmWasmClient + Sync, C: SigningCosmWasmClient + Sync,
@@ -762,3 +530,264 @@ impl<C> NyxdClient<C> {
.await .await
} }
} }
impl<C> NyxdClient<C> {
pub fn current_config(&self) -> &Config {
&self.config
}
pub fn current_chain_details(&self) -> &ChainDetails {
&self.config.chain_details
}
pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
self.config.mixnet_contract_address = Some(address);
}
pub fn set_vesting_contract_address(&mut self, address: AccountId) {
self.config.vesting_contract_address = Some(address);
}
pub fn set_bandwidth_claim_contract_address(&mut self, address: AccountId) {
self.config.bandwidth_claim_contract_address = Some(address);
}
pub fn set_coconut_bandwidth_contract_address(&mut self, address: AccountId) {
self.config.coconut_bandwidth_contract_address = Some(address);
}
pub fn set_multisig_contract_address(&mut self, address: AccountId) {
self.config.multisig_contract_address = Some(address);
}
pub fn set_service_provider_contract_address(&mut self, address: AccountId) {
self.config.service_provider_contract_address = Some(address);
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn mixnet_contract_address(&self) -> &AccountId {
self.config.mixnet_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn vesting_contract_address(&self) -> &AccountId {
self.config.vesting_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn bandwidth_claim_contract_address(&self) -> &AccountId {
self.config
.bandwidth_claim_contract_address
.as_ref()
.unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn coconut_bandwidth_contract_address(&self) -> &AccountId {
self.config
.coconut_bandwidth_contract_address
.as_ref()
.unwrap()
}
pub fn group_contract_address(&self) -> &AccountId {
self.config.group_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn multisig_contract_address(&self) -> &AccountId {
self.config.multisig_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn coconut_dkg_contract_address(&self) -> &AccountId {
self.config.coconut_dkg_contract_address.as_ref().unwrap()
}
// The service provider directory contract is optional, so we return an Option not a Result
pub fn service_provider_contract_address(&self) -> Option<&AccountId> {
self.config.service_provider_contract_address.as_ref()
}
// The name service contract is optional, so we return an Option not a Result
pub fn name_service_contract_address(&self) -> Option<&AccountId> {
self.config.name_service_contract_address.as_ref()
}
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
self.simulated_gas_multiplier = multiplier;
}
pub async fn query_contract_smart<M, T>(
&self,
contract: &AccountId,
query_msg: &M,
) -> Result<T, NyxdError>
where
C: CosmWasmClient + Sync,
M: ?Sized + Serialize + Sync,
for<'a> T: Deserialize<'a>,
{
self.client.query_contract_smart(contract, query_msg).await
}
pub async fn query_contract_raw(
&self,
contract: &AccountId,
query_data: Vec<u8>,
) -> Result<Vec<u8>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.query_contract_raw(contract, query_data).await
}
pub fn gas_adjustment(&self) -> GasAdjustment {
self.simulated_gas_multiplier
}
// =============
// CHAIN RELATED
// =============
// CHAIN QUERIES
pub async fn get_account_details(
&self,
address: &AccountId,
) -> Result<Option<Account>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_account(address).await
}
pub async fn get_account_public_key(
&self,
address: &AccountId,
) -> Result<Option<cosmrs::crypto::PublicKey>, NyxdError>
where
C: CosmWasmClient + Sync,
{
if let Some(account) = self.client.get_account(address).await? {
let base_account = account.try_get_base_account()?;
return Ok(base_account.pubkey);
}
Ok(None)
}
pub async fn get_current_block_timestamp(&self) -> Result<TendermintTime, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.get_block_timestamp(None).await
}
pub async fn get_block_timestamp(
&self,
height: Option<u32>,
) -> Result<TendermintTime, NyxdError>
where
C: CosmWasmClient + Sync,
{
Ok(self.client.get_block(height).await?.block.header.time)
}
pub async fn get_block(&self, height: Option<u32>) -> Result<BlockResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_block(height).await
}
pub async fn get_current_block_height(&self) -> Result<Height, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_height().await
}
/// Obtains the hash of a block specified by the provided height.
///
/// # Arguments
///
/// * `height`: height of the block for which we want to obtain the hash.
pub async fn get_block_hash(&self, height: u32) -> Result<Hash, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client
.get_block(Some(height))
.await
.map(|block| block.block_id.hash)
}
pub async fn get_validators(
&self,
height: u64,
paging: Paging,
) -> Result<ValidatorResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
Ok(self.client.validators(height as u32, paging).await?)
}
pub async fn get_balance(
&self,
address: &AccountId,
denom: String,
) -> Result<Option<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_balance(address, denom).await
}
pub async fn get_all_balances(&self, address: &AccountId) -> Result<Vec<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_all_balances(address).await
}
pub async fn get_tx(&self, id: Hash) -> Result<TxResponse, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_tx(id).await
}
pub async fn search_tx(&self, query: Query) -> Result<Vec<TxResponse>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.search_tx(query).await
}
pub async fn get_total_supply(&self) -> Result<Vec<Coin>, NyxdError>
where
C: CosmWasmClient + Sync,
{
self.client.get_total_supply().await
}
}
@@ -8,19 +8,24 @@ mod dkg_query_client;
mod group_query_client; mod group_query_client;
mod mixnet_query_client; mod mixnet_query_client;
mod multisig_query_client; mod multisig_query_client;
mod name_service_query_client;
mod sp_directory_query_client;
mod vesting_query_client; mod vesting_query_client;
#[cfg(feature = "signing")]
mod coconut_bandwidth_signing_client; mod coconut_bandwidth_signing_client;
#[cfg(feature = "signing")]
mod dkg_signing_client; mod dkg_signing_client;
#[cfg(feature = "signing")]
mod mixnet_signing_client; mod mixnet_signing_client;
#[cfg(feature = "signing")]
mod multisig_signing_client; mod multisig_signing_client;
mod vesting_signing_client; #[cfg(feature = "signing")]
mod sp_directory_query_client;
mod sp_directory_signing_client;
mod name_service_query_client;
mod name_service_signing_client; mod name_service_signing_client;
#[cfg(feature = "signing")]
mod sp_directory_signing_client;
#[cfg(feature = "signing")]
mod vesting_signing_client;
pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient; pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
pub use dkg_query_client::DkgQueryClient; pub use dkg_query_client::DkgQueryClient;
@@ -31,10 +36,17 @@ pub use name_service_query_client::NameServiceQueryClient;
pub use sp_directory_query_client::SpDirectoryQueryClient; pub use sp_directory_query_client::SpDirectoryQueryClient;
pub use vesting_query_client::VestingQueryClient; pub use vesting_query_client::VestingQueryClient;
#[cfg(feature = "signing")]
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient; pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
#[cfg(feature = "signing")]
pub use dkg_signing_client::DkgSigningClient; pub use dkg_signing_client::DkgSigningClient;
#[cfg(feature = "signing")]
pub use mixnet_signing_client::MixnetSigningClient; pub use mixnet_signing_client::MixnetSigningClient;
#[cfg(feature = "signing")]
pub use multisig_signing_client::MultisigSigningClient; pub use multisig_signing_client::MultisigSigningClient;
#[cfg(feature = "signing")]
pub use name_service_signing_client::NameServiceSigningClient; pub use name_service_signing_client::NameServiceSigningClient;
#[cfg(feature = "signing")]
pub use sp_directory_signing_client::SpDirectorySigningClient; pub use sp_directory_signing_client::SpDirectorySigningClient;
#[cfg(feature = "signing")]
pub use vesting_signing_client::VestingSigningClient; pub use vesting_signing_client::VestingSigningClient;
@@ -63,7 +63,6 @@ impl SignerData {
} }
} }
#[cfg(feature = "nyxd-client")]
pub fn new_from_sequence_response( pub fn new_from_sequence_response(
response: crate::nyxd::cosmwasm_client::types::SequenceResponse, response: crate::nyxd::cosmwasm_client::types::SequenceResponse,
chain_id: chain::Id, chain_id: chain::Id,
+3 -3
View File
@@ -14,7 +14,7 @@ clap = { version = "4.0", features = ["derive"] }
cw-utils = { workspace = true } cw-utils = { workspace = true }
handlebars = "3.0.1" handlebars = "3.0.1"
humantime-serde = "1.0" humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] } k256 = { workspace = true, features = ["ecdsa", "sha256"] }
log = { workspace = true } log = { workspace = true }
rand = {version = "0.6", features = ["std"] } rand = {version = "0.6", features = ["std"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
@@ -25,10 +25,10 @@ toml = "0.5.6"
url = "2.2" url = "2.2"
tap = "1" tap = "1"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" } cosmrs = { workspace = true }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
nym-validator-client = { path = "../client-libs/validator-client", features = ["nyxd-client"] } nym-validator-client = { path = "../client-libs/validator-client", features = ["signing", "http-client"] }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] } nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] }
nym-network-defaults = { path = "../network-defaults" } nym-network-defaults = { path = "../network-defaults" }
@@ -56,6 +56,8 @@ pub async fn generate(args: Args) {
.expect("threshold can't be converted to Decimal"), .expect("threshold can't be converted to Decimal"),
}, },
max_voting_period: Duration::Time(args.max_voting_period), max_voting_period: Duration::Time(args.max_voting_period),
executor: None,
proposal_deposit: None,
coconut_bandwidth_contract_address: coconut_bandwidth_contract_address.to_string(), coconut_bandwidth_contract_address: coconut_bandwidth_contract_address.to_string(),
coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(), coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(),
}; };
@@ -6,7 +6,7 @@ use log::info;
use nym_mixnet_contract_common::{Coin, MixId}; use nym_mixnet_contract_common::{Coin, MixId};
use nym_validator_client::nyxd::traits::MixnetQueryClient; use nym_validator_client::nyxd::traits::MixnetQueryClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -5,7 +5,7 @@ use clap::Parser;
use log::info; use log::info;
use nym_mixnet_contract_common::MixId; use nym_mixnet_contract_common::MixId;
use nym_validator_client::nyxd::traits::MixnetQueryClient; use nym_validator_client::nyxd::traits::MixnetQueryClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -6,7 +6,7 @@ use clap::Parser;
use log::info; use log::info;
use nym_mixnet_contract_common::GatewayConfigUpdate; use nym_mixnet_contract_common::GatewayConfigUpdate;
use nym_validator_client::nyxd::traits::MixnetQueryClient; use nym_validator_client::nyxd::traits::MixnetQueryClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -7,7 +7,7 @@ use log::{info, warn};
use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::signing::MessageSignature;
use nym_mixnet_contract_common::{Coin, Gateway}; use nym_mixnet_contract_common::{Coin, Gateway};
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -5,7 +5,7 @@ use crate::context::SigningClient;
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_validator_client::nyxd::traits::MixnetSigningClient; use nym_validator_client::nyxd::traits::MixnetSigningClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -35,9 +35,14 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
info!("Create family join permit sign payload"); info!("Create family join permit sign payload");
// get the address of our mixnode to recover the family head information // get the address of our mixnode to recover the family head information
let Some(mixnode) = client.get_owned_mixnode(&args.address).await.unwrap().mixnode_details else { let Some(mixnode) = client
.get_owned_mixnode(&args.address)
.await
.unwrap()
.mixnode_details
else {
eprintln!("{} does not seem to even own a mixnode!", args.address); eprintln!("{} does not seem to even own a mixnode!", args.address);
return return;
}; };
// make sure this mixnode is actually a family head // make sure this mixnode is actually a family head
@@ -8,7 +8,7 @@ use nym_contracts_common::signing::MessageSignature;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::families::FamilyHead; use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::traits::MixnetSigningClient; use nym_validator_client::nyxd::traits::MixnetSigningClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -6,7 +6,7 @@ use clap::Parser;
use log::info; use log::info;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_validator_client::nyxd::traits::MixnetSigningClient; use nym_validator_client::nyxd::traits::MixnetSigningClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -7,7 +7,7 @@ use log::info;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::families::FamilyHead; use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::traits::MixnetSigningClient; use nym_validator_client::nyxd::traits::MixnetSigningClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -6,7 +6,7 @@ use clap::Parser;
use log::info; use log::info;
use nym_mixnet_contract_common::MixNodeConfigUpdate; use nym_mixnet_contract_common::MixNodeConfigUpdate;
use nym_validator_client::nyxd::traits::MixnetQueryClient; use nym_validator_client::nyxd::traits::MixnetQueryClient;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -11,7 +11,7 @@ use nym_mixnet_contract_common::{MixNode, Percent};
use nym_network_defaults::{ use nym_network_defaults::{
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
}; };
use nym_validator_client::nyxd::{CosmWasmCoin, VestingSigningClient}; use nym_validator_client::nyxd::{traits::VestingSigningClient, CosmWasmCoin};
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -5,7 +5,7 @@ use crate::context::SigningClient;
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_mixnet_contract_common::Coin; use nym_mixnet_contract_common::Coin;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -4,7 +4,7 @@
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_mixnet_contract_common::Coin; use nym_mixnet_contract_common::Coin;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -4,7 +4,7 @@
use crate::context::SigningClient; use crate::context::SigningClient;
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_validator_client::nyxd::VestingSigningClient; use nym_validator_client::nyxd::traits::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -10,7 +10,7 @@ pub fn secp256k1_verify_with_public_key(
public_key_as_bytes: &[u8], public_key_as_bytes: &[u8],
signature_as_hex: String, signature_as_hex: String,
message: String, message: String,
) -> Result<(), k256::ecdsa::signature::Error> { ) -> Result<(), k256::ecdsa::Error> {
let verifying_key = VerifyingKey::from_sec1_bytes(public_key_as_bytes)?; let verifying_key = VerifyingKey::from_sec1_bytes(public_key_as_bytes)?;
let signature = Signature::from_str(&signature_as_hex)?; let signature = Signature::from_str(&signature_as_hex)?;
let message_as_bytes = message.into_bytes(); let message_as_bytes = message.into_bytes();
@@ -6,7 +6,7 @@ use std::str::FromStr;
use crate::context::QueryClient; use crate::context::QueryClient;
use crate::utils::show_error; use crate::utils::show_error;
use cosmrs::tx::Hash; use cosmrs::tendermint::Hash;
use serde_json::json; use serde_json::json;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@@ -5,7 +5,7 @@ use clap::Parser;
use cosmrs::AccountId; use cosmrs::AccountId;
use log::{error, info}; use log::{error, info};
use nym_validator_client::nyxd::{Coin, VestingQueryClient}; use nym_validator_client::nyxd::{traits::VestingQueryClient, Coin};
use crate::context::QueryClient; use crate::context::QueryClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -8,8 +8,8 @@ use log::info;
use nym_mixnet_contract_common::Coin; use nym_mixnet_contract_common::Coin;
use nym_network_defaults::NymNetworkDetails; use nym_network_defaults::NymNetworkDetails;
use nym_validator_client::nyxd::traits::VestingSigningClient;
use nym_validator_client::nyxd::AccountId; use nym_validator_client::nyxd::AccountId;
use nym_validator_client::nyxd::VestingSigningClient;
use nym_validator_client::nyxd::{CosmosCoin, Denom}; use nym_validator_client::nyxd::{CosmosCoin, Denom};
use nym_vesting_contract_common::messages::VestingSpecification; use nym_vesting_contract_common::messages::VestingSpecification;
use nym_vesting_contract_common::PledgeCap; use nym_vesting_contract_common::PledgeCap;
@@ -6,7 +6,7 @@ use cosmrs::AccountId;
use cosmwasm_std::Coin as CosmWasmCoin; use cosmwasm_std::Coin as CosmWasmCoin;
use log::{error, info}; use log::{error, info};
use nym_validator_client::nyxd::{Coin, VestingQueryClient}; use nym_validator_client::nyxd::{traits::VestingQueryClient, Coin};
use crate::context::QueryClient; use crate::context::QueryClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -4,7 +4,10 @@
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_validator_client::nyxd::{Coin, VestingQueryClient, VestingSigningClient}; use nym_validator_client::nyxd::{
traits::{VestingQueryClient, VestingSigningClient},
Coin,
};
use crate::context::SigningClient; use crate::context::SigningClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -14,7 +14,7 @@ pub struct InstantiateMsg {
pub mix_denom: String, pub mix_denom: String,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
DepositFunds { data: DepositData }, DepositFunds { data: DepositData },
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use crate::msg::ExecuteMsg; use crate::msg::ExecuteMsg;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct SpendCredentialData { pub struct SpendCredentialData {
funds: Coin, funds: Coin,
blinded_serial_number: String, blinded_serial_number: String,
@@ -43,7 +43,7 @@ pub enum SpendCredentialStatus {
Spent, Spent,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredential { pub struct SpendCredential {
funds: Coin, funds: Coin,
blinded_serial_number: String, blinded_serial_number: String,
@@ -74,7 +74,7 @@ impl SpendCredential {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedSpendCredentialResponse { pub struct PagedSpendCredentialResponse {
pub spend_credentials: Vec<SpendCredential>, pub spend_credentials: Vec<SpendCredential>,
pub per_page: usize, pub per_page: usize,
@@ -95,7 +95,7 @@ impl PagedSpendCredentialResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredentialResponse { pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>, pub spend_credential: Option<SpendCredential>,
} }
@@ -15,7 +15,7 @@ pub type Nonce = u32;
// define this type explicitly for [hopefully] better usability // define this type explicitly for [hopefully] better usability
// (so you wouldn't need to worry about whether you should use bytes, bs58, etc.) // (so you wouldn't need to worry about whether you should use bytes, bs58, etc.)
#[derive(Clone, Debug, PartialEq, JsonSchema)] #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct MessageSignature(Vec<u8>); pub struct MessageSignature(Vec<u8>);
impl MessageSignature { impl MessageSignature {
@@ -6,6 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
cosmwasm-schema = { workspace = true }
cw4 = { workspace = true } cw4 = { workspace = true }
cw-controllers = { workspace = true }
schemars = "0.8" schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] } serde = { version = "1.0.103", default-features = false, features = ["derive"] }
@@ -1,13 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> use cosmwasm_schema::{cw_serde, QueryResponses};
// SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cw4::Member; use cw4::Member;
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] #[cw_serde]
#[serde(rename_all = "snake_case")]
pub struct InstantiateMsg { pub struct InstantiateMsg {
/// The admin is the only account that can update the group state. /// The admin is the only account that can update the group state.
/// Omit it to make the group immutable. /// Omit it to make the group immutable.
@@ -15,8 +9,7 @@ pub struct InstantiateMsg {
pub members: Vec<Member>, pub members: Vec<Member>,
} }
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] #[cw_serde]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
/// Change the admin /// Change the admin
UpdateAdmin { admin: Option<String> }, UpdateAdmin { admin: Option<String> },
@@ -32,23 +25,24 @@ pub enum ExecuteMsg {
RemoveHook { addr: String }, RemoveHook { addr: String },
} }
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)] #[cw_serde]
#[serde(rename_all = "snake_case")] #[derive(QueryResponses)]
pub enum QueryMsg { pub enum QueryMsg {
/// Return AdminResponse #[returns(cw_controllers::AdminResponse)]
Admin {}, Admin {},
/// Return TotalWeightResponse #[returns(cw4::TotalWeightResponse)]
TotalWeight {}, TotalWeight { at_height: Option<u64> },
/// Returns MembersListResponse #[returns(cw4::MemberListResponse)]
ListMembers { ListMembers {
start_after: Option<String>, start_after: Option<String>,
limit: Option<u32>, limit: Option<u32>,
}, },
/// Returns MemberResponse #[returns(cw4::MemberResponse)]
Member { Member {
addr: String, addr: String,
at_height: Option<u64>, at_height: Option<u64>,
}, },
/// Shows all registered hooks. Returns HooksResponse. /// Shows all registered hooks.
#[returns(cw_controllers::HooksResponse)]
Hooks {}, Hooks {},
} }
@@ -37,7 +37,7 @@ pub fn generate_owner_storage_subkey(
} }
} }
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct Delegation { pub struct Delegation {
/// Address of the owner of this delegation. /// Address of the owner of this delegation.
pub owner: Addr, pub owner: Addr,
@@ -114,7 +114,7 @@ impl Delegation {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixNodeDelegationsResponse { pub struct PagedMixNodeDelegationsResponse {
pub delegations: Vec<Delegation>, pub delegations: Vec<Delegation>,
pub start_next_after: Option<OwnerProxySubKey>, pub start_next_after: Option<OwnerProxySubKey>,
@@ -129,7 +129,7 @@ impl PagedMixNodeDelegationsResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedDelegatorDelegationsResponse { pub struct PagedDelegatorDelegationsResponse {
pub delegations: Vec<Delegation>, pub delegations: Vec<Delegation>,
pub start_next_after: Option<(MixId, OwnerProxySubKey)>, pub start_next_after: Option<(MixId, OwnerProxySubKey)>,
@@ -147,7 +147,7 @@ impl PagedDelegatorDelegationsResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeDelegationResponse { pub struct MixNodeDelegationResponse {
pub delegation: Option<Delegation>, pub delegation: Option<Delegation>,
pub mixnode_still_bonded: bool, pub mixnode_still_bonded: bool,
@@ -162,7 +162,7 @@ impl MixNodeDelegationResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedAllDelegationsResponse { pub struct PagedAllDelegationsResponse {
pub delegations: Vec<Delegation>, pub delegations: Vec<Delegation>,
pub start_next_after: Option<StorageKey>, pub start_next_after: Option<StorageKey>,
@@ -23,7 +23,7 @@ pub struct Gateway {
pub version: String, pub version: String,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayBond { pub struct GatewayBond {
pub pledge_amount: Coin, pub pledge_amount: Coin,
pub owner: Addr, pub owner: Addr,
@@ -132,7 +132,7 @@ impl GatewayConfigUpdate {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedGatewayResponse { pub struct PagedGatewayResponse {
pub nodes: Vec<GatewayBond>, pub nodes: Vec<GatewayBond>,
pub per_page: usize, pub per_page: usize,
@@ -153,13 +153,13 @@ impl PagedGatewayResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayOwnershipResponse { pub struct GatewayOwnershipResponse {
pub address: Addr, pub address: Addr,
pub gateway: Option<GatewayBond>, pub gateway: Option<GatewayBond>,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayBondResponse { pub struct GatewayBondResponse {
pub identity: IdentityKey, pub identity: IdentityKey,
pub gateway: Option<GatewayBond>, pub gateway: Option<GatewayBond>,
@@ -489,7 +489,7 @@ impl CurrentIntervalResponse {
} }
} }
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingEpochEventsResponse { pub struct PendingEpochEventsResponse {
pub seconds_until_executable: i64, pub seconds_until_executable: i64,
pub events: Vec<PendingEpochEvent>, pub events: Vec<PendingEpochEvent>,
@@ -510,7 +510,7 @@ impl PendingEpochEventsResponse {
} }
} }
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingIntervalEventsResponse { pub struct PendingIntervalEventsResponse {
pub seconds_until_executable: i64, pub seconds_until_executable: i64,
pub events: Vec<PendingIntervalEvent>, pub events: Vec<PendingIntervalEvent>,
@@ -33,7 +33,7 @@ impl RewardedSetNodeStatus {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeDetails { pub struct MixNodeDetails {
pub bond_information: MixNodeBond, pub bond_information: MixNodeBond,
pub rewarding_details: MixNodeRewarding, pub rewarding_details: MixNodeRewarding,
@@ -86,7 +86,7 @@ impl MixNodeDetails {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeRewarding { pub struct MixNodeRewarding {
/// Information provided by the operator that influence the cost function. /// Information provided by the operator that influence the cost function.
pub cost_params: MixNodeCostParams, pub cost_params: MixNodeCostParams,
@@ -465,7 +465,7 @@ impl MixNodeRewarding {
} }
// operator information + data assigned by the contract(s) // operator information + data assigned by the contract(s)
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeBond { pub struct MixNodeBond {
/// Unique id assigned to the bonded mixnode. /// Unique id assigned to the bonded mixnode.
pub mix_id: MixId, pub mix_id: MixId,
@@ -559,7 +559,7 @@ pub struct MixNode {
pub version: String, pub version: String,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeCostParams { pub struct MixNodeCostParams {
pub profit_margin_percent: Percent, pub profit_margin_percent: Percent,
@@ -686,7 +686,7 @@ impl MixNodeConfigUpdate {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixnodeBondsResponse { pub struct PagedMixnodeBondsResponse {
pub nodes: Vec<MixNodeBond>, pub nodes: Vec<MixNodeBond>,
pub per_page: usize, pub per_page: usize,
@@ -703,7 +703,7 @@ impl PagedMixnodeBondsResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixnodesDetailsResponse { pub struct PagedMixnodesDetailsResponse {
pub nodes: Vec<MixNodeDetails>, pub nodes: Vec<MixNodeDetails>,
pub per_page: usize, pub per_page: usize,
@@ -745,19 +745,19 @@ impl PagedUnbondedMixnodesResponse {
} }
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixOwnershipResponse { pub struct MixOwnershipResponse {
pub address: Addr, pub address: Addr,
pub mixnode_details: Option<MixNodeDetails>, pub mixnode_details: Option<MixNodeDetails>,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixnodeDetailsResponse { pub struct MixnodeDetailsResponse {
pub mix_id: MixId, pub mix_id: MixId,
pub mixnode_details: Option<MixNodeDetails>, pub mixnode_details: Option<MixNodeDetails>,
} }
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixnodeRewardingDetailsResponse { pub struct MixnodeRewardingDetailsResponse {
pub mix_id: MixId, pub mix_id: MixId,
pub rewarding_details: Option<MixNodeRewarding>, pub rewarding_details: Option<MixNodeRewarding>,
@@ -7,19 +7,19 @@ use crate::{BlockHeight, EpochEventId, IntervalEventId, MixId};
use cosmwasm_std::{Addr, Coin}; use cosmwasm_std::{Addr, Coin};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingEpochEvent { pub struct PendingEpochEvent {
pub id: EpochEventId, pub id: EpochEventId,
pub event: PendingEpochEventData, pub event: PendingEpochEventData,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingEpochEventData { pub struct PendingEpochEventData {
pub created_at: BlockHeight, pub created_at: BlockHeight,
pub kind: PendingEpochEventKind, pub kind: PendingEpochEventKind,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PendingEpochEventKind { pub enum PendingEpochEventKind {
// can't just pass the `Delegation` struct here as it's impossible to determine // can't just pass the `Delegation` struct here as it's impossible to determine
// `cumulative_reward_ratio` ahead of time // `cumulative_reward_ratio` ahead of time
@@ -68,19 +68,19 @@ impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingIntervalEvent { pub struct PendingIntervalEvent {
pub id: IntervalEventId, pub id: IntervalEventId,
pub event: PendingIntervalEventData, pub event: PendingIntervalEventData,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingIntervalEventData { pub struct PendingIntervalEventData {
pub created_at: BlockHeight, pub created_at: BlockHeight,
pub kind: PendingIntervalEventKind, pub kind: PendingIntervalEventKind,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PendingIntervalEventKind { pub enum PendingIntervalEventKind {
ChangeMixCostParams { ChangeMixCostParams {
mix_id: MixId, mix_id: MixId,
@@ -35,7 +35,7 @@ pub struct RewardDistribution {
pub delegates: Decimal, pub delegates: Decimal,
} }
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)] #[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub struct PendingRewardResponse { pub struct PendingRewardResponse {
pub amount_staked: Option<Coin>, pub amount_staked: Option<Coin>,
pub amount_earned: Option<Coin>, pub amount_earned: Option<Coin>,
@@ -46,7 +46,7 @@ pub struct PendingRewardResponse {
pub mixnode_still_fully_bonded: bool, pub mixnode_still_fully_bonded: bool,
} }
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)] #[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub struct EstimatedCurrentEpochRewardResponse { pub struct EstimatedCurrentEpochRewardResponse {
pub original_stake: Option<Coin>, pub original_stake: Option<Coin>,
@@ -22,7 +22,7 @@ pub type EpochEventId = u32;
pub type IntervalEventId = u32; pub type IntervalEventId = u32;
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq, Eq)]
pub struct LayerAssignment { pub struct LayerAssignment {
mix_id: MixId, mix_id: MixId,
layer: Layer, layer: Layer,
@@ -118,7 +118,7 @@ impl Index<Layer> for LayerDistribution {
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ContractState { pub struct ContractState {
pub owner: Addr, // only the owner account can update state pub owner: Addr, // only the owner account can update state
pub rewarding_validator_address: Addr, pub rewarding_validator_address: Addr,
@@ -130,7 +130,7 @@ pub struct ContractState {
pub params: ContractStateParams, pub params: ContractStateParams,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ContractStateParams { pub struct ContractStateParams {
/// Minimum amount a delegator must stake in orders for his delegation to get accepted. /// Minimum amount a delegator must stake in orders for his delegation to get accepted.
pub minimum_mixnode_delegation: Option<Coin>, pub minimum_mixnode_delegation: Option<Coin>,
@@ -9,6 +9,8 @@ edition = "2021"
cw-utils = { workspace = true } cw-utils = { workspace = true }
cw3 = { workspace = true } cw3 = { workspace = true }
cw4 = { workspace= true } cw4 = { workspace= true }
cw-storage-plus = { workspace = true }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
schemars = "0.8" schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] } serde = { version = "1.0.103", default-features = false, features = ["derive"] }
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::StdError; use cosmwasm_std::StdError;
use cw_utils::ThresholdError; use cw3::DepositError;
use cw_utils::{PaymentError, ThresholdError};
use thiserror::Error; use thiserror::Error;
@@ -17,9 +18,6 @@ pub enum ContractError {
#[error("Group contract invalid address '{addr}'")] #[error("Group contract invalid address '{addr}'")]
InvalidGroup { addr: String }, InvalidGroup { addr: String },
#[error("Coconut bandwidth contract address not found")]
InvalidCoconutBandwidth {},
#[error("Unauthorized")] #[error("Unauthorized")]
Unauthorized {}, Unauthorized {},
@@ -43,4 +41,10 @@ pub enum ContractError {
#[error("Cannot close completed or passed proposals")] #[error("Cannot close completed or passed proposals")]
WrongCloseStatus {}, WrongCloseStatus {},
#[error("{0}")]
Payment(#[from] PaymentError),
#[error("{0}")]
Deposit(#[from] DepositError),
} }
@@ -1,2 +1,3 @@
pub mod error; pub mod error;
pub mod msg; pub mod msg;
pub mod state;
@@ -1,15 +1,15 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema; use cosmwasm_schema::{cw_serde, QueryResponses};
use serde::{Deserialize, Serialize};
use cosmwasm_std::{CosmosMsg, Empty}; use cosmwasm_std::{CosmosMsg, Empty};
use cw3::Vote; use cw3::{UncheckedDepositInfo, Vote};
use cw4::MemberChangedHookMsg; use cw4::MemberChangedHookMsg;
use cw_utils::{Duration, Expiration, Threshold}; use cw_utils::{Duration, Expiration, Threshold};
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] use crate::state::Executor;
#[cw_serde]
pub struct InstantiateMsg { pub struct InstantiateMsg {
// this is the group contract that contains the member list // this is the group contract that contains the member list
pub group_addr: String, pub group_addr: String,
@@ -17,11 +17,15 @@ pub struct InstantiateMsg {
pub coconut_dkg_contract_address: String, pub coconut_dkg_contract_address: String,
pub threshold: Threshold, pub threshold: Threshold,
pub max_voting_period: Duration, pub max_voting_period: Duration,
// who is able to execute passed proposals
// None means that anyone can execute
pub executor: Option<Executor>,
/// The cost of creating a proposal (if any).
pub proposal_deposit: Option<UncheckedDepositInfo>,
} }
// TODO: add some T variants? Maybe good enough as fixed Empty for now // TODO: add some T variants? Maybe good enough as fixed Empty for now
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[cw_serde]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
Propose { Propose {
title: String, title: String,
@@ -45,41 +49,44 @@ pub enum ExecuteMsg {
} }
// We can also add this as a cw3 extension // We can also add this as a cw3 extension
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)] #[cw_serde]
#[serde(rename_all = "snake_case")] #[derive(QueryResponses)]
pub enum QueryMsg { pub enum QueryMsg {
/// Return ThresholdResponse #[returns(cw_utils::ThresholdResponse)]
Threshold {}, Threshold {},
/// Returns ProposalResponse #[returns(cw3::ProposalResponse)]
Proposal { proposal_id: u64 }, Proposal { proposal_id: u64 },
/// Returns ProposalListResponse #[returns(cw3::ProposalListResponse)]
ListProposals { ListProposals {
start_after: Option<u64>, start_after: Option<u64>,
limit: Option<u32>, limit: Option<u32>,
}, },
/// Returns ProposalListResponse #[returns(cw3::ProposalListResponse)]
ReverseProposals { ReverseProposals {
start_before: Option<u64>, start_before: Option<u64>,
limit: Option<u32>, limit: Option<u32>,
}, },
/// Returns VoteResponse #[returns(cw3::VoteResponse)]
Vote { proposal_id: u64, voter: String }, Vote { proposal_id: u64, voter: String },
/// Returns VoteListResponse #[returns(cw3::VoteListResponse)]
ListVotes { ListVotes {
proposal_id: u64, proposal_id: u64,
start_after: Option<String>, start_after: Option<String>,
limit: Option<u32>, limit: Option<u32>,
}, },
/// Returns VoterInfo #[returns(cw3::VoterResponse)]
Voter { address: String }, Voter { address: String },
/// Returns VoterListResponse #[returns(cw3::VoterListResponse)]
ListVoters { ListVoters {
start_after: Option<String>, start_after: Option<String>,
limit: Option<u32>, limit: Option<u32>,
}, },
/// Gets the current configuration.
#[returns(crate::state::Config)]
Config {},
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")] #[cw_serde]
pub struct MigrateMsg { pub struct MigrateMsg {
pub coconut_bandwidth_address: String, pub coconut_bandwidth_address: String,
pub coconut_dkg_address: String, pub coconut_dkg_address: String,
@@ -0,0 +1,59 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, QuerierWrapper};
use cw3::DepositInfo;
use cw4::Cw4Contract;
use cw_storage_plus::Item;
use cw_utils::{Duration, Threshold};
use crate::error::ContractError;
/// Defines who is able to execute proposals once passed
#[cw_serde]
pub enum Executor {
/// Any member of the voting group, even with 0 points
Member,
/// Only the given address
Only(Addr),
}
#[cw_serde]
pub struct Config {
pub threshold: Threshold,
pub max_voting_period: Duration,
// Total weight and voters are queried from this contract
pub group_addr: Cw4Contract,
pub coconut_bandwidth_addr: Addr,
pub coconut_dkg_addr: Addr,
// who is able to execute passed proposals
// None means that anyone can execute
pub executor: Option<Executor>,
/// The price, if any, of creating a new proposal.
pub proposal_deposit: Option<DepositInfo>,
}
impl Config {
// Executor can be set in 3 ways:
// - Member: any member of the voting group is authorized
// - Only: only passed address is authorized
// - None: Everyone are authorized
pub fn authorize(&self, querier: &QuerierWrapper, sender: &Addr) -> Result<(), ContractError> {
if let Some(executor) = &self.executor {
match executor {
Executor::Member => {
self.group_addr
.is_member(querier, sender, None)?
.ok_or(ContractError::Unauthorized {})?;
}
Executor::Only(addr) => {
if addr != sender {
return Err(ContractError::Unauthorized {});
}
}
}
}
Ok(())
}
}
// unique items
pub const CONFIG: Item<Config> = Item::new("config");
@@ -28,7 +28,7 @@ pub enum Period {
After, After,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct PledgeData { pub struct PledgeData {
pub amount: Coin, pub amount: Coin,
pub block_time: Timestamp, pub block_time: Timestamp,
@@ -49,7 +49,7 @@ impl PledgeData {
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub enum PledgeCap { pub enum PledgeCap {
Percent(Percent), Percent(Percent),
Absolute(Uint128), // This has to be in unym Absolute(Uint128), // This has to be in unym
@@ -77,7 +77,7 @@ impl Default for PledgeCap {
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct OriginalVestingResponse { pub struct OriginalVestingResponse {
pub amount: Coin, pub amount: Coin,
pub number_of_periods: usize, pub number_of_periods: usize,

Some files were not shown because too many files have changed in this diff Show More