From 11b2a7ad3d5600934a44b0e90af47eed5e9dac43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Wed, 1 Dec 2021 11:49:23 +0100 Subject: [PATCH 01/13] Rename contract_address to mixnet_contract_address --- .../validator-client/src/nymd/mod.rs | 72 +++++++++---------- .../connection_handler/eth_events.rs | 2 +- .../src-tauri/src/operations/account.rs | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 3b08f5c9f0..bea653f6f5 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -44,7 +44,7 @@ pub mod wallet; #[derive(Debug)] pub struct NymdClient { client: C, - contract_address: Option, + mixnet_contract_address: Option, client_address: Option>, gas_price: GasPrice, custom_gas_limits: HashMap, @@ -53,14 +53,14 @@ pub struct NymdClient { impl NymdClient { pub fn connect( endpoint: U, - contract_address: AccountId, + mixnet_contract_address: AccountId, ) -> Result, NymdError> where U: TryInto, { Ok(NymdClient { client: QueryNymdClient::new(endpoint)?, - contract_address: Some(contract_address), + mixnet_contract_address: Some(mixnet_contract_address), client_address: None, gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -72,7 +72,7 @@ impl NymdClient { // maybe the wallet could be made into a generic, but for now, let's just have this one implementation pub fn connect_with_signer( endpoint: U, - contract_address: Option, + mixnet_contract_address: Option, signer: DirectSecp256k1HdWallet, ) -> Result, NymdError> where @@ -86,7 +86,7 @@ impl NymdClient { Ok(NymdClient { client: SigningNymdClient::connect_with_signer(endpoint, signer)?, - contract_address, + mixnet_contract_address, client_address: Some(client_address), gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -95,7 +95,7 @@ impl NymdClient { pub fn connect_with_mnemonic( endpoint: U, - contract_address: Option, + mixnet_contract_address: Option, mnemonic: bip39::Mnemonic, ) -> Result, NymdError> where @@ -110,7 +110,7 @@ impl NymdClient { Ok(NymdClient { client: SigningNymdClient::connect_with_signer(endpoint, wallet)?, - contract_address, + mixnet_contract_address, client_address: Some(client_address), gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -135,15 +135,15 @@ impl NymdClient { self.custom_gas_limits.clone() } - pub fn contract_address(&self) -> Result<&AccountId, NymdError> { - self.contract_address + pub fn mixnet_contract_address(&self) -> Result<&AccountId, NymdError> { + self.mixnet_contract_address .as_ref() .ok_or(NymdError::NoContractAddressAvailable) } // now the question is as follows: will denom always be in the format of `u{prefix}`? pub fn denom(&self) -> Result { - Ok(format!("u{}", self.contract_address()?.prefix()) + Ok(format!("u{}", self.mixnet_contract_address()?.prefix()) .parse() .unwrap()) } @@ -214,7 +214,7 @@ impl NymdClient { { let request = QueryMsg::StateParams {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -224,7 +224,7 @@ impl NymdClient { { let request = QueryMsg::GetContractVersion {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -236,7 +236,7 @@ impl NymdClient { { let request = QueryMsg::CurrentRewardingInterval {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -253,7 +253,7 @@ impl NymdClient { rewarding_interval_nonce, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -263,7 +263,7 @@ impl NymdClient { { let request = QueryMsg::LayerDistribution {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -273,7 +273,7 @@ impl NymdClient { { let request = QueryMsg::GetRewardPool {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -283,7 +283,7 @@ impl NymdClient { { let request = QueryMsg::GetCirculatingSupply {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -293,7 +293,7 @@ impl NymdClient { { let request = QueryMsg::GetSybilResistancePercent {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -303,7 +303,7 @@ impl NymdClient { { let request = QueryMsg::GetEpochRewardPercent {}; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -317,7 +317,7 @@ impl NymdClient { }; let response: MixOwnershipResponse = self .client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await?; Ok(response.mixnode) } @@ -332,7 +332,7 @@ impl NymdClient { }; let response: GatewayOwnershipResponse = self .client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await?; Ok(response.gateway) } @@ -350,7 +350,7 @@ impl NymdClient { limit: page_limit, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -367,7 +367,7 @@ impl NymdClient { limit: page_limit, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -387,7 +387,7 @@ impl NymdClient { limit: page_limit, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -405,7 +405,7 @@ impl NymdClient { limit: page_limit, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -425,7 +425,7 @@ impl NymdClient { limit: page_limit, }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -443,7 +443,7 @@ impl NymdClient { delegator: delegator.to_string(), }; self.client - .query_contract_smart(self.contract_address()?, &request) + .query_contract_smart(self.mixnet_contract_address()?, &request) .await } @@ -591,7 +591,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Bonding mixnode from rust!", @@ -611,7 +611,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Unbonding mixnode from rust!", @@ -637,7 +637,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Delegating to mixnode from rust!", @@ -662,7 +662,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Removing mixnode delegation from rust!", @@ -686,7 +686,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Bonding gateway from rust!", @@ -706,7 +706,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Unbonding gateway from rust!", @@ -728,7 +728,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Updating contract state from rust!", @@ -752,7 +752,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Beginning mixnode rewarding procedure", @@ -776,7 +776,7 @@ impl NymdClient { self.client .execute( self.address(), - self.contract_address()?, + self.mixnet_contract_address()?, &req, fee, "Finishing mixnode rewarding procedure", diff --git a/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs b/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs index 1998e9baed..6cba087795 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs @@ -100,7 +100,7 @@ impl ERC20Bridge { credential: &TokenCredential, ) -> Result<(), RequestHandlingError> { // It's ok to unwrap here, as the cosmos contract and denom are set correctly - let contract_address = self.nymd_client.contract_address().unwrap(); + let contract_address = self.nymd_client.mixnet_contract_address().unwrap(); let coin = CosmosCoin { denom: Denom::from_str(DENOM).unwrap(), amount: Decimal::from(100000u64), diff --git a/nym-wallet/src-tauri/src/operations/account.rs b/nym-wallet/src-tauri/src/operations/account.rs index a359df60d8..090a130016 100644 --- a/nym-wallet/src-tauri/src/operations/account.rs +++ b/nym-wallet/src-tauri/src/operations/account.rs @@ -41,7 +41,7 @@ pub async fn connect_with_mnemonic( client = _connect_with_mnemonic(mnemonic, &r_state.config()); } - let contract_address = match client.contract_address() { + let contract_address = match client.mixnet_contract_address() { Ok(address) => address.to_string(), Err(e) => return Err(format_err!(e)), }; From 34c9726ac97338511b17d2f9db9609e79308dfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Wed, 1 Dec 2021 13:25:16 +0100 Subject: [PATCH 02/13] Add vesting contract address to validator client library --- .../validator-client/src/client.rs | 26 ++++++++++++++----- .../validator-client/src/nymd/mod.rs | 13 ++++++++++ common/network-defaults/src/lib.rs | 1 + explorer-api/src/mix_nodes/mod.rs | 8 ++++-- .../connection_handler/eth_events.rs | 1 + validator-api/src/nymd_client.rs | 6 +++-- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index ac90aa08dc..119de967b3 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -15,6 +15,9 @@ use mixnet_contract::{Delegation, GatewayBond, MixNodeBond}; use mixnet_contract::{ MixnetContractVersion, MixnodeRewardingStatusResponse, RewardingIntervalResponse, }; + +#[cfg(feature = "nymd-client")] +use std::str::FromStr; use url::Url; #[cfg(feature = "nymd-client")] @@ -22,6 +25,7 @@ pub struct Config { api_url: Url, nymd_url: Url, mixnet_contract_address: Option, + vesting_contract_address: Option, mixnode_page_limit: Option, gateway_page_limit: Option, @@ -34,10 +38,12 @@ impl Config { nymd_url: Url, api_url: Url, mixnet_contract_address: Option, + vesting_contract_address: Option, ) -> Self { Config { nymd_url, mixnet_contract_address, + vesting_contract_address, api_url, mixnode_page_limit: None, gateway_page_limit: None, @@ -64,6 +70,7 @@ impl Config { #[cfg(feature = "nymd-client")] pub struct Client { mixnet_contract_address: Option, + vesting_contract_address: Option, mnemonic: Option, mixnode_page_limit: Option, @@ -85,11 +92,13 @@ impl Client { let nymd_client = NymdClient::connect_with_mnemonic( config.nymd_url.as_str(), config.mixnet_contract_address.clone(), + config.vesting_contract_address.clone(), mnemonic.clone(), )?; Ok(Client { mixnet_contract_address: config.mixnet_contract_address, + vesting_contract_address: config.vesting_contract_address, mnemonic: Some(mnemonic), mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, @@ -103,6 +112,7 @@ impl Client { self.nymd = NymdClient::connect_with_mnemonic( new_endpoint.as_ref(), self.mixnet_contract_address.clone(), + self.vesting_contract_address.clone(), self.mnemonic.clone().unwrap(), )?; Ok(()) @@ -115,16 +125,19 @@ impl Client { let validator_api_client = validator_api::Client::new(config.api_url.clone()); let nymd_client = NymdClient::connect( config.nymd_url.as_str(), - config - .mixnet_contract_address - .clone() - .ok_or(ValidatorClientError::NymdError( - NymdError::NoContractAddressAvailable, - ))?, + config.mixnet_contract_address.clone().unwrap_or( + cosmrs::AccountId::from_str(network_defaults::DEFAULT_MIXNET_CONTRACT_ADDRESS) + .unwrap(), + ), + config.vesting_contract_address.clone().unwrap_or( + cosmrs::AccountId::from_str(network_defaults::DEFAULT_VESTING_CONTRACT_ADDRESS) + .unwrap(), + ), )?; Ok(Client { mixnet_contract_address: config.mixnet_contract_address, + vesting_contract_address: config.vesting_contract_address, mnemonic: None, mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, @@ -138,6 +151,7 @@ impl Client { self.nymd = NymdClient::connect( new_endpoint.as_ref(), self.mixnet_contract_address.clone().unwrap(), + self.vesting_contract_address.clone().unwrap(), )?; Ok(()) } diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index bea653f6f5..209d1c04fe 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -45,6 +45,7 @@ pub mod wallet; pub struct NymdClient { client: C, mixnet_contract_address: Option, + vesting_contract_address: Option, client_address: Option>, gas_price: GasPrice, custom_gas_limits: HashMap, @@ -54,6 +55,7 @@ impl NymdClient { pub fn connect( endpoint: U, mixnet_contract_address: AccountId, + vesting_contract_address: AccountId, ) -> Result, NymdError> where U: TryInto, @@ -61,6 +63,7 @@ impl NymdClient { Ok(NymdClient { client: QueryNymdClient::new(endpoint)?, mixnet_contract_address: Some(mixnet_contract_address), + vesting_contract_address: Some(vesting_contract_address), client_address: None, gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -73,6 +76,7 @@ impl NymdClient { pub fn connect_with_signer( endpoint: U, mixnet_contract_address: Option, + vesting_contract_address: Option, signer: DirectSecp256k1HdWallet, ) -> Result, NymdError> where @@ -87,6 +91,7 @@ impl NymdClient { Ok(NymdClient { client: SigningNymdClient::connect_with_signer(endpoint, signer)?, mixnet_contract_address, + vesting_contract_address, client_address: Some(client_address), gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -96,6 +101,7 @@ impl NymdClient { pub fn connect_with_mnemonic( endpoint: U, mixnet_contract_address: Option, + vesting_contract_address: Option, mnemonic: bip39::Mnemonic, ) -> Result, NymdError> where @@ -111,6 +117,7 @@ impl NymdClient { Ok(NymdClient { client: SigningNymdClient::connect_with_signer(endpoint, wallet)?, mixnet_contract_address, + vesting_contract_address, client_address: Some(client_address), gas_price: Default::default(), custom_gas_limits: Default::default(), @@ -141,6 +148,12 @@ impl NymdClient { .ok_or(NymdError::NoContractAddressAvailable) } + pub fn vesting_contract_address(&self) -> Result<&AccountId, NymdError> { + self.vesting_contract_address + .as_ref() + .ok_or(NymdError::NoContractAddressAvailable) + } + // now the question is as follows: will denom always be in the format of `u{prefix}`? pub fn denom(&self) -> Result { Ok(format!("u{}", self.mixnet_contract_address()?.prefix()) diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index 2e02299ce2..53011af603 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -63,6 +63,7 @@ pub fn default_api_endpoints() -> Vec { } pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "punk10pyejy66429refv3g35g2t7am0was7yalwrzen"; +pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = ""; pub const REWARDING_VALIDATOR_ADDRESS: &str = "punk1v9qauwdq5terag6uvfsdytcs2d0sdmfdy7hgk3"; /// How much bandwidth (in bytes) one token can buy diff --git a/explorer-api/src/mix_nodes/mod.rs b/explorer-api/src/mix_nodes/mod.rs index 7ebbbedc85..8ea26fdec2 100644 --- a/explorer-api/src/mix_nodes/mod.rs +++ b/explorer-api/src/mix_nodes/mod.rs @@ -224,8 +224,12 @@ fn new_nymd_client() -> validator_client::Client { let nymd_url = default_nymd_endpoints()[0].clone(); let api_url = default_api_endpoints()[0].clone(); - let client_config = - validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract.parse().unwrap())); + let client_config = validator_client::Config::new( + nymd_url, + api_url, + Some(mixnet_contract.parse().unwrap()), + None, + ); validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!") } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs b/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs index 6cba087795..76ab228448 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/eth_events.rs @@ -43,6 +43,7 @@ impl ERC20Bridge { let nymd_client = NymdClient::connect_with_mnemonic( nymd_url.as_ref(), AccountId::from_str(COSMOS_CONTRACT_ADDRESS).ok(), + None, mnemonic, ) .expect("Could not create nymd client"); diff --git a/validator-api/src/nymd_client.rs b/validator-api/src/nymd_client.rs index 90e3e033db..6289f845af 100644 --- a/validator-api/src/nymd_client.rs +++ b/validator-api/src/nymd_client.rs @@ -45,7 +45,8 @@ impl Client { .parse() .expect("the mixnet contract address is invalid!"); - let client_config = validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract)); + let client_config = + validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract), None); let inner = validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!"); @@ -71,7 +72,8 @@ impl Client { .parse() .expect("the mnemonic is invalid!"); - let client_config = validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract)); + let client_config = + validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract), None); let inner = validator_client::Client::new_signing(client_config, mnemonic) .expect("Failed to connect to nymd!"); From b175480ba50a3ed58a56ca23dd53dc73db116367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Wed, 1 Dec 2021 15:45:18 +0100 Subject: [PATCH 03/13] Bond/delegate mixnode with rust client --- .../validator-client/src/nymd/mod.rs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 209d1c04fe..aff0f3a853 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -613,6 +613,34 @@ impl NymdClient { .await } + /// Announce a mixnode on behalf of the owner, paying a fee. + pub async fn bond_mixnode_on_behalf( + &self, + mixnode: MixNode, + owner: String, + bond: Coin, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::BondMixnode); + + let req = ExecuteMsg::BondMixnodeOnBehalf { + mix_node: mixnode, + owner, + }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Bonding mixnode on behalf from rust!", + vec![cosmwasm_coin_to_cosmos_coin(bond)], + ) + .await + } + /// Unbond a mixnode, removing it from the network and reclaiming staked coins pub async fn unbond_mixnode(&self) -> Result where @@ -659,6 +687,35 @@ impl NymdClient { .await } + /// Delegates specified amount of stake to particular mixnode on + /// behalf of a particular delegator. + pub async fn delegate_to_mixnode_on_behalf( + &self, + mix_identity: &str, + delegate: &str, + amount: &Coin, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::DelegateToMixnode); + + let req = ExecuteMsg::DelegateToMixnodeOnBehalf { + mix_identity: mix_identity.to_string(), + delegate: delegate.to_string(), + }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Delegating to mixnode on behalf from rust!", + vec![cosmwasm_coin_ptr_to_cosmos_coin(amount)], + ) + .await + } + /// Removes stake delegation from a particular mixnode. pub async fn remove_mixnode_delegation( &self, From 2f68439916d49cf90680fc3b6057eec21cfc4761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Thu, 2 Dec 2021 15:14:03 +0100 Subject: [PATCH 04/13] Unbond/undelegate mixnode with rust client --- .../validator-client/src/nymd/mod.rs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index aff0f3a853..01d0df7113 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -661,6 +661,26 @@ impl NymdClient { .await } + /// 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 + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::UnbondMixnode); + + let req = ExecuteMsg::UnbondMixnodeOnBehalf { owner }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Unbonding mixnode on behalf from rust!", + Vec::new(), + ) + .await + } + /// Delegates specified amount of stake to particular mixnode. pub async fn delegate_to_mixnode( &self, @@ -741,6 +761,33 @@ impl NymdClient { .await } + /// Removes stake delegation from a particular mixnode on behalf of a particular delegator. + pub async fn remove_mixnode_delegation_on_behalf( + &self, + mix_identity: &str, + delegate: &str, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::UndelegateFromMixnode); + + let req = ExecuteMsg::UndelegateFromMixnodeOnBehalf { + mix_identity: mix_identity.to_string(), + delegate: delegate.to_string(), + }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Removing mixnode delegation on behalf from rust!", + Vec::new(), + ) + .await + } + /// Announce a gateway, paying a fee. pub async fn bond_gateway( &self, From c10038e6880b9a2b5bffe35acdae71a2870325a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Thu, 2 Dec 2021 15:18:21 +0100 Subject: [PATCH 05/13] Add client-side Operations as well, in case fees need to be modified --- .../validator-client/src/nymd/fee_helpers.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/fee_helpers.rs b/common/client-libs/validator-client/src/nymd/fee_helpers.rs index 242d576f77..66eb7aac6b 100644 --- a/common/client-libs/validator-client/src/nymd/fee_helpers.rs +++ b/common/client-libs/validator-client/src/nymd/fee_helpers.rs @@ -17,9 +17,13 @@ pub enum Operation { Send, BondMixnode, + BondOnBehalfMixnode, UnbondMixnode, + UnbondOnBehalfMixnode, DelegateToMixnode, + DelegateOnBehalfToMixnode, UndelegateFromMixnode, + UndelegateOnBehalfFromMixnode, BondGateway, UnbondGateway, @@ -43,11 +47,17 @@ impl fmt::Display for Operation { Operation::ChangeAdmin => f.write_str("ChangeAdmin"), Operation::Send => f.write_str("Send"), Operation::BondMixnode => f.write_str("BondMixnode"), + Operation::BondOnBehalfMixnode => f.write_str("BondOnBehalfMixnode"), Operation::UnbondMixnode => f.write_str("UnbondMixnode"), + Operation::UnbondOnBehalfMixnode => f.write_str("UnbondOnBehalfMixnode"), Operation::BondGateway => f.write_str("BondGateway"), Operation::UnbondGateway => f.write_str("UnbondGateway"), Operation::DelegateToMixnode => f.write_str("DelegateToMixnode"), + Operation::DelegateOnBehalfToMixnode => f.write_str("DelegateOnBehalfToMixnode"), Operation::UndelegateFromMixnode => f.write_str("UndelegateFromMixnode"), + Operation::UndelegateOnBehalfFromMixnode => { + f.write_str("UndelegateOnBehalfFromMixnode") + } Operation::UpdateStateParams => f.write_str("UpdateStateParams"), Operation::BeginMixnodeRewarding => f.write_str("BeginMixnodeRewarding"), Operation::FinishMixnodeRewarding => f.write_str("FinishMixnodeRewarding"), @@ -66,9 +76,13 @@ impl Operation { Operation::Send => 80_000u64.into(), Operation::BondMixnode => 175_000u64.into(), + Operation::BondOnBehalfMixnode => 175_000u64.into(), Operation::UnbondMixnode => 175_000u64.into(), + Operation::UnbondOnBehalfMixnode => 175_000u64.into(), Operation::DelegateToMixnode => 175_000u64.into(), + Operation::DelegateOnBehalfToMixnode => 175_000u64.into(), Operation::UndelegateFromMixnode => 175_000u64.into(), + Operation::UndelegateOnBehalfFromMixnode => 175_000u64.into(), Operation::BondGateway => 175_000u64.into(), Operation::UnbondGateway => 175_000u64.into(), From 718170c651d65b1745dc1ab33424fb376736b9a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Thu, 2 Dec 2021 15:40:50 +0100 Subject: [PATCH 06/13] Update tauri client --- nym-wallet/src-tauri/src/operations/account.rs | 1 + nym-wallet/src/types/rust/operation.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/nym-wallet/src-tauri/src/operations/account.rs b/nym-wallet/src-tauri/src/operations/account.rs index 090a130016..697aacdd1e 100644 --- a/nym-wallet/src-tauri/src/operations/account.rs +++ b/nym-wallet/src-tauri/src/operations/account.rs @@ -106,6 +106,7 @@ fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> NymdClient client, diff --git a/nym-wallet/src/types/rust/operation.ts b/nym-wallet/src/types/rust/operation.ts index 44c6d684c4..8d4ea7fe8e 100644 --- a/nym-wallet/src/types/rust/operation.ts +++ b/nym-wallet/src/types/rust/operation.ts @@ -5,9 +5,13 @@ export type Operation = | "ChangeAdmin" | "Send" | "BondMixnode" + | "BondOnBehalfMixnode" | "UnbondMixnode" + | "UnbondOnBehalfMixnode" | "DelegateToMixnode" + | "DelegateOnBehalfToMixnode" | "UndelegateFromMixnode" + | "UndelegateOnBehalfFromMixnode" | "BondGateway" | "UnbondGateway" | "UpdateStateParams" From 6417feaaedafe5d85ce2a87cac213de7ce56a145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Thu, 2 Dec 2021 16:16:01 +0100 Subject: [PATCH 07/13] Fix clippy --- common/client-libs/validator-client/src/client.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 119de967b3..494591c562 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -125,14 +125,14 @@ impl Client { let validator_api_client = validator_api::Client::new(config.api_url.clone()); let nymd_client = NymdClient::connect( config.nymd_url.as_str(), - config.mixnet_contract_address.clone().unwrap_or( + config.mixnet_contract_address.clone().unwrap_or_else(|| { cosmrs::AccountId::from_str(network_defaults::DEFAULT_MIXNET_CONTRACT_ADDRESS) - .unwrap(), - ), - config.vesting_contract_address.clone().unwrap_or( + .unwrap() + }), + config.vesting_contract_address.clone().unwrap_or_else(|| { cosmrs::AccountId::from_str(network_defaults::DEFAULT_VESTING_CONTRACT_ADDRESS) - .unwrap(), - ), + .unwrap() + }), )?; Ok(Client { From d4736bac279f2d5e30aa77e53a6a4a0515206a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Fri, 3 Dec 2021 09:49:24 +0100 Subject: [PATCH 08/13] Fix gas for operations --- .../validator-client/src/nymd/fee_helpers.rs | 26 +++++++++---------- .../validator-client/src/nymd/mod.rs | 8 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/common/client-libs/validator-client/src/nymd/fee_helpers.rs b/common/client-libs/validator-client/src/nymd/fee_helpers.rs index 66eb7aac6b..6f5b94e954 100644 --- a/common/client-libs/validator-client/src/nymd/fee_helpers.rs +++ b/common/client-libs/validator-client/src/nymd/fee_helpers.rs @@ -17,13 +17,13 @@ pub enum Operation { Send, BondMixnode, - BondOnBehalfMixnode, + BondMixnodeOnBehalf, UnbondMixnode, - UnbondOnBehalfMixnode, + UnbondMixnodeOnBehalf, DelegateToMixnode, - DelegateOnBehalfToMixnode, + DelegateToMixnodeOnBehalf, UndelegateFromMixnode, - UndelegateOnBehalfFromMixnode, + UndelegateFromMixnodeOnBehalf, BondGateway, UnbondGateway, @@ -47,16 +47,16 @@ impl fmt::Display for Operation { Operation::ChangeAdmin => f.write_str("ChangeAdmin"), Operation::Send => f.write_str("Send"), Operation::BondMixnode => f.write_str("BondMixnode"), - Operation::BondOnBehalfMixnode => f.write_str("BondOnBehalfMixnode"), + Operation::BondMixnodeOnBehalf => f.write_str("BondMixnodeOnBehalf"), Operation::UnbondMixnode => f.write_str("UnbondMixnode"), - Operation::UnbondOnBehalfMixnode => f.write_str("UnbondOnBehalfMixnode"), + Operation::UnbondMixnodeOnBehalf => f.write_str("UnbondMixnodeOnBehalf"), Operation::BondGateway => f.write_str("BondGateway"), Operation::UnbondGateway => f.write_str("UnbondGateway"), Operation::DelegateToMixnode => f.write_str("DelegateToMixnode"), - Operation::DelegateOnBehalfToMixnode => f.write_str("DelegateOnBehalfToMixnode"), + Operation::DelegateToMixnodeOnBehalf => f.write_str("DelegateToMixnodeOnBehalf"), Operation::UndelegateFromMixnode => f.write_str("UndelegateFromMixnode"), - Operation::UndelegateOnBehalfFromMixnode => { - f.write_str("UndelegateOnBehalfFromMixnode") + Operation::UndelegateFromMixnodeOnBehalf => { + f.write_str("UndelegateFromMixnodeOnBehalf") } Operation::UpdateStateParams => f.write_str("UpdateStateParams"), Operation::BeginMixnodeRewarding => f.write_str("BeginMixnodeRewarding"), @@ -76,13 +76,13 @@ impl Operation { Operation::Send => 80_000u64.into(), Operation::BondMixnode => 175_000u64.into(), - Operation::BondOnBehalfMixnode => 175_000u64.into(), + Operation::BondMixnodeOnBehalf => 200_000u64.into(), Operation::UnbondMixnode => 175_000u64.into(), - Operation::UnbondOnBehalfMixnode => 175_000u64.into(), + Operation::UnbondMixnodeOnBehalf => 175_000u64.into(), Operation::DelegateToMixnode => 175_000u64.into(), - Operation::DelegateOnBehalfToMixnode => 175_000u64.into(), + Operation::DelegateToMixnodeOnBehalf => 175_000u64.into(), Operation::UndelegateFromMixnode => 175_000u64.into(), - Operation::UndelegateOnBehalfFromMixnode => 175_000u64.into(), + Operation::UndelegateFromMixnodeOnBehalf => 175_000u64.into(), Operation::BondGateway => 175_000u64.into(), Operation::UnbondGateway => 175_000u64.into(), diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 01d0df7113..49f76edb09 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -623,7 +623,7 @@ impl NymdClient { where C: SigningCosmWasmClient + Sync, { - let fee = self.get_fee(Operation::BondMixnode); + let fee = self.get_fee(Operation::BondMixnodeOnBehalf); let req = ExecuteMsg::BondMixnodeOnBehalf { mix_node: mixnode, @@ -666,7 +666,7 @@ impl NymdClient { where C: SigningCosmWasmClient + Sync, { - let fee = self.get_fee(Operation::UnbondMixnode); + let fee = self.get_fee(Operation::UnbondMixnodeOnBehalf); let req = ExecuteMsg::UnbondMixnodeOnBehalf { owner }; self.client @@ -718,7 +718,7 @@ impl NymdClient { where C: SigningCosmWasmClient + Sync, { - let fee = self.get_fee(Operation::DelegateToMixnode); + let fee = self.get_fee(Operation::DelegateToMixnodeOnBehalf); let req = ExecuteMsg::DelegateToMixnodeOnBehalf { mix_identity: mix_identity.to_string(), @@ -770,7 +770,7 @@ impl NymdClient { where C: SigningCosmWasmClient + Sync, { - let fee = self.get_fee(Operation::UndelegateFromMixnode); + let fee = self.get_fee(Operation::UndelegateFromMixnodeOnBehalf); let req = ExecuteMsg::UndelegateFromMixnodeOnBehalf { mix_identity: mix_identity.to_string(), From 67f847e674aa9526dba578741cd526bf0f66954c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Fri, 3 Dec 2021 15:01:31 +0100 Subject: [PATCH 09/13] Add batched delegated mixnode bonds --- .../validator-client/src/nymd/mod.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 49f76edb09..490ac63511 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -181,6 +181,16 @@ impl NymdClient { operation.determine_fee(&self.gas_price, gas_limit) } + pub fn get_fee_multiple(&self, operation: Operation, times: u64) -> Fee { + let default_gas_limit = operation.default_gas_limit(); + let gas_limit_unit = self + .custom_gas_limits + .get(&operation) + .unwrap_or(&default_gas_limit); + let gas_limit = Gas::from(gas_limit_unit.value() * times); + Operation::determine_custom_fee(&self.gas_price, gas_limit) + } + pub fn calculate_custom_fee(&self, gas_limit: impl Into) -> Fee { Operation::determine_custom_fee(&self.gas_price, gas_limit.into()) } @@ -641,6 +651,40 @@ impl NymdClient { .await } + /// Announce multiple mixnodes on behalf of other owners, paying a fee. + pub async fn bond_multiple_mixnodes_on_behalf( + &self, + mixnode_bond: Vec, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee_multiple(Operation::BondMixnodeOnBehalf, mixnode_bond.len() as u64); + + let reqs: Vec<(ExecuteMsg, Vec)> = mixnode_bond + .into_iter() + .map(|bond| { + ( + ExecuteMsg::BondMixnodeOnBehalf { + mix_node: bond.mix_node, + owner: bond.owner.to_string(), + }, + vec![cosmwasm_coin_to_cosmos_coin(bond.bond_amount)], + ) + }) + .collect(); + + self.client + .execute_multiple( + self.address(), + self.mixnet_contract_address()?, + reqs, + fee, + "Bonding multiple mixnodes on behalf from rust!", + ) + .await + } + /// Unbond a mixnode, removing it from the network and reclaiming staked coins pub async fn unbond_mixnode(&self) -> Result where From 51e82fe9308193c30070af7e034dbadc2df9eccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Fri, 3 Dec 2021 15:25:47 +0100 Subject: [PATCH 10/13] Add gateway bond on behalf functions --- .../validator-client/src/nymd/fee_helpers.rs | 6 ++ .../validator-client/src/nymd/mod.rs | 86 ++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/common/client-libs/validator-client/src/nymd/fee_helpers.rs b/common/client-libs/validator-client/src/nymd/fee_helpers.rs index 6f5b94e954..21d82ea429 100644 --- a/common/client-libs/validator-client/src/nymd/fee_helpers.rs +++ b/common/client-libs/validator-client/src/nymd/fee_helpers.rs @@ -26,7 +26,9 @@ pub enum Operation { UndelegateFromMixnodeOnBehalf, BondGateway, + BondGatewayOnBehalf, UnbondGateway, + UnbondGatewayOnBehalf, UpdateStateParams, @@ -51,7 +53,9 @@ impl fmt::Display for Operation { Operation::UnbondMixnode => f.write_str("UnbondMixnode"), 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"), @@ -85,7 +89,9 @@ impl Operation { 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::UpdateStateParams => 175_000u64.into(), Operation::BeginMixnodeRewarding => 175_000u64.into(), diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 490ac63511..dcb09d8d41 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -654,14 +654,14 @@ impl NymdClient { /// Announce multiple mixnodes on behalf of other owners, paying a fee. pub async fn bond_multiple_mixnodes_on_behalf( &self, - mixnode_bond: Vec, + mixnode_bonds: Vec, ) -> Result where C: SigningCosmWasmClient + Sync, { - let fee = self.get_fee_multiple(Operation::BondMixnodeOnBehalf, mixnode_bond.len() as u64); + let fee = self.get_fee_multiple(Operation::BondMixnodeOnBehalf, mixnode_bonds.len() as u64); - let reqs: Vec<(ExecuteMsg, Vec)> = mixnode_bond + let reqs: Vec<(ExecuteMsg, Vec)> = mixnode_bonds .into_iter() .map(|bond| { ( @@ -856,6 +856,65 @@ impl NymdClient { .await } + /// Announce a gateway on behalf of the owner, paying a fee. + pub async fn bond_gateway_on_behalf( + &self, + gateway: Gateway, + owner: String, + bond: Coin, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::BondGatewayOnBehalf); + + let req = ExecuteMsg::BondGatewayOnBehalf { gateway, owner }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Bonding gateway on behalf from rust!", + vec![cosmwasm_coin_to_cosmos_coin(bond)], + ) + .await + } + + /// Announce multiple gateways on behalf of other owners, paying a fee. + pub async fn bond_multiple_gateways_on_behalf( + &self, + gateway_bonds: Vec, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee_multiple(Operation::BondGatewayOnBehalf, gateway_bonds.len() as u64); + + let reqs: Vec<(ExecuteMsg, Vec)> = gateway_bonds + .into_iter() + .map(|bond| { + ( + ExecuteMsg::BondGatewayOnBehalf { + gateway: bond.gateway, + owner: bond.owner.to_string(), + }, + vec![cosmwasm_coin_to_cosmos_coin(bond.bond_amount)], + ) + }) + .collect(); + + self.client + .execute_multiple( + self.address(), + self.mixnet_contract_address()?, + reqs, + fee, + "Bonding multiple gateways on behalf from rust!", + ) + .await + } + /// Unbond a gateway, removing it from the network and reclaiming staked coins pub async fn unbond_gateway(&self) -> Result where @@ -876,6 +935,27 @@ impl NymdClient { .await } + /// 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 + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee(Operation::UnbondGatewayOnBehalf); + + let req = ExecuteMsg::UnbondGatewayOnBehalf { owner }; + self.client + .execute( + self.address(), + self.mixnet_contract_address()?, + &req, + fee, + "Unbonding gateway on behalf from rust!", + Vec::new(), + ) + .await + } + pub async fn update_contract_settings( &self, new_params: ContractStateParams, From b809eb6c5f1dce0897eb5b9e4c56b08ad96a2ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Fri, 3 Dec 2021 16:06:23 +0100 Subject: [PATCH 11/13] Batch delegations on behalf as well --- .../validator-client/src/nymd/mod.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index dcb09d8d41..27264bd448 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -780,6 +780,43 @@ impl NymdClient { .await } + /// Delegates specified amount of stake to multiple mixnodes on behalf of multiple delegators. + pub async fn delegate_to_multiple_mixnodes_on_behalf( + &self, + mixnode_delegations: Vec, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee_multiple( + Operation::DelegateToMixnodeOnBehalf, + mixnode_delegations.len() as u64, + ); + + let reqs: Vec<(ExecuteMsg, Vec)> = mixnode_delegations + .into_iter() + .map(|delegation| { + ( + ExecuteMsg::DelegateToMixnodeOnBehalf { + mix_identity: delegation.node_identity(), + delegate: delegation.owner().to_string(), + }, + vec![cosmwasm_coin_to_cosmos_coin(delegation.amount().clone())], + ) + }) + .collect(); + + self.client + .execute_multiple( + self.address(), + self.mixnet_contract_address()?, + reqs, + fee, + "Delegating to multiple mixnodes on behalf from rust!", + ) + .await + } + /// Removes stake delegation from a particular mixnode. pub async fn remove_mixnode_delegation( &self, From f542c28e89d4e9b88fae6406974561ce0d7f6c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C8=99u?= Date: Fri, 3 Dec 2021 19:04:56 +0100 Subject: [PATCH 12/13] Batching for sends --- .../nymd/cosmwasm_client/signing_client.rs | 27 +++++++++++++++++++ .../validator-client/src/nymd/mod.rs | 15 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs index ab650b36c0..acc7a33765 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs @@ -319,6 +319,33 @@ pub trait SigningCosmWasmClient: CosmWasmClient { .await } + async fn send_tokens_multiple( + &self, + sender_address: &AccountId, + msgs: I, + fee: Fee, + memo: impl Into + Send + 'static, + ) -> Result + where + I: IntoIterator)> + Send, + { + let messages = msgs + .into_iter() + .map(|(to_address, amount)| { + MsgSend { + from_address: sender_address.clone(), + to_address, + amount, + } + .to_any() + .map_err(|_| NymdError::SerializationError("MsgExecuteContract".to_owned())) + }) + .collect::>()?; + + self.sign_and_broadcast_commit(sender_address, messages, fee, memo) + .await + } + async fn delegate_tokens( &self, delegator_address: &AccountId, diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 27264bd448..50cb73677b 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -486,6 +486,21 @@ impl NymdClient { .await } + /// Send funds from one address to multiple others + pub async fn send_multiple( + &self, + msgs: Vec<(AccountId, Vec)>, + memo: impl Into + Send + 'static, + ) -> Result + where + C: SigningCosmWasmClient + Sync, + { + let fee = self.get_fee_multiple(Operation::Send, msgs.len() as u64); + self.client + .send_tokens_multiple(self.address(), msgs, fee, memo) + .await + } + pub async fn execute( &self, contract_address: &AccountId, From 9fb44f9672816ee400d6482c54ab6bf8e60a1d32 Mon Sep 17 00:00:00 2001 From: neacsu Date: Fri, 3 Dec 2021 18:16:55 +0000 Subject: [PATCH 13/13] [ci skip] Generate TS types --- nym-wallet/src/types/rust/operation.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nym-wallet/src/types/rust/operation.ts b/nym-wallet/src/types/rust/operation.ts index 8d4ea7fe8e..29be609406 100644 --- a/nym-wallet/src/types/rust/operation.ts +++ b/nym-wallet/src/types/rust/operation.ts @@ -5,15 +5,17 @@ export type Operation = | "ChangeAdmin" | "Send" | "BondMixnode" - | "BondOnBehalfMixnode" + | "BondMixnodeOnBehalf" | "UnbondMixnode" - | "UnbondOnBehalfMixnode" + | "UnbondMixnodeOnBehalf" | "DelegateToMixnode" - | "DelegateOnBehalfToMixnode" + | "DelegateToMixnodeOnBehalf" | "UndelegateFromMixnode" - | "UndelegateOnBehalfFromMixnode" + | "UndelegateFromMixnodeOnBehalf" | "BondGateway" + | "BondGatewayOnBehalf" | "UnbondGateway" + | "UnbondGatewayOnBehalf" | "UpdateStateParams" | "BeginMixnodeRewarding" | "FinishMixnodeRewarding"; \ No newline at end of file