Compare commits

..

5 Commits

Author SHA1 Message Date
pierre 649e763732 fix constant declaration duplication 2023-07-21 14:49:41 +02:00
pierre 03ef5254cc switch to dentenvy 2023-07-21 10:47:37 +02:00
pierre e2f8611876 add env vars during ci build 2023-07-20 18:38:01 +02:00
pierre 57d6f1dcfa wip 2023-07-20 18:22:18 +02:00
pierre b79f774c48 remove hardcoded dsn urls
pass them as env vars
2023-07-20 18:19:44 +02:00
538 changed files with 8526 additions and 47548 deletions
@@ -1,25 +0,0 @@
name: Check Contract Schema
on:
push:
paths:
- 'contracts/**'
- 'common/**'
pull_request:
paths:
- 'contracts/**'
- 'common/**'
jobs:
check-schema:
name: Generate and check schema
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Generate the schema
run: make contract-schema
- name: Check for diff
run: git diff --exit-code
+3 -3
View File
@@ -48,12 +48,12 @@ jobs:
RUSTFLAGS: '-C link-arg=-s' RUSTFLAGS: '-C link-arg=-s'
with: with:
command: build command: build
args: --manifest-path contracts/Cargo.toml --workspace --lib --target wasm32-unknown-unknown args: --manifest-path contracts/Cargo.toml --workspace --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1 - uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --lib --manifest-path contracts/Cargo.toml args: --manifest-path contracts/Cargo.toml
- uses: actions-rs/cargo@v1 - uses: actions-rs/cargo@v1
with: with:
@@ -64,4 +64,4 @@ jobs:
if: ${{ matrix.rust != 'nightly' }} if: ${{ matrix.rust != 'nightly' }}
with: with:
command: clippy command: clippy
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings args: --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
@@ -19,7 +19,7 @@ jobs:
outputs: outputs:
release_id: ${{ steps.create-release.outputs.id }} release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }} release_date: ${{ fromJSON(steps.create-release.outputs.assets[0].published_at) }}
version: ${{ steps.release-info.outputs.version }} version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }} filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }} file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -31,20 +31,10 @@ 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 }}
@@ -115,10 +105,9 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
ref=${{ github.ref_name }} semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
semver="${ref##nym-connect-}" && semver="${semver##v}" echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "filename=nym-connect_$version_x64.dmg" >> "$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:
@@ -19,7 +19,7 @@ jobs:
outputs: outputs:
release_id: ${{ steps.create-release.outputs.id }} release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }} release_date: ${{ fromJSON(steps.create-release.outputs.assets[0].published_at) }}
version: ${{ steps.release-info.outputs.version }} version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }} filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }} file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -82,10 +82,9 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
ref=${{ github.ref_name }} semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
semver="${ref##nym-connect-}" && semver="${semver##v}" echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "filename=nym-connect_$version_amd64.AppImage" >> "$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:
@@ -19,7 +19,7 @@ jobs:
outputs: outputs:
release_id: ${{ steps.create-release.outputs.id }} release_id: ${{ steps.create-release.outputs.id }}
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }} release_date: ${{ fromJSON(steps.create-release.outputs.assets[0].published_at) }}
version: ${{ steps.release-info.outputs.version }} version: ${{ steps.release-info.outputs.version }}
filename: ${{ steps.release-info.outputs.filename }} filename: ${{ steps.release-info.outputs.filename }}
file_hash: ${{ steps.release-info.outputs.file_hash }} file_hash: ${{ steps.release-info.outputs.file_hash }}
@@ -101,10 +101,9 @@ jobs:
- id: release-info - id: release-info
name: Prepare release info name: Prepare release info
run: | run: |
ref=${{ github.ref_name }} semver="${${{ github.ref_name }}##nym-connect-}" && semver="${semver##v}"
semver="${ref##nym-connect-}" && semver="${semver##v}" echo "version=$semver" >> "$GITHUB_OUTPUT"
echo "version=${semver}" >> "$GITHUB_OUTPUT" echo "filename=nym-connect_$version_x64_en-US.msi" >> "$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_${semver}_x64.dmg" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${version}_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_${semver}_amd64.AppImage" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${version}_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_${semver}_x64_en-US.msi" >> "$GITHUB_OUTPUT" echo "filename=nym-wallet_${version}_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:
-50
View File
@@ -1,50 +0,0 @@
name: Typescript SDK docs
on:
push:
paths:
- "sdk/typescript/**"
pull_request:
paths:
- "sdk/typescript/**"
jobs:
build:
runs-on: custom-runner-linux
steps:
- uses: actions/checkout@v2
- name: Install rsync
run: sudo apt-get install rsync
continue-on-error: true
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Setup yarn
run: npm install -g yarn
- name: Install
run: yarn
- name: Matrix - Node Install
run: npm install
working-directory: .github/workflows/support-files
- name: Matrix - Send Notification
env:
NYM_NOTIFICATION_KIND: ts-packages
NYM_PROJECT_NAME: "ts-packages"
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
GIT_BRANCH: "${GITHUB_REF##*/}"
IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
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
-22
View File
@@ -4,28 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased] ## [Unreleased]
## [v1.1.24] (2023-08-08)
- Latency based gateway selection is serial and slow ([#3710])
- Network-requester: strip comments from allow lists ([#3625])
- Remove (or start maintaining) `upgrade` commands from all binaries ([#3600])
- Set sphinx as default packet type ([#3748])
- Apply fix from feature/ephemera to develop too (#3698) ([#3742])
- Feature/coco demos ([#3732])
- Add updates to community list projects ([#3722])
- Add geo-aware mixnet topology provider ([#3713])
- Add updates to community list projects ([#3711])
[#3710]: https://github.com/nymtech/nym/issues/3710
[#3625]: https://github.com/nymtech/nym/issues/3625
[#3600]: https://github.com/nymtech/nym/issues/3600
[#3748]: https://github.com/nymtech/nym/pull/3748
[#3742]: https://github.com/nymtech/nym/pull/3742
[#3732]: https://github.com/nymtech/nym/pull/3732
[#3722]: https://github.com/nymtech/nym/pull/3722
[#3713]: https://github.com/nymtech/nym/pull/3713
[#3711]: https://github.com/nymtech/nym/pull/3711
## [v1.1.23] (2023-07-04) ## [v1.1.23] (2023-07-04)
- nym-cli: add client identity key signing support ([#3576]) - nym-cli: add client identity key signing support ([#3576])
Generated
+277 -391
View File
File diff suppressed because it is too large Load Diff
+12 -21
View File
@@ -74,7 +74,6 @@ members = [
"common/types", "common/types",
"common/wasm-utils", "common/wasm-utils",
"explorer-api", "explorer-api",
"explorer-api/explorer-api-requests",
"gateway", "gateway",
"gateway/gateway-requests", "gateway/gateway-requests",
"integrations/bity", "integrations/bity",
@@ -118,38 +117,30 @@ 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.3.0" cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.3.0" cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.3.0" cosmwasm-std = "=1.2.5"
# use 0.5.0 as that's the version used by cosmwasm-std 1.3.0 cosmwasm-storage = "=1.2.5"
# (and ideally we don't want to pull the same dependency twice) cosmrs = "=0.8.0"
serde-json-wasm = "=0.5.0"
cosmwasm-storage = "=1.3.0"
cosmrs = "=0.14.0"
# same version as used by cosmrs
cw-utils = "=1.0.1" cw-utils = "=1.0.1"
cw-storage-plus = "=1.1.0" cw-storage-plus = "=1.0.1"
cw2 = { version = "=1.1.0" } cw2 = { version = "=1.0.1" }
cw3 = { version = "=1.1.0" } cw3 = { version = "=1.0.1" }
cw4 = { version = "=1.1.0" } cw3-fixed-multisig = { version = "=1.0.1" }
cw-controllers = { version = "=1.1.0" } 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.11"
getrandom = "0.2.10" getrandom = "0.2.10"
k256 = "0.13"
lazy_static = "1.4.0" lazy_static = "1.4.0"
log = "0.4" log = "0.4"
once_cell = "1.7.2" once_cell = "1.7.2"
rand = "0.8.5" rand = "0.8.5"
reqwest = "0.11.18"
serde = "1.0.152" serde = "1.0.152"
serde_json = "1.0.91" serde_json = "1.0.91"
tap = "1.0.1" tap = "1.0.1"
tendermint-rpc = "0.32" # same version as used by cosmrs
thiserror = "1.0.38" thiserror = "1.0.38"
tokio = "1.24.1" tokio = "1.24.1"
url = "2.2" url = "2.2"
zeroize = "1.6.0" zeroize = "1.6.0"
# wasm-related dependencies
wasmtimer = "0.2.0"
+2 -5
View File
@@ -73,7 +73,7 @@ endef
# Generate targets for the various cargo workspaces # Generate targets for the various cargo workspaces
$(eval $(call add_cargo_workspace,main,.)) $(eval $(call add_cargo_workspace,main,.))
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown)) $(eval $(call add_cargo_workspace,contracts,contracts,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown)) $(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown))
$(eval $(call add_cargo_workspace,wallet,nym-wallet,)) $(eval $(call add_cargo_workspace,wallet,nym-wallet,))
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop)) $(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
@@ -104,7 +104,7 @@ NAME_SERVICE_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_name_service.wasm
wasm: wasm-build wasm-opt wasm: wasm-build wasm-opt
wasm-build: wasm-build:
RUSTFLAGS='-C link-arg=-s' cargo build --lib --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
wasm-opt: wasm-opt:
wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT) wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT)
@@ -112,9 +112,6 @@ wasm-opt:
wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT)
wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT) wasm-opt --disable-sign-ext -Os $(NAME_SERVICE_CONTRACT) -o $(NAME_SERVICE_CONTRACT)
contract-schema:
$(MAKE) -C contracts schema
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Misc # Misc
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
+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" } nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.24" version = "1.1.23"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client" description = "Implementation of the Nym Client"
edition = "2021" edition = "2021"
@@ -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 = ["http-client"] } nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] }
nym-client-websocket-requests = { path = "websocket-requests" } nym-client-websocket-requests = { path = "websocket-requests" }
[dev-dependencies] [dev-dependencies]
-16
View File
@@ -1,16 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
+7 -15
View File
@@ -10,7 +10,7 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::{error, info}; use log::{error, info};
use nym_bin_common::bin_info; use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{ use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails, OnDiskGatewayDetails, PersistedGatewayDetails,
@@ -22,12 +22,12 @@ use nym_config::OptionalSet;
use std::error::Error; use std::error::Error;
use std::net::IpAddr; use std::net::IpAddr;
pub(crate) mod build_info;
pub(crate) mod init; pub(crate) mod init;
pub(crate) mod run; pub(crate) mod run;
lazy_static! { lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print(); pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
} }
// Helper for passing LONG_VERSION to clap // Helper for passing LONG_VERSION to clap
@@ -42,10 +42,6 @@ pub(crate) struct Cli {
#[clap(short, long)] #[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>, pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)] #[clap(subcommand)]
command: Commands, command: Commands,
} }
@@ -58,9 +54,6 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters /// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run), Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions /// Generate shell completions
Completions(ArgShell), Completions(ArgShell),
@@ -80,13 +73,12 @@ pub(crate) struct OverrideConfig {
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
} }
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> { pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-native-client"; let bin_name = "nym-native-client";
match args.command { match &args.command {
Commands::Init(m) => init::execute(&m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(&m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
} }
+4 -7
View File
@@ -14,13 +14,10 @@ pub mod websocket;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
} }
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.24" version = "1.1.23"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021" edition = "2021"
-16
View File
@@ -1,16 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Args;
use nym_bin_common::bin_info_owned;
use nym_bin_common::output_format::OutputFormat;
#[derive(Args)]
pub(crate) struct BuildInfo {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub(crate) fn execute(args: BuildInfo) {
println!("{}", args.output.format(&bin_info_owned!()))
}
-1
View File
@@ -94,7 +94,6 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs, use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode, fastmode: init_config.fastmode,
no_cover: init_config.no_cover, no_cover: init_config.no_cover,
geo_routing: None,
medium_toggle: false, medium_toggle: false,
nyxd_urls: init_config.nyxd_urls, nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode, enabled_credentials_mode: init_config.enabled_credentials_mode,
+8 -29
View File
@@ -10,25 +10,24 @@ use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::{error, info}; use log::{error, info};
use nym_bin_common::bin_info; use nym_bin_common::build_information::BinaryBuildInformation;
use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_client_core::client::base_client::storage::gateway_details::{ use nym_client_core::client::base_client::storage::gateway_details::{
OnDiskGatewayDetails, PersistedGatewayDetails, OnDiskGatewayDetails, PersistedGatewayDetails,
}; };
use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::config::{GatewayEndpointConfig, TopologyStructure};
use nym_client_core::error::ClientCoreError; use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet; use nym_config::OptionalSet;
use nym_sphinx::params::{PacketSize, PacketType}; use nym_sphinx::params::{PacketSize, PacketType};
use std::error::Error; use std::error::Error;
pub(crate) mod build_info;
pub mod init; pub mod init;
pub(crate) mod run; pub(crate) mod run;
lazy_static! { lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print(); pub static ref PRETTY_BUILD_INFORMATION: String =
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print();
} }
// Helper for passing LONG_VERSION to clap // Helper for passing LONG_VERSION to clap
@@ -43,10 +42,6 @@ pub(crate) struct Cli {
#[clap(short, long)] #[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>, pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Flag used for disabling the printed banner in tty.
#[clap(long)]
pub(crate) no_banner: bool,
#[clap(subcommand)] #[clap(subcommand)]
command: Commands, command: Commands,
} }
@@ -59,9 +54,6 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters /// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run), Run(run::Run),
/// Show build information of this binary
BuildInfo(build_info::BuildInfo),
/// Generate shell completions /// Generate shell completions
Completions(ArgShell), Completions(ArgShell),
@@ -76,20 +68,18 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>, use_anonymous_replies: Option<bool>,
fastmode: bool, fastmode: bool,
no_cover: bool, no_cover: bool,
geo_routing: Option<CountryGroup>,
medium_toggle: bool, medium_toggle: bool,
nyxd_urls: Option<Vec<url::Url>>, nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>, enabled_credentials_mode: Option<bool>,
outfox: bool, outfox: bool,
} }
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> { pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-socks5-client"; let bin_name = "nym-socks5-client";
match args.command { match &args.command {
Commands::Init(m) => init::execute(&m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(&m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
} }
@@ -101,13 +91,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16); let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
let no_per_hop_delays = args.medium_toggle; let no_per_hop_delays = args.medium_toggle;
let topology_structure = if args.medium_toggle || args.geo_routing.is_some() {
// TODO: rethink the default group. I just picked one for now.
TopologyStructure::GeoAware(args.geo_routing.unwrap_or(CountryGroup::Europe))
} else {
TopologyStructure::default()
};
let packet_type = if args.outfox { let packet_type = if args.outfox {
PacketType::Outfox PacketType::Outfox
} else { } else {
@@ -131,10 +114,6 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
// NOTE: see comment above about the order of the other disble cover traffic config // NOTE: see comment above about the order of the other disble cover traffic config
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover) .with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type) .with_base(BaseClientConfig::with_packet_type, packet_type)
.with_base(
BaseClientConfig::with_topology_structure,
topology_structure,
)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies) .with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
.with_optional(Config::with_port, args.port) .with_optional(Config::with_port, args.port)
.with_optional_base_custom_env( .with_optional_base_custom_env(
-13
View File
@@ -11,7 +11,6 @@ use clap::Args;
use log::*; use log::*;
use nym_bin_common::version_checker::is_minor_version_compatible; use nym_bin_common::version_checker::is_minor_version_compatible;
use nym_client_core::client::base_client::storage::OnDiskPersistent; use nym_client_core::client::base_client::storage::OnDiskPersistent;
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
use nym_crypto::asymmetric::identity; use nym_crypto::asymmetric::identity;
use nym_socks5_client_core::NymClient; use nym_socks5_client_core::NymClient;
use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::clients::Recipient;
@@ -61,10 +60,6 @@ pub(crate) struct Run {
#[clap(long, hide = true)] #[clap(long, hide = true)]
no_cover: bool, no_cover: bool,
/// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only.
#[clap(long, hide = true, value_parser = validate_country_group)]
geo_routing: Option<CountryGroup>,
/// Enable medium mixnet traffic, for experiments only. /// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc. /// This includes things like disabling cover traffic, no per hop delays, etc.
#[clap(long, hide = true)] #[clap(long, hide = true)]
@@ -87,7 +82,6 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies, use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode, fastmode: run_config.fastmode,
no_cover: run_config.no_cover, no_cover: run_config.no_cover,
geo_routing: run_config.geo_routing,
medium_toggle: run_config.medium_toggle, medium_toggle: run_config.medium_toggle,
nyxd_urls: run_config.nyxd_urls, nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode, enabled_credentials_mode: run_config.enabled_credentials_mode,
@@ -96,13 +90,6 @@ impl From<Run> for OverrideConfig {
} }
} }
fn validate_country_group(s: &str) -> Result<CountryGroup, String> {
match s.parse() {
Ok(cg) => Ok(cg),
Err(_) => Err(format!("failed to parse country group: {}", s)),
}
}
// this only checks compatibility between config the binary. It does not take into consideration // this only checks compatibility between config the binary. It does not take into consideration
// network version. It might do so in the future. // network version. It might do so in the future.
fn version_check(cfg: &Config) -> bool { fn version_check(cfg: &Config) -> bool {
+4 -7
View File
@@ -13,13 +13,10 @@ pub mod error;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
maybe_print_banner(crate_name!(), crate_version!());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.as_ref());
commands::execute(&args).await
if !args.no_banner {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
commands::execute(args).await
} }
+216 -361
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -33,7 +33,7 @@ wasm-bindgen-futures = "0.4"
thiserror = "1.0.40" thiserror = "1.0.40"
zeroize = "1.6.0" zeroize = "1.6.0"
wasmtimer = { version = "0.2.0", features = ["tokio"] } wasm-timer = { git = "https://github.com/mmsinclair/wasm-timer", rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"}
# internal # internal
nym-node-tester-utils = { path = "../../common/node-tester-utils" } nym-node-tester-utils = { path = "../../common/node-tester-utils" }
-1
View File
@@ -246,7 +246,6 @@ impl From<TopologyWasm> for ConfigTopology {
topology.topology_resolution_timeout_ms, topology.topology_resolution_timeout_ms,
), ),
disable_refreshing: topology.disable_refreshing, disable_refreshing: topology.disable_refreshing,
topology_structure: Default::default(),
} }
} }
} }
@@ -10,7 +10,6 @@ use std::collections::HashSet;
use std::time::Duration; use std::time::Duration;
use tokio::sync::MutexGuard as AsyncMutexGuard; use tokio::sync::MutexGuard as AsyncMutexGuard;
use wasm_utils::{console_error, console_log, console_warn}; use wasm_utils::{console_error, console_log, console_warn};
use wasmtimer::tokio::sleep;
pub(crate) struct EphemeralTestReceiver<'a> { pub(crate) struct EphemeralTestReceiver<'a> {
sent_packets: u32, sent_packets: u32,
@@ -91,7 +90,7 @@ impl<'a> EphemeralTestReceiver<'a> {
} }
pub(crate) async fn perform_test(mut self) -> NodeTestResult { pub(crate) async fn perform_test(mut self) -> NodeTestResult {
let mut timeout_fut = sleep(self.timeout_duration); let mut timeout_fut = wasm_timer::Delay::new(self.timeout_duration);
loop { loop {
tokio::select! { tokio::select! {
+2 -1
View File
@@ -18,6 +18,7 @@ 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 = ["signing"] features = ["nyxd-client"]
@@ -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};
+29 -70
View File
@@ -5,13 +5,9 @@
// and be used by our smart contracts // and be used by our smart contracts
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Debug)] #[derive(Debug)]
pub struct BinaryBuildInformation { pub struct BinaryBuildInformation {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: &'static str,
// VERGEN_BUILD_TIMESTAMP // VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`. /// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str, pub build_timestamp: &'static str,
@@ -47,9 +43,8 @@ pub struct BinaryBuildInformation {
impl BinaryBuildInformation { impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific // explicitly require the build_version to be passed as it's binary specific
pub const fn new(binary_name: &'static str, build_version: &'static str) -> Self { pub const fn new(build_version: &'static str) -> Self {
BinaryBuildInformation { BinaryBuildInformation {
binary_name,
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"), build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version, build_version,
commit_sha: env!("VERGEN_GIT_SHA"), commit_sha: env!("VERGEN_GIT_SHA"),
@@ -63,7 +58,6 @@ impl BinaryBuildInformation {
pub fn to_owned(&self) -> BinaryBuildInformationOwned { pub fn to_owned(&self) -> BinaryBuildInformationOwned {
BinaryBuildInformationOwned { BinaryBuildInformationOwned {
binary_name: self.binary_name.to_owned(),
build_timestamp: self.build_timestamp.to_owned(), build_timestamp: self.build_timestamp.to_owned(),
build_version: self.build_version.to_owned(), build_version: self.build_version.to_owned(),
commit_sha: self.commit_sha.to_owned(), commit_sha: self.commit_sha.to_owned(),
@@ -76,15 +70,39 @@ impl BinaryBuildInformation {
} }
pub fn pretty_print(&self) -> String { pub fn pretty_print(&self) -> String {
self.to_owned().to_string() format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BinaryBuildInformationOwned { pub struct BinaryBuildInformationOwned {
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
pub binary_name: String,
// VERGEN_BUILD_TIMESTAMP // VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`. /// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: String, pub build_timestamp: String,
@@ -117,62 +135,3 @@ pub struct BinaryBuildInformationOwned {
/// Provides the cargo profile that was used for the build, for example `debug`. /// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: String, pub cargo_profile: String,
} }
impl Display for BinaryBuildInformationOwned {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Binary Name:",
self.binary_name,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
// since this macro will get expanded at the callsite, it will pull in correct binary version
#[macro_export]
macro_rules! bin_info {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
};
}
#[macro_export]
macro_rules! bin_info_owned {
() => {
$crate::build_information::BinaryBuildInformation::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
.to_owned()
};
}
+8 -10
View File
@@ -10,29 +10,27 @@ rust-version = "1.66"
[dependencies] [dependencies]
async-trait = { workspace = true } async-trait = { workspace = true }
base64 = "0.21.2" base64 = "0.21.2"
dashmap = "5.4.0"
dirs = "4.0" dirs = "4.0"
dashmap = "5.4.0"
futures = "0.3" futures = "0.3"
humantime-serde = "1.0" humantime-serde = "1.0"
log = { workspace = true } log = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] } rand = { version = "0.7.3", features = ["wasm-bindgen"] }
reqwest = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
sha2 = "0.10.6" sha2 = "0.10.6"
tap = "1.0.1" tap = "1.0.1"
thiserror = "1.0.34" thiserror = "1.0.34"
time = "0.3.17"
tokio = { version = "1.24.1", features = ["macros"]}
tungstenite = { version = "0.13.0", default-features = false }
url = { version ="2.2", features = ["serde"] } url = { version ="2.2", features = ["serde"] }
tungstenite = { version = "0.13.0", default-features = false }
tokio = { version = "1.24.1", features = ["macros"]}
time = "0.3.17"
zeroize = { workspace = true } zeroize = { workspace = true }
# internal # internal
nym-bandwidth-controller = { path = "../bandwidth-controller" } nym-bandwidth-controller = { path = "../bandwidth-controller" }
nym-config = { path = "../config" } nym-config = { path = "../config" }
nym-crypto = { path = "../crypto" } nym-crypto = { path = "../crypto" }
nym-explorer-api-requests = { path = "../../explorer-api/explorer-api-requests" }
nym-gateway-client = { path = "../client-libs/gateway-client" } nym-gateway-client = { path = "../client-libs/gateway-client" }
#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] } #gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] }
nym-gateway-requests = { path = "../../gateway/gateway-requests" } nym-gateway-requests = { path = "../../gateway/gateway-requests" }
@@ -47,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 = ["signing", "http-client"] features = ["nyxd-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"
@@ -71,9 +69,9 @@ version = "0.4"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
version = "0.2.83" version = "0.2.83"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
workspace = true git = "https://github.com/mmsinclair/wasm-timer"
features = ["tokio"] rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers] [target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers]
version = "0.2.4" version = "0.2.4"
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::received_buffer::ReceivedBufferMessage; use super::received_buffer::ReceivedBufferMessage;
use super::topology_control::geo_aware_provider::GeoAwareTopologyProvider;
use crate::client::base_client::storage::MixnetClientStorage; use crate::client::base_client::storage::MixnetClientStorage;
use crate::client::cover_traffic_stream::LoopCoverTrafficStream; use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender}; use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
@@ -340,20 +339,14 @@ where
fn setup_topology_provider( fn setup_topology_provider(
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>, custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
provider_from_config: config::TopologyStructure,
nym_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
) -> Box<dyn TopologyProvider + Send + Sync> { ) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api // if no custom provider was ... provided ..., create one using nym-api
custom_provider.unwrap_or_else(|| match provider_from_config { custom_provider.unwrap_or_else(|| {
config::TopologyStructure::NymApi => Box::new(NymApiTopologyProvider::new( Box::new(NymApiTopologyProvider::new(
nym_api_urls, nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(), env!("CARGO_PKG_VERSION").to_string(),
)), ))
config::TopologyStructure::GeoAware(group) => Box::new(GeoAwareTopologyProvider::new(
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
group,
)),
}) })
} }
@@ -528,10 +521,8 @@ where
let topology_provider = Self::setup_topology_provider( let topology_provider = Self::setup_topology_provider(
self.custom_topology_provider.take(), self.custom_topology_provider.take(),
self.config.debug.topology.topology_structure,
self.config.get_nym_api_endpoints(), self.config.get_nym_api_endpoints(),
); );
Self::start_topology_refresher( Self::start_topology_refresher(
topology_provider, topology_provider,
self.config.debug.topology, self.config.debug.topology,
@@ -19,10 +19,10 @@ use std::time::Duration;
use tokio::sync::mpsc::error::TrySendError; use tokio::sync::mpsc::error::TrySendError;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio::time::{sleep, Sleep}; use tokio::time;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::{sleep, Sleep}; use wasm_timer;
pub struct LoopCoverTrafficStream<R> pub struct LoopCoverTrafficStream<R>
where where
@@ -39,7 +39,11 @@ where
/// Internal state, determined by `average_message_sending_delay`, /// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out. /// used to keep track of when a next packet should be sent out.
next_delay: Pin<Box<Sleep>>, #[cfg(not(target_arch = "wasm32"))]
next_delay: Pin<Box<time::Sleep>>,
#[cfg(target_arch = "wasm32")]
next_delay: Pin<Box<wasm_timer::Delay>>,
/// Channel used for sending prepared nym packets to `MixTrafficController` that sends them /// Channel used for sending prepared nym packets to `MixTrafficController` that sends them
/// out to the network without any further delays. /// out to the network without any further delays.
@@ -86,9 +90,17 @@ where
// The next interval value is `next_poisson_delay` after the one that just // The next interval value is `next_poisson_delay` after the one that just
// yielded. // yielded.
let now = self.next_delay.deadline(); #[cfg(not(target_arch = "wasm32"))]
let next = now + next_poisson_delay; {
self.next_delay.as_mut().reset(next); let now = self.next_delay.deadline();
let next = now + next_poisson_delay;
self.next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
self.next_delay.as_mut().reset(next_poisson_delay);
}
Poll::Ready(Some(())) Poll::Ready(Some(()))
} }
@@ -108,7 +120,11 @@ impl LoopCoverTrafficStream<OsRng> {
) -> Self { ) -> Self {
let rng = OsRng; let rng = OsRng;
let next_delay = Box::pin(sleep(Default::default())); #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(Default::default()));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(Default::default()));
LoopCoverTrafficStream { LoopCoverTrafficStream {
ack_key, ack_key,
@@ -126,7 +142,12 @@ impl LoopCoverTrafficStream<OsRng> {
} }
fn set_next_delay(&mut self, amount: Duration) { fn set_next_delay(&mut self, amount: Duration) {
let next_delay = Box::pin(sleep(amount)); #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(amount));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(amount));
self.next_delay = next_delay; self.next_delay = next_delay;
} }
@@ -2,12 +2,13 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::time::Duration; use std::time::Duration;
use wasm_timer;
pub use wasmtimer::{std::Instant, tokio::*}; pub use wasm_timer::*;
pub type IntervalStream = gloo_timers::future::IntervalStream; pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant { pub(crate) fn get_time_now() -> Instant {
Instant::now() wasm_timer::Instant::now()
} }
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream { pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
@@ -27,10 +27,9 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio::time::{sleep, Sleep}; use tokio::time;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::{sleep, Sleep}; use wasm_timer;
mod sending_delay_controller; mod sending_delay_controller;
@@ -83,7 +82,11 @@ where
/// Internal state, determined by `average_message_sending_delay`, /// Internal state, determined by `average_message_sending_delay`,
/// used to keep track of when a next packet should be sent out. /// used to keep track of when a next packet should be sent out.
next_delay: Option<Pin<Box<Sleep>>>, #[cfg(not(target_arch = "wasm32"))]
next_delay: Option<Pin<Box<time::Sleep>>>,
#[cfg(target_arch = "wasm32")]
next_delay: Option<Pin<Box<wasm_timer::Delay>>>,
// To make sure we don't overload the mix_tx channel, we limit the rate we are pushing // To make sure we don't overload the mix_tx channel, we limit the rate we are pushing
// messages. // messages.
@@ -370,9 +373,17 @@ where
// The next interval value is `next_poisson_delay` after the one that just // The next interval value is `next_poisson_delay` after the one that just
// yielded. // yielded.
let now = next_delay.deadline(); #[cfg(not(target_arch = "wasm32"))]
let next = now + next_poisson_delay; {
next_delay.as_mut().reset(next); let now = next_delay.deadline();
let next = now + next_poisson_delay;
next_delay.as_mut().reset(next);
}
#[cfg(target_arch = "wasm32")]
{
next_delay.as_mut().reset(next_poisson_delay);
}
// On every iteration we get new messages from upstream. Given that these come bunched // On every iteration we get new messages from upstream. Given that these come bunched
// in `Vec`, this ensures that on average we will fetch messages faster than we can // in `Vec`, this ensures that on average we will fetch messages faster than we can
@@ -410,7 +421,12 @@ where
self.config.traffic.message_sending_average_delay, self.config.traffic.message_sending_average_delay,
); );
let next_delay = Box::pin(sleep(sampled)); #[cfg(not(target_arch = "wasm32"))]
let next_delay = Box::pin(time::sleep(sampled));
#[cfg(target_arch = "wasm32")]
let next_delay = Box::pin(wasm_timer::Delay::new(sampled));
self.next_delay = Some(next_delay); self.next_delay = Some(next_delay);
Poll::Pending Poll::Pending
@@ -1,319 +0,0 @@
use std::{collections::HashMap, fmt};
use log::{debug, error, info};
use nym_explorer_api_requests::PrettyDetailedMixNodeBond;
use nym_topology::{
nym_topology_from_detailed,
provider_trait::{async_trait, TopologyProvider},
NymTopology,
};
use nym_validator_client::client::MixId;
use rand::{prelude::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use url::Url;
const MIN_NODES_PER_LAYER: usize = 1;
const EXPLORER_API_MIXNODES_URL: &str = "https://explorer.nymtech.net/api/v1/mix-nodes";
// TODO: create a explorer-api-client
async fn fetch_mixnodes_from_explorer_api() -> Option<Vec<PrettyDetailedMixNodeBond>> {
reqwest::get(EXPLORER_API_MIXNODES_URL)
.await
.ok()?
.json::<Vec<PrettyDetailedMixNodeBond>>()
.await
.ok()
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum CountryGroup {
Europe,
NorthAmerica,
SouthAmerica,
Oceania,
Asia,
Africa,
Unknown,
}
impl CountryGroup {
// We map contry codes into group, which initially are continent codes to a first approximation,
// but we do it manually to reserve the right to tweak this distribution for our purposes.
fn new(country_code: &str) -> Self {
let country_code = country_code.to_uppercase();
use CountryGroup::*;
match country_code.as_ref() {
// Europe
"AT" => Europe,
"BG" => Europe,
"CH" => Europe,
"CY" => Europe,
"CZ" => Europe,
"DE" => Europe,
"DK" => Europe,
"ES" => Europe,
"FI" => Europe,
"FR" => Europe,
"GB" => Europe,
"GR" => Europe,
"IE" => Europe,
"IT" => Europe,
"LT" => Europe,
"LU" => Europe,
"LV" => Europe,
"MD" => Europe,
"MT" => Europe,
"NL" => Europe,
"NO" => Europe,
"PL" => Europe,
"RO" => Europe,
"SE" => Europe,
"SK" => Europe,
"TR" => Europe,
"UA" => Europe,
// North America
"CA" => NorthAmerica,
"MX" => NorthAmerica,
"US" => NorthAmerica,
// South America
"AR" => SouthAmerica,
"BR" => SouthAmerica,
"CL" => SouthAmerica,
"CO" => SouthAmerica,
"CR" => SouthAmerica,
"GT" => SouthAmerica,
// Oceania
"AU" => Oceania,
// Asia
"AM" => Asia,
"BH" => Asia,
"CN" => Asia,
"GE" => Asia,
"HK" => Asia,
"ID" => Asia,
"IL" => Asia,
"IN" => Asia,
"JP" => Asia,
"KH" => Asia,
"KR" => Asia,
"KZ" => Asia,
"MY" => Asia,
"RU" => Asia,
"SG" => Asia,
"TH" => Asia,
"VN" => Asia,
// Africa
"SC" => Africa,
"UG" => Africa,
"ZA" => Africa,
// And group level codes work too
"EU" => Europe,
"NA" => NorthAmerica,
"SA" => SouthAmerica,
"OC" => Oceania,
"AS" => Asia,
"AF" => Africa,
// And some aliases
"EUROPE" => Europe,
"NORTHAMERICA" => NorthAmerica,
"SOUTHAMERICA" => SouthAmerica,
"OCEANIA" => Oceania,
"ASIA" => Asia,
"AFRICA" => Africa,
_ => {
info!("Unknown country code: {}", country_code);
Unknown
}
}
}
}
impl fmt::Display for CountryGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CountryGroup::*;
match self {
Europe => write!(f, "EU"),
NorthAmerica => write!(f, "NA"),
SouthAmerica => write!(f, "SA"),
Oceania => write!(f, "OC"),
Asia => write!(f, "AS"),
Africa => write!(f, "AF"),
Unknown => write!(f, "Unknown"),
}
}
}
impl std::str::FromStr for CountryGroup {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let group = CountryGroup::new(s);
if group == CountryGroup::Unknown {
Err(())
} else {
Ok(group)
}
}
}
impl CountryGroup {
#[allow(unused)]
fn known(self) -> Option<CountryGroup> {
use CountryGroup::*;
match self {
Europe | NorthAmerica | SouthAmerica | Oceania | Asia | Africa => Some(self),
Unknown => None,
}
}
}
fn group_mixnodes_by_country_code(
mixnodes: Vec<PrettyDetailedMixNodeBond>,
) -> HashMap<CountryGroup, Vec<MixId>> {
mixnodes
.into_iter()
.fold(HashMap::<CountryGroup, Vec<MixId>>::new(), |mut acc, m| {
if let Some(ref location) = m.location {
let country_code = location.two_letter_iso_country_code.clone();
let group_code = CountryGroup::new(country_code.as_str());
let mixnodes = acc.entry(group_code).or_insert_with(Vec::new);
mixnodes.push(m.mix_id);
}
acc
})
}
fn log_mixnode_distribution(mixnodes: &HashMap<CountryGroup, Vec<MixId>>) {
let mixnode_distribution = mixnodes
.iter()
.map(|(k, v)| format!("{}: {}", k, v.len()))
.collect::<Vec<_>>()
.join(", ");
debug!("Mixnode distribution - {}", mixnode_distribution);
}
fn check_layer_integrity(topology: NymTopology) -> Result<(), ()> {
let mixes = topology.mixes();
if mixes.keys().len() < 3 {
error!("Layer is missing in topology!");
return Err(());
}
for (layer, mixnodes) in mixes {
debug!("Layer {:?} has {} mixnodes", layer, mixnodes.len());
if mixnodes.len() < MIN_NODES_PER_LAYER {
error!(
"There are only {} mixnodes in layer {:?}",
mixnodes.len(),
layer
);
return Err(());
}
}
Ok(())
}
pub struct GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient,
filter_on: CountryGroup,
client_version: String,
}
impl GeoAwareTopologyProvider {
pub fn new(
mut nym_api_urls: Vec<Url>,
client_version: String,
filter_on: CountryGroup,
) -> GeoAwareTopologyProvider {
log::info!(
"Creating geo-aware topology provider with filter on {:?}",
filter_on
);
nym_api_urls.shuffle(&mut thread_rng());
GeoAwareTopologyProvider {
validator_client: nym_validator_client::client::NymApiClient::new(
nym_api_urls[0].clone(),
),
filter_on,
client_version,
}
}
async fn get_topology(&self) -> Option<NymTopology> {
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
}
Ok(mixes) => mixes,
};
let gateways = match self.validator_client.get_cached_gateways().await {
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
}
Ok(gateways) => gateways,
};
// Also fetch mixnodes cached by explorer-api, with the purpose of getting their
// geolocation.
debug!("Fetching mixnodes from explorer-api...");
let Some(mixnodes_from_explorer_api) = fetch_mixnodes_from_explorer_api().await else {
error!("failed to get mixnodes from explorer-api");
return None;
};
// Partition mixnodes_from_explorer_api according to the value of
// two_letter_iso_country_code.
// NOTE: we construct the full distribution here, but only use the one we're interested in.
// The reason we this instead of a straight filter is that this opens up the possibility to
// complement a small grouping with mixnodes from adjecent countries.
let mixnode_distribution = group_mixnodes_by_country_code(mixnodes_from_explorer_api);
log_mixnode_distribution(&mixnode_distribution);
let Some(filtered_mixnode_ids) = mixnode_distribution.get(&self.filter_on) else {
error!("no mixnodes found for: {}", self.filter_on);
return None;
};
let mixnodes = mixnodes
.into_iter()
.filter(|m| filtered_mixnode_ids.contains(&m.mix_id()))
.collect::<Vec<_>>();
let topology = nym_topology_from_detailed(mixnodes, gateways)
.filter_system_version(&self.client_version);
// TODO: return real error type
check_layer_integrity(topology.clone()).ok()?;
Some(topology)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
#[cfg(target_arch = "wasm32")]
#[async_trait(?Send)]
impl TopologyProvider for GeoAwareTopologyProvider {
// this will be manually refreshed on a timer specified inside mixnet client config
async fn get_new_topology(&mut self) -> Option<NymTopology> {
self.get_topology().await
}
}
@@ -10,7 +10,6 @@ use nym_topology::NymTopologyError;
use std::time::Duration; use std::time::Duration;
mod accessor; mod accessor;
pub mod geo_aware_provider;
pub(crate) mod nym_api_provider; pub(crate) mod nym_api_provider;
// TODO: move it to config later // TODO: move it to config later
+1 -21
View File
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use url::Url; use url::Url;
use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError}; use crate::error::ClientCoreError;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
@@ -158,15 +158,6 @@ impl Config {
self self
} }
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
self.set_topology_structure(topology_structure);
self
}
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
self.debug.topology.topology_structure = topology_structure;
}
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self { pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
if no_per_hop_delays { if no_per_hop_delays {
self.set_no_per_hop_delays() self.set_no_per_hop_delays()
@@ -475,16 +466,6 @@ pub struct Topology {
/// the first valid instance. /// the first valid instance.
/// Supersedes `topology_refresh_rate_ms`. /// Supersedes `topology_refresh_rate_ms`.
pub disable_refreshing: bool, pub disable_refreshing: bool,
/// Specifies the mixnode topology to be used for sending packets.
pub topology_structure: TopologyStructure,
}
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum TopologyStructure {
#[default]
NymApi,
GeoAware(CountryGroup),
} }
impl Default for Topology { impl Default for Topology {
@@ -493,7 +474,6 @@ impl Default for Topology {
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE, topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT, topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
disable_refreshing: false, disable_refreshing: false,
topology_structure: TopologyStructure::default(),
} }
} }
} }
@@ -267,7 +267,6 @@ impl From<TopologyV1_1_20_2> for Topology {
topology_refresh_rate: value.topology_refresh_rate, topology_refresh_rate: value.topology_refresh_rate,
topology_resolution_timeout: value.topology_resolution_timeout, topology_resolution_timeout: value.topology_resolution_timeout,
disable_refreshing: value.disable_refreshing, disable_refreshing: value.disable_refreshing,
topology_structure: Default::default(),
} }
} }
} }
+24 -29
View File
@@ -27,22 +27,17 @@ use tokio_tungstenite::connect_async;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream}; use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>; type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient; use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer::Instant;
#[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket; use wasm_utils::websocket::JSWebsocket;
#[cfg(target_arch = "wasm32")]
use wasmtimer::std::Instant;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
#[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"))]
@@ -129,9 +124,15 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
Ok::<(), ClientCoreError>(()) Ok::<(), ClientCoreError>(())
}; };
let timeout = sleep(PING_TIMEOUT); // thanks to wasm we can't use tokio::time::timeout : (
#[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(PING_TIMEOUT);
#[cfg(not(target_arch = "wasm32"))]
tokio::pin!(timeout); tokio::pin!(timeout);
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(PING_TIMEOUT);
tokio::select! { tokio::select! {
_ = &mut timeout => { _ = &mut timeout => {
warn!("timed out while trying to perform measurement...") warn!("timed out while trying to perform measurement...")
@@ -157,29 +158,23 @@ 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!( info!("choosing gateway by latency...");
"choosing gateway by latency, pinging {} gateways ...",
gateways.len()
);
let gateways_with_latency = Arc::new(tokio::sync::Mutex::new(Vec::new())); let mut gateways_with_latency = Vec::new();
futures::stream::iter(gateways) for gateway in gateways {
.for_each_concurrent(CONCURRENT_GATEWAYS_MEASURED, |gateway| async { let id = *gateway.identity();
let id = *gateway.identity(); trace!("measuring latency to {id}...");
trace!("measuring latency to {id}..."); let with_latency = match measure_latency(gateway).await {
match measure_latency(gateway).await { Ok(res) => res,
Ok(with_latency) => { Err(err) => {
debug!("{id}: {:?}", with_latency.latency); warn!("failed to measure {id}: {err}");
gateways_with_latency.lock().await.push(with_latency); continue;
} }
Err(err) => { };
warn!("failed to measure {id}: {err}"); debug!("{id}: {:?}", with_latency.latency);
} 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!");
+3 -3
View File
@@ -58,9 +58,9 @@ path = "../../wasm-utils"
features = ["websocket"] features = ["websocket"]
# only import it in wasm. Prefer proper tokio timer in non-wasm # only import it in wasm. Prefer proper tokio timer in non-wasm
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-timer]
workspace = true git = "https://github.com/mmsinclair/wasm-timer"
features = ["tokio"] rev = "b9d1a54ad514c2f230a026afe0dde341e98cd7b6"
# this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate # this is due to tungstenite using `rand` 0.8 and associated changes in `getrandom` crate
# which now does not support wasm32-unknown-unknown target by default. # which now does not support wasm32-unknown-unknown target by default.
@@ -31,16 +31,14 @@ use tungstenite::protocol::Message;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use nym_validator_client::nyxd::traits::DkgQueryClient; use nym_validator_client::nyxd::traits::DkgQueryClient;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(not(target_arch = "wasm32"))]
use tokio_tungstenite::connect_async; use tokio_tungstenite::connect_async;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use nym_bandwidth_controller::wasm_mockups::DkgQueryClient; use nym_bandwidth_controller::wasm_mockups::DkgQueryClient;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_utils::websocket::JSWebsocket; use wasm_timer;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep; use wasm_utils::websocket::JSWebsocket;
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10; const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5); const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
@@ -200,7 +198,15 @@ impl<C, St> GatewayClient<C, St> {
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
sleep(self.reconnection_backoff).await; tokio::time::sleep(self.reconnection_backoff).await;
#[cfg(target_arch = "wasm32")]
if let Err(err) = wasm_timer::Delay::new(self.reconnection_backoff).await {
error!(
"the timer has gone away while in reconnection backoff! - {}",
err
);
}
} }
// final attempt (done separately to be able to return a proper error) // final attempt (done separately to be able to return a proper error)
@@ -229,9 +235,16 @@ impl<C, St> GatewayClient<C, St> {
_ => return Err(GatewayClientError::ConnectionInInvalidState), _ => return Err(GatewayClientError::ConnectionInInvalidState),
}; };
let timeout = sleep(self.response_timeout_duration); #[cfg(not(target_arch = "wasm32"))]
let timeout = tokio::time::sleep(self.response_timeout_duration);
#[cfg(not(target_arch = "wasm32"))]
tokio::pin!(timeout); tokio::pin!(timeout);
// technically the `wasm_timer` also works outside wasm, but unless required,
// I really prefer to just stick to tokio
#[cfg(target_arch = "wasm32")]
let mut timeout = wasm_timer::Delay::new(self.response_timeout_duration);
loop { loop {
tokio::select! { tokio::select! {
_ = self.shutdown.recv() => { _ = self.shutdown.recv() => {
+33 -23
View File
@@ -20,6 +20,7 @@ nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig
nym-name-service-common = { path = "../../cosmwasm-smart-contracts/name-service" } nym-name-service-common = { path = "../../cosmwasm-smart-contracts/name-service" }
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" } nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" } nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts/service-provider-directory" }
nym-vesting-contract = { path = "../../../contracts/vesting" }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
@@ -34,30 +35,27 @@ 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" }
async-trait = { workspace = true } # required for nyxd-client
# 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" } nym-config = { path = "../../config", optional = true }
cosmrs = { workspace = true, features = ["bip32", "cosmwasm"] } cosmrs = { workspace = true, features = ["rpc", "bip32", "cosmwasm"], optional = true }
#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 } cw3 = { workspace = true, optional = true }
cw4 = { workspace = true } cw4 = { workspace = true, optional = true }
prost = { version = "0.11", default-features = false } prost = { version = "0.10", default-features = false, optional = true }
flate2 = { version = "1.0.20" } flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5" } sha2 = { version = "0.9.5", optional = true }
itertools = { version = "0.10" } itertools = { version = "0.10", optional = true }
zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] } zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true, optional = true }
[dev-dependencies] [dev-dependencies]
bip39 = { workspace = true } bip39 = { workspace = true }
#cosmrs = { workspace = true, 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"
@@ -66,23 +64,35 @@ 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 = ["http-client", "signing"] required-features = ["nyxd-client"]
[[example]] [[example]]
name = "query_service_provider_directory" name = "query_service_provider_directory"
# TODO: validate the requirements required-features = ["nyxd-client"]
required-features = ["http-client", "signing"]
[[example]] [[example]]
name = "query_name_service" name = "query_name_service"
# TODO: validate the requirements required-features = ["nyxd-client"]
required-features = ["http-client", "signing"]
[features] [features]
http-client = ["cosmrs/rpc", "openssl"] nyxd-client = [
"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::HttpClient; use cosmrs::rpc::{self, 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(),
}, },
100000u32, 100000,
); );
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 = tendermint_rpc::client::Client::broadcast_tx_commit(&broadcaster, tx_bytes) let res = rpc::Client::broadcast_tx_commit(&broadcaster, tx_bytes.into())
.await .await
.unwrap(); .unwrap();
@@ -16,35 +16,37 @@ 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 = "http-client")] #[cfg(feature = "nyxd-client")]
use crate::nyxd::QueryNyxdClient; use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
use crate::nyxd::{self, CosmWasmClient, NyxdClient}; #[cfg(feature = "nyxd-client")]
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(all(feature = "signing", feature = "http-client"))] #[cfg(feature = "nyxd-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>,
@@ -53,6 +55,7 @@ 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,
@@ -116,6 +119,7 @@ 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>,
@@ -127,7 +131,7 @@ pub struct Client<C> {
pub nyxd: NyxdClient<C>, pub nyxd: NyxdClient<C>,
} }
#[cfg(all(feature = "signing", feature = "http-client"))] #[cfg(feature = "nyxd-client")]
impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> { impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
pub fn new_signing( pub fn new_signing(
config: Config, config: Config,
@@ -161,7 +165,7 @@ impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
} }
} }
#[cfg(feature = "http-client")] #[cfg(feature = "nyxd-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());
@@ -185,6 +189,7 @@ 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
@@ -567,6 +572,7 @@ 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)
@@ -629,9 +635,11 @@ 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::TendermintErrorRpc(e))) => { Ok(Err(NyxdError::TendermintError(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,6 +15,7 @@ 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,10 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod client; pub mod client;
#[cfg(feature = "http-client")] #[cfg(feature = "nyxd-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")]
@@ -15,4 +16,5 @@ 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,6 +52,7 @@ impl<'a> Div<GasPrice> for &'a Coin {
} else { } else {
implicit_gas_limit.u128() as u64 implicit_gas_limit.u128() as u64
} }
.into()
} }
} }
@@ -190,32 +191,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); assert_eq!(157520, res.value());
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); assert_eq!(49382715600, res.value());
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); assert_eq!(40, res.value());
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); assert_eq!(121555915721, res.value());
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); assert_eq!(150_000_000, res.value());
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); assert_eq!(121500, res.value());
} }
#[test] #[test]
@@ -1,16 +1,15 @@
// Copyright 2021-2023 - 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; 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, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse, Account, Code, CodeDetails, Contract, ContractCodeHistoryEntry, ContractCodeId,
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,
@@ -19,28 +18,22 @@ 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::*;
QueryCodeRequest, QueryCodeResponse, QueryCodesRequest, QueryCodesResponse, use cosmrs::rpc::endpoint::block::Response as BlockResponse;
QueryContractHistoryRequest, QueryContractHistoryResponse, QueryContractInfoRequest, use cosmrs::rpc::endpoint::broadcast;
QueryContractInfoResponse, QueryContractsByCodeRequest, QueryContractsByCodeResponse, use cosmrs::rpc::endpoint::tx::Response as TxResponse;
QueryRawContractStateRequest, QueryRawContractStateResponse, QuerySmartContractStateRequest, use cosmrs::rpc::query::Query;
QuerySmartContractStateResponse, use cosmrs::rpc::{self, HttpClient, Order};
}; use cosmrs::tendermint::abci::Transaction;
use cosmrs::tendermint::{block, chain, Hash}; use cosmrs::tendermint::{abci, block, chain};
use cosmrs::{AccountId, Coin as CosmosCoin, Tx}; use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx};
use prost::Message; use prost::Message;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::{TryFrom, TryInto};
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 cosmrs::rpc::HttpClient { impl CosmWasmClient for HttpClient {
fn broadcast_polling_rate(&self) -> Duration { fn broadcast_polling_rate(&self) -> Duration {
Duration::from_secs(4) Duration::from_secs(4)
} }
@@ -51,7 +44,7 @@ impl CosmWasmClient for cosmrs::rpc::HttpClient {
} }
#[async_trait] #[async_trait]
pub trait CosmWasmClient: TendermintClient { pub trait CosmWasmClient: rpc::Client {
// 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;
@@ -62,7 +55,7 @@ pub trait CosmWasmClient: TendermintClient {
// require proof? // require proof?
async fn make_abci_query<Req, Res>( async fn make_abci_query<Req, Res>(
&self, &self,
path: Option<String>, path: Option<abci::Path>,
req: Req, req: Req,
) -> Result<Res, NyxdError> ) -> Result<Res, NyxdError>
where where
@@ -88,7 +81,7 @@ pub trait CosmWasmClient: TendermintClient {
// 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".to_owned()); let path = Some("/cosmos.auth.v1beta1.Query/Account".parse().unwrap());
let req = QueryAccountRequest { let req = QueryAccountRequest {
address: address.to_string(), address: address.to_string(),
@@ -126,7 +119,7 @@ pub trait CosmWasmClient: TendermintClient {
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".to_owned()); let path = Some("/cosmos.bank.v1beta1.Query/Balance".parse().unwrap());
let req = QueryBalanceRequest { let req = QueryBalanceRequest {
address: address.to_string(), address: address.to_string(),
@@ -144,7 +137,7 @@ pub trait CosmWasmClient: TendermintClient {
} }
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".to_owned()); let path = Some("/cosmos.bank.v1beta1.Query/AllBalances".parse().unwrap());
let mut raw_balances = Vec::new(); let mut raw_balances = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -175,7 +168,7 @@ pub trait CosmWasmClient: TendermintClient {
} }
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".to_owned()); let path = Some("/cosmos.bank.v1beta1.Query/TotalSupply".parse().unwrap());
let mut supply = Vec::new(); let mut supply = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -202,7 +195,7 @@ pub trait CosmWasmClient: TendermintClient {
.map_err(|_| NyxdError::SerializationError("Coins".to_owned())) .map_err(|_| NyxdError::SerializationError("Coins".to_owned()))
} }
async fn get_tx(&self, id: Hash) -> Result<TxResponse, NyxdError> { async fn get_tx(&self, id: tx::Hash) -> Result<TxResponse, NyxdError> {
Ok(self.tx(id, false).await?) Ok(self.tx(id, false).await?)
} }
@@ -238,36 +231,30 @@ pub trait CosmWasmClient: TendermintClient {
} }
/// Broadcast a transaction, returning immediately. /// Broadcast a transaction, returning immediately.
async fn broadcast_tx_async<T>(&self, tx: T) -> Result<broadcast::tx_async::Response, NyxdError> async fn broadcast_tx_async(
where &self,
T: Into<Vec<u8>> + Send, tx: Transaction,
{ ) -> Result<broadcast::tx_async::Response, NyxdError> {
Ok(tendermint_rpc::client::Client::broadcast_tx_async(self, tx).await?) Ok(rpc::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<T>(&self, tx: T) -> Result<broadcast::tx_sync::Response, NyxdError> async fn broadcast_tx_sync(
where &self,
T: Into<Vec<u8>> + Send, tx: Transaction,
{ ) -> Result<broadcast::tx_sync::Response, NyxdError> {
Ok(tendermint_rpc::client::Client::broadcast_tx_sync(self, tx).await?) Ok(rpc::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<T>( async fn broadcast_tx_commit(
&self, &self,
tx: T, tx: Transaction,
) -> Result<broadcast::tx_commit::Response, NyxdError> ) -> Result<broadcast::tx_commit::Response, NyxdError> {
where Ok(rpc::Client::broadcast_tx_commit(self, tx).await?)
T: Into<Vec<u8>> + Send,
{
Ok(tendermint_rpc::client::Client::broadcast_tx_commit(self, tx).await?)
} }
async fn broadcast_tx<T>(&self, tx: T) -> Result<TxResponse, NyxdError> async fn broadcast_tx(&self, tx: Transaction) -> 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() {
@@ -303,8 +290,8 @@ pub trait CosmWasmClient: TendermintClient {
} }
} }
async fn get_codes(&self) -> Result<Vec<CodeInfoResponse>, NyxdError> { async fn get_codes(&self) -> Result<Vec<Code>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/Codes".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/Codes".parse().unwrap());
let mut raw_codes = Vec::new(); let mut raw_codes = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -324,14 +311,14 @@ pub trait CosmWasmClient: TendermintClient {
} }
} }
Ok(raw_codes 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".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/Code".parse().unwrap());
let req = QueryCodeRequest { code_id }; let req = QueryCodeRequest { code_id };
@@ -346,7 +333,7 @@ pub trait CosmWasmClient: TendermintClient {
} }
} }
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".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/ContractsByCode".parse().unwrap());
let mut raw_contracts = Vec::new(); let mut raw_contracts = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -377,7 +364,7 @@ pub trait CosmWasmClient: TendermintClient {
} }
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".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/ContractInfo".parse().unwrap());
let req = QueryContractInfoRequest { let req = QueryContractInfoRequest {
address: address.to_string(), address: address.to_string(),
@@ -402,7 +389,7 @@ pub trait CosmWasmClient: TendermintClient {
&self, &self,
address: &AccountId, address: &AccountId,
) -> Result<Vec<ContractCodeHistoryEntry>, NyxdError> { ) -> Result<Vec<ContractCodeHistoryEntry>, NyxdError> {
let path = Some("/cosmwasm.wasm.v1.Query/ContractHistory".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/ContractHistory".parse().unwrap());
let mut raw_entries = Vec::new(); let mut raw_entries = Vec::new();
let mut pagination = None; let mut pagination = None;
@@ -425,10 +412,10 @@ pub trait CosmWasmClient: TendermintClient {
} }
} }
Ok(raw_entries 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(
@@ -436,7 +423,7 @@ pub trait CosmWasmClient: TendermintClient {
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".to_owned()); let path = Some("/cosmwasm.wasm.v1.Query/RawContractState".parse().unwrap());
let req = QueryRawContractStateRequest { let req = QueryRawContractStateRequest {
address: address.to_string(), address: address.to_string(),
@@ -492,7 +479,7 @@ pub trait CosmWasmClient: TendermintClient {
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".to_owned()); let path = Some("/cosmos.tx.v1beta1.Service/Simulate".parse().unwrap());
let req = SimulateRequest { let req = SimulateRequest {
tx: tx.map(Into::into), tx: tx.map(Into::into),
@@ -3,7 +3,12 @@
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 tendermint_rpc::endpoint::broadcast; use cosmrs::proto::cosmos::base::v1beta1::Coin as ProtoCoin;
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>;
@@ -16,7 +21,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, raw_log: self.check_tx.log.value().to_owned(),
}); });
} }
@@ -25,7 +30,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, raw_log: self.deliver_tx.log.value().to_owned(),
}); });
} }
@@ -40,7 +45,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, raw_log: self.tx_result.log.value().to_owned(),
}); });
} }
@@ -48,12 +53,7 @@ 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,3 +83,14 @@ 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,6 +2,7 @@
// 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};
@@ -48,7 +49,7 @@ fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
Ok(logs) Ok(logs)
} }
pub fn parse_raw_logs(raw: String) -> Result<Vec<Log>, NyxdError> { pub fn parse_raw_logs(raw: abci::Log) -> Result<Vec<Log>, NyxdError> {
parse_raw_str_logs(raw.as_ref()) parse_raw_str_logs(raw.as_ref())
} }
@@ -1,22 +1,17 @@
// 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;
#[cfg(feature = "http-client")] use crate::nyxd::GasPrice;
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>,
@@ -24,11 +19,10 @@ 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: crate::nyxd::GasPrice, gas_price: 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,37 +9,29 @@ 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}; use cosmrs::tx::{self, Msg, Raw};
use cosmrs::{cosmwasm, AccountId, Any, Tx}; use cosmrs::{cosmwasm, rpc, 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;
#[cfg(feature = "http-client")] const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
use crate::signing::tx_signer::TxSigner; const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
#[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 {
@@ -131,10 +123,7 @@ 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 { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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
@@ -195,10 +184,8 @@ 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 { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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
@@ -225,7 +212,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 = sealed::cosmwasm::MsgUpdateAdmin { let change_admin_msg = 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(),
@@ -238,10 +225,8 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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,
@@ -256,7 +241,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 = sealed::cosmwasm::MsgClearAdmin { let change_admin_msg = cosmwasm::MsgClearAdmin {
sender: sender_address.clone(), sender: sender_address.clone(),
contract: contract_address.clone(), contract: contract_address.clone(),
} }
@@ -268,10 +253,8 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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,
@@ -305,10 +288,8 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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,
@@ -342,13 +323,11 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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.into(), data: tx_res.tx_result.data,
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
gas_info, gas_info,
}) })
@@ -385,13 +364,11 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.await? .await?
.check_response()?; .check_response()?;
let gas_info = GasInfo { let gas_info = GasInfo::new(tx_res.tx_result.gas_wanted, tx_res.tx_result.gas_used);
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.into(), data: tx_res.tx_result.data,
transaction_hash: tx_res.hash, transaction_hash: tx_res.hash,
gas_info, gas_info,
}) })
@@ -625,7 +602,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).await CosmWasmClient::broadcast_tx_async(self, tx_bytes.into()).await
} }
/// Broadcast a transaction, returning the response from `CheckTx`. /// Broadcast a transaction, returning the response from `CheckTx`.
@@ -645,7 +622,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).await CosmWasmClient::broadcast_tx_sync(self, tx_bytes.into()).await
} }
/// Broadcast a transaction, returning the response from `DeliverTx`. /// Broadcast a transaction, returning the response from `DeliverTx`.
@@ -666,7 +643,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).await CosmWasmClient::broadcast_tx_commit(self, tx_bytes.into()).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.
@@ -687,7 +664,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).await self.broadcast_tx(tx_bytes.into()).await
} }
async fn sign( async fn sign(
@@ -732,7 +709,6 @@ 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,
@@ -746,7 +722,6 @@ 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,
@@ -795,13 +770,12 @@ impl<S> Client<S> {
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> tendermint_rpc::client::Client for Client<S> impl<S> rpc::Client for Client<S>
where where
S: Send + Sync, S: Send + Sync,
{ {
async fn perform<R>(&self, request: R) -> Result<R::Output, tendermint_rpc::Error> async fn perform<R>(&self, request: R) -> Result<R::Response, rpc::Error>
where where
R: SimpleRequest, R: SimpleRequest,
{ {
@@ -809,7 +783,6 @@ where
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> CosmWasmClient for Client<S> impl<S> CosmWasmClient for Client<S>
where where
@@ -824,7 +797,6 @@ where
} }
} }
#[cfg(feature = "http-client")]
#[async_trait] #[async_trait]
impl<S> SigningCosmWasmClient for Client<S> impl<S> SigningCosmWasmClient for Client<S>
where where
@@ -848,7 +820,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<tx::Raw, NyxdError> { ) -> Result<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)?)
@@ -861,173 +833,9 @@ 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<tx::Raw, NyxdError> { ) -> Result<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,35 +3,36 @@
// 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::auth::{BaseAccount, ModuleAccount}; use cosmrs::crypto::PublicKey;
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::Result as ProtoAbciResult; use cosmrs::proto::cosmos::base::abci::v1beta1::{
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, DelayedVestingAccount as ProtoDelayedVestingAccount, Period as ProtoPeriod,
PeriodicVestingAccount as ProtoPeriodicVestingAccount, PeriodicVestingAccount as ProtoPeriodicVestingAccount,
PermanentLockedAccount as ProtoPermanentLockedAccount, PermanentLockedAccount as ProtoPermanentLockedAccount,
}; };
use cosmrs::tendermint::{abci, Hash}; use cosmrs::proto::cosmwasm::wasm::v1::{
use cosmrs::tx::{AccountNumber, SequenceNumber}; CodeInfoResponse, ContractCodeHistoryEntry as ProtoContractCodeHistoryEntry,
use cosmrs::vesting::{ ContractCodeHistoryOperationType, ContractInfo as ProtoContractInfo,
BaseVestingAccount, ContinuousVestingAccount, DelayedVestingAccount, PeriodicVestingAccount,
PermanentLockedAccount,
}; };
use cosmrs::{AccountId, Any, Coin as CosmosCoin}; use cosmrs::tendermint::abci;
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)]
@@ -43,6 +44,215 @@ 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),
@@ -125,32 +335,183 @@ 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: CodeInfoResponse, pub code_info: Code,
/// 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: CodeInfoResponse, data: Vec<u8>) -> Self { pub fn new(code_info: Code, 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 contract_info: ContractInfo, pub code_id: ContractCodeId,
/// 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,
contract_info, code_id: contract_info.code_id,
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,
} }
} }
} }
@@ -174,15 +535,31 @@ 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 events = value let mut events = Vec::with_capacity(value.events.len());
.events
.into_iter() for proto_event in value.events.into_iter() {
.map(TryInto::try_into) let type_str = proto_event.r#type;
.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,
@@ -201,10 +578,7 @@ 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: value.gas_info.map(|gas_info| gas_info.into()),
.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()?,
}) })
} }
@@ -234,7 +608,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: Hash, pub transaction_hash: tx::Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -271,7 +645,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: Hash, pub transaction_hash: tx::Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -281,7 +655,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: Hash, pub transaction_hash: tx::Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -291,7 +665,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: Hash, pub transaction_hash: tx::Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -300,10 +674,10 @@ pub struct MigrateResult {
pub struct ExecuteResult { pub struct ExecuteResult {
pub logs: Vec<Log>, pub logs: Vec<Log>,
pub data: Vec<u8>, pub data: Data,
/// Transaction hash (might be used as transaction ID) /// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash, pub transaction_hash: tx::Hash,
pub gas_info: GasInfo, pub gas_info: GasInfo,
} }
@@ -2,39 +2,34 @@
// 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::{
tendermint::{abci::Code as AbciCode, block}, rpc::endpoint::abci_query::AbciQuery,
AccountId, tendermint::{
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,
@@ -48,10 +43,7 @@ pub enum NyxdError {
InvalidTxHash(String), InvalidTxHash(String),
#[error("Tendermint RPC request failed - {0}")] #[error("Tendermint RPC request failed - {0}")]
TendermintErrorRpc(#[from] TendermintRpcError), TendermintError(#[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),
@@ -99,7 +91,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: Hash, hash: tx::Hash,
height: Option<block::Height>, height: Option<block::Height>,
code: u32, code: u32,
raw_log: String, raw_log: String,
@@ -109,7 +101,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: Hash, hash: tx::Hash,
height: Option<block::Height>, height: Option<block::Height>,
code: u32, code: u32,
raw_log: String, raw_log: String,
@@ -124,7 +116,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: String, log: abci::Log,
pretty_log: Option<String>, pretty_log: Option<String>,
}, },
@@ -138,7 +130,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: Hash, timeout: Duration }, BroadcastTimeout { hash: tx::Hash, timeout: Duration },
#[error("Cosmwasm std error: {0}")] #[error("Cosmwasm std error: {0}")]
CosmwasmStdError(#[from] cosmwasm_std::StdError), CosmwasmStdError(#[from] cosmwasm_std::StdError),
@@ -156,7 +148,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.into(), code,
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),
}), }),
@@ -165,8 +157,11 @@ 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: &str) -> Option<String> { fn try_parse_abci_log(log: &abci::Log) -> Option<String> {
if log.contains("Maximum amount of locked coins has already been pledged") { if log
.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
@@ -176,7 +171,7 @@ fn try_parse_abci_log(log: &str) -> 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::TendermintErrorRpc(TendermintRpcError( NyxdError::TendermintError(TendermintRpcError(
TendermintRpcErrorDetail::Response(err), TendermintRpcErrorDetail::Response(err),
_, _,
)) => { )) => {
@@ -203,7 +198,7 @@ impl NyxdError {
pub fn is_tendermint_response_duplicate(&self) -> bool { pub fn is_tendermint_response_duplicate(&self) -> bool {
match &self { match &self {
NyxdError::TendermintErrorRpc(TendermintRpcError( NyxdError::TendermintError(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); let limit_uint128 = Uint128::from(gas_limit.value());
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; let gas_limit: Gas = 157500u64.into();
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
@@ -32,7 +32,7 @@ impl Display for AutoFeeGrant {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Fee { pub enum Fee {
Manual(tx::Fee), Manual(#[serde(with = "sealed::TxFee")] tx::Fee),
Auto(Option<GasAdjustment>), Auto(Option<GasAdjustment>),
PayerGranterAuto(AutoFeeGrant), PayerGranterAuto(AutoFeeGrant),
} }
@@ -116,8 +116,63 @@ impl GasAdjustable for Gas {
if adjustment == 1.0 { if adjustment == 1.0 {
*self *self
} else { } else {
let adjusted = (*self as f32 * adjustment).ceil(); let adjusted = (self.value() as f32 * adjustment).ceil();
adjusted as u64 (adjusted as u64).into()
} }
} }
} }
// 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
mod sealed {
use cosmrs::tx::{self, Gas};
use cosmrs::Coin as CosmosCoin;
use cosmrs::{AccountId, Denom as CosmosDenom};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Serialize, Deserialize, Clone)]
struct Coin {
denom: CosmosDenom,
amount: u128,
}
impl From<Coin> for CosmosCoin {
fn from(val: Coin) -> Self {
CosmosCoin {
denom: val.denom,
amount: val.amount,
}
}
}
impl From<CosmosCoin> for Coin {
fn from(val: CosmosCoin) -> Self {
Coin {
denom: val.denom,
amount: val.amount,
}
}
}
fn coin_vec_ser<S: Serializer>(val: &[CosmosCoin], serializer: S) -> Result<S::Ok, S::Error> {
let vec: Vec<Coin> = val.iter().cloned().map(Into::into).collect();
vec.serialize(serializer)
}
fn coin_vec_deser<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Vec<CosmosCoin>, D::Error> {
let vec: Vec<Coin> = Deserialize::deserialize(deserializer)?;
Ok(vec.iter().cloned().map(Into::into).collect())
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "tx::Fee")]
pub(super) struct TxFee {
#[serde(serialize_with = "coin_vec_ser")]
#[serde(deserialize_with = "coin_vec_deser")]
pub amount: Vec<CosmosCoin>,
pub gas_limit: Gas,
pub payer: Option<AccountId>,
pub granter: Option<AccountId>,
}
}
@@ -1,67 +1,51 @@
// 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::types::Account; use crate::nyxd::cosmwasm_client::signing_client;
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 tendermint_rpc::{endpoint::block::Response as BlockResponse, query::Query}; use std::convert::TryInto;
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::tendermint::abci::{response::DeliverTx, Event, EventAttribute}; pub use cosmrs::rpc::endpoint::tx::Response as TxResponse;
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::{self, Algorithm, Hash}; pub use cosmrs::tendermint::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}; pub use cosmrs::tx::{self, Gas};
pub use cosmrs::Coin as CosmosCoin; pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::Gas;
pub use cosmrs::{bip32, AccountId, Denom}; pub use cosmrs::{bip32, AccountId, Denom};
use cosmwasm_std::Addr;
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 tendermint_rpc::{client::Client as TendermintClient, Request, Response, SimpleRequest};
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; pub use signing_client::Client as SigningNyxdClient;
pub use traits::{VestingQueryClient, VestingSigningClient};
#[cfg(all(feature = "signing", feature = "http-client"))]
pub type DirectSigningNyxdClient = SigningNyxdClient<DirectSecp256k1HdWallet>; pub type DirectSigningNyxdClient = SigningNyxdClient<DirectSecp256k1HdWallet>;
pub mod coin; pub mod coin;
@@ -78,6 +62,7 @@ pub struct Config {
// however, I'd really prefer to use something more strongly typed (i.e. AccountId vs String) // however, I'd really prefer to use something more strongly typed (i.e. AccountId vs String)
pub(crate) mixnet_contract_address: Option<AccountId>, pub(crate) mixnet_contract_address: Option<AccountId>,
pub(crate) vesting_contract_address: Option<AccountId>, pub(crate) vesting_contract_address: Option<AccountId>,
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>, pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
pub(crate) group_contract_address: Option<AccountId>, pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>, pub(crate) multisig_contract_address: Option<AccountId>,
@@ -125,6 +110,10 @@ impl Config {
details.contracts.vesting_contract_address.as_ref(), details.contracts.vesting_contract_address.as_ref(),
prefix, prefix,
)?, )?,
bandwidth_claim_contract_address: Self::parse_optional_account(
details.contracts.bandwidth_claim_contract_address.as_ref(),
prefix,
)?,
coconut_bandwidth_contract_address: Self::parse_optional_account( coconut_bandwidth_contract_address: Self::parse_optional_account(
details details
.contracts .contracts
@@ -163,13 +152,10 @@ 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
@@ -179,12 +165,11 @@ impl NyxdClient<QueryNyxdClient> {
client: QueryNyxdClient::new(endpoint)?, client: QueryNyxdClient::new(endpoint)?,
config, config,
client_address: None, client_address: None,
simulated_gas_multiplier: crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER, simulated_gas_multiplier: 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>(
@@ -202,14 +187,12 @@ 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,
@@ -231,11 +214,10 @@ 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: crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER, simulated_gas_multiplier: 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>,
@@ -248,47 +230,133 @@ where
} }
} }
#[cfg(feature = "signing")] impl<C> NyxdClient<C> {
impl<C> NyxdClient<C> pub fn current_config(&self) -> &Config {
where &self.config
C: SigningCosmWasmClient + Sync,
{
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 pub fn current_chain_details(&self) -> &ChainDetails {
where &self.config.chain_details
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 async fn account_sequence(&self) -> Result<SequenceResponse, NyxdError> pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
where self.config.mixnet_contract_address = Some(address);
C: SigningCosmWasmClient + Sync,
{
self.client.get_sequence(self.address()).await
} }
pub fn signer(&self) -> &<C as SigningCosmWasmClient>::Signer pub fn set_vesting_contract_address(&mut self, address: AccountId) {
where self.config.vesting_contract_address = Some(address);
C: SigningCosmWasmClient,
{
self.client.signer()
} }
pub fn gas_price(&self) -> &GasPrice 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: SigningCosmWasmClient, C: CosmWasmClient + Sync,
M: ?Sized + Serialize + Sync,
for<'a> T: Deserialize<'a>,
{ {
self.client.gas_price() 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 wrap_contract_execute_message<M>( pub fn wrap_contract_execute_message<M>(
@@ -309,6 +377,175 @@ where
}) })
} }
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,
@@ -525,249 +762,3 @@ where
.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_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 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,9 +8,10 @@ use async_trait::async_trait;
use cosmrs::AccountId; use cosmrs::AccountId;
use nym_contracts_common::signing::Nonce; use nym_contracts_common::signing::Nonce;
use nym_mixnet_contract_common::delegation::{MixNodeDelegationResponse, OwnerProxySubKey}; use nym_mixnet_contract_common::delegation::{MixNodeDelegationResponse, OwnerProxySubKey};
use nym_mixnet_contract_common::families::Family;
use nym_mixnet_contract_common::mixnode::{ use nym_mixnet_contract_common::mixnode::{
MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse, PagedUnbondedMixnodesResponse, MixNodeDetails, MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
StakeSaturationResponse, UnbondedMixnodeResponse, PagedUnbondedMixnodesResponse, StakeSaturationResponse, UnbondedMixnodeResponse,
}; };
use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams}; use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams};
use nym_mixnet_contract_common::rewarding::{ use nym_mixnet_contract_common::rewarding::{
@@ -18,15 +19,14 @@ use nym_mixnet_contract_common::rewarding::{
}; };
use nym_mixnet_contract_common::{ use nym_mixnet_contract_common::{
delegation, ContractBuildInformation, ContractState, ContractStateParams, delegation, ContractBuildInformation, ContractState, ContractStateParams,
CurrentIntervalResponse, EpochEventId, EpochStatus, FamilyByHeadResponse, CurrentIntervalResponse, EpochEventId, EpochStatus, GatewayBondResponse,
FamilyByLabelResponse, FamilyMembersByHeadResponse, FamilyMembersByLabelResponse, GatewayOwnershipResponse, IdentityKey, IntervalEventId, LayerDistribution, MixId,
GatewayBondResponse, GatewayOwnershipResponse, IdentityKey, IntervalEventId, LayerDistribution, MixOwnershipResponse, MixnodeDetailsResponse, NumberOfPendingEventsResponse,
MixId, MixOwnershipResponse, MixnodeDetailsByIdentityResponse, MixnodeDetailsResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedFamiliesResponse,
NumberOfPendingEventsResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse, PagedMembersResponse, PagedMixNodeDelegationsResponse,
PagedFamiliesResponse, PagedGatewayResponse, PagedMembersResponse, PagedMixnodeBondsResponse, PagedRewardedSetResponse, PendingEpochEventResponse,
PagedMixNodeDelegationsResponse, PagedMixnodeBondsResponse, PagedRewardedSetResponse, PendingEpochEventsResponse, PendingIntervalEventResponse, PendingIntervalEventsResponse,
PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEventResponse, QueryMsg as MixnetQueryMsg,
PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg,
}; };
use serde::Deserialize; use serde::Deserialize;
@@ -100,24 +100,6 @@ pub trait MixnetQueryClient {
.await .await
} }
async fn get_family_members_by_head<S: Into<String> + Send>(
&self,
head: S,
) -> Result<FamilyMembersByHeadResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyMembersByHead { head: head.into() })
.await
}
async fn get_family_members_by_label<S: Into<String> + Send>(
&self,
label: S,
) -> Result<FamilyMembersByLabelResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyMembersByLabel {
label: label.into(),
})
.await
}
// mixnode-related: // mixnode-related:
async fn get_mixnode_bonds_paged( async fn get_mixnode_bonds_paged(
@@ -196,7 +178,7 @@ pub trait MixnetQueryClient {
async fn get_mixnode_details_by_identity( async fn get_mixnode_details_by_identity(
&self, &self,
mix_identity: IdentityKey, mix_identity: IdentityKey,
) -> Result<MixnodeDetailsByIdentityResponse, NyxdError> { ) -> Result<Option<MixNodeDetails>, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity { self.query_mixnet_contract(MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity {
mix_identity, mix_identity,
}) })
@@ -433,17 +415,14 @@ pub trait MixnetQueryClient {
.await .await
} }
async fn get_node_family_by_label( async fn get_node_family_by_label(&self, label: &str) -> Result<Option<Family>, NyxdError> {
&self,
label: &str,
) -> Result<FamilyByLabelResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel { self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel {
label: label.to_string(), label: label.to_string(),
}) })
.await .await
} }
async fn get_node_family_by_head(&self, head: &str) -> Result<FamilyByHeadResponse, NyxdError> { async fn get_node_family_by_head(&self, head: &str) -> Result<Option<Family>, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead { self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead {
head: head.to_string(), head: head.to_string(),
}) })
@@ -8,25 +8,20 @@ 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;
#[cfg(feature = "signing")]
mod name_service_signing_client;
#[cfg(feature = "signing")]
mod sp_directory_signing_client;
#[cfg(feature = "signing")]
mod vesting_signing_client; mod vesting_signing_client;
mod sp_directory_query_client;
mod sp_directory_signing_client;
mod name_service_query_client;
mod name_service_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;
pub use group_query_client::GroupQueryClient; pub use group_query_client::GroupQueryClient;
@@ -36,17 +31,10 @@ 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;
@@ -10,11 +10,12 @@ use cosmwasm_std::{Coin as CosmWasmCoin, Timestamp};
use nym_contracts_common::ContractBuildInformation; use nym_contracts_common::ContractBuildInformation;
use nym_mixnet_contract_common::MixId; use nym_mixnet_contract_common::MixId;
use nym_vesting_contract_common::{ use nym_vesting_contract_common::{
messages::QueryMsg as VestingQueryMsg, Account, AccountVestingCoins, AccountsResponse, messages::QueryMsg as VestingQueryMsg, AccountVestingCoins, AccountsResponse,
AllDelegationsResponse, BaseVestingAccountInfo, DelegationTimesResponse, AllDelegationsResponse, BaseVestingAccountInfo, DelegationTimesResponse,
OriginalVestingResponse, Period, PledgeData, VestingCoinsResponse, VestingDelegation, OriginalVestingResponse, Period, PledgeData, VestingCoinsResponse, VestingDelegation,
}; };
use serde::Deserialize; use serde::Deserialize;
use vesting_contract::vesting::Account;
#[async_trait] #[async_trait]
pub trait VestingQueryClient { pub trait VestingQueryClient {
@@ -12,8 +12,10 @@ use nym_mixnet_contract_common::families::FamilyHead;
use nym_mixnet_contract_common::gateway::GatewayConfigUpdate; use nym_mixnet_contract_common::gateway::GatewayConfigUpdate;
use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams}; use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
use nym_mixnet_contract_common::{Gateway, MixId, MixNode}; use nym_mixnet_contract_common::{Gateway, MixId, MixNode};
use nym_vesting_contract_common::messages::ExecuteMsg as VestingExecuteMsg; use nym_vesting_contract_common::messages::{
use nym_vesting_contract_common::{PledgeCap, VestingSpecification}; ExecuteMsg as VestingExecuteMsg, VestingSpecification,
};
use nym_vesting_contract_common::PledgeCap;
#[async_trait] #[async_trait]
pub trait VestingSigningClient { pub trait VestingSigningClient {
@@ -63,6 +63,7 @@ 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,
+1 -1
View File
@@ -28,7 +28,7 @@ tap = "1"
cosmrs = { workspace = true } cosmrs = { workspace = true }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
nym-validator-client = { path = "../client-libs/validator-client", features = ["signing", "http-client"] } nym-validator-client = { path = "../client-libs/validator-client", features = ["nyxd-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" }
@@ -34,7 +34,6 @@ pub async fn delegate_to_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -29,7 +29,6 @@ pub async fn claim_delegator_reward(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -29,7 +29,6 @@ pub async fn vesting_claim_delegator_reward(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -29,7 +29,6 @@ pub async fn undelegate_from_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::VestingSigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -40,7 +40,6 @@ pub async fn vesting_delegate_to_mixnode(args: Args, client: SigningClient) {
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::VestingSigningClient;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -34,7 +34,6 @@ pub async fn vesting_undelegate_from_mixnode(args: Args, client: SigningClient)
.get_mixnode_details_by_identity(identity_key) .get_mixnode_details_by_identity(identity_key)
.await .await
.expect("contract query failed") .expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist"); .expect("mixnode with the specified identity doesnt exist");
node_details.mix_id() node_details.mix_id()
} }
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::traits::VestingSigningClient; use nym_validator_client::nyxd::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -50,7 +50,6 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
.get_node_family_by_head(mixnode.bond_information.identity()) .get_node_family_by_head(mixnode.bond_information.identity())
.await .await
.unwrap() .unwrap()
.family
.is_none() .is_none()
{ {
eprintln!("{} does not even seem to own a family!", args.address); eprintln!("{} does not even seem to own a family!", args.address);
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -28,7 +28,7 @@ pub struct Args {
pub async fn join_family(args: Args, client: SigningClient) { pub async fn join_family(args: Args, client: SigningClient) {
info!("Join family"); info!("Join family");
let family_head = FamilyHead::new(args.family_head.to_base58_string()); let family_head = FamilyHead::new(&args.family_head.to_base58_string());
let res = if args.with_vesting_account { let res = if args.with_vesting_account {
client client
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::traits::VestingSigningClient; use nym_validator_client::nyxd::VestingSigningClient;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct Args { pub struct Args {
@@ -23,7 +23,7 @@ pub struct Args {
pub async fn leave_family(args: Args, client: SigningClient) { pub async fn leave_family(args: Args, client: SigningClient) {
info!("Leave family"); info!("Leave family");
let family_head = FamilyHead::new(args.family_head.to_base58_string()); let family_head = FamilyHead::new(&args.family_head.to_base58_string());
let res = if args.with_vesting_account { let res = if args.with_vesting_account {
client client
@@ -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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::{traits::VestingSigningClient, CosmWasmCoin}; use nym_validator_client::nyxd::{CosmWasmCoin, 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_mixnet_contract_common::Coin; use nym_mixnet_contract_common::Coin;
use nym_validator_client::nyxd::traits::VestingSigningClient; use nym_validator_client::nyxd::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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::traits::VestingSigningClient; use nym_validator_client::nyxd::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::Error> { ) -> Result<(), k256::ecdsa::signature::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::tendermint::Hash; use cosmrs::tx::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::{traits::VestingQueryClient, Coin}; use nym_validator_client::nyxd::{Coin, VestingQueryClient};
use crate::context::QueryClient; use crate::context::QueryClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -8,10 +8,10 @@ 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::types::VestingSpecification; use nym_vesting_contract_common::messages::VestingSpecification;
use nym_vesting_contract_common::PledgeCap; use nym_vesting_contract_common::PledgeCap;
use crate::context::SigningClient; use crate::context::SigningClient;
@@ -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::{traits::VestingQueryClient, Coin}; use nym_validator_client::nyxd::{Coin, VestingQueryClient};
use crate::context::QueryClient; use crate::context::QueryClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -4,10 +4,7 @@
use clap::Parser; use clap::Parser;
use log::info; use log::info;
use nym_validator_client::nyxd::{ use nym_validator_client::nyxd::{Coin, VestingQueryClient, VestingSigningClient};
traits::{VestingQueryClient, VestingSigningClient},
Coin,
};
use crate::context::SigningClient; use crate::context::SigningClient;
use crate::utils::show_error; use crate::utils::show_error;
@@ -7,9 +7,6 @@ edition = "2021"
[dependencies] [dependencies]
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true } schemars = "0.8"
cw2 = { workspace = true, optional = true } serde = { version = "1.0.103", default-features = false, features = ["derive"] }
nym-multisig-contract-common = { path = "../multisig-contract" } nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = ["cw2"]
@@ -1,9 +1,10 @@
// 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 cosmwasm_schema::cw_serde; use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct DepositData { pub struct DepositData {
deposit_info: String, deposit_info: String,
identity_key: String, identity_key: String,
@@ -1,41 +1,39 @@
// 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::{deposit::DepositData, spend_credential::SpendCredentialData};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin; use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cfg(feature = "schema")] use crate::{deposit::DepositData, spend_credential::SpendCredentialData};
use crate::spend_credential::{PagedSpendCredentialResponse, SpendCredentialResponse};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct InstantiateMsg { pub struct InstantiateMsg {
pub multisig_addr: String, pub multisig_addr: String,
pub pool_addr: String, pub pool_addr: String,
pub mix_denom: String, pub mix_denom: String,
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
DepositFunds { data: DepositData }, DepositFunds { data: DepositData },
SpendCredential { data: SpendCredentialData }, SpendCredential { data: SpendCredentialData },
ReleaseFunds { funds: Coin }, ReleaseFunds { funds: Coin },
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cfg_attr(feature = "schema", derive(QueryResponses))] #[serde(rename_all = "snake_case")]
pub enum QueryMsg { pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(SpendCredentialResponse))] GetSpentCredential {
GetSpentCredential { blinded_serial_number: String }, blinded_serial_number: String,
},
#[cfg_attr(feature = "schema", returns(PagedSpendCredentialResponse))]
GetAllSpentCredentials { GetAllSpentCredentials {
limit: Option<u32>, limit: Option<u32>,
start_after: Option<String>, start_after: Option<String>,
}, },
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {} pub struct MigrateMsg {}
@@ -1,13 +1,14 @@
// 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 cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg}; use cosmwasm_std::{from_binary, to_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg};
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg; use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::msg::ExecuteMsg; use crate::msg::ExecuteMsg;
#[cw_serde] #[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,
@@ -36,14 +37,13 @@ impl SpendCredentialData {
} }
} }
#[cw_serde] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
#[derive(Copy)]
pub enum SpendCredentialStatus { pub enum SpendCredentialStatus {
InProgress, InProgress,
Spent, Spent,
} }
#[cw_serde] #[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,12 +74,10 @@ impl SpendCredential {
} }
} }
#[cw_serde] #[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,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<String>, pub start_next_after: Option<String>,
} }
@@ -97,7 +95,7 @@ impl PagedSpendCredentialResponse {
} }
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredentialResponse { pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>, pub spend_credential: Option<SpendCredential>,
} }
@@ -6,12 +6,10 @@ 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 }
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
cw-utils = { workspace = true } cw-utils = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" } contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
nym-multisig-contract-common = { path = "../multisig-contract" } nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = []
@@ -2,10 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, NodeIndex}; use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr; use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct DealerDetails { pub struct DealerDetails {
pub address: Addr, pub address: Addr,
pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof, pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
@@ -13,8 +14,8 @@ pub struct DealerDetails {
pub assigned_index: NodeIndex, pub assigned_index: NodeIndex,
} }
#[cw_serde] #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive(Copy)] #[serde(rename_all = "snake_case")]
pub enum DealerType { pub enum DealerType {
Current, Current,
Past, Past,
@@ -27,7 +28,8 @@ impl DealerType {
} }
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct DealerDetailsResponse { pub struct DealerDetailsResponse {
pub details: Option<DealerDetails>, pub details: Option<DealerDetails>,
pub dealer_type: DealerType, pub dealer_type: DealerType,
@@ -42,12 +44,11 @@ impl DealerDetailsResponse {
} }
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct PagedDealerResponse { pub struct PagedDealerResponse {
pub dealers: Vec<DealerDetails>, pub dealers: Vec<DealerDetails>,
pub per_page: usize, pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>, pub start_next_after: Option<Addr>,
} }
@@ -65,7 +66,8 @@ impl PagedDealerResponse {
} }
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct ContractDealing { pub struct ContractDealing {
pub dealing: ContractSafeBytes, pub dealing: ContractSafeBytes,
pub dealer: Addr, pub dealer: Addr,
@@ -77,12 +79,11 @@ impl ContractDealing {
} }
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct PagedDealingsResponse { pub struct PagedDealingsResponse {
pub dealings: Vec<ContractDealing>, pub dealings: Vec<ContractDealing>,
pub per_page: usize, pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>, pub start_next_after: Option<Addr>,
} }
@@ -3,19 +3,11 @@
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration}; use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration};
use crate::verification_key::VerificationKeyShare; use crate::verification_key::VerificationKeyShare;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr; use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cfg(feature = "schema")] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
use crate::{
dealer::{DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse},
types::{Epoch, InitialReplacementData},
verification_key::PagedVKSharesResponse,
};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
#[cw_serde]
pub struct InstantiateMsg { pub struct InstantiateMsg {
pub group_addr: String, pub group_addr: String,
pub multisig_addr: String, pub multisig_addr: String,
@@ -23,7 +15,8 @@ pub struct InstantiateMsg {
pub mix_denom: String, pub mix_denom: String,
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg { pub enum ExecuteMsg {
RegisterDealer { RegisterDealer {
bte_key_with_proof: EncodedBTEPublicKeyWithProof, bte_key_with_proof: EncodedBTEPublicKeyWithProof,
@@ -51,41 +44,28 @@ pub enum ExecuteMsg {
AdvanceEpochState {}, AdvanceEpochState {},
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[cfg_attr(feature = "schema", derive(QueryResponses))] #[serde(rename_all = "snake_case")]
pub enum QueryMsg { pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(Epoch))]
GetCurrentEpochState {}, GetCurrentEpochState {},
#[cfg_attr(feature = "schema", returns(u64))]
GetCurrentEpochThreshold {}, GetCurrentEpochThreshold {},
#[cfg_attr(feature = "schema", returns(Option<InitialReplacementData>))]
GetInitialDealers {}, GetInitialDealers {},
GetDealerDetails {
#[cfg_attr(feature = "schema", returns(DealerDetailsResponse))] dealer_address: String,
GetDealerDetails { dealer_address: String }, },
#[cfg_attr(feature = "schema", returns(PagedDealerResponse))]
GetCurrentDealers { GetCurrentDealers {
limit: Option<u32>, limit: Option<u32>,
start_after: Option<String>, start_after: Option<String>,
}, },
#[cfg_attr(feature = "schema", returns(PagedDealerResponse))]
GetPastDealers { GetPastDealers {
limit: Option<u32>, limit: Option<u32>,
start_after: Option<String>, start_after: Option<String>,
}, },
#[cfg_attr(feature = "schema", returns(PagedDealingsResponse))]
GetDealing { GetDealing {
idx: u64, idx: u64,
limit: Option<u32>, limit: Option<u32>,
start_after: Option<String>, start_after: Option<String>,
}, },
#[cfg_attr(feature = "schema", returns(PagedVKSharesResponse))]
GetVerificationKeys { GetVerificationKeys {
epoch_id: EpochId, epoch_id: EpochId,
limit: Option<u32>, limit: Option<u32>,
@@ -93,5 +73,6 @@ pub enum QueryMsg {
}, },
} }
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {} pub struct MigrateMsg {}
@@ -1,7 +1,8 @@
// Copyright 2022-2023 - 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 cosmwasm_schema::cw_serde; use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::str::FromStr; use std::str::FromStr;
@@ -17,14 +18,15 @@ pub type EpochId = u64;
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential // 2 public attributes, 2 private attributes, 1 fixed for coconut credential
pub const TOTAL_DEALINGS: usize = 2 + 2 + 1; pub const TOTAL_DEALINGS: usize = 2 + 2 + 1;
#[cw_serde] #[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub struct InitialReplacementData { pub struct InitialReplacementData {
pub initial_dealers: Vec<Addr>, pub initial_dealers: Vec<Addr>,
pub initial_height: u64, pub initial_height: u64,
} }
#[cw_serde] #[derive(
#[derive(Copy)] Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, JsonSchema,
)]
pub struct TimeConfiguration { pub struct TimeConfiguration {
// The time sign-up is open for dealers to join // The time sign-up is open for dealers to join
pub public_key_submission_time_secs: u64, pub public_key_submission_time_secs: u64,
@@ -73,8 +75,8 @@ impl Default for TimeConfiguration {
} }
} }
#[cw_serde] #[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[derive(Copy, Default)] #[serde(rename_all = "snake_case")]
pub struct Epoch { pub struct Epoch {
pub state: EpochState, pub state: EpochState,
pub epoch_id: EpochId, pub epoch_id: EpochId,
@@ -153,8 +155,8 @@ impl Epoch {
// 8. InProgress -> all receivers have all their secrets derived and all is good // 8. InProgress -> all receivers have all their secrets derived and all is good
// //
// Note: It's important that the variant ordering is not changed otherwise it would mess up the derived `PartialOrd` // Note: It's important that the variant ordering is not changed otherwise it would mess up the derived `PartialOrd`
#[cw_serde] #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[derive(Copy)] #[serde(rename_all = "snake_case")]
pub enum EpochState { pub enum EpochState {
PublicKeySubmission { resharing: bool }, PublicKeySubmission { resharing: bool },
DealingExchange { resharing: bool }, DealingExchange { resharing: bool },
@@ -3,14 +3,14 @@
use crate::msg::ExecuteMsg; use crate::msg::ExecuteMsg;
use crate::types::{EpochId, NodeIndex}; use crate::types::{EpochId, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_binary, to_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg}; use cosmwasm_std::{from_binary, to_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
use cw_utils::Expiration; use cw_utils::Expiration;
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg; use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
use serde::{Deserialize, Serialize};
pub type VerificationKeyShare = String; pub type VerificationKeyShare = String;
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ContractVKShare { pub struct ContractVKShare {
pub share: VerificationKeyShare, pub share: VerificationKeyShare,
pub announce_address: String, pub announce_address: String,
@@ -20,12 +20,11 @@ pub struct ContractVKShare {
pub verified: bool, pub verified: bool,
} }
#[cw_serde] #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct PagedVKSharesResponse { pub struct PagedVKSharesResponse {
pub shares: Vec<ContractVKShare>, pub shares: Vec<ContractVKShare>,
pub per_page: usize, pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>, pub start_next_after: Option<Addr>,
} }
@@ -10,10 +10,9 @@ repository = { workspace = true }
[dependencies] [dependencies]
bs58 = "0.4.0" bs58 = "0.4.0"
cosmwasm-std = { workspace = true } cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
schemars = "0.8" schemars = "0.8"
serde = { workspace = true, features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
thiserror = { workspace = true } thiserror = "1"
[dev-dependencies] [dev-dependencies]
serde_json = { workspace = true } serde_json = "1.0.0"

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