Merge branch 'develop' into feature-219-explorer-small-changes

This commit is contained in:
gala1234
2022-05-26 12:05:28 +02:00
42 changed files with 1074 additions and 618 deletions
Generated
+72 -67
View File
@@ -664,8 +664,8 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc347c19eb5b940f396ac155822caee6662f850d97306890ac3773ed76c90c5a"
dependencies = [
"prost",
"prost-types",
"prost 0.9.0",
"prost-types 0.9.0",
"tonic",
"tonic-build",
"tracing-core",
@@ -683,7 +683,7 @@ dependencies = [
"futures",
"hdrhistogram",
"humantime 2.1.0",
"prost-types",
"prost-types 0.9.0",
"serde",
"serde_json",
"thread_local",
@@ -761,60 +761,29 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cosmos-sdk-proto"
version = "0.9.0"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0254ffee603f5301d6a66963d9e1cc5091479c22e2e925e1f7689c8027a0828"
checksum = "f109fe191e73898d74b8020c50f86018364ad19bc30318aa074616c382b52856"
dependencies = [
"prost",
"prost-types",
"tendermint-proto",
]
[[package]]
name = "cosmos-sdk-proto"
version = "0.9.0"
source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496"
dependencies = [
"prost",
"prost-types",
"prost 0.10.3",
"prost-types 0.10.1",
"tendermint-proto",
]
[[package]]
name = "cosmrs"
version = "0.4.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "505ea048e9ff2f906d6b954f9f8157d903ca468bfb301d906b40ecc25ba6838d"
checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533"
dependencies = [
"bip32",
"cosmos-sdk-proto 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cosmos-sdk-proto",
"ecdsa 0.13.4",
"eyre",
"getrandom 0.2.6",
"k256 0.10.4",
"prost",
"prost-types",
"rand_core 0.6.3",
"serde",
"serde_json",
"subtle-encoding",
"tendermint",
"thiserror",
]
[[package]]
name = "cosmrs"
version = "0.4.1"
source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496"
dependencies = [
"bip32",
"cosmos-sdk-proto 0.9.0 (git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation)",
"ecdsa 0.13.4",
"eyre",
"getrandom 0.2.6",
"k256 0.10.4",
"prost",
"prost-types",
"prost 0.10.3",
"prost-types 0.10.1",
"rand_core 0.6.3",
"serde",
"serde_json",
@@ -938,7 +907,7 @@ version = "0.1.0"
dependencies = [
"bls12_381 0.5.0",
"coconut-interface",
"cosmrs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cosmrs",
"crypto",
"network-defaults",
"rand 0.7.3",
@@ -1181,6 +1150,7 @@ dependencies = [
"byteorder",
"digest 0.9.0",
"rand_core 0.5.1",
"serde",
"subtle 2.4.1",
"zeroize",
]
@@ -2384,11 +2354,12 @@ dependencies = [
"headers",
"http",
"hyper",
"hyper-tls",
"native-tls",
"hyper-rustls",
"rustls-native-certs",
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tower-service",
"webpki",
]
[[package]]
@@ -3937,7 +3908,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
dependencies = [
"bytes",
"prost-derive",
"prost-derive 0.9.0",
]
[[package]]
name = "prost"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f"
dependencies = [
"bytes",
"prost-derive 0.10.1",
]
[[package]]
@@ -3953,8 +3934,8 @@ dependencies = [
"log",
"multimap",
"petgraph",
"prost",
"prost-types",
"prost 0.9.0",
"prost-types 0.9.0",
"regex",
"tempfile",
"which",
@@ -3973,6 +3954,19 @@ dependencies = [
"syn",
]
[[package]]
name = "prost-derive"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "prost-types"
version = "0.9.0"
@@ -3980,7 +3974,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
dependencies = [
"bytes",
"prost",
"prost 0.9.0",
]
[[package]]
name = "prost-types"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68"
dependencies = [
"bytes",
"prost 0.10.3",
]
[[package]]
@@ -5464,9 +5468,9 @@ dependencies = [
[[package]]
name = "tendermint"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9ef686b8ecd36550d0581f0989c9d8607090b23005df479d8e6ba348b5800b9"
checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949"
dependencies = [
"async-trait",
"bytes",
@@ -5477,8 +5481,8 @@ dependencies = [
"k256 0.10.4",
"num-traits",
"once_cell",
"prost",
"prost-types",
"prost 0.10.3",
"prost-types 0.10.1",
"ripemd160",
"serde",
"serde_bytes",
@@ -5495,9 +5499,9 @@ dependencies = [
[[package]]
name = "tendermint-config"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc127f82e7a8c7337c1f293d65a821380d3407c4c44bc979ef4da0ebc3b31ed"
checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd"
dependencies = [
"flex-error",
"serde",
@@ -5509,16 +5513,16 @@ dependencies = [
[[package]]
name = "tendermint-proto"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e0a0251fd81bed7420bea0f4d91c2a58f6c9fa34d5b2f70bed0ba8890de5aa"
checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874"
dependencies = [
"bytes",
"flex-error",
"num-derive",
"num-traits",
"prost",
"prost-types",
"prost 0.10.3",
"prost-types 0.10.1",
"serde",
"serde_bytes",
"subtle-encoding",
@@ -5527,9 +5531,9 @@ dependencies = [
[[package]]
name = "tendermint-rpc"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626c493e9ced3a9de37583bbd929f4b6dbd49aa513ab9b4776aa44a9332ce9b5"
checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6"
dependencies = [
"async-trait",
"bytes",
@@ -5856,8 +5860,8 @@ dependencies = [
"hyper-timeout",
"percent-encoding",
"pin-project",
"prost",
"prost-derive",
"prost 0.9.0",
"prost-derive 0.9.0",
"tokio",
"tokio-stream",
"tokio-util 0.6.9",
@@ -6200,7 +6204,7 @@ dependencies = [
"coconut-interface",
"colored",
"config",
"cosmrs 0.4.1 (git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation)",
"cosmrs",
"cosmwasm-std",
"flate2",
"futures",
@@ -6208,7 +6212,7 @@ dependencies = [
"log",
"mixnet-contract-common",
"network-defaults",
"prost",
"prost 0.10.3",
"reqwest",
"serde",
"serde_json",
@@ -6628,6 +6632,7 @@ checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
dependencies = [
"curve25519-dalek",
"rand_core 0.5.1",
"serde",
"zeroize",
]
@@ -32,8 +32,8 @@ validator-api-requests = { path = "../../../validator-api/validator-api-requests
async-trait = { version = "0.1.51", optional = true }
bip39 = { version = "1", features = ["rand"], optional = true }
config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/nymtech/cosmos-rust", branch = "bugfix/account-id-length-validation", features = ["rpc", "bip32", "cosmwasm"], optional = true}
prost = { version = "0.9", default-features = false, optional = true }
cosmrs = { version = "0.7.0", features = ["rpc", "bip32", "cosmwasm"], optional = true}
prost = { version = "0.10", default-features = false, optional = true }
flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5", optional = true }
itertools = { version = "0.10", optional = true }
@@ -483,6 +483,9 @@ pub trait CosmWasmClient: rpc::Client {
// deprecation warning is due to the fact the protobuf files built were based on cosmos-sdk 0.44,
// where they prefer using tx_bytes directly. However, in 0.42, which we are using at the time
// of writing this, the option does not work
// TODO: we should really stop using the `tx` argument here and use `tx_bytes` exlusively,
// however, at the time of writing this update, while our QA and mainnet networks do support it,
// sandbox is still running old version of wasmd that lacks support for `tx_bytes`
#[allow(deprecated)]
async fn query_simulate(
&self,
@@ -68,6 +68,7 @@ pub(crate) fn create_pagination(key: Vec<u8>) -> PageRequest {
offset: 0,
limit: 0,
count_total: false,
reverse: false,
}
}
@@ -1,9 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::convert::TryInto;
use std::time::Duration;
use crate::nymd::cosmwasm_client::client::CosmWasmClient;
use crate::nymd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
use crate::nymd::cosmwasm_client::logs::{self, parse_raw_logs};
use crate::nymd::cosmwasm_client::types::*;
use crate::nymd::error::NymdError;
use crate::nymd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
use crate::nymd::wallet::DirectSecp256k1HdWallet;
use crate::nymd::{GasPrice, TxResponse};
use async_trait::async_trait;
use cosmrs::bank::MsgSend;
use cosmrs::distribution::MsgWithdrawDelegatorReward;
@@ -17,28 +22,35 @@ use log::debug;
use serde::Serialize;
use sha2::Digest;
use sha2::Sha256;
use crate::nymd::cosmwasm_client::client::CosmWasmClient;
use crate::nymd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
use crate::nymd::cosmwasm_client::logs::{self, parse_raw_logs};
use crate::nymd::cosmwasm_client::types::*;
use crate::nymd::error::NymdError;
use crate::nymd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
use crate::nymd::wallet::DirectSecp256k1HdWallet;
use crate::nymd::{CosmosCoin, GasPrice, TxResponse};
// we need to have **a** valid secp256k1 signature for simulation purposes.
// it doesn't matter what it is as long as it parses correctly
const DUMMY_SECP256K1_SIGNATURE: &[u8] = &[
54, 167, 169, 61, 100, 173, 231, 87, 1, 113, 179, 49, 102, 141, 67, 22, 170, 153, 52, 88, 178,
159, 200, 11, 37, 138, 76, 221, 187, 70, 104, 123, 98, 216, 190, 249, 149, 81, 1, 158, 0, 220,
32, 147, 101, 60, 64, 77, 44, 83, 221, 119, 170, 124, 109, 177, 73, 116, 46, 57, 102, 181, 98,
91,
];
use std::convert::TryInto;
use std::time::Duration;
const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
fn empty_fee() -> tx::Fee {
tx::Fee {
amount: vec![],
gas_limit: Default::default(),
payer: None,
granter: None,
}
}
fn single_unspecified_signer_auth(
public_key: Option<tx::SignerPublicKey>,
sequence_number: tx::SequenceNumber,
) -> tx::AuthInfo {
tx::SignerInfo {
public_key,
mode_info: tx::ModeInfo::Single(tx::mode_info::Single {
mode: SignMode::Unspecified,
}),
sequence: sequence_number,
}
.auth_info(empty_fee())
}
#[async_trait]
pub trait SigningCosmWasmClient: CosmWasmClient {
fn signer(&self) -> &DirectSecp256k1HdWallet;
@@ -64,33 +76,21 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
let sequence_response = self.get_sequence(signer_address).await?;
let partial_tx = Tx {
body: tx::Body {
messages,
memo: memo.into(),
timeout_height: 0u32.into(),
extension_options: vec![],
non_critical_extension_options: vec![],
},
auth_info: tx::AuthInfo {
signer_infos: vec![tx::SignerInfo {
public_key,
mode_info: tx::ModeInfo::Single(tx::mode_info::Single {
mode: SignMode::Unspecified,
}),
sequence: sequence_response.sequence,
}],
fee: tx::Fee::from_amount_and_gas(
CosmosCoin {
denom: "".parse().unwrap(),
amount: 0u64.into(),
},
0,
),
},
signatures: vec![DUMMY_SECP256K1_SIGNATURE.try_into().unwrap()],
body: tx::Body::new(messages, memo, 0u32),
auth_info: single_unspecified_signer_auth(public_key, sequence_response.sequence),
signatures: vec![Vec::new()],
};
self.query_simulate(Some(partial_tx), Vec::new()).await
// for completion sake, once we're able to transition into using `tx_bytes`,
// we might want to use something like this instead:
// let tx_raw: tx::Raw = cosmrs::proto::cosmos::tx::v1beta1::TxRaw {
// body_bytes: partial_tx.body.into_bytes().unwrap(),
// auth_info_bytes: partial_tx.auth_info.into_bytes().unwrap(),
// signatures: partial_tx.signatures,
// }
// .into();
// self.query_simulate(None, tx_raw.to_bytes().unwrap()).await
}
async fn upload(
@@ -452,7 +452,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
let undelegate_msg = MsgUndelegate {
delegator_address: delegator_address.to_owned(),
validator_address: validator_address.to_owned(),
amount: Some(amount),
amount,
}
.to_any()
.map_err(|_| NymdError::SerializationError("MsgUndelegate".to_owned()))?;
@@ -489,7 +489,7 @@ impl TryFrom<ProtoContractCodeHistoryEntry> for ContractCodeHistoryEntry {
}
}
#[derive(Debug)]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct GasInfo {
/// GasWanted is the maximum units of work we allow this tx to perform.
pub gas_wanted: Gas,
@@ -21,9 +21,12 @@ pub enum NymdError {
#[error("There was an issue with bip32 - {0}")]
Bip32Error(#[from] bip32::Error),
#[error("There was an issue with bip32 - {0}")]
#[error("There was an issue with bip39 - {0}")]
Bip39Error(#[from] bip39::Error),
#[error("There was an issue on the cosmrs side - {0}")]
CosmrsError(#[from] cosmrs::Error),
#[error("Failed to derive account address")]
AccountDerivationError,
@@ -39,10 +42,10 @@ pub enum NymdError {
#[error("There was an issue with a tendermint RPC request - {0}")]
TendermintError(#[from] TendermintRpcError),
#[error("There was an issue when attempting to serialize data")]
#[error("There was an issue when attempting to serialize data ({0})")]
SerializationError(String),
#[error("There was an issue when attempting to deserialize data")]
#[error("There was an issue when attempting to deserialize data ({0})")]
DeserializationError(String),
#[error("There was an issue when attempting to encode our protobuf data - {0}")]
@@ -107,7 +107,6 @@ mod tests {
assert!(".25upunk".parse::<GasPrice>().is_err());
assert!("0.025 upunk".parse::<GasPrice>().is_err());
assert!("0.025UPUNK".parse::<GasPrice>().is_err());
}
#[test]
@@ -1,195 +0,0 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nymd::GasPrice;
use cosmrs::tx::{Fee, Gas};
use cosmrs::Coin;
use serde::{Deserialize, Serialize};
use std::fmt;
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(
test,
ts(export, export_to = "../../../nym-wallet/src/types/rust/operation.ts")
)]
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum Operation {
Upload,
Init,
Migrate,
ChangeAdmin,
Send,
BondMixnode,
BondMixnodeOnBehalf,
UnbondMixnode,
UnbondMixnodeOnBehalf,
UpdateMixnodeConfig,
DelegateToMixnode,
DelegateToMixnodeOnBehalf,
UndelegateFromMixnode,
UndelegateFromMixnodeOnBehalf,
BondGateway,
BondGatewayOnBehalf,
UnbondGateway,
UnbondGatewayOnBehalf,
UpdateContractSettings,
BeginMixnodeRewarding,
FinishMixnodeRewarding,
TrackUnbondGateway,
TrackUnbondMixnode,
WithdrawVestedCoins,
TrackUndelegation,
CreatePeriodicVestingAccount,
AdvanceCurrentInterval,
AdvanceCurrentEpoch,
WriteRewardedSet,
ClearRewardedSet,
UpdateMixnetAddress,
CheckpointMixnodes,
ReconcileDelegations,
}
pub(crate) fn calculate_fee(gas_price: &GasPrice, gas_limit: Gas) -> Coin {
gas_price * gas_limit
}
impl fmt::Display for Operation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Operation::Upload => f.write_str("Upload"),
Operation::Init => f.write_str("Init"),
Operation::Migrate => f.write_str("Migrate"),
Operation::ChangeAdmin => f.write_str("ChangeAdmin"),
Operation::Send => f.write_str("Send"),
Operation::BondMixnode => f.write_str("BondMixnode"),
Operation::BondMixnodeOnBehalf => f.write_str("BondMixnodeOnBehalf"),
Operation::UnbondMixnode => f.write_str("UnbondMixnode"),
Operation::UpdateMixnodeConfig => f.write_str("UpdateMixnodeConfig"),
Operation::UnbondMixnodeOnBehalf => f.write_str("UnbondMixnodeOnBehalf"),
Operation::BondGateway => f.write_str("BondGateway"),
Operation::BondGatewayOnBehalf => f.write_str("BondGatewayOnBehalf"),
Operation::UnbondGateway => f.write_str("UnbondGateway"),
Operation::UnbondGatewayOnBehalf => f.write_str("UnbondGatewayOnBehalf"),
Operation::DelegateToMixnode => f.write_str("DelegateToMixnode"),
Operation::DelegateToMixnodeOnBehalf => f.write_str("DelegateToMixnodeOnBehalf"),
Operation::UndelegateFromMixnode => f.write_str("UndelegateFromMixnode"),
Operation::UndelegateFromMixnodeOnBehalf => {
f.write_str("UndelegateFromMixnodeOnBehalf")
}
Operation::UpdateContractSettings => f.write_str("UpdateContractSettings"),
Operation::BeginMixnodeRewarding => f.write_str("BeginMixnodeRewarding"),
Operation::FinishMixnodeRewarding => f.write_str("FinishMixnodeRewarding"),
Operation::TrackUnbondGateway => f.write_str("TrackUnbondGateway"),
Operation::TrackUnbondMixnode => f.write_str("TrackUnbondMixnode"),
Operation::WithdrawVestedCoins => f.write_str("WithdrawVestedCoins"),
Operation::TrackUndelegation => f.write_str("TrackUndelegation"),
Operation::CreatePeriodicVestingAccount => f.write_str("CreatePeriodicVestingAccount"),
Operation::AdvanceCurrentInterval => f.write_str("AdvanceCurrentInterval"),
Operation::WriteRewardedSet => f.write_str("WriteRewardedSet"),
Operation::ClearRewardedSet => f.write_str("ClearRewardedSet"),
Operation::UpdateMixnetAddress => f.write_str("UpdateMixnetAddress"),
Operation::CheckpointMixnodes => f.write_str("CheckpointMixnodes"),
Operation::ReconcileDelegations => f.write_str("ReconcileDelegations"),
Operation::AdvanceCurrentEpoch => f.write_str("AdvanceCurrentEpoch"),
}
}
}
impl Operation {
// TODO: some value tweaking
pub fn default_gas_limit(&self) -> Gas {
match self {
Operation::Upload => 3_000_000u64.into(),
Operation::Init => 500_000u64.into(),
Operation::Migrate => 200_000u64.into(),
Operation::ChangeAdmin => 80_000u64.into(),
Operation::Send => 80_000u64.into(),
Operation::BondMixnode => 175_000u64.into(),
Operation::BondMixnodeOnBehalf => 200_000u64.into(),
Operation::UnbondMixnode => 175_000u64.into(),
Operation::UnbondMixnodeOnBehalf => 175_000u64.into(),
Operation::UpdateMixnodeConfig => 175_000u64.into(),
Operation::DelegateToMixnode => 175_000u64.into(),
Operation::DelegateToMixnodeOnBehalf => 175_000u64.into(),
Operation::UndelegateFromMixnode => 175_000u64.into(),
Operation::UndelegateFromMixnodeOnBehalf => 175_000u64.into(),
Operation::BondGateway => 175_000u64.into(),
Operation::BondGatewayOnBehalf => 200_000u64.into(),
Operation::UnbondGateway => 175_000u64.into(),
Operation::UnbondGatewayOnBehalf => 200_000u64.into(),
Operation::UpdateContractSettings => 175_000u64.into(),
Operation::BeginMixnodeRewarding => 175_000u64.into(),
Operation::FinishMixnodeRewarding => 175_000u64.into(),
Operation::TrackUnbondGateway => 175_000u64.into(),
Operation::TrackUnbondMixnode => 175_000u64.into(),
Operation::WithdrawVestedCoins => 175_000u64.into(),
Operation::TrackUndelegation => 175_000u64.into(),
Operation::CreatePeriodicVestingAccount => 175_000u64.into(),
Operation::AdvanceCurrentInterval => 175_000u64.into(),
Operation::WriteRewardedSet => 175_000u64.into(),
Operation::ClearRewardedSet => 175_000u64.into(),
Operation::UpdateMixnetAddress => 80_000u64.into(),
Operation::CheckpointMixnodes => 175_000u64.into(),
Operation::ReconcileDelegations => 500_000u64.into(),
Operation::AdvanceCurrentEpoch => 175_000u64.into(),
}
}
pub(crate) fn determine_custom_fee(gas_price: &GasPrice, gas_limit: Gas) -> Fee {
// we need to know 2 of the following 3 parameters (the third one is being implicit) in order to construct Fee:
// (source: https://docs.cosmos.network/v0.42/basics/gas-fees.html)
// - gas price
// - gas limit
// - fees
let fee = calculate_fee(gas_price, gas_limit);
Fee::from_amount_and_gas(fee, gas_limit)
}
pub fn default_fee(&self, gas_price: &GasPrice) -> Fee {
Self::determine_custom_fee(gas_price, self.default_gas_limit())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn calculating_fee() {
let expected = Coin {
denom: "upunk".parse().unwrap(),
amount: 1000u64.into(),
};
let gas_price = "1upunk".parse().unwrap();
let gas_limit = 1000u64.into();
assert_eq!(expected, calculate_fee(&gas_price, gas_limit));
let expected = Coin {
denom: "upunk".parse().unwrap(),
amount: 50u64.into(),
};
let gas_price = "0.05upunk".parse().unwrap();
let gas_limit = 1000u64.into();
assert_eq!(expected, calculate_fee(&gas_price, gas_limit));
let expected = Coin {
denom: "upunk".parse().unwrap(),
amount: 100000u64.into(),
};
let gas_price = "100upunk".parse().unwrap();
let gas_limit = 1000u64.into();
assert_eq!(expected, calculate_fee(&gas_price, gas_limit))
}
}
@@ -2,15 +2,15 @@
// SPDX-License-Identifier: Apache-2.0
use cosmrs::tx;
use serde::{Deserialize, Serialize};
pub mod gas_price;
pub mod helpers;
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: f32 = 1.3;
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Fee {
Manual(tx::Fee),
Manual(#[serde(with = "sealed::TxFee")] tx::Fee),
Auto(Option<f32>),
}
@@ -31,3 +31,91 @@ impl Default for Fee {
Fee::Auto(Some(DEFAULT_SIMULATED_GAS_MULTIPLIER))
}
}
// 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, Decimal as CosmosDecimal, Denom as CosmosDenom};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
fn cosmos_denom_inner_getter(val: &CosmosDenom) -> String {
val.as_ref().to_string()
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDenom")]
struct Denom(#[serde(getter = "cosmos_denom_inner_getter")] String);
impl From<Denom> for CosmosDenom {
fn from(val: Denom) -> Self {
val.0.parse().unwrap()
}
}
fn cosmos_decimal_inner_getter(val: &CosmosDecimal) -> u64 {
// haha, this code is so disgusting. I'll make a PR on cosmrs to slightly alleviate those issues...
// note: unwrap here is fine as the to_string is just returning a stringified u64 which, well, is a valid u64
val.to_string().parse().unwrap()
}
// at the time of writing it the current cosmrs' Decimal is extremely limited...
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDecimal")]
struct Decimal(#[serde(getter = "cosmos_decimal_inner_getter")] u64);
impl From<Decimal> for CosmosDecimal {
fn from(val: Decimal) -> Self {
val.0.into()
}
}
#[derive(Serialize, Deserialize, Clone)]
struct Coin {
#[serde(with = "Denom")]
denom: CosmosDenom,
#[serde(with = "Decimal")]
amount: CosmosDecimal,
}
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>,
}
}
@@ -4,15 +4,16 @@
use crate::nymd::cosmwasm_client::signing_client;
use crate::nymd::cosmwasm_client::types::{
Account, ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions,
InstantiateResult, MigrateResult, SequenceResponse, UploadResult,
InstantiateResult, MigrateResult, SequenceResponse, SimulateResponse, UploadResult,
};
use crate::nymd::error::NymdError;
use crate::nymd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
use crate::nymd::wallet::DirectSecp256k1HdWallet;
use cosmrs::rpc::Error as TendermintRpcError;
use cosmrs::rpc::HttpClientUrl;
use cosmrs::tx::Msg;
use cosmwasm_std::{Coin, Uint128};
pub use fee::gas_price::GasPrice;
use fee::helpers::Operation;
use mixnet_contract_common::mixnode::DelegationEvent;
use mixnet_contract_common::{
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayOwnershipResponse,
@@ -22,14 +23,13 @@ use mixnet_contract_common::{
PagedRewardedSetResponse, QueryMsg, RewardedSetUpdateDetails,
};
use serde::Serialize;
use std::collections::HashMap;
use std::convert::TryInto;
pub use crate::nymd::cosmwasm_client::client::CosmWasmClient;
pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient;
pub use crate::nymd::fee::Fee;
use crate::nymd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
pub use cosmrs::bank::MsgSend;
use cosmrs::cosmwasm;
pub use cosmrs::rpc::endpoint::tx::Response as TxResponse;
pub use cosmrs::rpc::endpoint::validators::Response as ValidatorResponse;
pub use cosmrs::rpc::HttpClient as QueryNymdClient;
@@ -42,7 +42,7 @@ pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
pub use cosmrs::tendermint::Time as TendermintTime;
pub use cosmrs::tx::{self, Gas};
pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{AccountId, Decimal, Denom};
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
pub use signing_client::Client as SigningNymdClient;
pub use traits::{VestingQueryClient, VestingSigningClient};
@@ -59,7 +59,6 @@ pub struct NymdClient<C> {
vesting_contract_address: Option<AccountId>,
erc20_bridge_contract_address: Option<AccountId>,
client_address: Option<Vec<AccountId>>,
custom_gas_limits: HashMap<Operation, Gas>,
simulated_gas_multiplier: f32,
}
@@ -79,7 +78,6 @@ impl NymdClient<QueryNymdClient> {
vesting_contract_address,
erc20_bridge_contract_address,
client_address: None,
custom_gas_limits: HashMap::default(),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
})
}
@@ -113,7 +111,6 @@ impl NymdClient<SigningNymdClient> {
vesting_contract_address,
erc20_bridge_contract_address,
client_address: Some(client_address),
custom_gas_limits: HashMap::default(),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
})
}
@@ -146,7 +143,6 @@ impl NymdClient<SigningNymdClient> {
vesting_contract_address,
erc20_bridge_contract_address,
client_address: Some(client_address),
custom_gas_limits: HashMap::default(),
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
})
}
@@ -175,6 +171,24 @@ impl<C> NymdClient<C> {
self.simulated_gas_multiplier = multiplier;
}
pub fn wrap_contract_execute_message<M>(
&self,
contract_address: &AccountId,
msg: &M,
funds: Vec<CosmosCoin>,
) -> Result<cosmwasm::MsgExecuteContract, NymdError>
where
C: SigningCosmWasmClient,
M: ?Sized + Serialize,
{
Ok(cosmwasm::MsgExecuteContract {
sender: self.address().clone(),
contract: contract_address.clone(),
msg: serde_json::to_vec(msg)?,
funds,
})
}
pub fn address(&self) -> &AccountId
where
C: SigningCosmWasmClient,
@@ -190,39 +204,6 @@ impl<C> NymdClient<C> {
self.client.gas_price()
}
pub fn set_custom_gas_limit(&mut self, operation: Operation, limit: Gas)
where
C: SigningCosmWasmClient + Sync,
{
self.custom_gas_limits.insert(operation, limit);
}
pub fn operation_fee(&self, operation: Operation) -> Fee
where
C: SigningCosmWasmClient + Sync,
{
if let Some(&gas_limit) = self.custom_gas_limits.get(&operation) {
Operation::determine_custom_fee(self.client.gas_price(), gas_limit).into()
} else {
Fee::Auto(Some(self.simulated_gas_multiplier))
}
}
pub fn repeated_operation_fee(&self, operation: Operation, count: u64) -> Fee
where
C: SigningCosmWasmClient + Sync,
{
if let Some(&gas_limit) = self.custom_gas_limits.get(&operation) {
Operation::determine_custom_fee(
self.client.gas_price(),
(gas_limit.value() * count).into(),
)
.into()
} else {
Fee::Auto(Some(self.simulated_gas_multiplier))
}
}
pub async fn account_sequence(&self) -> Result<SequenceResponse, NymdError>
where
C: SigningCosmWasmClient + Sync,
@@ -634,17 +615,39 @@ impl<C> NymdClient<C> {
.await
}
pub async fn simulate<I, M>(&self, messages: I) -> Result<SimulateResponse, NymdError>
where
C: SigningCosmWasmClient + Sync,
I: IntoIterator<Item = M> + Send,
M: Msg,
{
self.client
.simulate(
self.address(),
messages
.into_iter()
.map(|msg| msg.into_any())
.collect::<Result<Vec<_>, _>>()
.map_err(|_| {
NymdError::SerializationError("custom simulate messages".to_owned())
})?,
"simulating execution of transactions",
)
.await
}
/// Send funds from one address to another
pub async fn send(
&self,
recipient: &AccountId,
amount: Vec<CosmosCoin>,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<TxResponse, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::Send);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.send_tokens(self.address(), recipient, amount, fee, memo)
.await
@@ -655,11 +658,12 @@ impl<C> NymdClient<C> {
&self,
msgs: Vec<(AccountId, Vec<CosmosCoin>)>,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<TxResponse, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.repeated_operation_fee(Operation::Send, msgs.len() as u64);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.send_tokens_multiple(self.address(), msgs, fee, memo)
.await
@@ -703,11 +707,12 @@ impl<C> NymdClient<C> {
&self,
wasm_code: Vec<u8>,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<UploadResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::Upload);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.upload(self.address(), wasm_code, fee, memo)
.await
@@ -720,12 +725,13 @@ impl<C> NymdClient<C> {
label: String,
memo: impl Into<String> + Send + 'static,
options: Option<InstantiateOptions>,
fee: Option<Fee>,
) -> Result<InstantiateResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
M: ?Sized + Serialize + Sync,
{
let fee = self.operation_fee(Operation::Init);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.instantiate(self.address(), code_id, msg, label, fee, memo, options)
.await
@@ -736,11 +742,12 @@ impl<C> NymdClient<C> {
contract_address: &AccountId,
new_admin: &AccountId,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<ChangeAdminResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::ChangeAdmin);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.update_admin(self.address(), contract_address, new_admin, fee, memo)
.await
@@ -750,11 +757,12 @@ impl<C> NymdClient<C> {
&self,
contract_address: &AccountId,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<ChangeAdminResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::ChangeAdmin);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.clear_admin(self.address(), contract_address, fee, memo)
.await
@@ -766,12 +774,13 @@ impl<C> NymdClient<C> {
code_id: ContractCodeId,
msg: &M,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<MigrateResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
M: ?Sized + Serialize + Sync,
{
let fee = self.operation_fee(Operation::Migrate);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.migrate(self.address(), contract_address, code_id, fee, msg, memo)
.await
@@ -783,11 +792,12 @@ impl<C> NymdClient<C> {
mixnode: MixNode,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::BondMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::BondMixnode {
mix_node: mixnode,
@@ -812,11 +822,12 @@ impl<C> NymdClient<C> {
owner: String,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::BondMixnodeOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::BondMixnodeOnBehalf {
mix_node: mixnode,
@@ -839,14 +850,12 @@ impl<C> NymdClient<C> {
pub async fn bond_multiple_mixnodes_on_behalf(
&self,
mixnode_bonds_with_sigs: Vec<(MixNodeBond, String)>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.repeated_operation_fee(
Operation::BondMixnodeOnBehalf,
mixnode_bonds_with_sigs.len() as u64,
);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let reqs: Vec<(ExecuteMsg, Vec<CosmosCoin>)> = mixnode_bonds_with_sigs
.into_iter()
@@ -874,11 +883,11 @@ impl<C> NymdClient<C> {
}
/// Unbond a mixnode, removing it from the network and reclaiming staked coins
pub async fn unbond_mixnode(&self) -> Result<ExecuteResult, NymdError>
pub async fn unbond_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UnbondMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UnbondMixnode {};
self.client
@@ -894,11 +903,15 @@ impl<C> NymdClient<C> {
}
/// Unbond a mixnode on behalf of the owner, removing it from the network and reclaiming staked coins
pub async fn unbond_mixnode_on_behalf(&self, owner: String) -> Result<ExecuteResult, NymdError>
pub async fn unbond_mixnode_on_behalf(
&self,
owner: String,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UnbondMixnodeOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UnbondMixnodeOnBehalf { owner };
self.client
@@ -917,11 +930,12 @@ impl<C> NymdClient<C> {
pub async fn update_mixnode_config(
&self,
profit_margin_percent: u8,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UpdateMixnodeConfig);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
@@ -943,11 +957,12 @@ impl<C> NymdClient<C> {
&self,
mix_identity: &str,
amount: &Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::DelegateToMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::DelegateToMixnode {
mix_identity: mix_identity.to_string(),
@@ -971,11 +986,12 @@ impl<C> NymdClient<C> {
mix_identity: &str,
delegate: &str,
amount: &Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::DelegateToMixnodeOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::DelegateToMixnodeOnBehalf {
mix_identity: mix_identity.to_string(),
@@ -997,14 +1013,12 @@ impl<C> NymdClient<C> {
pub async fn delegate_to_multiple_mixnodes_on_behalf(
&self,
mixnode_delegations: Vec<Delegation>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.repeated_operation_fee(
Operation::DelegateToMixnodeOnBehalf,
mixnode_delegations.len() as u64,
);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let reqs: Vec<(ExecuteMsg, Vec<CosmosCoin>)> = mixnode_delegations
.into_iter()
@@ -1034,11 +1048,12 @@ impl<C> NymdClient<C> {
pub async fn remove_mixnode_delegation(
&self,
mix_identity: &str,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UndelegateFromMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UndelegateFromMixnode {
mix_identity: mix_identity.to_string(),
@@ -1060,11 +1075,12 @@ impl<C> NymdClient<C> {
&self,
mix_identity: &str,
delegate: &str,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UndelegateFromMixnodeOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UndelegateFromMixnodeOnBehalf {
mix_identity: mix_identity.to_string(),
@@ -1088,11 +1104,12 @@ impl<C> NymdClient<C> {
gateway: Gateway,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::BondGateway);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::BondGateway {
gateway,
@@ -1117,11 +1134,12 @@ impl<C> NymdClient<C> {
owner: String,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::BondGatewayOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::BondGatewayOnBehalf {
gateway,
@@ -1144,14 +1162,12 @@ impl<C> NymdClient<C> {
pub async fn bond_multiple_gateways_on_behalf(
&self,
gateway_bonds_with_sigs: Vec<(GatewayBond, String)>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.repeated_operation_fee(
Operation::BondGatewayOnBehalf,
gateway_bonds_with_sigs.len() as u64,
);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let reqs: Vec<(ExecuteMsg, Vec<CosmosCoin>)> = gateway_bonds_with_sigs
.into_iter()
@@ -1179,11 +1195,11 @@ impl<C> NymdClient<C> {
}
/// Unbond a gateway, removing it from the network and reclaiming staked coins
pub async fn unbond_gateway(&self) -> Result<ExecuteResult, NymdError>
pub async fn unbond_gateway(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UnbondGateway);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UnbondGateway {};
self.client
@@ -1200,11 +1216,15 @@ impl<C> NymdClient<C> {
/// Unbond a gateway on behalf of the owner, removing it from the
/// network and reclaiming staked coins
pub async fn unbond_gateway_on_behalf(&self, owner: String) -> Result<ExecuteResult, NymdError>
pub async fn unbond_gateway_on_behalf(
&self,
owner: String,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UnbondGatewayOnBehalf);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UnbondGatewayOnBehalf { owner };
self.client
@@ -1222,11 +1242,12 @@ impl<C> NymdClient<C> {
pub async fn update_contract_settings(
&self,
new_params: ContractStateParams,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::UpdateContractSettings);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::UpdateContractStateParams(new_params);
self.client
@@ -1241,11 +1262,11 @@ impl<C> NymdClient<C> {
.await
}
pub async fn advance_current_epoch(&self) -> Result<ExecuteResult, NymdError>
pub async fn advance_current_epoch(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::AdvanceCurrentEpoch);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::AdvanceCurrentEpoch {};
self.client
@@ -1260,11 +1281,11 @@ impl<C> NymdClient<C> {
.await
}
pub async fn reconcile_delegations(&self) -> Result<ExecuteResult, NymdError>
pub async fn reconcile_delegations(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::ReconcileDelegations);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::ReconcileDelegations {};
self.client
@@ -1279,11 +1300,11 @@ impl<C> NymdClient<C> {
.await
}
pub async fn checkpoint_mixnodes(&self) -> Result<ExecuteResult, NymdError>
pub async fn checkpoint_mixnodes(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::CheckpointMixnodes);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::CheckpointMixnodes {};
self.client
@@ -1302,11 +1323,12 @@ impl<C> NymdClient<C> {
&self,
rewarded_set: Vec<IdentityKey>,
expected_active_set_size: u32,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = self.operation_fee(Operation::WriteRewardedSet);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = ExecuteMsg::WriteRewardedSet {
rewarded_set,
@@ -4,8 +4,7 @@
pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient;
use crate::nymd::cosmwasm_client::types::ExecuteResult;
use crate::nymd::error::NymdError;
use crate::nymd::fee::helpers::Operation;
use crate::nymd::{cosmwasm_coin_to_cosmos_coin, NymdClient};
use crate::nymd::{cosmwasm_coin_to_cosmos_coin, Fee, NymdClient};
use async_trait::async_trait;
use cosmwasm_std::Coin;
use mixnet_contract_common::{Gateway, IdentityKey, IdentityKeyRef, MixNode};
@@ -16,23 +15,30 @@ pub trait VestingSigningClient {
async fn vesting_update_mixnode_config(
&self,
profix_margin_percent: u8,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn update_mixnet_address(&self, address: &str) -> Result<ExecuteResult, NymdError>;
async fn update_mixnet_address(
&self,
address: &str,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_bond_gateway(
&self,
gateway: Gateway,
owner_signature: &str,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_unbond_gateway(&self) -> Result<ExecuteResult, NymdError>;
async fn vesting_unbond_gateway(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>;
async fn vesting_track_unbond_gateway(
&self,
owner: &str,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_bond_mixnode(
@@ -40,33 +46,42 @@ pub trait VestingSigningClient {
mix_node: MixNode,
owner_signature: &str,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_unbond_mixnode(&self) -> Result<ExecuteResult, NymdError>;
async fn vesting_unbond_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError>;
async fn vesting_track_unbond_mixnode(
&self,
owner: &str,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn withdraw_vested_coins(&self, amount: Coin) -> Result<ExecuteResult, NymdError>;
async fn withdraw_vested_coins(
&self,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_track_undelegation(
&self,
address: &str,
mix_identity: IdentityKey,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_delegate_to_mixnode<'a>(
&self,
mix_identity: IdentityKeyRef<'a>,
amount: &Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn vesting_undelegate_from_mixnode<'a>(
&self,
mix_identity: IdentityKeyRef<'a>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
async fn create_periodic_vesting_account(
@@ -75,18 +90,62 @@ pub trait VestingSigningClient {
staking_address: Option<String>,
vesting_spec: Option<VestingSpecification>,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError>;
}
#[async_trait]
impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient<C> {
async fn vesting_update_mixnode_config(
&self,
profit_margin_percent: u8,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
};
self.client
.execute(
self.address(),
self.vesting_contract_address()?,
&req,
fee,
"VestingContract::UpdateMixnetConfig",
vec![],
)
.await
}
async fn update_mixnet_address(
&self,
address: &str,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::UpdateMixnetAddress {
address: address.to_string(),
};
self.client
.execute(
self.address(),
self.vesting_contract_address()?,
&req,
fee,
"VestingContract::UpdateMixnetAddress",
vec![],
)
.await
}
async fn vesting_bond_gateway(
&self,
gateway: Gateway,
owner_signature: &str,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::BondGateway);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::BondGateway {
gateway,
owner_signature: owner_signature.to_string(),
@@ -104,8 +163,8 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
.await
}
async fn vesting_unbond_gateway(&self) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::UnbondGateway);
async fn vesting_unbond_gateway(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError> {
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::UnbondGateway {};
self.client
.execute(
@@ -123,8 +182,9 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
&self,
owner: &str,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::TrackUnbondGateway);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::TrackUnbondGateway {
owner: owner.to_string(),
amount,
@@ -146,8 +206,9 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
mix_node: MixNode,
owner_signature: &str,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::BondMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::BondMixnode {
mix_node,
owner_signature: owner_signature.to_string(),
@@ -165,8 +226,8 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
.await
}
async fn vesting_unbond_mixnode(&self) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::UnbondMixnode);
async fn vesting_unbond_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NymdError> {
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::UnbondMixnode {};
self.client
.execute(
@@ -184,8 +245,9 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
&self,
owner: &str,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::TrackUnbondMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::TrackUnbondMixnode {
owner: owner.to_string(),
amount,
@@ -201,9 +263,12 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
)
.await
}
async fn withdraw_vested_coins(&self, amount: Coin) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::WithdrawVestedCoins);
async fn withdraw_vested_coins(
&self,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::WithdrawVestedCoins { amount };
self.client
.execute(
@@ -216,14 +281,14 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
)
.await
}
async fn vesting_track_undelegation(
&self,
address: &str,
mix_identity: IdentityKey,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::TrackUndelegation);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::TrackUndelegation {
owner: address.to_string(),
mix_identity,
@@ -244,8 +309,9 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
&self,
mix_identity: IdentityKeyRef<'a>,
amount: &Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::DelegateToMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::DelegateToMixnode {
mix_identity: mix_identity.into(),
amount: amount.clone(),
@@ -261,11 +327,13 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
)
.await
}
async fn vesting_undelegate_from_mixnode<'a>(
&self,
mix_identity: IdentityKeyRef<'a>,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::UndelegateFromMixnode);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::UndelegateFromMixnode {
mix_identity: mix_identity.into(),
};
@@ -280,14 +348,16 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
)
.await
}
async fn create_periodic_vesting_account(
&self,
owner_address: &str,
staking_address: Option<String>,
vesting_spec: Option<VestingSpecification>,
amount: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::CreatePeriodicVestingAccount);
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
let req = VestingExecuteMsg::CreateAccount {
owner_address: owner_address.to_string(),
staking_address,
@@ -304,41 +374,4 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
)
.await
}
async fn update_mixnet_address(&self, address: &str) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::UpdateMixnetAddress);
let req = VestingExecuteMsg::UpdateMixnetAddress {
address: address.to_string(),
};
self.client
.execute(
self.address(),
self.vesting_contract_address()?,
&req,
fee,
"VestingContract::UpdateMixnetAddress",
vec![],
)
.await
}
async fn vesting_update_mixnode_config(
&self,
profit_margin_percent: u8,
) -> Result<ExecuteResult, NymdError> {
let fee = self.operation_fee(Operation::UpdateMixnodeConfig);
let req = VestingExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
};
self.client
.execute(
self.address(),
self.vesting_contract_address()?,
&req,
fee,
"VestingContract::UpdateMixnetConfig",
vec![],
)
.await
}
}
@@ -5,6 +5,8 @@ use cosmwasm_std::{Coin, Timestamp};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use messages::{ExecuteMsg, InitMsg, MigrateMsg, QueryMsg};
pub mod events;
pub mod messages;
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] }
cosmrs = { version = "0.4.1", optional = true }
cosmrs = { version = "0.7.0", optional = true }
thiserror = "1.0"
url = "2.2"
+24 -22
View File
@@ -828,8 +828,9 @@ dependencies = [
[[package]]
name = "cosmos-sdk-proto"
version = "0.9.0"
source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f109fe191e73898d74b8020c50f86018364ad19bc30318aa074616c382b52856"
dependencies = [
"prost",
"prost-types",
@@ -838,8 +839,9 @@ dependencies = [
[[package]]
name = "cosmrs"
version = "0.4.1"
source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533"
dependencies = [
"bip32",
"cosmos-sdk-proto",
@@ -2355,11 +2357,12 @@ dependencies = [
"headers",
"http",
"hyper",
"hyper-tls",
"native-tls",
"hyper-rustls",
"rustls-native-certs",
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tower-service",
"webpki",
]
[[package]]
@@ -3007,7 +3010,6 @@ dependencies = [
"coconut-interface",
"colored",
"config",
"cosmrs",
"cosmwasm-std",
"dirs",
"dotenv",
@@ -3642,9 +3644,9 @@ dependencies = [
[[package]]
name = "prost"
version = "0.9.0"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f"
dependencies = [
"bytes",
"prost-derive",
@@ -3652,9 +3654,9 @@ dependencies = [
[[package]]
name = "prost-derive"
version = "0.9.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
dependencies = [
"anyhow",
"itertools",
@@ -3665,9 +3667,9 @@ dependencies = [
[[package]]
name = "prost-types"
version = "0.9.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68"
dependencies = [
"bytes",
"prost",
@@ -5004,9 +5006,9 @@ dependencies = [
[[package]]
name = "tendermint"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9ef686b8ecd36550d0581f0989c9d8607090b23005df479d8e6ba348b5800b9"
checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949"
dependencies = [
"async-trait",
"bytes",
@@ -5035,9 +5037,9 @@ dependencies = [
[[package]]
name = "tendermint-config"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc127f82e7a8c7337c1f293d65a821380d3407c4c44bc979ef4da0ebc3b31ed"
checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd"
dependencies = [
"flex-error",
"serde",
@@ -5049,9 +5051,9 @@ dependencies = [
[[package]]
name = "tendermint-proto"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e0a0251fd81bed7420bea0f4d91c2a58f6c9fa34d5b2f70bed0ba8890de5aa"
checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874"
dependencies = [
"bytes",
"flex-error",
@@ -5067,9 +5069,9 @@ dependencies = [
[[package]]
name = "tendermint-rpc"
version = "0.23.3"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626c493e9ced3a9de37583bbd929f4b6dbd49aa513ab9b4776aa44a9332ce9b5"
checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6"
dependencies = [
"async-trait",
"bytes",
+2 -1
View File
@@ -11,7 +11,7 @@
"tauri:build": "yarn tauri build",
"tsc": "tsc --noEmit true",
"tsc:watch": "tsc --noEmit true --watch",
"dev": "yarn run webpack:dev & yarn run tauri:dev",
"dev": "run-p tauri:dev webpack:dev",
"prebuild": "yarn --cwd .. build",
"build": "run-s webpack:prod tauri:build",
"lint": "eslint src",
@@ -35,6 +35,7 @@
"clsx": "^1.1.1",
"date-fns": "^2.28.0",
"notistack": "^2.0.3",
"npm-run-all": "^4.1.5",
"qrcode.react": "^1.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
+1 -2
View File
@@ -47,8 +47,7 @@ argon2 = { version = "0.3.2", features = ["std"] }
base64 = "0.13"
zeroize = "1.4.3"
cosmrs = { git = "https://github.com/nymtech/cosmos-rust", branch = "bugfix/account-id-length-validation", features = ["rpc", "bip32", "cosmwasm"] }
cosmwasm-std = "1.0.0-beta3"
cosmwasm-std = "1.0.0-beta8"
validator-client = { path = "../../common/client-libs/validator-client", features = [
"nymd-client",
+4 -37
View File
@@ -2,8 +2,6 @@
use crate::error::BackendError;
use crate::network::Network;
use cosmrs::Decimal;
use cosmrs::Denom as CosmosDenom;
use cosmwasm_std::Coin as CosmWasmCoin;
use cosmwasm_std::Uint128;
use serde::{Deserialize, Serialize};
@@ -11,7 +9,9 @@ use std::convert::TryFrom;
use std::ops::{Add, Sub};
use std::str::FromStr;
use strum::IntoEnumIterator;
use validator_client::nymd::{CosmosCoin, GasPrice};
use validator_client::nymd::CosmosCoin;
use validator_client::nymd::Decimal;
use validator_client::nymd::Denom as CosmosDenom;
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(test, ts(export, export, export_to = "../src/types/rust/denom.ts"))]
@@ -56,17 +56,6 @@ pub struct Coin {
denom: Denom,
}
impl TryFrom<GasPrice> for Coin {
type Error = BackendError;
fn try_from(g: GasPrice) -> Result<Self, Self::Error> {
Ok(Coin {
amount: g.amount.to_string(),
denom: Denom::from_str(&g.denom.to_string())?,
})
}
}
// Allows adding minor and major denominations, output will have the LHS denom.
impl Add for Coin {
type Output = Self;
@@ -204,7 +193,7 @@ impl From<CosmosCoin> for Coin {
fn from(c: CosmosCoin) -> Coin {
Coin {
amount: c.amount.to_string(),
denom: Denom::from_str(&c.denom.to_string()).unwrap(),
denom: Denom::from_str(c.denom.as_ref()).unwrap(),
}
}
}
@@ -222,9 +211,6 @@ impl From<CosmWasmCoin> for Coin {
mod test {
use super::*;
use crate::error::BackendError;
use cosmrs::Coin as CosmosCoin;
use cosmrs::Decimal;
use cosmrs::Denom as CosmosDenom;
use cosmwasm_std::Coin as CosmWasmCoin;
use serde_json::json;
use std::convert::TryFrom;
@@ -430,23 +416,4 @@ mod test {
assert_eq!(Coin::minor("1") - Coin::major("1"), Coin::minor("-999999"));
assert_eq!(Coin::major("1") - Coin::minor("1"), Coin::major("0.999999"));
}
#[test]
fn coin_from_gas_price() {
assert_eq!(
Coin::try_from(GasPrice::from_str("42unym").unwrap()).unwrap(),
Coin {
amount: "42".to_string(),
denom: Denom::Minor,
}
);
assert_eq!(
Coin::try_from(GasPrice::from_str("42nym").unwrap()).unwrap(),
Coin {
amount: "42".to_string(),
denom: Denom::Major,
}
);
}
}
+4 -3
View File
@@ -15,6 +15,7 @@ use std::str::FromStr;
use std::{fs, io, path::PathBuf};
use strum::IntoEnumIterator;
use url::Url;
use validator_client::nymd::AccountId as CosmosAccountId;
pub const REMOTE_SOURCE_OF_VALIDATOR_URLS: &str =
"https://nymtech.net/.wellknown/wallet/validators.json";
@@ -211,7 +212,7 @@ impl Config {
.flat_map(|c| c.validators().cloned())
}
pub fn get_mixnet_contract_address(&self, network: WalletNetwork) -> Option<cosmrs::AccountId> {
pub fn get_mixnet_contract_address(&self, network: WalletNetwork) -> Option<CosmosAccountId> {
self
.base
.networks
@@ -221,7 +222,7 @@ impl Config {
.ok()
}
pub fn get_vesting_contract_address(&self, network: WalletNetwork) -> Option<cosmrs::AccountId> {
pub fn get_vesting_contract_address(&self, network: WalletNetwork) -> Option<CosmosAccountId> {
self
.base
.networks
@@ -234,7 +235,7 @@ impl Config {
pub fn get_bandwidth_claim_contract_address(
&self,
network: WalletNetwork,
) -> Option<cosmrs::AccountId> {
) -> Option<CosmosAccountId> {
self
.base
.networks
+19 -9
View File
@@ -3,11 +3,13 @@
windows_subsystem = "windows"
)]
use crate::menu::AddDefaultSubmenus;
use crate::operations::{mixnet, simulate, validator_api, vesting};
use crate::state::State;
use mixnet_contract_common::{Gateway, MixNode};
use std::sync::Arc;
use tauri::Menu;
use tokio::sync::RwLock;
use validator_client::nymd::fee::helpers::Operation;
mod coin;
mod config;
@@ -21,13 +23,6 @@ mod state;
mod utils;
mod wallet_storage;
use crate::menu::AddDefaultSubmenus;
use crate::operations::mixnet;
use crate::operations::validator_api;
use crate::operations::vesting;
use crate::state::State;
fn main() {
dotenv::dotenv().ok();
setup_logging();
@@ -79,7 +74,6 @@ fn main() {
state::save_config_to_files,
utils::major_to_minor,
utils::minor_to_major,
utils::outdated_get_approximate_fee,
utils::owns_gateway,
utils::owns_mixnode,
utils::get_env,
@@ -111,6 +105,22 @@ fn main() {
vesting::queries::vesting_get_gateway_pledge,
vesting::queries::vesting_get_mixnode_pledge,
vesting::queries::vesting_start_time,
// simulate endpoints
simulate::admin::simulate_update_contract_settings,
simulate::mixnet::simulate_bond_gateway,
simulate::mixnet::simulate_bond_mixnode,
simulate::mixnet::simulate_unbond_gateway,
simulate::mixnet::simulate_unbond_mixnode,
simulate::mixnet::simulate_update_mixnode,
simulate::mixnet::simulate_delegate_to_mixnode,
simulate::mixnet::simulate_undelegate_from_mixnode,
simulate::cosmos::simulate_send,
simulate::vesting::simulate_vesting_bond_gateway,
simulate::vesting::simulate_vesting_bond_mixnode,
simulate::vesting::simulate_vesting_unbond_gateway,
simulate::vesting::simulate_vesting_unbond_mixnode,
simulate::vesting::simulate_vesting_update_mixnode,
simulate::vesting::simulate_withdraw_vested_coins,
])
.menu(Menu::new().add_default_app_submenu_if_macos())
.run(tauri::generate_context!())
+1 -1
View File
@@ -1,7 +1,6 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmrs::Denom;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
@@ -9,6 +8,7 @@ use strum::EnumIter;
use config::defaults::all::Network as ConfigNetwork;
use config::defaults::{mainnet, qa, sandbox};
use validator_client::nymd::Denom;
#[allow(clippy::upper_case_acronyms)]
#[cfg_attr(test, derive(ts_rs::TS))]
@@ -10,7 +10,6 @@ use crate::wallet_storage::{self, DEFAULT_LOGIN_ID};
use bip39::{Language, Mnemonic};
use config::defaults::all::Network;
use config::defaults::COSMOS_DERIVATION_PATH;
use cosmrs::bip32::DerivationPath;
use itertools::Itertools;
use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize};
@@ -21,9 +20,10 @@ use std::sync::Arc;
use strum::IntoEnumIterator;
use tokio::sync::RwLock;
use url::Url;
use validator_client::nymd::bip32::DerivationPath;
use validator_client::nymd::wallet::{AccountData, DirectSecp256k1HdWallet};
use validator_client::{nymd::SigningNymdClient, Client};
use validator_client::nymd::{AccountId as CosmosAccountId, SigningNymdClient};
use validator_client::Client;
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/account.ts"))]
@@ -525,7 +525,7 @@ async fn set_state_with_all_accounts(
.iter()
.map(|account| {
let mnemonic = account.mnemonic();
let addresses: HashMap<WalletNetwork, cosmrs::AccountId> = WalletNetwork::iter()
let addresses: HashMap<WalletNetwork, CosmosAccountId> = WalletNetwork::iter()
.map(|network| {
let config_network: Network = network.into();
(
@@ -570,7 +570,7 @@ pub async fn remove_account_for_password(
fn derive_address(
mnemonic: bip39::Mnemonic,
prefix: &str,
) -> Result<cosmrs::AccountId, BackendError> {
) -> Result<CosmosAccountId, BackendError> {
DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?
.try_derive_accounts()?
.first()
@@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::Fee;
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/stateparams.ts"))]
@@ -52,11 +53,12 @@ pub async fn get_contract_settings(
#[tauri::command]
pub async fn update_contract_settings(
params: TauriContractStateParams,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<TauriContractStateParams, BackendError> {
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
nymd_client!(state)
.update_contract_settings(mixnet_contract_settings_params.clone())
.update_contract_settings(mixnet_contract_settings_params.clone(), fee)
.await?;
Ok(mixnet_contract_settings_params.into())
}
@@ -7,35 +7,39 @@ use cosmwasm_std::Uint128;
use mixnet_contract_common::{GatewayBond, MixNodeBond};
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::Fee;
#[tauri::command]
pub async fn bond_gateway(
gateway: Gateway,
pledge: Coin,
owner_signature: String,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
let denom = state.read().await.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.bond_gateway(gateway, owner_signature, pledge)
.bond_gateway(gateway, owner_signature, pledge, fee)
.await?;
Ok(())
}
#[tauri::command]
pub async fn unbond_gateway(
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state).unbond_gateway().await?;
nymd_client!(state).unbond_gateway(fee).await?;
Ok(())
}
#[tauri::command]
pub async fn unbond_mixnode(
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state).unbond_mixnode().await?;
nymd_client!(state).unbond_mixnode(fee).await?;
Ok(())
}
@@ -44,12 +48,13 @@ pub async fn bond_mixnode(
mixnode: MixNode,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
let denom = state.read().await.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.bond_mixnode(mixnode, owner_signature, pledge)
.bond_mixnode(mixnode, owner_signature, pledge, fee)
.await?;
Ok(())
}
@@ -57,10 +62,11 @@ pub async fn bond_mixnode(
#[tauri::command]
pub async fn update_mixnode(
profit_margin_percent: u8,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state)
.update_mixnode_config(profit_margin_percent)
.update_mixnode_config(profit_margin_percent, fee)
.await?;
Ok(())
}
@@ -8,6 +8,7 @@ use cosmwasm_std::{Coin as CosmWasmCoin, Uint128};
use mixnet_contract_common::{IdentityKey, PagedDelegatorDelegationsResponse};
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::Fee;
#[tauri::command]
pub async fn get_pending_delegation_events(
@@ -27,12 +28,13 @@ pub async fn get_pending_delegation_events(
pub async fn delegate_to_mixnode(
identity: &str,
amount: Coin,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<DelegationResult, BackendError> {
let denom = state.read().await.current_network().denom();
let delegation: CosmWasmCoin = amount.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.delegate_to_mixnode(identity, &delegation)
.delegate_to_mixnode(identity, &delegation, fee)
.await?;
Ok(DelegationResult::new(
nymd_client!(state).address().as_ref(),
@@ -44,10 +46,11 @@ pub async fn delegate_to_mixnode(
#[tauri::command]
pub async fn undelegate_from_mixnode(
identity: &str,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<DelegationResult, BackendError> {
nymd_client!(state)
.remove_mixnode_delegation(identity)
.remove_mixnode_delegation(identity, fee)
.await?;
Ok(DelegationResult::new(
nymd_client!(state).address().as_ref(),
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::{AccountId, CosmosCoin, TxResponse};
use validator_client::nymd::{AccountId, CosmosCoin, Fee, TxResponse};
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/tauritxresult.ts"))]
@@ -50,13 +50,14 @@ pub async fn send(
address: &str,
amount: Coin,
memo: String,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<TauriTxResult, BackendError> {
let address = AccountId::from_str(address)?;
let network_denom = state.read().await.current_network().denom();
let cosmos_amount: CosmosCoin = amount.clone().into_cosmos_coin(&network_denom)?;
let result = nymd_client!(state)
.send(&address, vec![cosmos_amount], memo)
.send(&address, vec![cosmos_amount], memo, fee)
.await?;
Ok(TauriTxResult::new(
result,
@@ -1,3 +1,4 @@
pub mod mixnet;
pub mod simulate;
pub mod validator_api;
pub mod vesting;
@@ -0,0 +1,32 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::BackendError;
use crate::mixnet::admin::TauriContractStateParams;
use crate::simulate::{FeeDetails, SimulateResult};
use crate::State;
use mixnet_contract_common::{ContractStateParams, ExecuteMsg};
use std::sync::Arc;
use tokio::sync::RwLock;
#[tauri::command]
pub async fn simulate_update_contract_settings(
params: TauriContractStateParams,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::UpdateContractStateParams(mixnet_contract_settings_params),
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
@@ -0,0 +1,38 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coin::Coin;
use crate::error::BackendError;
use crate::operations::simulate::{FeeDetails, SimulateResult};
use crate::state::State;
use std::str::FromStr;
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::{AccountId, MsgSend};
#[tauri::command]
pub async fn simulate_send(
address: &str,
amount: Coin,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let to_address = AccountId::from_str(address)?;
let network_denom = guard.current_network().denom();
let amount = vec![amount.clone().into_cosmos_coin(&network_denom)?];
let client = guard.current_client()?;
let from_address = client.nymd.address().clone();
let gas_price = client.nymd.gas_price().clone();
// TODO: I'm still not 100% convinced whether this should be exposed here or handled somewhere else in the client code
let msg = MsgSend {
from_address,
to_address,
amount,
};
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
@@ -0,0 +1,179 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coin::Coin;
use crate::error::BackendError;
use crate::simulate::{FeeDetails, SimulateResult};
use crate::State;
use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode};
use std::sync::Arc;
use tokio::sync::RwLock;
#[tauri::command]
pub async fn simulate_bond_gateway(
gateway: Gateway,
pledge: Coin,
owner_signature: String,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let pledge = pledge.into_cosmos_coin(&network_denom)?;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
// TODO: I'm still not 100% convinced whether this should be exposed here or handled somewhere else in the client code
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::BondGateway {
gateway,
owner_signature,
},
vec![pledge],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_unbond_gateway(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::UnbondGateway {},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_bond_mixnode(
mixnode: MixNode,
owner_signature: String,
pledge: Coin,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let pledge = pledge.into_cosmos_coin(&network_denom)?;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::BondMixnode {
mix_node: mixnode,
owner_signature,
},
vec![pledge],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_unbond_mixnode(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::UnbondMixnode {},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_update_mixnode(
profit_margin_percent: u8,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_delegate_to_mixnode(
identity: &str,
amount: Coin,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let delegation = amount.into_cosmos_coin(&network_denom)?;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::DelegateToMixnode {
mix_identity: identity.to_string(),
},
vec![delegation],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_undelegate_from_mixnode(
identity: &str,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let mixnet_contract = client.nymd.mixnet_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
mixnet_contract,
&ExecuteMsg::UndelegateFromMixnode {
mix_identity: identity.to_string(),
},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
@@ -0,0 +1,65 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coin::Coin;
use serde::{Deserialize, Serialize};
use validator_client::nymd::cosmwasm_client::types::GasInfo;
use validator_client::nymd::{tx, CosmosCoin, Fee, GasPrice};
pub mod admin;
pub mod cosmos;
pub mod mixnet;
pub mod vesting;
// technically we could have also exposed a result: Option<AbciResult> field from the SimulateResponse,
// but in the context of the wallet it's really irrelevant and useless for the time being
pub(crate) struct SimulateResult {
// As I mentioned somewhere before, from what I've seen in manual testing,
// gas estimation does not exist if transaction itself fails to get executed.
// for example if you attempt to send a 'BondMixnode' with invalid signature
pub gas_info: Option<GasInfo>,
pub gas_price: GasPrice,
}
impl SimulateResult {
pub fn new(gas_info: Option<GasInfo>, gas_price: GasPrice) -> Self {
SimulateResult {
gas_info,
gas_price,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeeDetails {
// expected to be used by the wallet in order to display detailed fee information to the user
pub amount: Option<Coin>,
pub fee: Fee,
}
impl SimulateResult {
pub fn detailed_fee(&self) -> FeeDetails {
FeeDetails {
amount: self.to_fee_amount().map(Into::into),
fee: self.to_fee(),
}
}
fn to_fee_amount(&self) -> Option<CosmosCoin> {
self
.gas_info
.map(|gas_info| &self.gas_price * gas_info.gas_used)
}
fn to_fee(&self) -> Fee {
self
.to_fee_amount()
.and_then(|fee_amount| {
self.gas_info.map(|gas_info| {
let gas_limit = gas_info.gas_used;
tx::Fee::from_amount_and_gas(fee_amount, gas_limit).into()
})
})
.unwrap_or_default()
}
}
@@ -0,0 +1,155 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coin::Coin;
use crate::error::BackendError;
use crate::simulate::{FeeDetails, SimulateResult};
use crate::State;
use mixnet_contract_common::{Gateway, MixNode};
use std::sync::Arc;
use tokio::sync::RwLock;
use vesting_contract_common::ExecuteMsg;
#[tauri::command]
pub async fn simulate_vesting_bond_gateway(
gateway: Gateway,
pledge: Coin,
owner_signature: String,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&network_denom)?;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::BondGateway {
gateway,
owner_signature,
amount: pledge,
},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_vesting_unbond_gateway(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::UnbondGateway {},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_vesting_bond_mixnode(
mixnode: MixNode,
owner_signature: String,
pledge: Coin,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&network_denom)?;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::BondMixnode {
mix_node: mixnode,
owner_signature,
amount: pledge,
},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_vesting_unbond_mixnode(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::UnbondMixnode {},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_vesting_update_mixnode(
profit_margin_percent: u8,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::UpdateMixnodeConfig {
profit_margin_percent,
},
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
#[tauri::command]
pub async fn simulate_withdraw_vested_coins(
amount: Coin,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<FeeDetails, BackendError> {
let guard = state.read().await;
let network_denom = guard.current_network().denom();
let amount = amount.into_cosmwasm_coin(&network_denom)?;
let client = guard.current_client()?;
let vesting_contract = client.nymd.vesting_contract_address()?;
let gas_price = client.nymd.gas_price().clone();
let msg = client.nymd.wrap_contract_execute_message(
vesting_contract,
&ExecuteMsg::WithdrawVestedCoins { amount },
vec![],
)?;
let result = client.nymd.simulate(vec![msg]).await?;
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
}
@@ -3,39 +3,41 @@ use crate::error::BackendError;
use crate::nymd_client;
use crate::state::State;
use crate::{Gateway, MixNode};
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::VestingSigningClient;
use validator_client::nymd::{Fee, VestingSigningClient};
#[tauri::command]
pub async fn vesting_bond_gateway(
gateway: Gateway,
pledge: Coin,
owner_signature: String,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
let denom = state.read().await.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.vesting_bond_gateway(gateway, &owner_signature, pledge)
.vesting_bond_gateway(gateway, &owner_signature, pledge, fee)
.await?;
Ok(())
}
#[tauri::command]
pub async fn vesting_unbond_gateway(
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state).vesting_unbond_gateway().await?;
nymd_client!(state).vesting_unbond_gateway(fee).await?;
Ok(())
}
#[tauri::command]
pub async fn vesting_unbond_mixnode(
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state).vesting_unbond_mixnode().await?;
nymd_client!(state).vesting_unbond_mixnode(fee).await?;
Ok(())
}
@@ -44,12 +46,13 @@ pub async fn vesting_bond_mixnode(
mixnode: MixNode,
owner_signature: String,
pledge: Coin,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
let denom = state.read().await.current_network().denom();
let pledge = pledge.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.vesting_bond_mixnode(mixnode, &owner_signature, pledge)
.vesting_bond_mixnode(mixnode, &owner_signature, pledge, fee)
.await?;
Ok(())
}
@@ -57,21 +60,25 @@ pub async fn vesting_bond_mixnode(
#[tauri::command]
pub async fn withdraw_vested_coins(
amount: Coin,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
let denom = state.read().await.current_network().denom();
let amount = amount.into_cosmwasm_coin(&denom)?;
nymd_client!(state).withdraw_vested_coins(amount).await?;
nymd_client!(state)
.withdraw_vested_coins(amount, fee)
.await?;
Ok(())
}
#[tauri::command]
pub async fn vesting_update_mixnode(
profit_margin_percent: u8,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<(), BackendError> {
nymd_client!(state)
.vesting_update_mixnode_config(profit_margin_percent)
.vesting_update_mixnode_config(profit_margin_percent, fee)
.await?;
Ok(())
}
@@ -6,7 +6,7 @@ use crate::utils::DelegationEvent;
use crate::utils::DelegationResult;
use std::sync::Arc;
use tokio::sync::RwLock;
use validator_client::nymd::VestingSigningClient;
use validator_client::nymd::{Fee, VestingSigningClient};
#[tauri::command]
pub async fn get_pending_vesting_delegation_events(
@@ -33,12 +33,13 @@ pub async fn get_pending_vesting_delegation_events(
pub async fn vesting_delegate_to_mixnode(
identity: &str,
amount: Coin,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<DelegationResult, BackendError> {
let denom = state.read().await.current_network().denom();
let delegation = amount.into_cosmwasm_coin(&denom)?;
nymd_client!(state)
.vesting_delegate_to_mixnode(identity, &delegation)
.vesting_delegate_to_mixnode(identity, &delegation, fee)
.await?;
Ok(DelegationResult::new(
nymd_client!(state).address().as_ref(),
@@ -50,10 +51,11 @@ pub async fn vesting_delegate_to_mixnode(
#[tauri::command]
pub async fn vesting_undelegate_from_mixnode(
identity: &str,
fee: Option<Fee>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<DelegationResult, BackendError> {
nymd_client!(state)
.vesting_undelegate_from_mixnode(identity)
.vesting_undelegate_from_mixnode(identity, fee)
.await?;
Ok(DelegationResult::new(
nymd_client!(state).address().as_ref(),
+2 -2
View File
@@ -3,7 +3,7 @@ use crate::network::Network;
use crate::{config, network_config};
use strum::IntoEnumIterator;
use validator_client::nymd::SigningNymdClient;
use validator_client::nymd::{AccountId as CosmosAccountId, SigningNymdClient};
use validator_client::Client;
use itertools::Itertools;
@@ -61,7 +61,7 @@ pub(crate) struct WalletAccountIds {
// The wallet account id
pub id: crate::wallet_storage::AccountId,
// The set of corresponding network identities derived from the mnemonic
pub addresses: HashMap<Network, cosmrs::AccountId>,
pub addresses: HashMap<Network, CosmosAccountId>,
}
impl State {
-16
View File
@@ -2,7 +2,6 @@ use crate::coin::{Coin, Denom};
use crate::error::BackendError;
use crate::nymd_client;
use crate::state::State;
use crate::Operation;
use mixnet_contract_common::mixnode::DelegationEvent as ContractDelegationEvent;
use mixnet_contract_common::mixnode::PendingUndelegate as ContractPendingUndelegate;
use mixnet_contract_common::Delegation;
@@ -70,21 +69,6 @@ pub async fn owns_gateway(
)
}
// NOTE: this uses OUTDATED defaults that might have no resemblance with the reality
// as for the actual transaction, the gas cost is being simulated beforehand
#[tauri::command]
pub async fn outdated_get_approximate_fee(
operation: Operation,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<Coin, BackendError> {
let approximate_fee = operation.default_fee(nymd_client!(state).gas_price());
let mut coin = Coin::new("0", &Denom::Major);
for f in approximate_fee.amount {
coin = coin + f.into();
}
Ok(coin)
}
#[cfg_attr(test, derive(ts_rs::TS))]
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/delegationresult.ts"))]
#[derive(Serialize, Deserialize)]
@@ -14,8 +14,8 @@
// In the future we might want to simplify by dropping the support for a single account entry,
// instead treating as muliple accounts with one entry.
use cosmrs::bip32::DerivationPath;
use serde::{Deserialize, Serialize};
use validator_client::nymd::bip32::DerivationPath;
use zeroize::Zeroize;
use crate::error::BackendError;
@@ -348,8 +348,8 @@ impl Drop for MnemonicAccount {
}
mod display_hd_path {
use cosmrs::bip32::DerivationPath;
use serde::{Deserialize, Deserializer, Serializer};
use validator_client::nymd::bip32::DerivationPath;
pub fn serialize<S: Serializer>(
hd_path: &DerivationPath,
@@ -14,9 +14,9 @@ pub(crate) use crate::wallet_storage::password::{AccountId, LoginId, UserPasswor
use crate::error::BackendError;
use crate::platform_constants::{STORAGE_DIR_NAME, WALLET_INFO_FILENAME};
use cosmrs::bip32::DerivationPath;
use std::fs::{self, create_dir_all, OpenOptions};
use std::path::{Path, PathBuf};
use validator_client::nymd::bip32::DerivationPath;
#[cfg(test)]
use self::account_data::MnemonicAccount;
+4 -2
View File
@@ -60,8 +60,10 @@ export const checkGatewayOwnership = async (): Promise<boolean> => {
// NOTE: this uses OUTDATED defaults that might have no resemblance with the reality
// as for the actual transaction, the gas cost is being simulated beforehand
export const getGasFee = async (operation: Operation): Promise<Coin> => {
const res: Coin = await invoke('outdated_get_approximate_fee', { operation });
return res;
// THIS NO LONGER EXISTS : )
// const res: Coin = await invoke('outdated_get_approximate_fee', { operation });
// return res;
return new Promise(((resolve, reject) => reject()))
};
export const getInclusionProbability = async (identity: string): Promise<InclusionProbabilityResponse> => {
+35 -21
View File
@@ -33,6 +33,7 @@ pub struct ServiceProvider {
db_path: PathBuf,
outbound_request_filter: OutboundRequestFilter,
open_proxy: bool,
enable_statistics: bool,
}
impl ServiceProvider {
@@ -40,6 +41,7 @@ impl ServiceProvider {
listening_address: String,
description: String,
open_proxy: bool,
enable_statistics: bool,
) -> ServiceProvider {
let allowed_hosts = HostsStore::new(
HostsStore::default_base_dir(),
@@ -65,6 +67,7 @@ impl ServiceProvider {
db_path,
outbound_request_filter,
open_proxy,
enable_statistics,
}
}
@@ -73,14 +76,16 @@ impl ServiceProvider {
async fn mixnet_response_listener(
mut websocket_writer: SplitSink<TSWebsocketStream, Message>,
mut mix_reader: mpsc::UnboundedReceiver<(Response, Recipient)>,
response_stats_data: &Arc<RwLock<StatsData>>,
response_stats_data: &Option<Arc<RwLock<StatsData>>>,
) {
// TODO: wire SURBs in here once they're available
while let Some((response, return_address)) = mix_reader.next().await {
response_stats_data
.write()
.await
.processed(return_address.identity(), response.data.len() as u32);
if let Some(response_stats_data) = response_stats_data {
response_stats_data
.write()
.await
.processed(return_address.identity(), response.data.len() as u32);
}
// make 'request' to native-websocket client
let response_message = ClientRequest::Send {
recipient: return_address,
@@ -226,7 +231,7 @@ impl ServiceProvider {
raw_request: &[u8],
controller_sender: &mut ControllerSender,
mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>,
request_stats_data: &Arc<RwLock<StatsData>>,
request_stats_data: &Option<Arc<RwLock<StatsData>>>,
connected_clients: &mut HashMap<ConnectionId, ClientIdentity>,
) {
let deserialized_msg = match Socks5Message::try_from_bytes(raw_request) {
@@ -239,7 +244,9 @@ impl ServiceProvider {
match deserialized_msg {
Socks5Message::Request(deserialized_request) => match deserialized_request {
Request::Connect(req) => {
connected_clients.insert(req.conn_id, *req.return_address.identity());
if self.enable_statistics {
connected_clients.insert(req.conn_id, *req.return_address.identity());
}
self.handle_proxy_connect(
controller_sender,
mix_input_sender,
@@ -250,11 +257,13 @@ impl ServiceProvider {
}
Request::Send(conn_id, data, closed) => {
if let Some(client_identity) = connected_clients.get(&conn_id) {
request_stats_data
.write()
.await
.processed(client_identity, data.len() as u32);
if let Some(request_stats_data) = request_stats_data {
if let Some(client_identity) = connected_clients.get(&conn_id) {
request_stats_data
.write()
.await
.processed(client_identity, data.len() as u32);
}
}
self.handle_proxy_send(controller_sender, conn_id, data, closed)
}
@@ -297,15 +306,20 @@ impl ServiceProvider {
active_connections_controller.run().await;
});
let mut stats = Statistics::new(self.description.clone(), interval, timer_receiver)
.await
.expect("Statistics controller could not be bootstrapped");
let request_stats_data = Arc::clone(stats.request_data());
let response_stats_data = Arc::clone(stats.response_data());
let mix_input_sender_clone = mix_input_sender.clone();
tokio::spawn(async move {
stats.run(&mix_input_sender_clone).await;
});
let mut request_stats_data = None;
let mut response_stats_data = None;
if self.enable_statistics {
let mut stats = Statistics::new(self.description.clone(), interval, timer_receiver)
.await
.expect("Statistics controller could not be bootstrapped");
request_stats_data = Some(Arc::clone(stats.request_data()));
response_stats_data = Some(Arc::clone(stats.response_data()));
let mix_input_sender_clone = mix_input_sender.clone();
tokio::spawn(async move {
stats.run(&mix_input_sender_clone).await;
});
}
#[cfg(feature = "stats-service")]
let storage = crate::storage::NetworkRequesterStorage::init(self.db_path.as_path())
@@ -16,6 +16,7 @@ mod websocket;
const OPEN_PROXY_ARG: &str = "open-proxy";
const WS_PORT: &str = "websocket-port";
const DESCRIPTION: &str = "description";
const ENABLE_STATISTICS: &str = "enable-statistics";
fn parse_args<'a>() -> ArgMatches<'a> {
App::new("Nym Network Requester")
@@ -34,13 +35,18 @@ fn parse_args<'a>() -> ArgMatches<'a> {
.short("p")
.takes_value(true),
)
.arg(
Arg::with_name(ENABLE_STATISTICS)
.help("enable mixnet statistics that get sent to a Nym server")
.long(ENABLE_STATISTICS)
.requires(DESCRIPTION),
)
.arg(
Arg::with_name(DESCRIPTION)
.help("service description")
.long(DESCRIPTION)
.short("d")
.takes_value(true)
.default_value("undefined"),
.takes_value(true),
)
.get_matches()
}
@@ -55,6 +61,11 @@ async fn main() {
println!("\n\nYOU HAVE STARTED IN 'OPEN PROXY' MODE. ANYONE WITH YOUR CLIENT ADDRESS CAN MAKE REQUESTS FROM YOUR MACHINE. PLEASE QUIT IF YOU DON'T UNDERSTAND WHAT YOU'RE DOING.\n\n");
}
let enable_statistics = matches.is_present(ENABLE_STATISTICS);
if enable_statistics {
println!("\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND STATISTICS TO A NYM SERVER. PLEASE QUIT IF YOU DON'T WANT THIS TO HAPPEN AND START WITHOUT THE {} FLAG .\n\n", ENABLE_STATISTICS);
}
let uri = format!(
"ws://localhost:{}",
matches
@@ -62,9 +73,12 @@ async fn main() {
.unwrap_or(&DEFAULT_WEBSOCKET_LISTENING_PORT.to_string())
);
let description = matches.value_of(DESCRIPTION).unwrap().to_string();
let description = matches
.value_of(DESCRIPTION)
.unwrap_or("undefined")
.to_string();
println!("Starting socks5 service provider:");
let mut server = core::ServiceProvider::new(uri, description, open_proxy);
let mut server = core::ServiceProvider::new(uri, description, open_proxy, enable_statistics);
server.run().await;
}
+14 -4
View File
@@ -272,7 +272,12 @@ impl<C> Client<C> {
where
C: SigningCosmWasmClient + Sync,
{
self.0.write().await.nymd.advance_current_epoch().await?;
self.0
.write()
.await
.nymd
.advance_current_epoch(None)
.await?;
Ok(())
}
@@ -281,7 +286,7 @@ impl<C> Client<C> {
where
C: SigningCosmWasmClient + Sync,
{
self.0.write().await.nymd.checkpoint_mixnodes().await?;
self.0.write().await.nymd.checkpoint_mixnodes(None).await?;
Ok(())
}
@@ -290,7 +295,12 @@ impl<C> Client<C> {
where
C: SigningCosmWasmClient + Sync,
{
self.0.write().await.nymd.reconcile_delegations().await?;
self.0
.write()
.await
.nymd
.reconcile_delegations(None)
.await?;
Ok(())
}
@@ -307,7 +317,7 @@ impl<C> Client<C> {
.write()
.await
.nymd
.write_rewarded_set(rewarded_set, expected_active_set_size)
.write_rewarded_set(rewarded_set, expected_active_set_size, None)
.await?;
Ok(())
}