From 895edea531d136a0d24f86d2a21ea36a53eecf32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 1 Jun 2022 13:32:38 +0100 Subject: [PATCH] Introduced concept of denom details No longer exposing plain 'DENOM' Denom registration + conversion Generating typescript type for DecCoin 'New' API on 'send' Further WIP work on transforming usages of MajorCurrencyAmount into DecCoin Further replacements of MajorCurrencyAmount into DecCoin Attempt at dec-coinifying get_all_mix_delegations Finished purge of MajorCurrencyAmount Display for Fee More unification for conversion methods Fixed up tests and made clippy happier Minor post-merge fixes Removed explicit Arc and RwLock from all tauri commands Fixed conversion to display coin More type-restrictive exported denom type Regenerated rust => ts types --- clients/credential/src/client.rs | 4 +- .../src/nymd/cosmwasm_client/client.rs | 4 +- .../validator-client/src/nymd/fee/mod.rs | 36 + .../validator-client/src/nymd/mod.rs | 6 +- .../mixnet-contract/src/delegation.rs | 2 +- .../mixnet-contract/src/mixnode.rs | 10 + .../vesting-contract/src/lib.rs | 14 +- common/network-defaults/src/all.rs | 31 +- common/network-defaults/src/lib.rs | 120 ++- common/network-defaults/src/mainnet.rs | 6 +- common/network-defaults/src/qa.rs | 6 +- common/network-defaults/src/sandbox.rs | 6 +- common/types/src/account.rs | 20 +- common/types/src/currency.rs | 805 +++++++++--------- common/types/src/delegation.rs | 147 +--- common/types/src/error.rs | 7 + common/types/src/fees.rs | 12 +- common/types/src/gas.rs | 86 +- common/types/src/gateway.rs | 43 +- common/types/src/mixnode.rs | 80 +- common/types/src/transaction.rs | 80 +- common/types/src/vesting.rs | 80 +- contracts/bandwidth-claim/src/lib.rs | 6 +- contracts/coconut-bandwidth/src/contract.rs | 15 +- contracts/coconut-bandwidth/src/error.rs | 4 +- .../coconut-bandwidth/src/support/tests.rs | 1 - .../coconut-bandwidth/src/transactions.rs | 18 +- contracts/mixnet/src/contract.rs | 5 +- contracts/mixnet/src/delegations/queries.rs | 8 +- contracts/mixnet/src/delegations/storage.rs | 6 +- .../mixnet/src/delegations/transactions.rs | 70 +- contracts/mixnet/src/error.rs | 6 +- contracts/mixnet/src/gateways/storage.rs | 4 +- contracts/mixnet/src/gateways/transactions.rs | 8 +- contracts/mixnet/src/mixnodes/storage.rs | 8 +- contracts/mixnet/src/mixnodes/transactions.rs | 10 +- contracts/mixnet/src/rewards/queries.rs | 7 +- contracts/mixnet/src/rewards/transactions.rs | 58 +- .../mixnet/src/support/tests/fixtures.rs | 10 +- contracts/mixnet/src/support/tests/mod.rs | 4 +- contracts/mixnet/src/support/tests/queries.rs | 4 +- contracts/vesting/src/contract.rs | 13 +- contracts/vesting/src/support/tests.rs | 6 +- contracts/vesting/src/vesting/account/mod.rs | 10 +- .../src/vesting/account/vesting_account.rs | 24 +- contracts/vesting/src/vesting/mod.rs | 28 +- .../nym-wallet/src/types/rust/AppEnv.ts | 2 + .../nym-wallet/src/types/rust/ValidatorUrl.ts | 2 + .../src/types/rust/ValidatorUrls.ts | 2 + nym-wallet/nym-wallet-types/src/network.rs | 17 + nym-wallet/src-tauri/src/error.rs | 5 + nym-wallet/src-tauri/src/main.rs | 6 +- nym-wallet/src-tauri/src/network_config.rs | 23 +- .../src/operations/mixnet/account.rs | 67 +- .../src-tauri/src/operations/mixnet/admin.rs | 19 +- .../src-tauri/src/operations/mixnet/bond.rs | 138 +-- .../src/operations/mixnet/delegate.rs | 182 ++-- .../src-tauri/src/operations/mixnet/epoch.rs | 6 +- .../src/operations/mixnet/rewards.rs | 12 +- .../src-tauri/src/operations/mixnet/send.rs | 43 +- .../src/operations/simulate/admin.rs | 8 +- .../src/operations/simulate/cosmos.rs | 15 +- .../src/operations/simulate/mixnet.rs | 62 +- .../src-tauri/src/operations/simulate/mod.rs | 13 +- .../src/operations/simulate/vesting.rs | 62 +- .../src/operations/validator_api/status.rs | 16 +- .../src-tauri/src/operations/vesting/bond.rs | 117 +-- .../src/operations/vesting/delegate.rs | 56 +- .../src/operations/vesting/queries.rs | 185 ++-- .../src/operations/vesting/rewards.rs | 12 +- nym-wallet/src-tauri/src/state.rs | 108 ++- nym-wallet/src-tauri/src/utils.rs | 23 +- tools/ts-rs-cli/src/main.rs | 7 +- ts-packages/types/src/types/rust/Account.ts | 7 +- .../types/src/types/rust/AccountEntry.ts | 6 +- .../src/types/rust/AccountWithMnemonic.ts | 7 +- ts-packages/types/src/types/rust/Balance.ts | 7 +- .../src/types/rust/CoreNodeStatusResponse.ts | 6 +- ts-packages/types/src/types/rust/Currency.ts | 7 - .../types/src/types/rust/CurrencyDenom.ts | 3 +- .../types/rust/CurrencyStringMajorAmount.ts | 1 - ts-packages/types/src/types/rust/DecCoin.ts | 3 + .../types/src/types/rust/Delegation.ts | 10 +- .../types/src/types/rust/DelegationEvent.ts | 12 +- .../src/types/rust/DelegationEventKind.ts | 3 +- .../types/src/types/rust/DelegationRecord.ts | 8 +- .../types/src/types/rust/DelegationResult.ts | 8 +- .../types/rust/DelegationSummaryResponse.ts | 10 +- .../types/rust/DelegationWithEverything.ts | 23 +- .../types/src/types/rust/FeeDetails.ts | 6 +- ts-packages/types/src/types/rust/Gas.ts | 6 +- ts-packages/types/src/types/rust/GasInfo.ts | 8 +- .../types/src/types/rust/GatewayBond.ts | 12 +- .../rust/InclusionProbabilityResponse.ts | 7 +- .../types/src/types/rust/MixNodeBond.ts | 15 +- .../types/src/types/rust/MixnodeStatus.ts | 3 +- .../src/types/rust/MixnodeStatusResponse.ts | 6 +- ts-packages/types/src/types/rust/Operation.ts | 36 - .../src/types/rust/OriginalVestingResponse.ts | 8 +- .../types/src/types/rust/PendingUndelegate.ts | 8 +- ts-packages/types/src/types/rust/Period.ts | 3 +- .../types/src/types/rust/PledgeData.ts | 7 +- .../src/types/rust/RpcTransactionResponse.ts | 13 +- .../types/src/types/rust/SelectionChance.ts | 3 +- .../types/src/types/rust/SendTxResult.ts | 15 +- .../src/types/rust/StakeSaturationResponse.ts | 6 +- .../src/types/rust/TransactionDetails.ts | 8 +- .../types/rust/TransactionExecuteResult.ts | 12 +- .../src/types/rust/VestingAccountInfo.ts | 12 +- .../types/src/types/rust/VestingPeriod.ts | 6 +- ts-packages/types/src/types/rust/index.ts | 40 - 111 files changed, 1713 insertions(+), 1794 deletions(-) create mode 100644 nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/AppEnv.ts create mode 100644 nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrl.ts create mode 100644 nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrls.ts delete mode 100644 ts-packages/types/src/types/rust/Currency.ts delete mode 100644 ts-packages/types/src/types/rust/CurrencyStringMajorAmount.ts create mode 100644 ts-packages/types/src/types/rust/DecCoin.ts delete mode 100644 ts-packages/types/src/types/rust/Operation.ts delete mode 100644 ts-packages/types/src/types/rust/index.ts diff --git a/clients/credential/src/client.rs b/clients/credential/src/client.rs index dae2d9e91f..ef0fc6d9fd 100644 --- a/clients/credential/src/client.rs +++ b/clients/credential/src/client.rs @@ -8,7 +8,7 @@ use url::Url; use crate::error::Result; use crate::{MNEMONIC, NYMD_URL}; -use network_defaults::{DEFAULT_NETWORK, DENOM, VOUCHER_INFO}; +use network_defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO}; use validator_client::nymd::traits::CoconutBandwidthSigningClient; use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient}; @@ -34,7 +34,7 @@ impl Client { encryption_key: String, fee: Option, ) -> Result { - let amount = Coin::new(amount as u128, DENOM.to_string()); + let amount = Coin::new(amount as u128, MIX_DENOM.base.to_string()); Ok(self .nymd_client .deposit( diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs index 08a3ce22a2..8da9d3192c 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs @@ -26,7 +26,7 @@ use cosmrs::rpc::{self, HttpClient, Order}; use cosmrs::tendermint::abci::Code as AbciCode; use cosmrs::tendermint::abci::Transaction; use cosmrs::tendermint::{abci, block, chain}; -use cosmrs::{tx, AccountId, Coin as CosmosCoin, Denom, Tx}; +use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx}; use prost::Message; use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; @@ -121,7 +121,7 @@ pub trait CosmWasmClient: rpc::Client { async fn get_balance( &self, address: &AccountId, - search_denom: Denom, + search_denom: String, ) -> Result, NymdError> { let path = Some("/cosmos.bank.v1beta1.Query/Balance".parse().unwrap()); diff --git a/common/client-libs/validator-client/src/nymd/fee/mod.rs b/common/client-libs/validator-client/src/nymd/fee/mod.rs index 7044fc6f9d..6bf71f37b0 100644 --- a/common/client-libs/validator-client/src/nymd/fee/mod.rs +++ b/common/client-libs/validator-client/src/nymd/fee/mod.rs @@ -1,8 +1,10 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::nymd::Coin; use cosmrs::tx; use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; pub mod gas_price; @@ -14,6 +16,40 @@ pub enum Fee { Auto(Option), } +impl Display for Fee { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Fee::Manual(fee) => { + write!(f, "Fee in manual mode with ")?; + for fee in &fee.amount { + write!(f, "{}{} paid in fees, ", fee.amount, fee.denom)?; + } + write!(f, "{} set as gas limit, ", fee.gas_limit)?; + if let Some(payer) = &fee.payer { + write!(f, "{payer} set as payer, ")?; + } + if let Some(granter) = &fee.granter { + write!(f, "{granter} set as granter")?; + } + Ok(()) + } + Fee::Auto(Some(multiplier)) => { + write!(f, "Fee in auto mode with {multiplier} simulated multiplier") + } + Fee::Auto(None) => write!(f, "Fee in auto mode with no custom simulated multiplier"), + } + } +} + +impl Fee { + pub fn try_get_manual_amount(&self) -> Option> { + match self { + Fee::Manual(tx_fee) => Some(tx_fee.amount.iter().cloned().map(Into::into).collect()), + Fee::Auto(_) => None, + } + } +} + impl From for Fee { fn from(fee: tx::Fee) -> Self { Fee::Manual(fee) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 8210879768..5a6f3c1df0 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -134,7 +134,7 @@ impl NymdClient { where U: TryInto, { - let denom = network.denom(); + let denom = network.mix_denom().base; let client_address = signer .try_derive_accounts()? .into_iter() @@ -176,7 +176,7 @@ impl NymdClient { U: TryInto, { let prefix = network.bech32_prefix(); - let denom = network.denom(); + let denom = network.mix_denom().base; let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?; let client_address = wallet .try_derive_accounts()? @@ -338,7 +338,7 @@ impl NymdClient { pub async fn get_balance( &self, address: &AccountId, - denom: Denom, + denom: String, ) -> Result, NymdError> where C: CosmWasmClient + Sync, diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs index 645245d8e6..d8555def8f 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs @@ -33,7 +33,7 @@ pub struct Delegation { pub node_identity: IdentityKey, pub amount: Coin, pub block_height: u64, - pub proxy: Option, // proxy address used to delegate the funds on behalf of anouther address + pub proxy: Option, // proxy address used to delegate the funds on behalf of another address } impl Eq for Delegation {} diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index 32b8611eff..dfd675e530 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -37,6 +37,16 @@ pub enum DelegationEvent { Undelegate(PendingUndelegate), } +impl DelegationEvent { + pub fn delegation_amount(&self) -> Option { + match self { + DelegationEvent::Delegate(delegation) => Some(delegation.amount.clone()), + // I think it would be nice to also expose an amount here to know how much we're undelegating + DelegationEvent::Undelegate(_) => None, + } + } +} + #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct PendingUndelegate { mix_identity: IdentityKey, diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs index b35b574819..d540f916c3 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs @@ -1,6 +1,6 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{Coin, Timestamp}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -11,7 +11,7 @@ pub mod events; pub mod messages; pub fn one_ucoin() -> Coin { - Coin::new(1, DENOM) + Coin::new(1, MIX_DENOM.base) } #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] @@ -28,8 +28,8 @@ pub enum Period { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct PledgeData { - amount: Coin, - block_time: Timestamp, + pub amount: Coin, + pub block_time: Timestamp, } impl PledgeData { @@ -48,9 +48,9 @@ impl PledgeData { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct OriginalVestingResponse { - amount: Coin, - number_of_periods: usize, - period_duration: u64, + pub amount: Coin, + pub number_of_periods: usize, + pub period_duration: u64, } impl OriginalVestingResponse { diff --git a/common/network-defaults/src/all.rs b/common/network-defaults/src/all.rs index bdc62fe952..7c5aa135bd 100644 --- a/common/network-defaults/src/all.rs +++ b/common/network-defaults/src/all.rs @@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt, str::FromStr}; use crate::{ - DefaultNetworkDetails, ValidatorDetails, MAINNET_DEFAULTS, QA_DEFAULTS, SANDBOX_DEFAULTS, + DefaultNetworkDetails, DenomDetails, DenomDetailsOwned, ValidatorDetails, MAINNET_DEFAULTS, + QA_DEFAULTS, SANDBOX_DEFAULTS, }; use thiserror::Error; @@ -24,7 +25,7 @@ pub enum Network { } impl Network { - fn details(&self) -> &DefaultNetworkDetails<'_> { + fn details(&self) -> &DefaultNetworkDetails { match self { Self::QA => &QA_DEFAULTS, Self::SANDBOX => &SANDBOX_DEFAULTS, @@ -36,8 +37,12 @@ impl Network { self.details().bech32_prefix } - pub fn denom(&self) -> &str { - self.details().denom + pub fn mix_denom(&self) -> &DenomDetails { + &self.details().mix_denom + } + + pub fn stake_denom(&self) -> &DenomDetails { + &self.details().stake_denom } pub fn mixnet_contract_address(&self) -> &str { @@ -97,18 +102,20 @@ impl fmt::Display for Network { #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct NetworkDetails { bech32_prefix: String, - denom: String, + mix_denom: DenomDetailsOwned, + stake_denom: DenomDetailsOwned, mixnet_contract_address: String, vesting_contract_address: String, bandwidth_claim_contract_address: String, validators: Vec, } -impl From<&DefaultNetworkDetails<'_>> for NetworkDetails { - fn from(details: &DefaultNetworkDetails<'_>) -> Self { +impl From<&DefaultNetworkDetails> for NetworkDetails { + fn from(details: &DefaultNetworkDetails) -> Self { NetworkDetails { bech32_prefix: details.bech32_prefix.into(), - denom: details.denom.into(), + mix_denom: details.mix_denom.into(), + stake_denom: details.stake_denom.into(), mixnet_contract_address: details.mixnet_contract_address.into(), vesting_contract_address: details.vesting_contract_address.into(), bandwidth_claim_contract_address: details.bandwidth_claim_contract_address.into(), @@ -117,6 +124,12 @@ impl From<&DefaultNetworkDetails<'_>> for NetworkDetails { } } +impl NetworkDetails { + pub fn base_mix_denom(&self) -> &str { + &self.mix_denom.base + } +} + #[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] pub struct SupportedNetworks { networks: HashMap, @@ -141,7 +154,7 @@ impl SupportedNetworks { pub fn denom(&self, network: Network) -> Option<&str> { self.networks .get(&network) - .map(|network_details| network_details.denom.as_str()) + .map(|network_details| network_details.base_mix_denom()) } pub fn mixnet_contract_address(&self, network: Network) -> Option<&str> { diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index 66c8621843..66861fb09e 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -17,24 +17,24 @@ pub mod sandbox; cfg_if::cfg_if! { if #[cfg(network = "mainnet")] { pub const DEFAULT_NETWORK: all::Network = all::Network::MAINNET; - pub const DENOM: &str = mainnet::DENOM; - pub const STAKE_DENOM: &str = mainnet::STAKE_DENOM; + pub const MIX_DENOM: DenomDetails = mainnet::MIX_DENOM; + pub const STAKE_DENOM: DenomDetails = mainnet::STAKE_DENOM; pub const ETH_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_CONTRACT_ADDRESS; pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_ERC20_CONTRACT_ADDRESS; } else if #[cfg(network = "qa")] { pub const DEFAULT_NETWORK: all::Network = all::Network::QA; - pub const DENOM: &str = qa::DENOM; - pub const STAKE_DENOM: &str = qa::STAKE_DENOM; + pub const MIX_DENOM: DenomDetails = qa::MIX_DENOM; + pub const STAKE_DENOM: DenomDetails = qa::STAKE_DENOM; pub const ETH_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_CONTRACT_ADDRESS; pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_ERC20_CONTRACT_ADDRESS; } else if #[cfg(network = "sandbox")] { pub const DEFAULT_NETWORK: all::Network = all::Network::SANDBOX; - pub const DENOM: &str = sandbox::DENOM; - pub const STAKE_DENOM: &str = sandbox::STAKE_DENOM; + pub const MIX_DENOM: DenomDetails = sandbox::MIX_DENOM; + pub const STAKE_DENOM: DenomDetails = sandbox::STAKE_DENOM; pub const ETH_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_CONTRACT_ADDRESS; pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_ERC20_CONTRACT_ADDRESS; @@ -45,47 +45,49 @@ cfg_if::cfg_if! { // future. If we do this, and also get rid of the references we could potentially unify with // `NetworkDetails`. #[derive(Debug)] -pub struct DefaultNetworkDetails<'a> { - bech32_prefix: &'a str, - denom: &'a str, - mixnet_contract_address: &'a str, - vesting_contract_address: &'a str, - bandwidth_claim_contract_address: &'a str, - coconut_bandwidth_contract_address: &'a str, - multisig_contract_address: &'a str, - rewarding_validator_address: &'a str, +pub struct DefaultNetworkDetails { + bech32_prefix: &'static str, + mix_denom: DenomDetails, + stake_denom: DenomDetails, + mixnet_contract_address: &'static str, + vesting_contract_address: &'static str, + bandwidth_claim_contract_address: &'static str, + coconut_bandwidth_contract_address: &'static str, + multisig_contract_address: &'static str, + rewarding_validator_address: &'static str, validators: Vec, } -static MAINNET_DEFAULTS: Lazy> = - Lazy::new(|| DefaultNetworkDetails { - bech32_prefix: mainnet::BECH32_PREFIX, - denom: mainnet::DENOM, - mixnet_contract_address: mainnet::MIXNET_CONTRACT_ADDRESS, - vesting_contract_address: mainnet::VESTING_CONTRACT_ADDRESS, - bandwidth_claim_contract_address: mainnet::BANDWIDTH_CLAIM_CONTRACT_ADDRESS, - coconut_bandwidth_contract_address: mainnet::COCONUT_BANDWIDTH_CONTRACT_ADDRESS, - multisig_contract_address: mainnet::MULTISIG_CONTRACT_ADDRESS, - rewarding_validator_address: mainnet::REWARDING_VALIDATOR_ADDRESS, - validators: mainnet::validators(), - }); +static MAINNET_DEFAULTS: Lazy = Lazy::new(|| DefaultNetworkDetails { + bech32_prefix: mainnet::BECH32_PREFIX, + mix_denom: mainnet::MIX_DENOM, + stake_denom: mainnet::STAKE_DENOM, + mixnet_contract_address: mainnet::MIXNET_CONTRACT_ADDRESS, + vesting_contract_address: mainnet::VESTING_CONTRACT_ADDRESS, + bandwidth_claim_contract_address: mainnet::BANDWIDTH_CLAIM_CONTRACT_ADDRESS, + coconut_bandwidth_contract_address: mainnet::COCONUT_BANDWIDTH_CONTRACT_ADDRESS, + multisig_contract_address: mainnet::MULTISIG_CONTRACT_ADDRESS, + rewarding_validator_address: mainnet::REWARDING_VALIDATOR_ADDRESS, + validators: mainnet::validators(), +}); -static SANDBOX_DEFAULTS: Lazy> = - Lazy::new(|| DefaultNetworkDetails { - bech32_prefix: sandbox::BECH32_PREFIX, - denom: sandbox::DENOM, - mixnet_contract_address: sandbox::MIXNET_CONTRACT_ADDRESS, - vesting_contract_address: sandbox::VESTING_CONTRACT_ADDRESS, - bandwidth_claim_contract_address: sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS, - coconut_bandwidth_contract_address: sandbox::COCONUT_BANDWIDTH_CONTRACT_ADDRESS, - multisig_contract_address: sandbox::MULTISIG_CONTRACT_ADDRESS, - rewarding_validator_address: sandbox::REWARDING_VALIDATOR_ADDRESS, - validators: sandbox::validators(), - }); +static SANDBOX_DEFAULTS: Lazy = Lazy::new(|| DefaultNetworkDetails { + bech32_prefix: sandbox::BECH32_PREFIX, + mix_denom: sandbox::MIX_DENOM, + stake_denom: sandbox::STAKE_DENOM, + mixnet_contract_address: sandbox::MIXNET_CONTRACT_ADDRESS, + vesting_contract_address: sandbox::VESTING_CONTRACT_ADDRESS, + bandwidth_claim_contract_address: sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS, + coconut_bandwidth_contract_address: sandbox::COCONUT_BANDWIDTH_CONTRACT_ADDRESS, + multisig_contract_address: sandbox::MULTISIG_CONTRACT_ADDRESS, + rewarding_validator_address: sandbox::REWARDING_VALIDATOR_ADDRESS, + validators: sandbox::validators(), +}); -static QA_DEFAULTS: Lazy> = Lazy::new(|| DefaultNetworkDetails { +static QA_DEFAULTS: Lazy = Lazy::new(|| DefaultNetworkDetails { bech32_prefix: qa::BECH32_PREFIX, - denom: qa::DENOM, + mix_denom: qa::MIX_DENOM, + stake_denom: qa::STAKE_DENOM, mixnet_contract_address: qa::MIXNET_CONTRACT_ADDRESS, vesting_contract_address: qa::VESTING_CONTRACT_ADDRESS, bandwidth_claim_contract_address: qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS, @@ -95,6 +97,42 @@ static QA_DEFAULTS: Lazy> = Lazy::new(|| DefaultN validators: qa::validators(), }); +#[derive(Debug, Copy, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub struct DenomDetails { + pub base: &'static str, + pub display: &'static str, + // i.e. display_amount * 10^display_exponent = base_amount + pub display_exponent: u32, +} + +impl DenomDetails { + pub const fn new(base: &'static str, display: &'static str, display_exponent: u32) -> Self { + DenomDetails { + base, + display, + display_exponent, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub struct DenomDetailsOwned { + pub base: String, + pub display: String, + // i.e. display_amount * 10^display_exponent = base_amount + pub display_exponent: u32, +} + +impl From for DenomDetailsOwned { + fn from(details: DenomDetails) -> Self { + DenomDetailsOwned { + base: details.base.to_owned(), + display: details.display.to_owned(), + display_exponent: details.display_exponent, + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct ValidatorDetails { // it is assumed those values are always valid since they're being provided in our defaults file diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index 0e9f16eb05..908270613f 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -1,11 +1,13 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::ValidatorDetails; +use crate::{DenomDetails, ValidatorDetails}; pub(crate) const BECH32_PREFIX: &str = "n"; pub const DENOM: &str = "unym"; -pub const STAKE_DENOM: &str = "unyx"; + +pub const MIX_DENOM: DenomDetails = DenomDetails::new("unym", "nym", 6); +pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6); pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g"; diff --git a/common/network-defaults/src/qa.rs b/common/network-defaults/src/qa.rs index c782e089ab..408cb5a0b5 100644 --- a/common/network-defaults/src/qa.rs +++ b/common/network-defaults/src/qa.rs @@ -1,11 +1,13 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::ValidatorDetails; +use crate::{DenomDetails, ValidatorDetails}; pub(crate) const BECH32_PREFIX: &str = "n"; pub const DENOM: &str = "unym"; -pub const STAKE_DENOM: &str = "unyx"; + +pub const MIX_DENOM: DenomDetails = DenomDetails::new("unym", "nym", 6); +pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6); pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep"; diff --git a/common/network-defaults/src/sandbox.rs b/common/network-defaults/src/sandbox.rs index a6cfc39514..4f1fe651ec 100644 --- a/common/network-defaults/src/sandbox.rs +++ b/common/network-defaults/src/sandbox.rs @@ -1,11 +1,13 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::ValidatorDetails; +use crate::{DenomDetails, ValidatorDetails}; pub(crate) const BECH32_PREFIX: &str = "nymt"; pub const DENOM: &str = "unymt"; -pub const STAKE_DENOM: &str = "unyxt"; + +pub const MIX_DENOM: DenomDetails = DenomDetails::new("unymt", "nymt", 6); +pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyxt", "nyxt", 6); pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j"; pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt14ejqjyq8um4p3xfqj74yld5waqljf88fn549lh"; diff --git a/common/types/src/account.rs b/common/types/src/account.rs index 00ec29a703..22887a897b 100644 --- a/common/types/src/account.rs +++ b/common/types/src/account.rs @@ -1,4 +1,4 @@ -use crate::currency::{CurrencyDenom, MajorCurrencyAmount}; +use crate::currency::{DecCoin, Denom}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -9,13 +9,16 @@ use serde::{Deserialize, Serialize}; )] #[derive(Serialize, Deserialize, JsonSchema)] pub struct Account { + // TODO: discuss with @MS whether it makes sense: + // 1. why are we restricting to single denom here? What if user holds both stake and mix currencies? + // 2. what's the `contract_address`? is it mixnet? vesting? coconut? why does it relate to an account anyway? pub contract_address: String, pub client_address: String, - pub denom: CurrencyDenom, + pub denom: Denom, } impl Account { - pub fn new(contract_address: String, client_address: String, denom: CurrencyDenom) -> Self { + pub fn new(contract_address: String, client_address: String, denom: Denom) -> Self { Account { contract_address, client_address, @@ -53,6 +56,15 @@ pub struct AccountEntry { )] #[derive(Serialize, Deserialize)] pub struct Balance { - pub amount: MajorCurrencyAmount, + pub amount: DecCoin, pub printable_balance: String, } + +impl Balance { + pub fn new(amount: DecCoin) -> Self { + Balance { + printable_balance: amount.to_string(), + amount, + } + } +} diff --git a/common/types/src/currency.rs b/common/types/src/currency.rs index 568b9ed3b8..183510193f 100644 --- a/common/types/src/currency.rs +++ b/common/types/src/currency.rs @@ -1,22 +1,26 @@ use crate::error::TypesError; -use cosmrs::Denom as CosmosDenom; -use cosmwasm_std::Coin as CosmWasmCoin; +use config::defaults::all::Network; +use config::defaults::DenomDetails; +use cosmwasm_std::Fraction; use cosmwasm_std::{Decimal, Uint128}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use std::cmp::Ordering; +use std::collections::HashMap; use std::convert::TryFrom; use std::fmt::{Display, Formatter}; -use std::ops::{Add, Mul}; -use std::str::FromStr; use strum::{Display, EnumString, EnumVariantNames}; -use validator_client::nymd::{Coin, CosmosCoin}; +use validator_client::nymd::Coin; + +#[cfg(feature = "generate-ts")] +use ts_rs::{Dependency, TS}; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", ts(export_to = "ts-packages/types/src/types/rust/CurrencyDenom.ts") )] -#[cfg_attr(feature = "generate-ts", ts(rename_all = "UPPERCASE"))] +#[cfg_attr(feature = "generate-ts", ts(rename_all = "lowercase"))] #[derive( Display, Serialize, @@ -28,9 +32,8 @@ use validator_client::nymd::{Coin, CosmosCoin}; PartialEq, JsonSchema, )] -#[serde(rename_all = "UPPERCASE")] -#[strum(serialize_all = "UPPERCASE")] -// TODO: this shouldn't be an enum... +#[serde(rename_all = "lowercase")] +#[strum(serialize_all = "lowercase")] pub enum CurrencyDenom { #[strum(ascii_case_insensitive)] Nym, @@ -42,474 +45,460 @@ pub enum CurrencyDenom { Nyxt, } -impl CurrencyDenom { - pub fn parse(value: &str) -> Result { - let mut denom = value.to_string(); - if denom.starts_with('u') { - denom = denom[1..].to_string(); +pub type Denom = String; + +#[derive(Debug, Default)] +pub struct RegisteredCoins(HashMap); + +impl RegisteredCoins { + pub fn default_denoms(network: Network) -> Self { + let mut network_coins = HashMap::new(); + network_coins.insert( + network.mix_denom().base.into(), + (*network.mix_denom()).into(), + ); + network_coins.insert( + network.stake_denom().base.into(), + (*network.stake_denom()).into(), + ); + RegisteredCoins(network_coins) + } + + pub fn insert(&mut self, denom: Denom, metadata: CoinMetadata) -> Option { + self.0.insert(denom, metadata) + } + + pub fn remove(&mut self, denom: &Denom) -> Option { + self.0.remove(denom) + } + + pub fn attempt_convert_to_base_coin(&self, coin: DecCoin) -> Result { + // check if this is already in the base denom + if self.0.contains_key(&coin.denom) { + // if we're converting a base DecCoin it CANNOT fail, unless somebody is providing + // bullshit data on purpose : ) + return coin.try_into(); + } else { + // TODO: this kinda suggests we may need a better data structure + for registered_coin in self.0.values() { + if let Some(exponent) = registered_coin.get_exponent(&coin.denom) { + let amount = try_convert_decimal_to_u128(coin.try_scale_up_value(exponent)?)?; + return Ok(Coin::new(amount, ®istered_coin.base)); + } + } } - match CurrencyDenom::from_str(&denom) { - Ok(res) => Ok(res), - Err(_e) => Err(TypesError::InvalidDenom(value.to_string())), + Err(TypesError::UnknownCoinDenom(coin.denom)) + } + + pub fn attempt_convert_to_display_dec_coin(&self, coin: Coin) -> Result { + for registered_coin in self.0.values() { + if let Some(exponent) = registered_coin.get_exponent(&coin.denom) { + // if this fails it means we haven't registered our display denom which honestly should never be the case + // unless somebody is rocking their own custom network + let display_exponent = registered_coin + .get_exponent(®istered_coin.display) + .ok_or_else(|| TypesError::UnknownCoinDenom(coin.denom.clone()))?; + + return match exponent.cmp(&display_exponent) { + Ordering::Greater => { + // we need to scale up, unlikely to ever be needed but included for completion sake, + // for example if we decided to created knym with exponent 9 and wanted to convert to nym with exponent 6 + Ok(DecCoin::new_scaled_up( + coin.amount, + ®istered_coin.display, + exponent - display_exponent, + )?) + } + // we're already in the display denom + Ordering::Equal => Ok(coin.into()), + Ordering::Less => { + // we need to scale down, the most common case, for example we're in base unym with exponent 0 and want to convert to nym with exponent 6 + Ok(DecCoin::new_scaled_down( + coin.amount, + ®istered_coin.display, + display_exponent - exponent, + )?) + } + }; + } } + + Err(TypesError::UnknownCoinDenom(coin.denom)) } } -impl TryFrom for CurrencyDenom { - type Error = TypesError; +// TODO: should this live here? +// attempts to replicate cosmos-sdk's coin metadata +// https://docs.cosmos.network/master/architecture/adr-024-coin-metadata.html +// this way we could more easily handle multiple coin types simultaneously (like nym/nyx/nymt/nyx + local currencies) +#[derive(Debug)] +pub struct DenomUnit { + pub denom: Denom, + pub exponent: u32, + // pub aliases: Vec, +} - fn try_from(value: CosmosDenom) -> Result { - CurrencyDenom::parse(&value.to_string()) +impl DenomUnit { + pub fn new(denom: Denom, exponent: u32) -> Self { + DenomUnit { denom, exponent } } } -#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] -#[cfg_attr( - feature = "generate-ts", - ts(export_to = "ts-packages/types/src/types/rust/CurrencyStringMajorAmount.ts") -)] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct MajorAmountString(String); // see https://github.com/Aleph-Alpha/ts-rs/issues/51 for exporting type aliases - -#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] -#[cfg_attr( - feature = "generate-ts", - ts(export_to = "ts-packages/types/src/types/rust/Currency.ts") -)] -// #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct MajorCurrencyAmount { - // temporarly going back to original impl to speed up merge - pub amount: MajorAmountString, - pub denom: CurrencyDenom, - // // temporary... - // #[cfg_attr(feature = "generate-ts", ts(skip))] - // pub coin: Coin, +#[derive(Debug)] +pub struct CoinMetadata { + pub denom_units: Vec, + pub base: Denom, + pub display: Denom, } -// impl JsonSchema for MajorCurrencyAmount { -// fn schema_name() -> String { -// todo!() -// } -// -// fn json_schema(gen: &mut SchemaGenerator) -> Schema { -// todo!() -// } -// } +impl CoinMetadata { + pub fn new(denom_units: Vec, base: Denom, display: Denom) -> Self { + CoinMetadata { + denom_units, + base, + display, + } + } + + pub fn get_exponent(&self, denom: &str) -> Option { + self.denom_units + .iter() + .find(|denom_unit| denom_unit.denom == denom) + .map(|denom_unit| denom_unit.exponent) + } +} + +impl From for CoinMetadata { + fn from(denom_details: DenomDetails) -> Self { + CoinMetadata::new( + vec![ + DenomUnit::new(denom_details.base.into(), 0), + DenomUnit::new(denom_details.display.into(), denom_details.display_exponent), + ], + denom_details.base.into(), + denom_details.display.into(), + ) + } +} // tries to semi-replicate cosmos-sdk's DecCoin for being able to handle tokens with decimal amounts // https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/types/dec_coin.go +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct DecCoin { - // + pub denom: Denom, + // Decimal is already serialized to string and using string in its schema, so lets also go straight to string for ts_rs + // todo: is `Decimal` the correct type to use? Do we want to depend on cosmwasm_std here? + pub amount: Decimal, } -impl MajorCurrencyAmount { - pub fn new(amount: &str, denom: CurrencyDenom) -> MajorCurrencyAmount { - MajorCurrencyAmount { - amount: MajorAmountString(amount.to_string()), - denom, +// I had to implement it manually to correctly set dependencies +#[cfg(feature = "generate-ts")] +impl TS for DecCoin { + const EXPORT_TO: Option<&'static str> = Some("ts-packages/types/src/types/rust/DecCoin.ts"); + + fn decl() -> String { + format!("type {} = {};", Self::name(), Self::inline()) + } + + fn name() -> String { + "DecCoin".into() + } + + fn inline() -> String { + "{ denom: CurrencyDenom, amount: string }".into() + } + + fn dependencies() -> Vec { + vec![Dependency::from_ty::() + .expect("TS was incorrectly defined on `CurrencyDenom`")] + } + + fn transparent() -> bool { + false + } +} + +impl DecCoin { + pub fn new_base>(amount: impl Into, denom: S) -> Self { + DecCoin { + denom: denom.into(), + amount: Decimal::from_atomics(amount, 0).unwrap(), } } - pub fn zero(denom: &CurrencyDenom) -> MajorCurrencyAmount { - MajorCurrencyAmount::new("0", denom.clone()) + pub fn zero>(denom: S) -> Self { + DecCoin { + denom: denom.into(), + amount: Decimal::zero(), + } } - // - // pub fn from_cosmrs_coin(coin: &CosmosCoin) -> Result { - // MajorCurrencyAmount::from_cosmrs_decimal_and_denom(coin.amount, coin.denom.to_string()) - // } - // - // pub fn from_minor_uint128_and_denom( - // amount_minor: Uint128, - // denom_minor: &str, - // ) -> Result { - // MajorCurrencyAmount::from_minor_decimal_and_denom( - // Decimal::from_atomics(amount_minor, 0)?, - // denom_minor, - // ) - // } - // - // pub fn from_minor_decimal_and_denom( - // amount_minor: Decimal, - // denom_minor: &str, - // ) -> Result { - // if !(denom_minor.starts_with('u') || denom_minor.starts_with('U')) { - // return Err(TypesError::InvalidDenom(denom_minor.to_string())); - // } - // let major = amount_minor / Uint128::from(1_000_000u64); - // if let Ok(denom) = CurrencyDenom::from_str(&denom_minor[1..].to_string()) { - // return Ok(MajorCurrencyAmount { - // amount: MajorAmountString(major.to_string()), - // denom, - // }); - // } - // Err(TypesError::InvalidDenom(denom_minor.to_string())) - // } - // pub fn from_decimal_and_denom( - // amount: Decimal, - // denom: String, - // ) -> Result { - // if denom.starts_with('u') || denom.starts_with('U') { - // return MajorCurrencyAmount::from_minor_decimal_and_denom(amount, &denom); - // } - // if let Ok(denom) = CurrencyDenom::from_str(denom.as_str()) { - // return Ok(MajorCurrencyAmount { - // amount: MajorAmountString(amount.to_string()), - // denom, - // }); - // } - // Err(TypesError::InvalidDenom(denom)) - // } - // pub fn from_cosmrs_decimal_and_denom( - // amount: CosmosDecimal, - // denom: String, - // ) -> Result { - // if denom.starts_with('u') || denom.starts_with('U') { - // return match Decimal::from_str(&amount.to_string()) { - // Ok(amount) => MajorCurrencyAmount::from_minor_decimal_and_denom(amount, &denom), - // Err(_e) => Err(TypesError::InvalidAmount(amount.to_string())), - // }; - // } - // - // if let Ok(denom) = CurrencyDenom::from_str(denom.as_str()) { - // return Ok(MajorCurrencyAmount { - // amount: MajorAmountString(amount.to_string()), - // denom, - // }); - // } - // Err(TypesError::InvalidDenom(denom)) - // } - // - // pub fn into_cosmos_coin(self) -> CosmosCoin { - // self.coin.into() - // } - // - // pub fn to_minor_uint128(&self) -> Result { - // if self.amount.0.contains('.') { - // // has a decimal point (Cosmos assumes "." is the decimal separator) - // let parts = self.amount.0.split('.'); - // let str = parts.collect_vec(); - // if str.is_empty() || str.len() > 2 { - // return Err(TypesError::InvalidAmount("Amount is invalid".to_string())); - // } - // if str.len() == 2 { - // // has a decimal, so check decimal places first - // if str[1].len() > 6 { - // return Err(TypesError::InvalidDenom( - // "Amount is invalid, only 6 decimal places of precision are allowed" - // .to_string(), - // )); - // } - // - // // so multiple whole part by 1e6 and add decimal part - // let whole_part = Uint128::from_str(str[0])? * Uint128::from(1_000_000u64); - // - // // TODO: has Rust got anything that deals with fixed point values, or parsing from format strings? Leading zeroes are causing issues - // return match format!("0.{}", str[1]).parse::() { - // Ok(decimal_part_float) => { - // // this makes an assumption that 6 decimal places of f64 can never lose precision - // let truncated = (decimal_part_float * 1_000_000.).trunc() as u32; - // let decimal_part = Uint128::from(truncated); - // let sum = whole_part + decimal_part; - // Ok(sum) - // } - // Err(_e) => Err(TypesError::InvalidAmount( - // "Amount decimal part is invalid".to_string(), - // )), - // }; - // } - // } - // - // let major = Uint128::from_str(&self.amount.0)?; - // let scaled = major * Uint128::new(1_000_000u128); - // Ok(scaled) - // } - // pub fn denom_to_string(&self) -> String { - // self.denom.to_string() - // } + pub fn new_scaled_up>( + base_amount: impl Into, + denom: S, + exponent: u32, + ) -> Result { + let base_amount = Decimal::from_atomics(base_amount, 0).unwrap(); + Ok(DecCoin { + denom: denom.into(), + amount: try_scale_up_decimal(base_amount, exponent)?, + }) + } + + pub fn new_scaled_down>( + base_amount: impl Into, + denom: S, + exponent: u32, + ) -> Result { + let base_amount = Decimal::from_atomics(base_amount, 0).unwrap(); + Ok(DecCoin { + denom: denom.into(), + amount: try_scale_down_decimal(base_amount, exponent)?, + }) + } + + pub fn try_scale_down_value(&self, exponent: u32) -> Result { + try_scale_down_decimal(self.amount, exponent) + } + + pub fn try_scale_up_value(&self, exponent: u32) -> Result { + try_scale_up_decimal(self.amount, exponent) + } } -impl Display for MajorCurrencyAmount { +// TODO: should thoese live here? +pub fn try_scale_down_decimal(dec: Decimal, exponent: u32) -> Result { + let rhs = 10u128 + .checked_pow(exponent) + .ok_or(TypesError::UnsupportedExponent(exponent))?; + let denominator = dec + .denominator() + .checked_mul(rhs.into()) + .map_err(|_| TypesError::UnsupportedExponent(exponent))?; + + Ok(Decimal::from_ratio(dec.numerator(), denominator)) +} + +pub fn try_scale_up_decimal(dec: Decimal, exponent: u32) -> Result { + let rhs = 10u128 + .checked_pow(exponent) + .ok_or(TypesError::UnsupportedExponent(exponent))?; + let denominator = dec + .denominator() + .checked_div(rhs.into()) + .map_err(|_| TypesError::UnsupportedExponent(exponent))?; + + Ok(Decimal::from_ratio(dec.numerator(), denominator)) +} + +pub fn try_convert_decimal_to_u128(dec: Decimal) -> Result { + let whole = dec.numerator() / dec.denominator(); + + // unwrap is fine as we're not dividing by zero here + let fractional = (dec.numerator()).checked_rem(dec.denominator()).unwrap(); + + // we cannot convert as we'd lose our decimal places + // (for example if somebody attempted to represent our gas price (WHICH YOU SHOULDN'T DO) as DecCoin) + if fractional != Uint128::zero() { + return Err(TypesError::LossyCoinConversion); + } + Ok(whole.u128()) +} + +// TODO: adjust the implementation to as required by @MS or @FT +impl Display for DecCoin { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{} {}", self.amount.0, self.denom) + write!(f, "{}{}", self.amount, self.denom) } } -// TODO: cleanup after merge -impl From for MajorCurrencyAmount { - fn from(c: CosmosCoin) -> Self { - MajorCurrencyAmount::from(Coin::from(c)) - } -} - -impl From for MajorCurrencyAmount { - fn from(c: CosmWasmCoin) -> Self { - MajorCurrencyAmount::from(Coin::from(c)) - } -} - -impl From for MajorCurrencyAmount { +impl From for DecCoin { fn from(coin: Coin) -> Self { - // current assumption: MajorCurrencyAmount is represented as decimal with 6 decimal points - // unwrap is fine as we haven't exceeded decimal range since our coins are at max 1B in value - // (this is a weak assumption, but for solving this merge conflict it's good enough temporary workaround) - let amount = Decimal::from_atomics(coin.amount, 6).unwrap(); - MajorCurrencyAmount { - amount: MajorAmountString(amount.to_string()), - denom: CurrencyDenom::parse(&coin.denom).expect("this will go away after the merge..."), - } + DecCoin::new_base(coin.amount, coin.denom) } } -// temporary... -impl From for CosmosCoin { - fn from(c: MajorCurrencyAmount) -> CosmosCoin { - let c: Coin = c.into(); - c.into() - } -} +// this conversion assumes same denomination +impl TryFrom for Coin { + type Error = TypesError; -impl From for CosmWasmCoin { - fn from(c: MajorCurrencyAmount) -> CosmWasmCoin { - let c: Coin = c.into(); - c.into() - } -} - -impl From for Coin { - fn from(c: MajorCurrencyAmount) -> Coin { - let decimal: Decimal = c - .amount - .0 - .parse() - .expect("stringified amount should have been a valid decimal"); - - // again, temporary - let exp = Uint128::new(1000000); - let val = decimal.mul(exp); - - // again, terrible assumption for denom, but it works temporarily... - Coin { - amount: val.u128(), - denom: format!("u{}", c.denom).to_lowercase(), - } - } -} - -impl Add for MajorCurrencyAmount { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - // again, temporary workaround to help with merge - (Coin::from(self).try_add(&Coin::from(rhs))) - .expect("provided coins had different denoms") - .into() + fn try_from(value: DecCoin) -> Result { + Ok(Coin { + amount: try_convert_decimal_to_u128(value.try_scale_down_value(0)?)?, + denom: value.denom, + }) } } #[cfg(test)] mod test { use super::*; - use cosmrs::Coin as CosmosCoin; - use cosmrs::Decimal as CosmosDecimal; - use cosmrs::Denom as CosmosDenom; - use cosmwasm_std::Coin as CosmWasmCoin; - use cosmwasm_std::Decimal as CosmWasmDecimal; - use serde_json::json; use std::convert::TryFrom; - use std::str::FromStr; use std::string::ToString; #[test] - fn json_to_major_currency_amount() { - let nym = json!({ - "amount": "1", - "denom": "NYM" - }); - let nymt = json!({ - "amount": "1", - "denom": "NYMT" - }); + fn dec_value_scale_down() { + let dec = DecCoin { + denom: "foo".to_string(), + amount: "1234007000".parse().unwrap(), + }; - let test_nym_amount = MajorCurrencyAmount::new("1", CurrencyDenom::Nym); - let test_nymt_amount = MajorCurrencyAmount::new("1", CurrencyDenom::Nymt); - - let nym_amount = serde_json::from_value::(nym).unwrap(); - let nymt_amount = serde_json::from_value::(nymt).unwrap(); - - assert_eq!(nym_amount, test_nym_amount); - assert_eq!(nymt_amount, test_nymt_amount); - } - - #[test] - fn minor_amount_json_to_major_currency_amount() { - let one_micro_nym = json!({ - "amount": "0.000001", - "denom": "NYM" - }); - - let expected_nym_amount = MajorCurrencyAmount::new("0.000001", CurrencyDenom::Nym); - let actual_nym_amount = - serde_json::from_value::(one_micro_nym).unwrap(); - - assert_eq!(expected_nym_amount, actual_nym_amount); - } - - #[test] - fn denom_from_str() { - assert_eq!(CurrencyDenom::from_str("nym").unwrap(), CurrencyDenom::Nym); assert_eq!( - CurrencyDenom::from_str("nymt").unwrap(), - CurrencyDenom::Nymt - ); - assert_eq!(CurrencyDenom::from_str("NYM").unwrap(), CurrencyDenom::Nym); - assert_eq!( - CurrencyDenom::from_str("NYMT").unwrap(), - CurrencyDenom::Nymt - ); - assert_eq!(CurrencyDenom::from_str("NyM").unwrap(), CurrencyDenom::Nym); - assert_eq!( - CurrencyDenom::from_str("NYmt").unwrap(), - CurrencyDenom::Nymt - ); - - assert!(matches!( - CurrencyDenom::from_str("foo").unwrap_err(), - strum::ParseError::VariantNotFound, - )); - - // denominations must all be major - assert!(matches!( - CurrencyDenom::from_str("unym").unwrap_err(), - strum::ParseError::VariantNotFound, - )); - assert!(matches!( - CurrencyDenom::from_str("unymt").unwrap_err(), - strum::ParseError::VariantNotFound, - )); - } - - #[test] - fn to_string() { - assert_eq!( - MajorCurrencyAmount::new("1", CurrencyDenom::Nym).to_string(), - "1 NYM" + "1234007000".parse::().unwrap(), + dec.try_scale_down_value(0).unwrap() ); assert_eq!( - MajorCurrencyAmount::new("1", CurrencyDenom::Nymt).to_string(), - "1 NYMT" + "123400700".parse::().unwrap(), + dec.try_scale_down_value(1).unwrap() ); assert_eq!( - MajorCurrencyAmount::new("1000000000000", CurrencyDenom::Nym).to_string(), - "1000000000000 NYM" + "12340070".parse::().unwrap(), + dec.try_scale_down_value(2).unwrap() + ); + assert_eq!( + "123400.7".parse::().unwrap(), + dec.try_scale_down_value(4).unwrap() + ); + + let dec = DecCoin { + denom: "foo".to_string(), + amount: "10000000000".parse().unwrap(), + }; + + assert_eq!( + "100".parse::().unwrap(), + dec.try_scale_down_value(8).unwrap() + ); + assert_eq!( + "1".parse::().unwrap(), + dec.try_scale_down_value(10).unwrap() + ); + assert_eq!( + "0.01".parse::().unwrap(), + dec.try_scale_down_value(12).unwrap() ); } #[test] - fn minor_coin_to_major_currency() { - let cosmos_coin = CosmosCoin { - amount: CosmosDecimal::from(1u64), - denom: CosmosDenom::from_str("unym").unwrap(), + fn dec_value_scale_up() { + let dec = DecCoin { + denom: "foo".to_string(), + amount: "1234.56".parse().unwrap(), }; - let c = MajorCurrencyAmount::from(cosmos_coin); - assert_eq!(c, MajorCurrencyAmount::new("0.000001", CurrencyDenom::Nym)); - } - #[test] - fn minor_cosmwasm_coin_to_major_currency() { - let coin = CosmWasmCoin { - amount: Uint128::from(1u64), - denom: "unym".to_string(), - }; - println!( - "from_atomics = {}", - CosmWasmDecimal::from_atomics(coin.amount.clone(), 6) - .unwrap() - .to_string() + assert_eq!( + "1234.56".parse::().unwrap(), + dec.try_scale_up_value(0).unwrap() ); - let c: MajorCurrencyAmount = coin.into(); - assert_eq!(c, MajorCurrencyAmount::new("0.000001", CurrencyDenom::Nym)); - } - - #[test] - fn minor_cosmwasm_coin_to_major_currency_2() { - let coin = CosmWasmCoin { - amount: Uint128::from(1_000_000u64), - denom: "unym".to_string(), - }; - println!( - "from_atomics = {:?}", - CosmWasmDecimal::from_atomics(coin.amount.clone(), 6) - .unwrap() - .to_string() + assert_eq!( + "12345.6".parse::().unwrap(), + dec.try_scale_up_value(1).unwrap() + ); + assert_eq!( + "123456".parse::().unwrap(), + dec.try_scale_up_value(2).unwrap() + ); + assert_eq!( + "1234560".parse::().unwrap(), + dec.try_scale_up_value(3).unwrap() + ); + assert_eq!( + "12345600".parse::().unwrap(), + dec.try_scale_up_value(4).unwrap() ); - let c: MajorCurrencyAmount = coin.into(); - assert_eq!(c, MajorCurrencyAmount::new("1", CurrencyDenom::Nym)); - } - #[test] - fn major_currency_to_minor_cosmos_coin() { - let expected_cosmos_coin = CosmosCoin { - amount: CosmosDecimal::from(1u64), - denom: CosmosDenom::from_str("unym").unwrap(), + let dec = DecCoin { + denom: "foo".to_string(), + amount: "0.00000123".parse().unwrap(), }; - let c = MajorCurrencyAmount::new("0.000001", CurrencyDenom::Nym); - let minor_cosmos_coin = c.into(); - assert_eq!(expected_cosmos_coin, minor_cosmos_coin); - assert_eq!("unym", minor_cosmos_coin.denom.to_string()); + + assert_eq!( + "0.0000123".parse::().unwrap(), + dec.try_scale_up_value(1).unwrap() + ); + assert_eq!( + "0.000123".parse::().unwrap(), + dec.try_scale_up_value(2).unwrap() + ); + assert_eq!( + "123".parse::().unwrap(), + dec.try_scale_up_value(8).unwrap() + ); + assert_eq!( + "1230".parse::().unwrap(), + dec.try_scale_up_value(9).unwrap() + ); + assert_eq!( + "12300".parse::().unwrap(), + dec.try_scale_up_value(10).unwrap() + ); } #[test] - fn major_currency_to_minor_cosmos_coin_2() { - let expected_cosmos_coin = CosmosCoin { - amount: CosmosDecimal::from(1000000u64), - denom: CosmosDenom::from_str("unym").unwrap(), + fn coin_to_dec_coin() { + let coin = Coin::new(123, "foo"); + let dec = DecCoin::from(coin.clone()); + assert_eq!(coin.denom, dec.denom); + assert_eq!(dec.amount, Decimal::from_atomics(coin.amount, 0).unwrap()); + } + + #[test] + fn dec_coin_to_coin() { + let dec = DecCoin { + denom: "foo".to_string(), + amount: "123".parse().unwrap(), }; - let c = MajorCurrencyAmount::new("1", CurrencyDenom::Nym); - let minor_cosmos_coin = c.into(); - assert_eq!(expected_cosmos_coin, minor_cosmos_coin); - assert_eq!("unym", minor_cosmos_coin.denom.to_string()); + let coin = Coin::try_from(dec.clone()).unwrap(); + assert_eq!(dec.denom, coin.denom); + assert_eq!(coin.amount, 123u128); } #[test] - fn minor_cosmos_coin_to_major_currency_string() { - // check minor cosmos coin is converted to major value - let cosmos_coin = CosmosCoin { - amount: CosmosDecimal::from(1u64), - denom: CosmosDenom::from_str("unym").unwrap(), - }; - let c = MajorCurrencyAmount::from(cosmos_coin); - assert_eq!(c.to_string(), "0.000001 NYM"); + fn converting_to_display() { + let reg = RegisteredCoins::default_denoms(Network::MAINNET); + let values = vec![ + (1u128, "0.000001"), + (10u128, "0.00001"), + (100u128, "0.0001"), + (1000u128, "0.001"), + (10000u128, "0.01"), + (100000u128, "0.1"), + (1000000u128, "1"), + (1234567u128, "1.234567"), + (123456700u128, "123.4567"), + ]; + + for (raw, expected) in values { + let coin = Coin::new(raw, Network::MAINNET.mix_denom().base); + let display = reg.attempt_convert_to_display_dec_coin(coin).unwrap(); + assert_eq!(Network::MAINNET.mix_denom().display, display.denom); + assert_eq!(expected, display.amount.to_string()); + } } #[test] - fn denom_to_string() { - let c = MajorCurrencyAmount::new("1", CurrencyDenom::Nym); - let denom = c.denom.to_string(); - assert_eq!(denom, "NYM".to_string()); - } + fn converting_to_base() { + let reg = RegisteredCoins::default_denoms(Network::MAINNET); + let values = vec![ + (1u128, "0.000001"), + (10u128, "0.00001"), + (100u128, "0.0001"), + (1000u128, "0.001"), + (10000u128, "0.01"), + (100000u128, "0.1"), + (1000000u128, "1"), + (1234567u128, "1.234567"), + (123456700u128, "123.4567"), + ]; - fn amounts() -> Vec<&'static str> { - vec![ - "1", - "10", - "100", - "1000", - "10000", - "100000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - ] + for (expected, raw_display) in values { + let coin = DecCoin { + denom: Network::MAINNET.mix_denom().display.into(), + amount: raw_display.parse().unwrap(), + }; + let base = reg.attempt_convert_to_base_coin(coin).unwrap(); + assert_eq!(Network::MAINNET.mix_denom().base, base.denom); + assert_eq!(expected, base.amount); + } } } diff --git a/common/types/src/delegation.rs b/common/types/src/delegation.rs index 8b273529dd..faadc16ab5 100644 --- a/common/types/src/delegation.rs +++ b/common/types/src/delegation.rs @@ -1,13 +1,10 @@ -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use log::error; +use crate::currency::{DecCoin, RegisteredCoins}; +use crate::error::TypesError; use mixnet_contract_common::mixnode::DelegationEvent as ContractDelegationEvent; use mixnet_contract_common::mixnode::PendingUndelegate as ContractPendingUndelegate; use mixnet_contract_common::Delegation as MixnetContractDelegation; - -use crate::currency::MajorCurrencyAmount; -use crate::error::TypesError; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( @@ -18,31 +15,22 @@ use crate::error::TypesError; pub struct Delegation { pub owner: String, pub node_identity: String, - pub amount: MajorCurrencyAmount, + pub amount: DecCoin, pub block_height: u64, - pub proxy: Option, // proxy address used to delegate the funds on behalf of anouther address + pub proxy: Option, // proxy address used to delegate the funds on behalf of another address } -impl TryFrom for Delegation { - type Error = TypesError; - - fn try_from(value: MixnetContractDelegation) -> Result { - let MixnetContractDelegation { - owner, - node_identity, - amount, - block_height, - proxy, - } = value; - - let amount: MajorCurrencyAmount = amount.into(); - +impl Delegation { + pub fn from_mixnet_contract( + delegation: MixnetContractDelegation, + reg: &RegisteredCoins, + ) -> Result { Ok(Delegation { - owner: owner.into_string(), - node_identity, - amount, - block_height, - proxy: proxy.map(|p| p.into_string()), + owner: delegation.owner.to_string(), + node_identity: delegation.node_identity, + amount: reg.attempt_convert_to_display_dec_coin(delegation.amount.into())?, + block_height: delegation.block_height, + proxy: delegation.proxy.map(|d| d.to_string()), }) } } @@ -54,7 +42,7 @@ impl TryFrom for Delegation { )] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)] pub struct DelegationRecord { - pub amount: MajorCurrencyAmount, + pub amount: DecCoin, pub block_height: u64, pub delegated_on_iso_datetime: String, } @@ -68,16 +56,16 @@ pub struct DelegationRecord { pub struct DelegationWithEverything { pub owner: String, pub node_identity: String, - pub amount: MajorCurrencyAmount, - pub total_delegation: Option, - pub pledge_amount: Option, + pub amount: DecCoin, + pub total_delegation: Option, + pub pledge_amount: Option, pub block_height: u64, pub delegated_on_iso_datetime: String, pub profit_margin_percent: Option, pub avg_uptime_percent: Option, pub stake_saturation: Option, pub proxy: Option, - pub accumulated_rewards: Option, + pub accumulated_rewards: Option, pub pending_events: Vec, pub history: Vec, } @@ -91,34 +79,7 @@ pub struct DelegationWithEverything { pub struct DelegationResult { source_address: String, target_address: String, - amount: Option, -} - -impl DelegationResult { - pub fn new( - source_address: &str, - target_address: &str, - amount: Option, - ) -> DelegationResult { - DelegationResult { - source_address: source_address.to_string(), - target_address: target_address.to_string(), - amount, - } - } -} - -impl TryFrom for DelegationResult { - type Error = TypesError; - - fn try_from(delegation: MixnetContractDelegation) -> Result { - let amount: MajorCurrencyAmount = delegation.amount.clone().into(); - Ok(DelegationResult { - source_address: delegation.owner().to_string(), - target_address: delegation.node_identity(), - amount: Some(amount), - }) - } + amount: Option, } #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] @@ -142,33 +103,31 @@ pub struct DelegationEvent { pub kind: DelegationEventKind, pub node_identity: String, pub address: String, - pub amount: Option, + pub amount: Option, pub block_height: u64, } -impl TryFrom for DelegationEvent { - type Error = TypesError; - - fn try_from(event: ContractDelegationEvent) -> Result { - match event { - ContractDelegationEvent::Delegate(delegation) => { - let amount: MajorCurrencyAmount = delegation.amount.into(); - Ok(DelegationEvent { - kind: DelegationEventKind::Delegate, - block_height: delegation.block_height, - address: delegation.owner.into_string(), - node_identity: delegation.node_identity, - amount: Some(amount), - }) - } - ContractDelegationEvent::Undelegate(pending_undelegate) => Ok(DelegationEvent { +impl DelegationEvent { + pub fn from_mixnet_contract( + event: ContractDelegationEvent, + reg: &RegisteredCoins, + ) -> Result { + Ok(match event { + ContractDelegationEvent::Delegate(delegation) => DelegationEvent { + kind: DelegationEventKind::Delegate, + block_height: delegation.block_height, + address: delegation.owner.into_string(), + node_identity: delegation.node_identity, + amount: Some(reg.attempt_convert_to_display_dec_coin(delegation.amount.into())?), + }, + ContractDelegationEvent::Undelegate(pending_undelegate) => DelegationEvent { kind: DelegationEventKind::Undelegate, block_height: pending_undelegate.block_height(), address: pending_undelegate.delegate().into_string(), node_identity: pending_undelegate.mix_identity(), amount: None, - }), - } + }, + }) } } @@ -196,30 +155,6 @@ impl From for PendingUndelegate { } } -pub fn from_contract_delegation_events( - events: Vec, -) -> Result, TypesError> { - let (events, errors): (Vec<_>, Vec<_>) = events - .into_iter() - .map(|delegation_event| delegation_event.try_into()) - .partition(Result::is_ok); - - if errors.is_empty() { - let events = events - .into_iter() - .filter_map(|e| e.ok()) - .collect::>(); - return Ok(events); - } - let errors = errors - .into_iter() - .filter_map(|e| e.err()) - .collect::>(); - - error!("Failed to convert delegations: {:?}", errors); - Err(TypesError::DelegationsInvalid) -} - #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -228,6 +163,6 @@ pub fn from_contract_delegation_events( #[derive(Deserialize, Serialize)] pub struct DelegationsSummaryResponse { pub delegations: Vec, - pub total_delegations: MajorCurrencyAmount, - pub total_rewards: MajorCurrencyAmount, + pub total_delegations: DecCoin, + pub total_rewards: DecCoin, } diff --git a/common/types/src/error.rs b/common/types/src/error.rs index d1903d643f..f7ed08dfd8 100644 --- a/common/types/src/error.rs +++ b/common/types/src/error.rs @@ -4,6 +4,7 @@ use thiserror::Error; use validator_client::validator_api::error::ValidatorAPIError; use validator_client::{nymd::error::NymdError, ValidatorClientError}; +// TODO: ask @MS why this even exists #[derive(Error, Debug)] pub enum TypesError { #[error("{source}")] @@ -61,6 +62,12 @@ pub enum TypesError { InvalidGatewayBond(), #[error("Invalid delegations")] DelegationsInvalid, + #[error("Attempted to use too huge currency exponent ({0})")] + UnsupportedExponent(u32), + #[error("Attempted to convert coin that would have resulted in loss of precision")] + LossyCoinConversion, + #[error("The provided coin has an unknown denomination - {0}")] + UnknownCoinDenom(String), } impl Serialize for TypesError { diff --git a/common/types/src/fees.rs b/common/types/src/fees.rs index 5037646c31..e91a8ac24b 100644 --- a/common/types/src/fees.rs +++ b/common/types/src/fees.rs @@ -1,9 +1,7 @@ +use crate::currency::DecCoin; use serde::{Deserialize, Serialize}; - use validator_client::nymd::Fee; -use crate::currency::MajorCurrencyAmount; - #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -12,7 +10,13 @@ use crate::currency::MajorCurrencyAmount; #[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, + pub amount: Option, #[cfg_attr(feature = "generate-ts", ts(skip))] pub fee: Fee, } + +impl FeeDetails { + pub fn new(amount: Option, fee: Fee) -> Self { + FeeDetails { amount, fee } + } +} diff --git a/common/types/src/gas.rs b/common/types/src/gas.rs index 8ffb475f4e..9441008569 100644 --- a/common/types/src/gas.rs +++ b/common/types/src/gas.rs @@ -1,48 +1,29 @@ -use crate::currency::MajorCurrencyAmount; -use crate::error::TypesError; use cosmrs::tx::Gas as CosmrsGas; use serde::{Deserialize, Serialize}; use validator_client::nymd::cosmwasm_client::types::GasInfo as ValidatorClientGasInfo; -use validator_client::nymd::GasPrice; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", ts(export_to = "ts-packages/types/src/types/rust/Gas.ts") )] -#[derive(Deserialize, Serialize, Clone)] +#[derive(Deserialize, Serialize, Copy, Clone, Debug)] pub struct Gas { /// units of gas used pub gas_units: u64, - // - // /// gas units converted to fee as major coin amount - // pub amount: MajorCurrencyAmount, } impl Gas { - pub fn from_cosmrs_gas(value: CosmrsGas, _denom_minor: &str) -> Result { - Ok(Gas { - gas_units: value.value(), - }) - - // // TODO: use simulator struct to do conversion to fee - // let value_u128 = Uint128::from(value.value()); - // let amount = Decimal::new(value_u128) * Decimal::from_str("0.0025")?; - // Ok(Gas { - // gas_units: value.value(), - // amount: MajorCurrencyAmount::from_minor_decimal_and_denom(amount, denom_minor)?, - // }) + pub fn from_u64(value: u64) -> Gas { + Gas { gas_units: value } } - pub fn from_u64(value: u64, _denom_minor: &str) -> Result { - Ok(Gas { gas_units: value }) - // todo!() - // // TODO: use simulator struct to do conversion to fee - // let value_u128 = Uint128::from(value); - // let amount = Decimal::new(value_u128) * Decimal::from_str("0.0025")?; - // Ok(Gas { - // gas_units: value, - // amount: MajorCurrencyAmount::from_minor_decimal_and_denom(amount, denom_minor)?, - // }) +} + +impl From for Gas { + fn from(gas: CosmrsGas) -> Self { + Gas { + gas_units: gas.value(), + } } } @@ -51,44 +32,29 @@ impl Gas { feature = "generate-ts", ts(export_to = "ts-packages/types/src/types/rust/GasInfo.ts") )] -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, Copy, Clone, Debug)] pub struct GasInfo { /// GasWanted is the maximum units of work we allow this tx to perform. - pub gas_wanted: u64, + pub gas_wanted: Gas, /// GasUsed is the amount of gas actually consumed. - pub gas_used: u64, + pub gas_used: Gas, +} - /// gas units converted to fee as major coin amount - pub fee: MajorCurrencyAmount, +impl From for GasInfo { + fn from(info: ValidatorClientGasInfo) -> Self { + GasInfo { + gas_wanted: info.gas_wanted.into(), + gas_used: info.gas_used.into(), + } + } } impl GasInfo { - pub fn from_validator_client_gas_info( - value: ValidatorClientGasInfo, - denom_minor: &str, - ) -> Result { - // terrible workaround, but I don't want to break the current flow (just yet) - let gas_price = GasPrice::new_with_default_price(denom_minor)?; - let fee = (&gas_price) * value.gas_used; - Ok(GasInfo { - gas_wanted: value.gas_wanted.value(), - gas_used: value.gas_used.value(), - fee: fee.into(), - }) - } - pub fn from_u64( - gas_wanted: u64, - gas_used: u64, - denom_minor: &str, - ) -> Result { - // terrible workaround, but I don't want to break the current flow (just yet) - let gas_price = GasPrice::new_with_default_price(denom_minor)?; - let fee = (&gas_price) * CosmrsGas::from(gas_used); - Ok(GasInfo { - gas_wanted, - gas_used, - fee: fee.into(), - }) + pub fn from_u64(gas_wanted: u64, gas_used: u64) -> GasInfo { + GasInfo { + gas_wanted: Gas::from_u64(gas_wanted), + gas_used: Gas::from_u64(gas_used), + } } } diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index d45d0f8274..46a79d5dff 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -1,4 +1,4 @@ -use crate::currency::MajorCurrencyAmount; +use crate::currency::{DecCoin, RegisteredCoins}; use crate::error::TypesError; use mixnet_contract_common::{ Gateway as MixnetContractGateway, GatewayBond as MixnetContractGatewayBond, @@ -54,7 +54,7 @@ impl From for Gateway { )] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayBond { - pub pledge_amount: MajorCurrencyAmount, + pub pledge_amount: DecCoin, pub owner: String, pub block_height: u64, pub gateway: Gateway, @@ -63,38 +63,15 @@ pub struct GatewayBond { impl GatewayBond { pub fn from_mixnet_contract_gateway_bond( - bond: Option, - ) -> Result, TypesError> { - match bond { - Some(bond) => { - let bond: GatewayBond = bond.try_into()?; - Ok(Some(bond)) - } - None => Ok(None), - } - } -} - -impl TryFrom for GatewayBond { - type Error = TypesError; - - fn try_from(value: MixnetContractGatewayBond) -> Result { - let MixnetContractGatewayBond { - pledge_amount, - owner, - block_height, - gateway, - proxy, - } = value; - - let pledge_amount: MajorCurrencyAmount = pledge_amount.into(); - + bond: MixnetContractGatewayBond, + reg: &RegisteredCoins, + ) -> Result { Ok(GatewayBond { - pledge_amount, - owner: owner.into_string(), - block_height, - gateway: gateway.into(), - proxy: proxy.map(|p| p.into_string()), + pledge_amount: reg.attempt_convert_to_display_dec_coin(bond.pledge_amount.into())?, + owner: bond.owner.to_string(), + block_height: bond.block_height, + gateway: bond.gateway.into(), + proxy: bond.proxy.map(|p| p.into_string()), }) } } diff --git a/common/types/src/mixnode.rs b/common/types/src/mixnode.rs index 85c65be18d..bae233871c 100644 --- a/common/types/src/mixnode.rs +++ b/common/types/src/mixnode.rs @@ -1,11 +1,11 @@ -use crate::currency::MajorCurrencyAmount; +use crate::currency::{DecCoin, RegisteredCoins}; use crate::error::TypesError; use mixnet_contract_common::{ - Coin as CosmWasmCoin, MixNode as MixnetContractMixNode, - MixNodeBond as MixnetContractMixNodeBond, + MixNode as MixnetContractMixNode, MixNodeBond as MixnetContractMixNodeBond, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use validator_client::nymd::Coin; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( @@ -58,67 +58,39 @@ impl From for MixNode { )] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixNodeBond { - pub pledge_amount: MajorCurrencyAmount, - pub total_delegation: MajorCurrencyAmount, + pub pledge_amount: DecCoin, + pub total_delegation: DecCoin, pub owner: String, pub layer: String, pub block_height: u64, pub mix_node: MixNode, pub proxy: Option, - pub accumulated_rewards: Option, + pub accumulated_rewards: Option, } impl MixNodeBond { pub fn from_mixnet_contract_mixnode_bond( - bond: Option, - ) -> Result, TypesError> { - match bond { - Some(bond) => { - let bond: MixNodeBond = bond.try_into()?; - Ok(Some(bond)) - } - None => Ok(None), - } - } -} - -impl TryFrom for MixNodeBond { - type Error = TypesError; - - fn try_from(value: MixnetContractMixNodeBond) -> Result { - let MixnetContractMixNodeBond { - pledge_amount, - total_delegation, - owner, - layer, - block_height, - mix_node, - proxy, - accumulated_rewards, - } = value; - - if pledge_amount.denom != total_delegation.denom { - return Err(TypesError::InvalidDenom( - "The pledge and delegation denominations do not match".to_string(), - )); - } - - let denom = total_delegation.denom.clone(); - - let pledge_amount: MajorCurrencyAmount = pledge_amount.into(); - let total_delegation: MajorCurrencyAmount = total_delegation.into(); - let accumulated_rewards: Option = - accumulated_rewards.map(|r| CosmWasmCoin::new(r.u128(), denom).into()); - + bond: MixnetContractMixNodeBond, + reg: &RegisteredCoins, + ) -> Result { + let denom = bond.pledge_amount.denom.clone(); Ok(MixNodeBond { - pledge_amount, - total_delegation, - owner: owner.into_string(), - layer: layer.into(), - block_height, - mix_node: mix_node.into(), - proxy: proxy.map(|p| p.into_string()), - accumulated_rewards, + pledge_amount: reg.attempt_convert_to_display_dec_coin(bond.pledge_amount.into())?, + total_delegation: reg + .attempt_convert_to_display_dec_coin(bond.total_delegation.into())?, + owner: bond.owner.into_string(), + layer: bond.layer.into(), + block_height: bond.block_height, + mix_node: bond.mix_node.into(), + proxy: bond.proxy.map(|p| p.to_string()), + accumulated_rewards: bond + .accumulated_rewards + .map(|reward| { + // here we're making an assumption that rewards always use the same denom as the pledge + // (which I think is a reasonable assumption) + reg.attempt_convert_to_display_dec_coin(Coin::new(reward.u128(), denom)) + }) + .transpose()?, }) } } diff --git a/common/types/src/transaction.rs b/common/types/src/transaction.rs index 956e8cfc92..3946ef00fa 100644 --- a/common/types/src/transaction.rs +++ b/common/types/src/transaction.rs @@ -1,6 +1,6 @@ -use crate::currency::MajorCurrencyAmount; +use crate::currency::DecCoin; use crate::error::TypesError; -use crate::gas::GasInfo; +use crate::gas::{Gas, GasInfo}; use serde::{Deserialize, Serialize}; use validator_client::nymd::cosmwasm_client::types::ExecuteResult; use validator_client::nymd::TxResponse; @@ -15,31 +15,23 @@ pub struct SendTxResult { pub block_height: u64, pub code: u32, pub details: TransactionDetails, - pub gas_used: u64, - pub gas_wanted: u64, + pub gas_used: Gas, + pub gas_wanted: Gas, pub tx_hash: String, - // pub fee: MajorCurrencyAmount, + pub fee: Option, } impl SendTxResult { - pub fn new( - t: TxResponse, - details: TransactionDetails, - _denom_minor: &str, - ) -> Result { - Ok(SendTxResult { + pub fn new(t: TxResponse, details: TransactionDetails, fee: Option) -> SendTxResult { + SendTxResult { block_height: t.height.value(), code: t.tx_result.code.value(), details, - gas_used: t.tx_result.gas_used.value(), - gas_wanted: t.tx_result.gas_wanted.value(), + gas_used: t.tx_result.gas_used.into(), + gas_wanted: t.tx_result.gas_wanted.into(), tx_hash: t.hash.to_string(), - // that is completely wrong: fee is what you told the validator to use beforehand - // fee: MajorCurrencyAmount::from_decimal_and_denom( - // Decimal::new(Uint128::from(t.tx_result.gas_used.value())), - // denom_minor.to_string(), - // )?, - }) + fee, + } } } @@ -50,11 +42,21 @@ impl SendTxResult { )] #[derive(Deserialize, Serialize, Debug)] pub struct TransactionDetails { - pub amount: MajorCurrencyAmount, + pub amount: DecCoin, pub from_address: String, pub to_address: String, } +impl TransactionDetails { + pub fn new(amount: DecCoin, from_address: String, to_address: String) -> Self { + TransactionDetails { + amount, + from_address, + to_address, + } + } +} + #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -66,18 +68,16 @@ pub struct TransactionExecuteResult { pub data_json: String, pub transaction_hash: String, pub gas_info: GasInfo, - pub fee: MajorCurrencyAmount, + pub fee: Option, } impl TransactionExecuteResult { pub fn from_execute_result( value: ExecuteResult, - denom_minor: &str, + fee: Option, ) -> Result { - let gas_info = GasInfo::from_validator_client_gas_info(value.gas_info, denom_minor)?; - let fee = gas_info.fee.clone(); Ok(TransactionExecuteResult { - gas_info, + gas_info: value.gas_info.into(), transaction_hash: value.transaction_hash.to_string(), data_json: ::serde_json::to_string_pretty(&value.data)?, logs_json: ::serde_json::to_string_pretty(&value.logs)?, @@ -97,30 +97,24 @@ pub struct RpcTransactionResponse { pub tx_result_json: String, pub block_height: u64, pub transaction_hash: String, - pub gas_info: GasInfo, - // pub fee: MajorCurrencyAmount, + pub gas_used: Gas, + pub gas_wanted: Gas, + pub fee: Option, } impl RpcTransactionResponse { pub fn from_tx_response( - value: &TxResponse, - denom_minor: &str, + t: &TxResponse, + fee: Option, ) -> Result { Ok(RpcTransactionResponse { - index: value.index, - gas_info: GasInfo::from_u64( - value.tx_result.gas_wanted.value(), - value.tx_result.gas_used.value(), - denom_minor, - )?, - transaction_hash: value.hash.to_string(), - tx_result_json: ::serde_json::to_string_pretty(&value.tx_result)?, - block_height: value.height.value(), - // wrong - // fee: MajorCurrencyAmount::from_decimal_and_denom( - // Decimal::new(Uint128::from(value.tx_result.gas_used.value())), - // denom_minor.to_string(), - // )?, + index: t.index, + gas_used: t.tx_result.gas_used.into(), + gas_wanted: t.tx_result.gas_wanted.into(), + transaction_hash: t.hash.to_string(), + tx_result_json: ::serde_json::to_string_pretty(&t.tx_result)?, + block_height: t.height.value(), + fee, }) } } diff --git a/common/types/src/vesting.rs b/common/types/src/vesting.rs index c20b0845e0..0c6b6a4c20 100644 --- a/common/types/src/vesting.rs +++ b/common/types/src/vesting.rs @@ -1,10 +1,10 @@ -use crate::currency::MajorCurrencyAmount; +use crate::currency::{DecCoin, RegisteredCoins}; use crate::error::TypesError; use serde::{Deserialize, Serialize}; -use vesting_contract::vesting::Account as VestingAccount; -use vesting_contract::vesting::VestingPeriod as VestingVestingPeriod; -use vesting_contract_common::OriginalVestingResponse as VestingOriginalVestingResponse; -use vesting_contract_common::PledgeData as VestingPledgeData; +use vesting_contract::vesting::Account as ContractVestingAccount; +use vesting_contract::vesting::VestingPeriod as ContractVestingPeriod; +use vesting_contract_common::OriginalVestingResponse as ContractOriginalVestingResponse; +use vesting_contract_common::PledgeData as ContractPledgeData; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( @@ -13,25 +13,19 @@ use vesting_contract_common::PledgeData as VestingPledgeData; )] #[derive(Serialize, Deserialize, Debug)] pub struct PledgeData { - pub amount: MajorCurrencyAmount, + pub amount: DecCoin, pub block_time: u64, } -impl TryFrom for PledgeData { - type Error = TypesError; - - fn try_from(data: VestingPledgeData) -> Result { - let amount: MajorCurrencyAmount = data.amount().into(); - Ok(Self { - amount, - block_time: data.block_time().seconds(), - }) - } -} - impl PledgeData { - pub fn and_then(data: VestingPledgeData) -> Option { - data.try_into().ok() + pub fn from_vesting_contract( + pledge: ContractPledgeData, + reg: &RegisteredCoins, + ) -> Result { + Ok(PledgeData { + amount: reg.attempt_convert_to_display_dec_coin(pledge.amount.into())?, + block_time: pledge.block_time.seconds(), + }) } } @@ -42,20 +36,20 @@ impl PledgeData { )] #[derive(Serialize, Deserialize, Debug)] pub struct OriginalVestingResponse { - amount: MajorCurrencyAmount, + amount: DecCoin, number_of_periods: usize, period_duration: u64, } -impl TryFrom for OriginalVestingResponse { - type Error = TypesError; - - fn try_from(data: VestingOriginalVestingResponse) -> Result { - let amount = data.amount().into(); - Ok(Self { - amount, - number_of_periods: data.number_of_periods(), - period_duration: data.period_duration(), +impl OriginalVestingResponse { + pub fn from_vesting_contract( + res: ContractOriginalVestingResponse, + reg: &RegisteredCoins, + ) -> Result { + Ok(OriginalVestingResponse { + amount: reg.attempt_convert_to_display_dec_coin(res.amount.into())?, + number_of_periods: res.number_of_periods, + period_duration: res.period_duration, }) } } @@ -71,24 +65,20 @@ pub struct VestingAccountInfo { staking_address: Option, start_time: u64, periods: Vec, - amount: MajorCurrencyAmount, + amount: DecCoin, } -impl TryFrom for VestingAccountInfo { - type Error = TypesError; - - fn try_from(account: VestingAccount) -> Result { - let mut periods = Vec::new(); - for period in account.periods() { - periods.push(period.into()); - } - let amount: MajorCurrencyAmount = account.coin().into(); - Ok(Self { +impl VestingAccountInfo { + pub fn from_vesting_contract( + account: ContractVestingAccount, + reg: &RegisteredCoins, + ) -> Result { + Ok(VestingAccountInfo { owner_address: account.owner_address().to_string(), staking_address: account.staking_address().map(|a| a.to_string()), start_time: account.start_time().seconds(), - periods, - amount, + periods: account.periods().into_iter().map(Into::into).collect(), + amount: reg.attempt_convert_to_display_dec_coin(account.coin.into())?, }) } } @@ -104,8 +94,8 @@ pub struct VestingPeriod { period_seconds: u64, } -impl From for VestingPeriod { - fn from(period: VestingVestingPeriod) -> Self { +impl From for VestingPeriod { + fn from(period: ContractVestingPeriod) -> Self { Self { start_time: period.start_time, period_seconds: period.period_seconds, diff --git a/contracts/bandwidth-claim/src/lib.rs b/contracts/bandwidth-claim/src/lib.rs index 53be5bfb7e..9dd88197e7 100644 --- a/contracts/bandwidth-claim/src/lib.rs +++ b/contracts/bandwidth-claim/src/lib.rs @@ -62,7 +62,7 @@ pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result, @@ -25,7 +25,7 @@ pub(crate) fn deposit_funds( if info.funds.len() > 1 { return Err(ContractError::MultipleDenoms); } - if info.funds[0].denom != DENOM { + if info.funds[0].denom != MIX_DENOM.base { return Err(ContractError::WrongDenom); } @@ -45,10 +45,12 @@ pub(crate) fn release_funds( info: MessageInfo, funds: Coin, ) -> Result { - if funds.denom != DENOM { + if funds.denom != MIX_DENOM.base { return Err(ContractError::WrongDenom); } - let current_balance = deps.querier.query_balance(env.contract.address, DENOM)?; + let current_balance = deps + .querier + .query_balance(env.contract.address, MIX_DENOM.base)?; if funds.amount > current_balance.amount { return Err(ContractError::NotEnoughFunds); } @@ -90,7 +92,7 @@ mod tests { Err(ContractError::NoCoin) ); - let coin = Coin::new(1000000, DENOM); + let coin = Coin::new(1000000, MIX_DENOM.base); let second_coin = Coin::new(1000000, "some_denom"); let info = mock_info("requester", &[coin, second_coin.clone()]); @@ -120,7 +122,7 @@ mod tests { verification_key.clone(), encryption_key.clone(), ); - let coin = Coin::new(deposit_value, DENOM); + let coin = Coin::new(deposit_value, MIX_DENOM.base); let info = mock_info("requester", &[coin]); let tx = deposit_funds(deps.as_mut(), env.clone(), info, data).unwrap(); @@ -169,7 +171,7 @@ mod tests { let mut deps = helpers::init_contract(); let env = mock_env(); let invalid_admin = "invalid admin"; - let funds = Coin::new(1, DENOM); + let funds = Coin::new(1, MIX_DENOM.base); let err = release_funds( deps.as_mut(), @@ -205,7 +207,7 @@ mod tests { fn valid_release() { let mut deps = helpers::init_contract(); let env = mock_env(); - let coin = Coin::new(1, DENOM); + let coin = Coin::new(1, MIX_DENOM.base); deps.querier .update_balance(env.contract.address.clone(), vec![coin.clone()]); diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 240055062c..a09d51101d 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -475,7 +475,8 @@ pub fn migrate(deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result) -> Result // SPDX-License-Identifier: Apache-2.0 -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{Addr, StdError}; use mixnet_contract_common::{error::MixnetContractError, IdentityKey}; use thiserror::Error; @@ -33,13 +33,13 @@ pub enum ContractError { #[error("MIXNET ({}): Unauthorized", line!())] Unauthorized, - #[error("MIXNET ({}): Wrong coin denomination, you must send {}", line!(), DENOM)] + #[error("MIXNET ({}): Wrong coin denomination, you must send {}", line!(), MIX_DENOM.base)] WrongDenom, #[error("MIXNET ({}): Received multiple coin types during staking", line!())] MultipleDenoms, - #[error("MIXNET ({}): No coin was sent for the bonding, you must send {}", line!(), DENOM)] + #[error("MIXNET ({}): No coin was sent for the bonding, you must send {}", line!(), MIX_DENOM.base)] NoBondFound, #[error("MIXNET ({}): Provided active set size is bigger than the rewarded set", line!())] diff --git a/contracts/mixnet/src/gateways/storage.rs b/contracts/mixnet/src/gateways/storage.rs index 4c74067bc6..6b79f5ed4e 100644 --- a/contracts/mixnet/src/gateways/storage.rs +++ b/contracts/mixnet/src/gateways/storage.rs @@ -36,7 +36,7 @@ pub(crate) fn gateways<'a>() -> IndexedMap<'a, IdentityKeyRef<'a>, GatewayBond, mod tests { use super::super::storage; use crate::support::tests; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::MockStorage; use cosmwasm_std::StdResult; use cosmwasm_std::Storage; @@ -84,7 +84,7 @@ mod tests { let pledge_amount = 1000; let gateway_bond = GatewayBond { - pledge_amount: coin(pledge_amount, DENOM), + pledge_amount: coin(pledge_amount, MIX_DENOM.base), owner: node_owner, block_height: 12_345, gateway: Gateway { diff --git a/contracts/mixnet/src/gateways/transactions.rs b/contracts/mixnet/src/gateways/transactions.rs index e264e53bcb..76689422bd 100644 --- a/contracts/mixnet/src/gateways/transactions.rs +++ b/contracts/mixnet/src/gateways/transactions.rs @@ -5,7 +5,7 @@ use super::storage; use crate::error::ContractError; use crate::mixnet_contract_settings::storage as mixnet_params_storage; use crate::support::helpers::{ensure_no_existing_bond, validate_node_identity_signature}; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{ wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128, }; @@ -203,7 +203,7 @@ fn validate_gateway_pledge( } // check that the denomination is correct - if pledge[0].denom != DENOM { + if pledge[0].denom != MIX_DENOM.base { return Err(ContractError::WrongDenom {}); } @@ -226,7 +226,7 @@ pub mod tests { use crate::gateways::transactions::validate_gateway_pledge; use crate::support::tests; use crate::support::tests::test_helpers; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, BankMsg, Response}; use cosmwasm_std::{from_binary, Addr, Uint128}; @@ -238,7 +238,7 @@ pub mod tests { // if we fail validation (by say not sending enough funds let insufficient_bond = Into::::into(INITIAL_GATEWAY_PLEDGE) - 1; - let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); + let info = mock_info("anyone", &coins(insufficient_bond, MIX_DENOM.base)); let (msg, _) = tests::messages::valid_bond_gateway_msg("anyone"); // we are informed that we didn't send enough funds diff --git a/contracts/mixnet/src/mixnodes/storage.rs b/contracts/mixnet/src/mixnodes/storage.rs index 91623c42dd..a45e8c74a2 100644 --- a/contracts/mixnet/src/mixnodes/storage.rs +++ b/contracts/mixnet/src/mixnodes/storage.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{StdResult, Storage, Uint128}; use cw_storage_plus::{Index, IndexList, IndexedSnapshotMap, Map, Strategy, UniqueIndex}; use mixnet_contract_common::{ @@ -171,7 +171,7 @@ pub(crate) fn read_full_mixnode_bond( Ok(Some(MixNodeBond { pledge_amount: stored_bond.pledge_amount, total_delegation: Coin { - denom: DENOM.to_owned(), + denom: MIX_DENOM.base.to_owned(), amount: total_delegation.unwrap_or_default(), }, owner: stored_bond.owner, @@ -190,7 +190,7 @@ mod tests { use super::super::storage; use super::*; use crate::support::tests; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::MockStorage; use cosmwasm_std::{coin, Addr, Uint128}; use mixnet_contract_common::{IdentityKey, MixNode}; @@ -223,7 +223,7 @@ mod tests { let pledge_value = 1000000000; let mixnode_bond = StoredMixnodeBond { - pledge_amount: coin(pledge_value, DENOM), + pledge_amount: coin(pledge_value, MIX_DENOM.base), owner: node_owner, layer: Layer::One, block_height: 12_345, diff --git a/contracts/mixnet/src/mixnodes/transactions.rs b/contracts/mixnet/src/mixnodes/transactions.rs index c64ed805f1..e0ff269665 100644 --- a/contracts/mixnet/src/mixnodes/transactions.rs +++ b/contracts/mixnet/src/mixnodes/transactions.rs @@ -7,7 +7,7 @@ use crate::mixnet_contract_settings::storage as mixnet_params_storage; use crate::mixnodes::layer_queries::query_layer_distribution; use crate::mixnodes::storage::StoredMixnodeBond; use crate::support::helpers::{ensure_no_existing_bond, validate_node_identity_signature}; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{ wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Storage, Uint128, }; @@ -364,7 +364,7 @@ fn validate_mixnode_pledge( } // check that the denomination is correct - if pledge[0].denom != DENOM { + if pledge[0].denom != MIX_DENOM.base { return Err(ContractError::WrongDenom {}); } @@ -381,15 +381,13 @@ fn validate_mixnode_pledge( #[cfg(test)] pub mod tests { - use std::f64::MIN; - use super::*; use crate::contract::{execute, query, INITIAL_MIXNODE_PLEDGE}; use crate::error::ContractError; use crate::mixnodes::transactions::validate_mixnode_pledge; use crate::support::tests; use crate::support::tests::test_helpers; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, BankMsg, Response}; use cosmwasm_std::{from_binary, Addr, Uint128}; @@ -404,7 +402,7 @@ pub mod tests { // if we don't send enough funds let insufficient_bond = Into::::into(INITIAL_MIXNODE_PLEDGE) - 1; - let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); + let info = mock_info("anyone", &coins(insufficient_bond, MIX_DENOM.base)); let (msg, _) = tests::messages::valid_bond_mixnode_msg("anyone"); // we are informed that we didn't send enough funds diff --git a/contracts/mixnet/src/rewards/queries.rs b/contracts/mixnet/src/rewards/queries.rs index 14329cdb8c..e93552cd1c 100644 --- a/contracts/mixnet/src/rewards/queries.rs +++ b/contracts/mixnet/src/rewards/queries.rs @@ -79,7 +79,7 @@ pub(crate) mod tests { use crate::delegations::transactions::try_delegate_to_mixnode; use crate::interval::storage::{save_epoch, save_epoch_reward_params}; use crate::rewards::transactions::try_reward_mixnode; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::{coin, Addr}; use mixnet_contract_common::{ Interval, RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT, @@ -181,7 +181,10 @@ pub(crate) mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]), + mock_info( + &*format!("delegator{:04}", i), + &[coin(200_000000, MIX_DENOM.base)], + ), node_identity.clone(), ) .unwrap(); diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index 239b992fc9..407197c3ab 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -14,7 +14,7 @@ use crate::mixnodes::storage::mixnodes; use crate::mixnodes::storage::{self as mixnodes_storage, StoredMixnodeBond}; use crate::rewards::helpers; use crate::support::helpers::is_authorized; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{ coins, wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, MessageInfo, Order, Response, Storage, Uint128, @@ -105,7 +105,7 @@ fn _try_claim_operator_reward( let return_tokens = BankMsg::Send { to_address: proxy.as_ref().unwrap_or(&owner).to_string(), - amount: coins(reward.u128(), DENOM), + amount: coins(reward.u128(), MIX_DENOM.base), }; let mut response = Response::default() @@ -115,7 +115,7 @@ fn _try_claim_operator_reward( if let Some(proxy) = proxy { let msg = Some(VestingContractExecuteMsg::TrackReward { address: owner.to_string(), - amount: Coin::new(reward.u128(), DENOM), + amount: Coin::new(reward.u128(), MIX_DENOM.base), }); let wasm_msg = wasm_execute(proxy, &msg, vec![one_ucoin()])?; @@ -153,7 +153,7 @@ pub fn _try_claim_delegator_reward( let return_tokens = BankMsg::Send { to_address: proxy.as_ref().unwrap_or(&owner).to_string(), - amount: coins(reward.u128(), DENOM), + amount: coins(reward.u128(), MIX_DENOM.base), }; let mut response = @@ -169,7 +169,7 @@ pub fn _try_claim_delegator_reward( if let Some(proxy) = proxy { let msg = Some(VestingContractExecuteMsg::TrackReward { address: owner.to_string(), - amount: Coin::new(reward.u128(), DENOM), + amount: Coin::new(reward.u128(), MIX_DENOM.base), }); let wasm_msg = wasm_execute(proxy, &msg, vec![one_ucoin()])?; @@ -436,7 +436,7 @@ pub fn _try_compound_delegator_reward( owner_address, Coin { amount: compounded_delegation, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, proxy, )?; @@ -721,7 +721,7 @@ pub mod tests { use crate::support::tests; use crate::support::tests::test_helpers; use az::CheckedCast; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coin, coins, Addr, StdError, Timestamp, Uint128}; use mixnet_contract_common::events::{ @@ -737,7 +737,7 @@ pub mod tests { let mut deps = test_helpers::init_contract(); let mut env = mock_env(); let sender = rewarding_validator_address(&deps.storage).unwrap(); - let info = mock_info(&sender, &coins(1000, DENOM)); + let info = mock_info(&sender, &coins(1000, MIX_DENOM.base)); crate::interval::transactions::init_epoch(&mut deps.storage, env.clone()).unwrap(); // bond the node @@ -878,7 +878,7 @@ pub mod tests { let initial_bond = 10000_000000; let initial_delegation = 20000_000000; let mixnode_bond = StoredMixnodeBond { - pledge_amount: coin(initial_bond, DENOM), + pledge_amount: coin(initial_bond, MIX_DENOM.base), owner: node_owner, layer: Layer::One, block_height: env.block.height, @@ -918,7 +918,7 @@ pub mod tests { &Delegation::new( Addr::unchecked("delegator"), node_identity.clone(), - coin(initial_delegation, DENOM), + coin(initial_delegation, MIX_DENOM.base), env.block.height, None, ), @@ -1098,7 +1098,7 @@ pub mod tests { assert_eq!(circulating_supply, 750_000_000_000_000u128); let sender = Addr::unchecked("alice"); - let stake = coins(10_000_000_000, DENOM); + let stake = coins(10_000_000_000, MIX_DENOM.base); let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng()); let owner_signature = keypair @@ -1151,14 +1151,14 @@ pub mod tests { let node_owner: Addr = Addr::unchecked("johnny"); let node_identity_2 = test_helpers::add_mixnode( node_owner.as_str(), - coins(10_000_000_000, DENOM), + coins(10_000_000_000, MIX_DENOM.base), deps.as_mut(), ); try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alice_d1", &[coin(8000_000000, DENOM)]), + mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]), node_identity_1.clone(), ) .unwrap(); @@ -1166,7 +1166,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alice_d2", &[coin(2000_000000, DENOM)]), + mock_info("alice_d2", &[coin(2000_000000, MIX_DENOM.base)]), node_identity_1.clone(), ) .unwrap(); @@ -1174,7 +1174,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("bob_d1", &[coin(8000_000000, DENOM)]), + mock_info("bob_d1", &[coin(8000_000000, MIX_DENOM.base)]), node_identity_2.clone(), ) .unwrap(); @@ -1182,7 +1182,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("bob_d2", &[coin(2000_000000, DENOM)]), + mock_info("bob_d2", &[coin(2000_000000, MIX_DENOM.base)]), node_identity_2.clone(), ) .unwrap(); @@ -1190,14 +1190,14 @@ pub mod tests { let node_owner: Addr = Addr::unchecked("alicebob"); let node_identity_3 = test_helpers::add_mixnode( node_owner.as_str(), - coins(10_000_000_000 * 2, DENOM), + coins(10_000_000_000 * 2, MIX_DENOM.base), deps.as_mut(), ); try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alicebob_d1", &[coin(8000_000000 * 2, DENOM)]), + mock_info("alicebob_d1", &[coin(8000_000000 * 2, MIX_DENOM.base)]), node_identity_3.clone(), ) .unwrap(); @@ -1205,7 +1205,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alicebob_d2", &[coin(2000_000000 * 2, DENOM)]), + mock_info("alicebob_d2", &[coin(2000_000000 * 2, MIX_DENOM.base)]), node_identity_3.clone(), ) .unwrap(); @@ -1216,7 +1216,6 @@ pub mod tests { ) .unwrap(); - let info = mock_info(rewarding_validator_address.as_ref(), &[]); env.block.height += 2 * constants::MINIMUM_BLOCK_AGE_FOR_REWARDING; let mix_1 = mixnodes_storage::read_full_mixnode_bond(&deps.storage, &node_identity_1) @@ -1305,7 +1304,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info("alice_d1", &[coin(8000_000000, DENOM)]), + mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]), node_identity_1.clone(), ) .unwrap(); @@ -1506,7 +1505,7 @@ pub mod tests { ); assert_eq!(mix_2_reward_result.reward().int(), 129557u128); - let mix_3_reward_result = mix_3.reward(¶ms3); + let _mix_3_reward_result = mix_3.reward(¶ms3); // assert_eq!(mix_3_reward_result.reward().int(), mix_1_reward_result.reward().int() + mix_2_reward_result.reward().int()); } @@ -1533,14 +1532,14 @@ pub mod tests { let node_owner: Addr = Addr::unchecked("alice"); let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - coins(10_000_000_000, DENOM), + coins(10_000_000_000, MIX_DENOM.base), deps.as_mut(), ); try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alice_d1", &[coin(8000_000000, DENOM)]), + mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]), node_identity.clone(), ) .unwrap(); @@ -1548,7 +1547,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info("alice_d2", &[coin(2000_000000, DENOM)]), + mock_info("alice_d2", &[coin(2000_000000, MIX_DENOM.base)]), node_identity.clone(), ) .unwrap(); @@ -1698,7 +1697,7 @@ pub mod tests { #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - coins(10000_000_000, DENOM), + coins(10000_000_000, MIX_DENOM.base), deps.as_mut(), ); @@ -1725,7 +1724,7 @@ pub mod tests { #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), - coins(10000_000_000, DENOM), + coins(10000_000_000, MIX_DENOM.base), deps.as_mut(), ); @@ -1733,7 +1732,10 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info(&*format!("delegator{:04}", i), &[coin(2000_000000, DENOM)]), + mock_info( + &*format!("delegator{:04}", i), + &[coin(2000_000000, MIX_DENOM.base)], + ), node_identity.clone(), ) .unwrap(); diff --git a/contracts/mixnet/src/support/tests/fixtures.rs b/contracts/mixnet/src/support/tests/fixtures.rs index 1a24782dd3..f8c5513c32 100644 --- a/contracts/mixnet/src/support/tests/fixtures.rs +++ b/contracts/mixnet/src/support/tests/fixtures.rs @@ -1,7 +1,7 @@ use crate::contract::INITIAL_MIXNODE_PLEDGE; use crate::mixnodes::storage as mixnodes_storage; use crate::{mixnodes::storage::StoredMixnodeBond, support::tests}; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{coin, Addr, Coin}; use mixnet_contract_common::reward_params::NodeRewardParams; use mixnet_contract_common::{Gateway, GatewayBond, Layer, MixNode}; @@ -37,7 +37,7 @@ pub fn gateway_bond_fixture(owner: &str) -> GatewayBond { ..tests::fixtures::gateway_fixture() }; GatewayBond::new( - coin(50, DENOM), + coin(50, MIX_DENOM.base), Addr::unchecked(owner), 12_345, gateway, @@ -47,7 +47,7 @@ pub fn gateway_bond_fixture(owner: &str) -> GatewayBond { pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::StoredMixnodeBond { StoredMixnodeBond::new( - coin(50, DENOM), + coin(50, MIX_DENOM.base), Addr::unchecked(owner), Layer::One, 12_345, @@ -64,14 +64,14 @@ pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::Stor pub fn good_mixnode_pledge() -> Vec { vec![Coin { - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), amount: INITIAL_MIXNODE_PLEDGE, }] } pub fn good_gateway_pledge() -> Vec { vec![Coin { - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), amount: INITIAL_MIXNODE_PLEDGE, }] } diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index 73bc4923ba..e8a1108317 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -17,7 +17,7 @@ pub mod test_helpers { use crate::mixnodes::storage as mixnodes_storage; use crate::mixnodes::transactions::try_add_mixnode; use crate::support::tests; - use config::defaults::{DEFAULT_NETWORK, DENOM}; + use config::defaults::{DEFAULT_NETWORK, MIX_DENOM}; use cosmwasm_std::testing::mock_dependencies; use cosmwasm_std::testing::mock_env; use cosmwasm_std::testing::mock_info; @@ -111,7 +111,7 @@ pub mod test_helpers { let delegation = Delegation { owner: Addr::unchecked(owner.into()), node_identity: mix.into(), - amount: coin(12345, DENOM), + amount: coin(12345, MIX_DENOM.base), block_height: block_height, proxy: None, }; diff --git a/contracts/mixnet/src/support/tests/queries.rs b/contracts/mixnet/src/support/tests/queries.rs index 9a9900501b..c42dd9b267 100644 --- a/contracts/mixnet/src/support/tests/queries.rs +++ b/contracts/mixnet/src/support/tests/queries.rs @@ -1,4 +1,4 @@ -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{ from_binary, testing::{mock_env, MockApi, MockQuerier, MockStorage}, @@ -45,5 +45,5 @@ pub fn query_contract_balance( deps: OwnedDeps, ) -> Vec { let querier = deps.as_ref().querier; - vec![querier.query_balance(address, DENOM).unwrap()] + vec![querier.query_balance(address, MIX_DENOM.base).unwrap()] } diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index e40feb27dd..469566faf8 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -4,7 +4,7 @@ use crate::traits::{ DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount, }; use crate::vesting::{populate_vesting_periods, Account}; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{ coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, Timestamp, @@ -147,8 +147,11 @@ pub fn try_withdraw_vested_coins( info: MessageInfo, deps: DepsMut<'_>, ) -> Result { - if amount.denom != DENOM { - return Err(ContractError::WrongDenom(amount.denom, DENOM.to_string())); + if amount.denom != MIX_DENOM.base { + return Err(ContractError::WrongDenom( + amount.denom, + MIX_DENOM.base.to_string(), + )); } let address = info.sender.clone(); @@ -611,10 +614,10 @@ fn validate_funds(funds: &[Coin]) -> Result { return Err(ContractError::MultipleDenoms); } - if funds[0].denom != DENOM { + if funds[0].denom != MIX_DENOM.base { return Err(ContractError::WrongDenom( funds[0].denom.clone(), - DENOM.to_string(), + MIX_DENOM.base.to_string(), )); } diff --git a/contracts/vesting/src/support/tests.rs b/contracts/vesting/src/support/tests.rs index b108f0a64a..eee85a9070 100644 --- a/contracts/vesting/src/support/tests.rs +++ b/contracts/vesting/src/support/tests.rs @@ -2,7 +2,7 @@ pub mod helpers { use crate::contract::instantiate; use crate::vesting::{populate_vesting_periods, Account}; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier}; use cosmwasm_std::{Addr, Coin, Empty, Env, MemoryStorage, OwnedDeps, Storage, Uint128}; use vesting_contract_common::messages::{InitMsg, VestingSpecification}; @@ -31,7 +31,7 @@ pub mod helpers { Some(Addr::unchecked("staking")), Coin { amount: Uint128::new(1_000_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, start_time_ts, periods, @@ -50,7 +50,7 @@ pub mod helpers { Some(Addr::unchecked("staking")), Coin { amount: Uint128::new(1_000_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, start_time, periods, diff --git a/contracts/vesting/src/vesting/account/mod.rs b/contracts/vesting/src/vesting/account/mod.rs index b25628deea..5418619cfe 100644 --- a/contracts/vesting/src/vesting/account/mod.rs +++ b/contracts/vesting/src/vesting/account/mod.rs @@ -25,11 +25,11 @@ fn generate_storage_key(storage: &mut dyn Storage) -> Result #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Account { - owner_address: Addr, - staking_address: Option, - start_time: Timestamp, - periods: Vec, - coin: Coin, + pub owner_address: Addr, + pub staking_address: Option, + pub start_time: Timestamp, + pub periods: Vec, + pub coin: Coin, storage_key: u32, } diff --git a/contracts/vesting/src/vesting/account/vesting_account.rs b/contracts/vesting/src/vesting/account/vesting_account.rs index 46da32e66d..489826b48c 100644 --- a/contracts/vesting/src/vesting/account/vesting_account.rs +++ b/contracts/vesting/src/vesting/account/vesting_account.rs @@ -1,7 +1,7 @@ use crate::errors::ContractError; use crate::storage::{delete_account, save_account, DELEGATIONS}; use crate::traits::VestingAccount; -use config::defaults::DENOM; +use config::defaults::MIX_DENOM; use cosmwasm_std::{Addr, Coin, Env, Order, Storage, Timestamp, Uint128}; use vesting_contract_common::{OriginalVestingResponse, Period}; @@ -38,7 +38,7 @@ impl VestingAccount for Account { .u128(), ), ), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -54,7 +54,7 @@ impl VestingAccount for Account { .u128() .saturating_sub(self.locked_coins(block_time, env, storage)?.amount.u128()), ), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -69,15 +69,15 @@ impl VestingAccount for Account { let amount = match period { Period::Before => Coin { amount: Uint128::new(0), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, Period::In(idx) => Coin { amount: Uint128::new(self.tokens_per_period()? * idx as u128), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, Period::After => Coin { amount: self.coin.amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, }; Ok(amount) @@ -91,7 +91,7 @@ impl VestingAccount for Account { Ok(Coin { amount: self.get_original_vesting().amount().amount - self.get_vested_coins(block_time, env)?.amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -143,7 +143,7 @@ impl VestingAccount for Account { Ok(Coin { amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -161,7 +161,7 @@ impl VestingAccount for Account { Ok(Coin { amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -197,7 +197,7 @@ impl VestingAccount for Account { Ok(Coin { amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } @@ -217,12 +217,12 @@ impl VestingAccount for Account { let amount = bond.amount().amount - bonded_free.amount; Ok(Coin { amount, - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } else { Ok(Coin { amount: Uint128::zero(), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }) } } diff --git a/contracts/vesting/src/vesting/mod.rs b/contracts/vesting/src/vesting/mod.rs index f14019cfaf..250b4e34f1 100644 --- a/contracts/vesting/src/vesting/mod.rs +++ b/contracts/vesting/src/vesting/mod.rs @@ -44,7 +44,7 @@ mod tests { use crate::traits::DelegatingAccount; use crate::traits::VestingAccount; use crate::traits::{GatewayBondingAccount, MixnodeBondingAccount}; - use config::defaults::DENOM; + use config::defaults::MIX_DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, Addr, Coin, Timestamp, Uint128}; use mixnet_contract_common::{Gateway, MixNode}; @@ -55,7 +55,7 @@ mod tests { fn test_account_creation() { let mut deps = init_contract(); let env = mock_env(); - let info = mock_info("not_admin", &coins(1_000_000_000_000, DENOM)); + let info = mock_info("not_admin", &coins(1_000_000_000_000, MIX_DENOM.base)); let msg = ExecuteMsg::CreateAccount { owner_address: "owner".to_string(), staking_address: Some("staking".to_string()), @@ -65,7 +65,7 @@ mod tests { let response = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone()); assert!(response.is_err()); - let info = mock_info("admin", &coins(1_000_000_000_000, DENOM)); + let info = mock_info("admin", &coins(1_000_000_000_000, MIX_DENOM.base)); let _response = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone()); let created_account = load_account(&Addr::unchecked("owner"), &deps.storage) .unwrap() @@ -131,7 +131,7 @@ mod tests { let msg = ExecuteMsg::WithdrawVestedCoins { amount: Coin { amount: Uint128::new(1), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, }; let info = mock_info("new_owner", &[]); @@ -262,7 +262,7 @@ mod tests { let delegation = Coin { amount: Uint128::new(500_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }; let ok = account.try_delegate_to_mixnode( @@ -388,7 +388,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(1_000_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -399,7 +399,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -414,7 +414,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -510,7 +510,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(1_000_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -522,7 +522,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -538,7 +538,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -630,7 +630,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(1_000_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -642,7 +642,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_000), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, @@ -658,7 +658,7 @@ mod tests { "alice".to_string(), Coin { amount: Uint128::new(500_000_000_001), - denom: DENOM.to_string(), + denom: MIX_DENOM.base.to_string(), }, &env, &mut deps.storage, diff --git a/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/AppEnv.ts b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/AppEnv.ts new file mode 100644 index 0000000000..111e2dfd13 --- /dev/null +++ b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/AppEnv.ts @@ -0,0 +1,2 @@ + +export interface AppEnv { ADMIN_ADDRESS: string | null, SHOW_TERMINAL: string | null, } \ No newline at end of file diff --git a/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrl.ts b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrl.ts new file mode 100644 index 0000000000..9c74679bac --- /dev/null +++ b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrl.ts @@ -0,0 +1,2 @@ + +export interface ValidatorUrl { url: string, name: string | null, } \ No newline at end of file diff --git a/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrls.ts b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrls.ts new file mode 100644 index 0000000000..2ac6693e0b --- /dev/null +++ b/nym-wallet/nym-wallet-types/nym-wallet/src/types/rust/ValidatorUrls.ts @@ -0,0 +1,2 @@ + +export interface Validator { nymd_url: string, nymd_name: string | null, api_url: string | null, } \ No newline at end of file diff --git a/nym-wallet/nym-wallet-types/src/network.rs b/nym-wallet/nym-wallet-types/src/network.rs index c653b3468b..e5a10d0492 100644 --- a/nym-wallet/nym-wallet-types/src/network.rs +++ b/nym-wallet/nym-wallet-types/src/network.rs @@ -28,6 +28,7 @@ impl Network { self.to_string().to_lowercase() } + #[deprecated] pub fn denom(&self) -> Denom { match self { // network defaults should be correctly formatted @@ -36,6 +37,22 @@ impl Network { Network::MAINNET => Denom::from_str(mainnet::DENOM).unwrap(), } } + + pub fn base_mix_denom(&self) -> &str { + match self { + Network::QA => qa::MIX_DENOM.base, + Network::SANDBOX => sandbox::MIX_DENOM.base, + Network::MAINNET => mainnet::MIX_DENOM.base, + } + } + + pub fn display_mix_denom(&self) -> &str { + match self { + Network::QA => qa::MIX_DENOM.display, + Network::SANDBOX => sandbox::MIX_DENOM.display, + Network::MAINNET => mainnet::MIX_DENOM.display, + } + } } impl Default for Network { diff --git a/nym-wallet/src-tauri/src/error.rs b/nym-wallet/src-tauri/src/error.rs index 04c954e6cb..ad7272fe4f 100644 --- a/nym-wallet/src-tauri/src/error.rs +++ b/nym-wallet/src-tauri/src/error.rs @@ -1,4 +1,5 @@ use nym_types::error::TypesError; +use nym_wallet_types::network::Network; use serde::{Serialize, Serializer}; use std::io; use std::num::ParseIntError; @@ -104,6 +105,10 @@ pub enum BackendError { FailedToDeriveAddress, #[error("{0}")] ValueParseError(#[from] ParseIntError), + #[error("The provided coin has an unknown denomination - {0}")] + UnknownCoinDenom(String), + #[error("Network {network} doesn't have any associated registered coin denoms")] + NoCoinsRegistered { network: Network }, } impl Serialize for BackendError { diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index a8efcf1bf8..8258595e90 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -4,9 +4,7 @@ )] use mixnet_contract_common::{Gateway, MixNode}; -use std::sync::Arc; use tauri::Menu; -use tokio::sync::RwLock; mod config; mod error; @@ -24,14 +22,14 @@ use crate::operations::simulate; use crate::operations::validator_api; use crate::operations::vesting; -use crate::state::State; +use crate::state::WalletState; fn main() { dotenv::dotenv().ok(); setup_logging(); tauri::Builder::default() - .manage(Arc::new(RwLock::new(State::default()))) + .manage(WalletState::default()) .invoke_handler(tauri::generate_handler![ mixnet::account::add_account_for_password, mixnet::account::connect_with_mnemonic, diff --git a/nym-wallet/src-tauri/src/network_config.rs b/nym-wallet/src-tauri/src/network_config.rs index 2a621922d5..43e872b717 100644 --- a/nym-wallet/src-tauri/src/network_config.rs +++ b/nym-wallet/src-tauri/src/network_config.rs @@ -1,20 +1,15 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::sync::Arc; - -use tokio::sync::RwLock; - +use crate::error::BackendError; +use crate::state::WalletState; use nym_wallet_types::network::Network as WalletNetwork; use nym_wallet_types::network_config::{Validator, ValidatorUrl, ValidatorUrls}; -use crate::error::BackendError; -use crate::state::State; - #[tauri::command] pub async fn get_validator_nymd_urls( network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let state = state.read().await; let urls: Vec = state.get_nymd_urls(network).collect(); @@ -24,7 +19,7 @@ pub async fn get_validator_nymd_urls( #[tauri::command] pub async fn get_validator_api_urls( network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let state = state.read().await; let urls: Vec = state.get_api_urls(network).collect(); @@ -35,7 +30,7 @@ pub async fn get_validator_api_urls( pub async fn select_validator_nymd_url( url: &str, network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::debug!("Selecting new validator nymd_url for {network}: {url}"); state @@ -49,7 +44,7 @@ pub async fn select_validator_nymd_url( pub async fn select_validator_api_url( url: &str, network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::debug!("Selecting new validator api_url for {network}: {url}"); state.write().await.select_validator_api_url(url, network)?; @@ -60,7 +55,7 @@ pub async fn select_validator_api_url( pub async fn add_validator( validator: Validator, network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::debug!("Add validator for {network}: {validator}"); let url = validator.try_into()?; @@ -72,7 +67,7 @@ pub async fn add_validator( pub async fn remove_validator( validator: Validator, network: WalletNetwork, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::debug!("Remove validator for {network}: {validator}"); let url = validator.try_into()?; @@ -83,7 +78,7 @@ pub async fn remove_validator( // Update the list of validators by fecthing additional ones remotely. If it fails, just ignore. #[tauri::command] pub async fn update_validator_urls( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { let mut w_state = state.write().await; let _r = w_state.fetch_updated_validator_urls().await; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/account.rs b/nym-wallet/src-tauri/src/operations/mixnet/account.rs index ae2635a18b..e126d6b5b8 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/account.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/account.rs @@ -1,8 +1,7 @@ use crate::config::{Config, CUSTOM_SIMULATED_GAS_MULTIPLIER}; use crate::error::BackendError; use crate::network_config; -use crate::nymd_client; -use crate::state::{State, WalletAccountIds}; +use crate::state::{WalletAccountIds, WalletState}; use crate::wallet_storage::{self, DEFAULT_LOGIN_ID}; use bip39::{Language, Mnemonic}; use config::defaults::all::Network; @@ -10,15 +9,11 @@ use config::defaults::COSMOS_DERIVATION_PATH; use cosmrs::bip32::DerivationPath; use itertools::Itertools; use nym_types::account::{Account, AccountEntry, Balance}; -use nym_types::currency::MajorCurrencyAmount; use nym_wallet_types::network::Network as WalletNetwork; use rand::seq::SliceRandom; use std::collections::HashMap; -use std::convert::TryInto; use std::str::FromStr; -use std::sync::Arc; use strum::IntoEnumIterator; -use tokio::sync::RwLock; use url::Url; use validator_client::nymd::wallet::{AccountData, DirectSecp256k1HdWallet}; use validator_client::{nymd::SigningNymdClient, Client}; @@ -26,33 +21,30 @@ use validator_client::{nymd::SigningNymdClient, Client}; #[tauri::command] pub async fn connect_with_mnemonic( mnemonic: String, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let mnemonic = Mnemonic::from_str(&mnemonic)?; _connect_with_mnemonic(mnemonic, state).await } #[tauri::command] -pub async fn get_balance( - state: tauri::State<'_, Arc>>, -) -> Result { - let denom = state.read().await.current_network().denom(); - match nymd_client!(state) - .get_balance(nymd_client!(state).address(), denom) - .await +pub async fn get_balance(state: tauri::State<'_, WalletState>) -> Result { + let guard = state.read().await; + let client = guard.current_client()?; + let address = client.nymd.address(); + let network = guard.current_network(); + let base_mix_denom = network.base_mix_denom(); + + match client + .nymd + .get_balance(address, base_mix_denom.to_string()) + .await? { - Ok(Some(coin)) => { - let amount = MajorCurrencyAmount::from(coin); - let printable_balance = amount.to_string(); - Ok(Balance { - amount, - printable_balance, - }) + Some(coin) => { + let amount = guard.attempt_convert_to_display_dec_coin(coin)?; + Ok(Balance::new(amount)) } - Ok(None) => Err(BackendError::NoBalance( - nymd_client!(state).address().to_string(), - )), - Err(e) => Err(BackendError::from(e)), + None => Err(BackendError::NoBalance(address.to_string())), } } @@ -68,18 +60,18 @@ pub fn validate_mnemonic(mnemonic: &str) -> bool { #[tauri::command] pub async fn switch_network( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, network: WalletNetwork, ) -> Result { let account = { let r_state = state.read().await; let client = r_state.client(network)?; - let denom = network.denom(); + let denom = network.base_mix_denom(); Account::new( client.nymd.mixnet_contract_address().to_string(), client.nymd.address().to_string(), - denom.try_into()?, + denom.into(), ) }; @@ -90,7 +82,7 @@ pub async fn switch_network( } #[tauri::command] -pub async fn logout(state: tauri::State<'_, Arc>>) -> Result<(), BackendError> { +pub async fn logout(state: tauri::State<'_, WalletState>) -> Result<(), BackendError> { state.write().await.logout(); Ok(()) } @@ -102,7 +94,7 @@ fn random_mnemonic() -> Mnemonic { async fn _connect_with_mnemonic( mnemonic: Mnemonic, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { { let mut w_state = state.write().await; @@ -162,7 +154,7 @@ async fn _connect_with_mnemonic( Some(client) => Ok(Account::new( client.nymd.mixnet_contract_address().to_string(), client.nymd.address().to_string(), - default_network.denom().try_into()?, + default_network.base_mix_denom().into(), )), None => Err(BackendError::NetworkNotSupported( config::defaults::DEFAULT_NETWORK, @@ -178,6 +170,7 @@ async fn _connect_with_mnemonic( let network: WalletNetwork = client.network.into(); let mut w_state = state.write().await; w_state.add_client(network, client); + w_state.register_default_denoms(network); } account_for_default_network @@ -322,7 +315,7 @@ pub fn create_password(mnemonic: &str, password: String) -> Result<(), BackendEr #[tauri::command] pub async fn sign_in_with_password( password: String, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!("Signing in with password"); @@ -362,7 +355,7 @@ fn extract_first_mnemonic( pub async fn sign_in_with_password_and_account_id( account_id: &str, password: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!("Signing in with password"); @@ -409,7 +402,7 @@ pub async fn add_account_for_password( mnemonic: &str, password: &str, account_id: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!("Adding account for the current password: {account_id}"); let mnemonic = Mnemonic::from_str(mnemonic)?; @@ -451,7 +444,7 @@ pub async fn add_account_for_password( async fn set_state_with_all_accounts( stored_login: wallet_storage::StoredLogin, first_id_when_converting: wallet_storage::AccountId, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::trace!("Set state with accounts:"); let all_accounts: Vec<_> = stored_login @@ -492,7 +485,7 @@ async fn set_state_with_all_accounts( pub async fn remove_account_for_password( password: &str, account_id: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::info!("Removing account: {account_id}"); // Currently we only support a single, default, id in the wallet @@ -523,7 +516,7 @@ fn derive_address( #[tauri::command] pub async fn list_accounts( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::trace!("Listing accounts"); let state = state.read().await; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/admin.rs b/nym-wallet/src-tauri/src/operations/mixnet/admin.rs index abfa3a48b5..faced61bce 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/admin.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/admin.rs @@ -1,19 +1,14 @@ -use std::convert::TryInto; -use std::sync::Arc; - -use tokio::sync::RwLock; - -use mixnet_contract_common::ContractStateParams; -use nym_wallet_types::admin::TauriContractStateParams; -use validator_client::nymd::Fee; - use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; +use mixnet_contract_common::ContractStateParams; +use nym_wallet_types::admin::TauriContractStateParams; +use std::convert::TryInto; +use validator_client::nymd::Fee; #[tauri::command] pub async fn get_contract_settings( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Getting contract settings"); let res = nymd_client!(state).get_contract_settings().await?.into(); @@ -25,7 +20,7 @@ pub async fn get_contract_settings( pub async fn update_contract_settings( params: TauriContractStateParams, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let mixnet_contract_settings_params: ContractStateParams = params.try_into()?; log::info!( diff --git a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs index 7c20d1bab6..c9b38ca102 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs @@ -1,56 +1,56 @@ use crate::error::BackendError; -use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; use crate::{Gateway, MixNode}; -use nym_types::currency::MajorCurrencyAmount; +use nym_types::currency::DecCoin; use nym_types::gateway::GatewayBond; use nym_types::mixnode::MixNodeBond; use nym_types::transaction::TransactionExecuteResult; -use std::sync::Arc; -use tokio::sync::RwLock; -use validator_client::nymd::{CosmWasmCoin, Fee}; +use validator_client::nymd::{Coin, Fee}; #[tauri::command] pub async fn bond_gateway( gateway: Gateway, - pledge: MajorCurrencyAmount, + pledge: DecCoin, owner_signature: String, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let pledge_minor = pledge.clone().into(); + let guard = state.read().await; + let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Bond gateway: identity_key = {}, pledge = {}, pledge_minor = {}, fee = {:?}", - &gateway.identity_key, + ">>> Bond gateway: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}", + gateway.identity_key, pledge, - &pledge_minor, + pledge_base, fee, ); - let res = nymd_client!(state) - .bond_gateway(gateway, owner_signature, pledge_minor, fee) + let res = guard + .current_client()? + .nymd + .bond_gateway(gateway, owner_signature, pledge_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn unbond_gateway( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!(">>> Unbond gateway, fee = {:?}", fee); - let res = nymd_client!(state).unbond_gateway(fee).await?; + let res = guard.current_client()?.nymd.unbond_gateway(fee).await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -58,43 +58,46 @@ pub async fn unbond_gateway( pub async fn bond_mixnode( mixnode: MixNode, owner_signature: String, - pledge: MajorCurrencyAmount, + pledge: DecCoin, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let pledge_minor = pledge.clone().into(); + let guard = state.read().await; + let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Bond mixnode: identity_key = {}, pledge = {}, pledge_minor = {}, fee = {:?}", + ">>> Bond mixnode: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}", mixnode.identity_key, pledge, - pledge_minor, + pledge_base, fee, ); - let res = nymd_client!(state) - .bond_mixnode(mixnode, owner_signature, pledge_minor, fee) + let res = guard + .current_client()? + .nymd + .bond_mixnode(mixnode, owner_signature, pledge_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn unbond_mixnode( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!(">>> Unbond mixnode, fee = {:?}", fee); - let res = nymd_client!(state).unbond_mixnode(fee).await?; + let res = guard.current_client()?.nymd.unbond_mixnode(fee).await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -102,34 +105,43 @@ pub async fn unbond_mixnode( pub async fn update_mixnode( profit_margin_percent: u8, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( ">>> Update mixnode: profit_margin_percent = {}, fee {:?}", profit_margin_percent, fee, ); - let res = nymd_client!(state) + let res = guard + .current_client()? + .nymd .update_mixnode_config(profit_margin_percent, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn mixnode_bond_details( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get mixnode bond details"); let guard = state.read().await; let client = guard.current_client()?; let bond = client.nymd.owns_mixnode(client.nymd.address()).await?; - let res = MixNodeBond::from_mixnet_contract_mixnode_bond(bond)?; + let res = bond + .map(|bond| { + guard + .registered_coins() + .map(|reg| MixNodeBond::from_mixnet_contract_mixnode_bond(bond, reg)) + }) + .transpose()? + .transpose()?; log::info!( "<<< identity_key = {:?}", res.as_ref().map(|r| r.mix_node.identity_key.to_string()) @@ -140,13 +152,21 @@ pub async fn mixnode_bond_details( #[tauri::command] pub async fn gateway_bond_details( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get gateway bond details"); let guard = state.read().await; let client = guard.current_client()?; let bond = client.nymd.owns_gateway(client.nymd.address()).await?; - let res = GatewayBond::from_mixnet_contract_gateway_bond(bond)?; + let res = bond + .map(|bond| { + guard + .registered_coins() + .map(|reg| GatewayBond::from_mixnet_contract_gateway_bond(bond, reg)) + }) + .transpose()? + .transpose()?; + log::info!( "<<< identity_key = {:?}", res.as_ref().map(|r| r.gateway.identity_key.to_string()) @@ -158,17 +178,23 @@ pub async fn gateway_bond_details( #[tauri::command] pub async fn get_operator_rewards( address: String, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Get operator rewards for {}", address); - let denom = state.read().await.current_network().denom(); - let rewards_as_minor = nymd_client!(state).get_operator_rewards(address).await?; - let coin = CosmWasmCoin::new(rewards_as_minor.u128(), denom.as_ref()); - let amount: MajorCurrencyAmount = coin.into(); + let guard = state.read().await; + let network = guard.current_network(); + let denom = network.base_mix_denom(); + let reward_amount = guard + .current_client()? + .nymd + .get_operator_rewards(address) + .await?; + let base_coin = Coin::new(reward_amount.u128(), denom); + let display_coin: DecCoin = guard.attempt_convert_to_display_dec_coin(base_coin.clone())?; log::info!( - "<<< rewards_as_minor = {}, amount = {}", - rewards_as_minor, - amount + "<<< rewards_base = {}, rewards_display = {}", + base_coin, + display_coin ); - Ok(amount) + Ok(display_coin) } diff --git a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs index 438256d8ff..d0d101584a 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs @@ -1,61 +1,64 @@ use crate::error::BackendError; -use crate::state::State; +use crate::state::WalletState; use crate::vesting::delegate::get_pending_vesting_delegation_events; use crate::{api_client, nymd_client}; -use cosmwasm_std::Coin as CosmWasmCoin; use mixnet_contract_common::IdentityKey; -use nym_types::currency::{CurrencyDenom, MajorCurrencyAmount}; +use nym_types::currency::DecCoin; use nym_types::delegation::{ - from_contract_delegation_events, Delegation, DelegationEvent, DelegationRecord, - DelegationWithEverything, DelegationsSummaryResponse, + Delegation, DelegationEvent, DelegationRecord, DelegationWithEverything, + DelegationsSummaryResponse, }; use nym_types::transaction::TransactionExecuteResult; use std::collections::HashMap; -use std::sync::Arc; -use tokio::sync::RwLock; -use validator_client::nymd::Fee; +use validator_client::nymd::{Coin, Fee}; #[tauri::command] pub async fn get_pending_delegation_events( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get pending delegation events"); - let events = nymd_client!(state) - .get_pending_delegation_events(nymd_client!(state).address().to_string(), None) + let guard = state.read().await; + let reg = guard.registered_coins()?; + let client = guard.current_client()?; + + let events = client + .nymd + .get_pending_delegation_events(client.nymd.address().to_string(), None) .await?; log::info!("<<< {} pending delegation events", events.len()); log::trace!("<<< pending delegation events = {:?}", events); - match from_contract_delegation_events(events) { - Ok(res) => Ok(res), - Err(e) => Err(e.into()), - } + Ok(events + .into_iter() + .map(|event| DelegationEvent::from_mixnet_contract(event, reg)) + .collect::>()?) } #[tauri::command] pub async fn delegate_to_mixnode( identity: &str, - amount: MajorCurrencyAmount, + amount: DecCoin, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let delegation = amount.clone().into(); + let guard = state.read().await; + let delegation_base = guard.attempt_convert_to_base_coin(amount.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Delegate to mixnode: identity_key = {}, amount = {}, minor_amount = {}, fee = {:?}", + ">>> Delegate to mixnode: identity_key = {}, display_amount = {}, base_amount = {}, fee = {:?}", identity, amount, - delegation, + delegation_base, fee, ); let res = nymd_client!(state) - .delegate_to_mixnode(identity, delegation, fee) + .delegate_to_mixnode(identity, delegation_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -63,50 +66,54 @@ pub async fn delegate_to_mixnode( pub async fn undelegate_from_mixnode( identity: &str, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( ">>> Undelegate from mixnode: identity_key = {}, fee = {:?}", identity, fee ); - let res = nymd_client!(state) + let res = guard + .current_client()? + .nymd .remove_mixnode_delegation(identity, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } struct DelegationWithHistory { pub delegation: Delegation, - pub amount_sum: MajorCurrencyAmount, + pub amount_sum: DecCoin, pub history: Vec, } #[tauri::command] pub async fn get_all_mix_delegations( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get all mixnode delegations"); + let guard = state.read().await; + let client = guard.current_client()?; + let reg = guard.registered_coins()?; + // TODO: add endpoint to validator API to get a single mix node bond - let mixnodes = api_client!(state).get_mixnodes().await?; + let mixnodes = client.validator_api.get_mixnodes().await?; - let address = nymd_client!(state).address().to_string(); - - let denom_minor = state.read().await.current_network().denom(); - let denom: CurrencyDenom = denom_minor.clone().try_into()?; + let address = client.nymd.address(); + let network = guard.current_network(); + let display_mix_denom = network.display_mix_denom(); + let base_mix_denom = network.base_mix_denom(); log::info!(" >>> Get delegations"); - let delegations = nymd_client!(state) - .get_delegator_delegations_paged(address.clone(), None, None) // get all delegations, ignoring paging - .await? - .delegations; + let delegations = client.get_all_delegator_delegations(address).await?; log::info!(" <<< {} delegations", delegations.len()); // first get pending events from the mixnet contract (operations made with unlocked tokens) @@ -125,20 +132,21 @@ pub async fn get_all_mix_delegations( let mut map: HashMap = HashMap::new(); - for pending_event in pending_events_for_account.clone() { + for pending_event in &pending_events_for_account { if delegations .iter() .any(|d| d.node_identity == pending_event.node_identity) { let amount = pending_event .amount - .unwrap_or_else(|| MajorCurrencyAmount::zero(&denom)); + .clone() + .unwrap_or_else(|| DecCoin::zero(display_mix_denom)); let delegation = DelegationWithHistory { delegation: Delegation { amount: amount.clone(), - node_identity: pending_event.node_identity, - proxy: None, - owner: pending_event.address, + node_identity: pending_event.node_identity.clone(), + proxy: None, // TODO: ask @MS about delegations via vesting contract => surely we'd have proxy there? + owner: pending_event.address.clone(), block_height: pending_event.block_height, }, amount_sum: amount, @@ -150,11 +158,13 @@ pub async fn get_all_mix_delegations( for d in delegations { // create record of delegation - let delegated_on_iso_datetime = nymd_client!(state) + let delegated_on_iso_datetime = client + .nymd .get_block_timestamp(Some(d.block_height as u32)) .await? .to_rfc3339(); - let amount: MajorCurrencyAmount = d.amount.clone().into(); + let amount = guard.attempt_convert_to_display_dec_coin(d.amount.clone().into())?; + let record = DelegationRecord { amount: amount.clone(), block_height: d.block_height, @@ -164,13 +174,15 @@ pub async fn get_all_mix_delegations( let entry = map .entry(d.node_identity.clone()) .or_insert(DelegationWithHistory { - delegation: d.try_into()?, + delegation: Delegation::from_mixnet_contract(d, reg)?, history: vec![], - amount_sum: MajorCurrencyAmount::zero(&amount.denom), + amount_sum: DecCoin::zero(display_mix_denom), }); + debug_assert_eq!(entry.amount_sum.denom, amount.denom); + entry.history.push(record); - entry.amount_sum = entry.amount_sum.clone() + amount; + entry.amount_sum.amount += amount.amount; } let mut with_everything: Vec = vec![]; @@ -196,25 +208,25 @@ pub async fn get_all_mix_delegations( .iter() .find(|m| m.mix_node.identity_key == node_identity); - let pledge_amount: Option = - mixnode.and_then(|m| m.pledge_amount.clone().try_into().ok()); + let pledge_amount = mixnode + .map(|m| guard.attempt_convert_to_display_dec_coin(m.pledge_amount.clone().into())) + .transpose()?; - let total_delegation: Option = - mixnode.and_then(|m| m.total_delegation.clone().try_into().ok()); + let total_delegation = mixnode + .map(|m| guard.attempt_convert_to_display_dec_coin(m.total_delegation.clone().into())) + .transpose()?; let profit_margin_percent: Option = mixnode.map(|m| m.mix_node.profit_margin_percent); log::trace!(" >>> Get accumulated rewards: address = {}", address); - let accumulated_rewards = match nymd_client!(state) - .get_delegator_rewards(address.clone(), node_identity.clone(), proxy.clone()) + let accumulated_rewards = match client + .nymd + .get_delegator_rewards(address.to_string(), node_identity.clone(), proxy.clone()) .await { Ok(rewards) => { - let reward = CosmWasmCoin { - denom: denom_minor.to_string(), - amount: rewards, - }; - let amount = MajorCurrencyAmount::from(reward); + let reward = Coin::new(rewards.u128(), base_mix_denom); + let amount = guard.attempt_convert_to_display_dec_coin(reward)?; log::trace!(" <<< rewards = {}, amount = {}", rewards, amount); Some(amount) } @@ -305,40 +317,52 @@ pub async fn get_delegator_rewards( address: String, mix_identity: IdentityKey, proxy: Option, - state: tauri::State<'_, Arc>>, -) -> Result { - let denom_minor = state.read().await.current_network().denom(); + state: tauri::State<'_, WalletState>, +) -> Result { log::info!( ">>> Get delegator rewards: mix_identity = {}, proxy = {:?}", mix_identity, proxy ); - let res = nymd_client!(state) + let guard = state.read().await; + let network = guard.current_network(); + let denom = network.base_mix_denom(); + let reward_amount = guard + .current_client()? + .nymd .get_delegator_rewards(address, mix_identity, proxy) .await?; - let coin = CosmWasmCoin::new(res.u128(), denom_minor.as_ref()); - let amount = coin.into(); - log::info!(">>> res = {}, amount = {}", res, amount); - Ok(amount) + let base_coin = Coin::new(reward_amount.u128(), denom); + let display_coin: DecCoin = guard.attempt_convert_to_display_dec_coin(base_coin.clone())?; + + log::info!( + "<<< rewards_base = {}, rewards_display = {}", + base_coin, + display_coin + ); + Ok(display_coin) } #[tauri::command] pub async fn get_delegation_summary( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Get delegation summary"); - let denom_minor = state.read().await.current_network().denom(); - let denom: CurrencyDenom = denom_minor.clone().try_into()?; + let guard = state.read().await; + let network = guard.current_network(); + let display_mix_denom = network.display_mix_denom(); let delegations = get_all_mix_delegations(state.clone()).await?; - let mut total_delegations = MajorCurrencyAmount::zero(&denom); - let mut total_rewards = MajorCurrencyAmount::zero(&denom); + let mut total_delegations = DecCoin::zero(display_mix_denom); + let mut total_rewards = DecCoin::zero(display_mix_denom); - for d in delegations.clone() { - total_delegations = total_delegations + d.amount; - if let Some(rewards) = d.accumulated_rewards { - total_rewards = total_rewards + rewards; + for d in &delegations { + debug_assert_eq!(d.amount.denom, display_mix_denom); + total_delegations.amount += d.amount.amount; + if let Some(rewards) = &d.accumulated_rewards { + debug_assert_eq!(rewards.denom, display_mix_denom); + total_rewards.amount += rewards.amount; } } log::info!( @@ -358,7 +382,7 @@ pub async fn get_delegation_summary( #[tauri::command] pub async fn get_all_pending_delegation_events( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get all pending delegation events"); diff --git a/nym-wallet/src-tauri/src/operations/mixnet/epoch.rs b/nym-wallet/src-tauri/src/operations/mixnet/epoch.rs index 5203e5bc62..2ca8fe0c05 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/epoch.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/epoch.rs @@ -1,13 +1,11 @@ use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; use nym_wallet_types::epoch::Epoch; -use std::sync::Arc; -use tokio::sync::RwLock; #[tauri::command] pub async fn get_current_epoch( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Get curren epoch"); let interval = nymd_client!(state).get_current_epoch().await?; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs index adc4612a34..61e729e75a 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs @@ -1,15 +1,13 @@ use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; use mixnet_contract_common::IdentityKey; -use std::sync::Arc; -use tokio::sync::RwLock; use validator_client::nymd::Fee; #[tauri::command] pub async fn claim_operator_reward( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_claim_operator_reward(fee) @@ -20,7 +18,7 @@ pub async fn claim_operator_reward( #[tauri::command] pub async fn compound_operator_reward( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_compound_operator_reward(fee) @@ -32,7 +30,7 @@ pub async fn compound_operator_reward( pub async fn claim_delegator_reward( mix_identity: IdentityKey, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_claim_delegator_reward(mix_identity, fee) @@ -44,7 +42,7 @@ pub async fn claim_delegator_reward( pub async fn compound_delegator_reward( mix_identity: IdentityKey, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_compound_delegator_reward(mix_identity, fee) diff --git a/nym-wallet/src-tauri/src/operations/mixnet/send.rs b/nym-wallet/src-tauri/src/operations/mixnet/send.rs index 30efde8566..0e4cbdd6a3 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/send.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/send.rs @@ -1,46 +1,43 @@ use crate::error::BackendError; -use crate::nymd_client; -use crate::state::State; -use nym_types::currency::MajorCurrencyAmount; +use crate::state::WalletState; +use nym_types::currency::DecCoin; use nym_types::transaction::{SendTxResult, TransactionDetails}; use std::str::FromStr; -use std::sync::Arc; -use tokio::sync::RwLock; use validator_client::nymd::{AccountId, Fee}; #[tauri::command] pub async fn send( address: &str, - amount: MajorCurrencyAmount, + amount: DecCoin, memo: String, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let address = AccountId::from_str(address)?; - let from_address = nymd_client!(state).address().to_string(); - let amount2 = amount.clone().into(); + let guard = state.read().await; + let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?; + + let to_address = AccountId::from_str(address)?; + let from_address = guard.current_client()?.nymd.address().to_string(); + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( - ">>> Send: amount = {}, minor_amount = {:?}, from = {}, to = {}, fee = {:?}", + ">>> Send: display_amount = {}, base_amount = {}, from = {}, to = {}, fee = {:?}", amount, - amount2, + amount_base, from_address, - address.as_ref(), + to_address, fee, ); - let raw_res = nymd_client!(state) - .send(&address, vec![amount2], memo, fee) + let raw_res = guard + .current_client()? + .nymd + .send(&to_address, vec![amount_base], memo, fee) .await?; log::info!("<<< tx hash = {}", raw_res.hash.to_string()); let res = SendTxResult::new( raw_res, - TransactionDetails { - from_address, - to_address: address.to_string(), - amount, - }, - denom_minor.as_ref(), - )?; + TransactionDetails::new(amount, from_address, to_address.to_string()), + fee_amount, + ); log::trace!("<<< {:?}", res); Ok(res) } diff --git a/nym-wallet/src-tauri/src/operations/simulate/admin.rs b/nym-wallet/src-tauri/src/operations/simulate/admin.rs index ac698f86c3..93535f2e42 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/admin.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/admin.rs @@ -3,16 +3,14 @@ use crate::error::BackendError; use crate::operations::simulate::{FeeDetails, SimulateResult}; -use crate::State; +use crate::WalletState; use mixnet_contract_common::{ContractStateParams, ExecuteMsg}; use nym_wallet_types::admin::TauriContractStateParams; -use std::sync::Arc; -use tokio::sync::RwLock; #[tauri::command] pub async fn simulate_update_contract_settings( params: TauriContractStateParams, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; let mixnet_contract_settings_params: ContractStateParams = params.try_into()?; @@ -28,5 +26,5 @@ pub async fn simulate_update_contract_settings( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } diff --git a/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs b/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs index 413df4e887..0da48e1dc5 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs @@ -3,23 +3,22 @@ use crate::error::BackendError; use crate::operations::simulate::{FeeDetails, SimulateResult}; -use crate::state::State; -use nym_types::currency::MajorCurrencyAmount; +use crate::state::WalletState; +use nym_types::currency::DecCoin; 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: MajorCurrencyAmount, - state: tauri::State<'_, Arc>>, + amount: DecCoin, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; + let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?; let to_address = AccountId::from_str(address)?; - let amount = vec![amount.into()]; + let amount = vec![amount_base.into()]; let client = guard.current_client()?; let from_address = client.nymd.address().clone(); @@ -33,5 +32,5 @@ pub async fn simulate_send( }; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } diff --git a/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs b/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs index 903819e235..16df47c762 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs @@ -4,22 +4,20 @@ use crate::error::BackendError; use crate::nymd_client; use crate::operations::simulate::{FeeDetails, SimulateResult}; -use crate::State; +use crate::WalletState; use mixnet_contract_common::IdentityKey; use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode}; -use nym_types::currency::MajorCurrencyAmount; -use std::sync::Arc; -use tokio::sync::RwLock; +use nym_types::currency::DecCoin; #[tauri::command] pub async fn simulate_bond_gateway( gateway: Gateway, - pledge: MajorCurrencyAmount, + pledge: DecCoin, owner_signature: String, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let pledge = pledge.into(); + let pledge = guard.attempt_convert_to_base_coin(pledge)?; let client = guard.current_client()?; let mixnet_contract = client.nymd.mixnet_contract_address(); @@ -36,12 +34,12 @@ pub async fn simulate_bond_gateway( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_unbond_gateway( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -56,18 +54,18 @@ pub async fn simulate_unbond_gateway( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_bond_mixnode( mixnode: MixNode, owner_signature: String, - pledge: MajorCurrencyAmount, - state: tauri::State<'_, Arc>>, + pledge: DecCoin, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let pledge = pledge.into(); + let pledge = guard.attempt_convert_to_base_coin(pledge)?; let client = guard.current_client()?; let mixnet_contract = client.nymd.mixnet_contract_address(); @@ -83,12 +81,12 @@ pub async fn simulate_bond_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_unbond_mixnode( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -103,13 +101,13 @@ pub async fn simulate_unbond_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_update_mixnode( profit_margin_percent: u8, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -126,17 +124,17 @@ pub async fn simulate_update_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_delegate_to_mixnode( identity: &str, - amount: MajorCurrencyAmount, - state: tauri::State<'_, Arc>>, + amount: DecCoin, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let delegation = amount.into(); + let delegation = guard.attempt_convert_to_base_coin(amount)?; let client = guard.current_client()?; let mixnet_contract = client.nymd.mixnet_contract_address(); @@ -151,13 +149,13 @@ pub async fn simulate_delegate_to_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_undelegate_from_mixnode( identity: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -174,51 +172,51 @@ pub async fn simulate_undelegate_from_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_claim_operator_reward( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_claim_operator_reward(None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_compound_operator_reward( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_compound_operator_reward(None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_claim_delegator_reward( mix_identity: IdentityKey, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_claim_delegator_reward(mix_identity, None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_compound_delegator_reward( mix_identity: IdentityKey, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_compound_delegator_reward(mix_identity, None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } diff --git a/nym-wallet/src-tauri/src/operations/simulate/mod.rs b/nym-wallet/src-tauri/src/operations/simulate/mod.rs index 4cbe3c0664..c030ea8ce8 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/mod.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/mod.rs @@ -1,7 +1,6 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use nym_types::currency::MajorCurrencyAmount; use nym_types::fees::FeeDetails; use validator_client::nymd::cosmwasm_client::types::GasInfo; use validator_client::nymd::{tx, CosmosCoin, Fee, GasPrice}; @@ -29,20 +28,12 @@ impl SimulateResult { } } - pub fn detailed_fee(&self) -> FeeDetails { - let amount = self.to_fee_amount().map(MajorCurrencyAmount::from); - FeeDetails { - amount, - fee: self.to_fee(), - } - } - - fn to_fee_amount(&self) -> Option { + pub(crate) fn to_fee_amount(&self) -> Option { self.gas_info .map(|gas_info| &self.gas_price * gas_info.gas_used) } - fn to_fee(&self) -> Fee { + pub(crate) fn to_fee(&self) -> Fee { self.to_fee_amount() .and_then(|fee_amount| { self.gas_info.map(|gas_info| { diff --git a/nym-wallet/src-tauri/src/operations/simulate/vesting.rs b/nym-wallet/src-tauri/src/operations/simulate/vesting.rs index b0f3f649d2..e00880c36b 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/vesting.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/vesting.rs @@ -4,23 +4,21 @@ use crate::error::BackendError; use crate::nymd_client; use crate::operations::simulate::{FeeDetails, SimulateResult}; -use crate::State; +use crate::WalletState; use mixnet_contract_common::IdentityKey; use mixnet_contract_common::{Gateway, MixNode}; -use nym_types::currency::MajorCurrencyAmount; -use std::sync::Arc; -use tokio::sync::RwLock; +use nym_types::currency::DecCoin; use vesting_contract_common::ExecuteMsg; #[tauri::command] pub async fn simulate_vesting_bond_gateway( gateway: Gateway, - pledge: MajorCurrencyAmount, + pledge: DecCoin, owner_signature: String, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let pledge = pledge.into(); + let pledge = guard.attempt_convert_to_base_coin(pledge)?; let client = guard.current_client()?; let vesting_contract = client.nymd.vesting_contract_address(); @@ -31,18 +29,18 @@ pub async fn simulate_vesting_bond_gateway( &ExecuteMsg::BondGateway { gateway, owner_signature, - amount: pledge, + amount: pledge.into(), }, vec![], )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_vesting_unbond_gateway( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -57,18 +55,18 @@ pub async fn simulate_vesting_unbond_gateway( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_vesting_bond_mixnode( mixnode: MixNode, owner_signature: String, - pledge: MajorCurrencyAmount, - state: tauri::State<'_, Arc>>, + pledge: DecCoin, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let pledge = pledge.into(); + let pledge = guard.attempt_convert_to_base_coin(pledge)?; let client = guard.current_client()?; let vesting_contract = client.nymd.vesting_contract_address(); @@ -79,18 +77,18 @@ pub async fn simulate_vesting_bond_mixnode( &ExecuteMsg::BondMixnode { mix_node: mixnode, owner_signature, - amount: pledge, + amount: pledge.into(), }, vec![], )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_vesting_unbond_mixnode( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -105,13 +103,13 @@ pub async fn simulate_vesting_unbond_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_vesting_update_mixnode( profit_margin_percent: u8, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; @@ -128,16 +126,16 @@ pub async fn simulate_vesting_update_mixnode( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_withdraw_vested_coins( - amount: MajorCurrencyAmount, - state: tauri::State<'_, Arc>>, + amount: DecCoin, + state: tauri::State<'_, WalletState>, ) -> Result { let guard = state.read().await; - let amount = amount.into(); + let amount = guard.attempt_convert_to_base_coin(amount)?.into(); let client = guard.current_client()?; let vesting_contract = client.nymd.vesting_contract_address(); @@ -150,51 +148,51 @@ pub async fn simulate_withdraw_vested_coins( )?; let result = client.nymd.simulate(vec![msg]).await?; - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price)) } #[tauri::command] pub async fn simulate_vesting_claim_operator_reward( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_vesting_claim_operator_reward(None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_vesting_compound_operator_reward( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_vesting_compound_operator_reward(None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_vesting_claim_delegator_reward( mix_identity: IdentityKey, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_vesting_claim_delegator_reward(mix_identity, None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } #[tauri::command] pub async fn simulate_vesting_compound_delegator_reward( mix_identity: IdentityKey, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { let result = nymd_client!(state) .simulate_vesting_compound_delegator_reward(mix_identity, None) .await?; let gas_price = nymd_client!(state).gas_price().clone(); - Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()?) } diff --git a/nym-wallet/src-tauri/src/operations/validator_api/status.rs b/nym-wallet/src-tauri/src/operations/validator_api/status.rs index 721c39bf82..7ff60d3e6b 100644 --- a/nym-wallet/src-tauri/src/operations/validator_api/status.rs +++ b/nym-wallet/src-tauri/src/operations/validator_api/status.rs @@ -3,9 +3,7 @@ use crate::api_client; use crate::error::BackendError; -use crate::state::State; -use std::sync::Arc; -use tokio::sync::RwLock; +use crate::state::WalletState; use validator_client::models::{ CoreNodeStatusResponse, InclusionProbabilityResponse, MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, @@ -15,7 +13,7 @@ use validator_client::models::{ pub async fn mixnode_core_node_status( identity: &str, since: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state) .get_mixnode_core_status_count(identity, since) @@ -26,7 +24,7 @@ pub async fn mixnode_core_node_status( pub async fn gateway_core_node_status( identity: &str, since: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state) .get_gateway_core_status_count(identity, since) @@ -36,7 +34,7 @@ pub async fn gateway_core_node_status( #[tauri::command] pub async fn mixnode_status( identity: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state).get_mixnode_status(identity).await?) } @@ -44,7 +42,7 @@ pub async fn mixnode_status( #[tauri::command] pub async fn mixnode_reward_estimation( identity: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state) .get_mixnode_reward_estimation(identity) @@ -54,7 +52,7 @@ pub async fn mixnode_reward_estimation( #[tauri::command] pub async fn mixnode_stake_saturation( identity: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state) .get_mixnode_stake_saturation(identity) @@ -64,7 +62,7 @@ pub async fn mixnode_stake_saturation( #[tauri::command] pub async fn mixnode_inclusion_probability( identity: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { Ok(api_client!(state) .get_mixnode_inclusion_probability(identity) diff --git a/nym-wallet/src-tauri/src/operations/vesting/bond.rs b/nym-wallet/src-tauri/src/operations/vesting/bond.rs index 67df1a2e6d..c567e4e908 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/bond.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/bond.rs @@ -1,48 +1,50 @@ use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; use crate::{Gateway, MixNode}; -use nym_types::currency::MajorCurrencyAmount; +use nym_types::currency::DecCoin; use nym_types::transaction::TransactionExecuteResult; -use std::sync::Arc; -use tokio::sync::RwLock; use validator_client::nymd::{Fee, VestingSigningClient}; #[tauri::command] pub async fn vesting_bond_gateway( gateway: Gateway, - pledge: MajorCurrencyAmount, + pledge: DecCoin, owner_signature: String, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let pledge_minor = pledge.clone().into(); + let guard = state.read().await; + let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Bond gateway with locked tokens: identity_key = {}, pledge = {}, pledge_minor = {}, fee = {:?}", - gateway.identity_key, - pledge, - pledge_minor, - fee, - ); - let res = nymd_client!(state) - .vesting_bond_gateway(gateway, &owner_signature, pledge_minor, fee) + ">>> Bond gateway with locked tokens: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}", + gateway.identity_key, + pledge, + pledge_base, + fee, + ); + let res = guard + .current_client()? + .nymd + .vesting_bond_gateway(gateway, &owner_signature, pledge_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn vesting_unbond_gateway( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( ">>> Unbond gateway bonded with locked tokens, fee = {:?}", fee @@ -51,8 +53,7 @@ pub async fn vesting_unbond_gateway( log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -60,71 +61,81 @@ pub async fn vesting_unbond_gateway( pub async fn vesting_bond_mixnode( mixnode: MixNode, owner_signature: String, - pledge: MajorCurrencyAmount, + pledge: DecCoin, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let pledge_minor = pledge.clone().into(); + let guard = state.read().await; + let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Bond mixnode with locked tokens: identity_key = {}, pledge = {}, pledge_minor = {}, fee = {:?}", + ">>> Bond mixnode with locked tokens: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}", mixnode.identity_key, pledge, - pledge_minor, + pledge_base, fee ); - let res = nymd_client!(state) - .vesting_bond_mixnode(mixnode, &owner_signature, pledge_minor, fee) + let res = guard + .current_client()? + .nymd + .vesting_bond_mixnode(mixnode, &owner_signature, pledge_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn vesting_unbond_mixnode( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( ">>> Unbond mixnode bonded with locked tokens, fee = {:?}", fee ); - let res = nymd_client!(state).vesting_unbond_mixnode(fee).await?; + let res = guard + .current_client()? + .nymd + .vesting_unbond_mixnode(fee) + .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } #[tauri::command] pub async fn withdraw_vested_coins( - amount: MajorCurrencyAmount, + amount: DecCoin, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let amount_minor = amount.clone().into(); + let guard = state.read().await; + let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Withdraw vested liquid coins: amount = {}, amount_minor = {}, fee = {:?}", + ">>> Withdraw vested liquid coins: amount_base = {}, amount_base = {}, fee = {:?}", amount, - amount_minor, + amount_base, fee ); - let res = nymd_client!(state) - .withdraw_vested_coins(amount_minor, fee) + let res = guard + .current_client()? + .nymd + .withdraw_vested_coins(amount_base, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -132,21 +143,23 @@ pub async fn withdraw_vested_coins( pub async fn vesting_update_mixnode( profit_margin_percent: u8, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( ">>> Update mixnode bonded with locked tokens: profit_margin_percent = {}, fee = {:?}", profit_margin_percent, fee, ); - let res = nymd_client!(state) + let res = guard + .current_client()? + .nymd .vesting_update_mixnode_config(profit_margin_percent, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } diff --git a/nym-wallet/src-tauri/src/operations/vesting/delegate.rs b/nym-wallet/src-tauri/src/operations/vesting/delegate.rs index 321fa69a1b..9ddde467a8 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/delegate.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/delegate.rs @@ -1,23 +1,18 @@ -use std::sync::Arc; - -use tokio::sync::RwLock; - -use nym_types::currency::MajorCurrencyAmount; -use nym_types::delegation::{from_contract_delegation_events, DelegationEvent}; +use crate::error::BackendError; +use crate::state::WalletState; +use nym_types::currency::DecCoin; +use nym_types::delegation::DelegationEvent; use nym_types::transaction::TransactionExecuteResult; use validator_client::nymd::{Fee, VestingSigningClient}; -use crate::error::BackendError; -use crate::nymd_client; -use crate::state::State; - #[tauri::command] pub async fn get_pending_vesting_delegation_events( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Get pending delegations from vesting contract"); let guard = state.read().await; + let reg = guard.registered_coins()?; let client = &guard.current_client()?.nymd; let vesting_contract = client.vesting_contract_address(); @@ -31,36 +26,39 @@ pub async fn get_pending_vesting_delegation_events( log::info!("<<< {} events", events.len()); log::trace!("<<< {:?}", events); - match from_contract_delegation_events(events) { - Ok(res) => Ok(res), - Err(e) => Err(e.into()), - } + Ok(events + .into_iter() + .map(|event| DelegationEvent::from_mixnet_contract(event, reg)) + .collect::>()?) } #[tauri::command] pub async fn vesting_delegate_to_mixnode( identity: &str, - amount: MajorCurrencyAmount, + amount: DecCoin, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let delegation = amount.clone().into(); + let guard = state.read().await; + let delegation = guard.attempt_convert_to_base_coin(amount.clone())?; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); + log::info!( - ">>> Delegate to mixnode with locked tokens: identity_key = {}, amount = {}, minor_amount = {}, fee = {:?}", + ">>> Delegate to mixnode with locked tokens: identity_key = {}, amount_display = {}, amount_base = {}, fee = {:?}", identity, amount, delegation, fee ); - let res = nymd_client!(state) + let res = guard + .current_client()? + .nymd .vesting_delegate_to_mixnode(identity, delegation, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } @@ -68,21 +66,23 @@ pub async fn vesting_delegate_to_mixnode( pub async fn vesting_undelegate_from_mixnode( identity: &str, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); + let guard = state.read().await; + let fee_amount = guard.convert_tx_fee(fee.as_ref()); log::info!( ">>> Undelegate from mixnode delegated with locked tokens: identity_key = {}, fee = {:?}", identity, fee, ); - let res = nymd_client!(state) + let res = guard + .current_client()? + .nymd .vesting_undelegate_from_mixnode(identity, fee) .await?; log::info!("<<< tx hash = {}", res.transaction_hash); log::trace!("<<< {:?}", res); Ok(TransactionExecuteResult::from_execute_result( - res, - denom_minor.as_ref(), + res, fee_amount, )?) } diff --git a/nym-wallet/src-tauri/src/operations/vesting/queries.rs b/nym-wallet/src-tauri/src/operations/vesting/queries.rs index 72c85f69d7..7d0d726a1c 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/queries.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/queries.rs @@ -1,92 +1,106 @@ -use std::sync::Arc; - +use crate::error::BackendError; +use crate::nymd_client; +use crate::state::WalletState; use cosmwasm_std::Timestamp; -use tokio::sync::RwLock; - -use nym_types::currency::MajorCurrencyAmount; +use nym_types::currency::DecCoin; use nym_types::vesting::VestingAccountInfo; use nym_types::vesting::{OriginalVestingResponse, PledgeData}; use validator_client::nymd::VestingQueryClient; use vesting_contract_common::Period; -use crate::error::BackendError; -use crate::nymd_client; -use crate::state::State; - #[tauri::command] pub async fn locked_coins( block_time: Option, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query locked coins"); - let res = nymd_client!(state) + let guard = state.read().await; + let client = guard.current_client()?; + + let res = client + .nymd .locked_coins( - nymd_client!(state).address().as_ref(), + client.nymd.address().as_ref(), block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< locked coins = {}", res); - Ok(res) + .await?; + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< locked coins = {}", display); + Ok(display) } #[tauri::command] pub async fn spendable_coins( block_time: Option, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query spendable coins"); - let res = nymd_client!(state) + let guard = state.read().await; + let client = guard.current_client()?; + + let res = client + .nymd .spendable_coins( - nymd_client!(state).address().as_ref(), + client.nymd.address().as_ref(), block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< spendable coins = {}", res); - Ok(res) + .await?; + + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< spendable coins = {}", display); + Ok(display) } #[tauri::command] pub async fn vested_coins( vesting_account_address: &str, block_time: Option, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query vested coins"); - let res = nymd_client!(state) + let guard = state.read().await; + + let res = guard + .current_client()? + .nymd .vested_coins( vesting_account_address, block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< vested coins = {}", res); - Ok(res) + .await?; + + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< vested coins = {}", display); + Ok(display) } #[tauri::command] pub async fn vesting_coins( vesting_account_address: &str, block_time: Option, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query vesting coins"); - let res = nymd_client!(state) + let guard = state.read().await; + + let res = guard + .current_client()? + .nymd .vesting_coins( vesting_account_address, block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< vesting coins = {}", res); - Ok(res) + .await?; + + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< vesting coins = {}", display); + Ok(display) } #[tauri::command] pub async fn vesting_start_time( vesting_account_address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Query vesting start time"); let res = nymd_client!(state) @@ -100,7 +114,7 @@ pub async fn vesting_start_time( #[tauri::command] pub async fn vesting_end_time( vesting_account_address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Query vesting end time"); let res = nymd_client!(state) @@ -114,13 +128,19 @@ pub async fn vesting_end_time( #[tauri::command] pub async fn original_vesting( vesting_account_address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Query original vesting"); - let res = nymd_client!(state) + let guard = state.read().await; + let reg = guard.registered_coins()?; + + let res = guard + .current_client()? + .nymd .original_vesting(vesting_account_address) - .await? - .try_into()?; + .await?; + + let res = OriginalVestingResponse::from_vesting_contract(res, reg)?; log::info!("<<< {:?}", res); Ok(res) } @@ -129,18 +149,23 @@ pub async fn original_vesting( pub async fn delegated_free( vesting_account_address: &str, block_time: Option, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query delegated free"); - let res = nymd_client!(state) + let guard = state.read().await; + + let res = guard + .current_client()? + .nymd .delegated_free( vesting_account_address, block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< delegated free = {}", res); - Ok(res) + .await?; + + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< delegated free = {}", display); + Ok(display) } /// Returns the total amount of delegated tokens that have vested @@ -148,30 +173,42 @@ pub async fn delegated_free( pub async fn delegated_vesting( block_time: Option, vesting_account_address: &str, - state: tauri::State<'_, Arc>>, -) -> Result { + state: tauri::State<'_, WalletState>, +) -> Result { log::info!(">>> Query delegated vesting"); - let res = nymd_client!(state) + let guard = state.read().await; + + let res = guard + .current_client()? + .nymd .delegated_vesting( vesting_account_address, block_time.map(Timestamp::from_seconds), ) - .await? - .into(); - log::info!("<<< delegated_vesting = {}", res); - Ok(res) + .await?; + + let display = guard.attempt_convert_to_display_dec_coin(res)?; + log::info!("<<< delegated_vesting = {}", display); + Ok(display) } #[tauri::command] pub async fn vesting_get_mixnode_pledge( address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Query vesting get mixnode pledge"); - let res = nymd_client!(state) + let guard = state.read().await; + let reg = guard.registered_coins()?; + + let res = guard + .current_client()? + .nymd .get_mixnode_pledge(address) .await? - .and_then(PledgeData::and_then); + .map(|pledge| PledgeData::from_vesting_contract(pledge, reg)) + .transpose()?; + log::info!("<<< {:?}", res); Ok(res) } @@ -179,13 +216,20 @@ pub async fn vesting_get_mixnode_pledge( #[tauri::command] pub async fn vesting_get_gateway_pledge( address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result, BackendError> { log::info!(">>> Query vesting get gateway pledge"); - let res = nymd_client!(state) + let guard = state.read().await; + let reg = guard.registered_coins()?; + + let res = guard + .current_client()? + .nymd .get_gateway_pledge(address) .await? - .and_then(PledgeData::and_then); + .map(|pledge| PledgeData::from_vesting_contract(pledge, reg)) + .transpose()?; + log::info!("<<< {:?}", res); Ok(res) } @@ -193,7 +237,7 @@ pub async fn vesting_get_gateway_pledge( #[tauri::command] pub async fn get_current_vesting_period( address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Query current vesting period"); let res = nymd_client!(state) @@ -206,10 +250,15 @@ pub async fn get_current_vesting_period( #[tauri::command] pub async fn get_account_info( address: &str, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result { log::info!(">>> Query account info"); - let res = nymd_client!(state).get_account(address).await?.try_into()?; + let guard = state.read().await; + let res = guard.registered_coins()?; + + let vesting_account = guard.current_client()?.nymd.get_account(address).await?; + let res = VestingAccountInfo::from_vesting_contract(vesting_account, res)?; + log::info!("<<< {:?}", res); Ok(res) } diff --git a/nym-wallet/src-tauri/src/operations/vesting/rewards.rs b/nym-wallet/src-tauri/src/operations/vesting/rewards.rs index e6b27fa78f..13cee7bbbd 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/rewards.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/rewards.rs @@ -1,14 +1,12 @@ use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; +use crate::state::WalletState; use mixnet_contract_common::IdentityKey; -use std::sync::Arc; -use tokio::sync::RwLock; use validator_client::nymd::Fee; #[tauri::command] pub async fn vesting_claim_operator_reward( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_vesting_claim_operator_reward(None) @@ -19,7 +17,7 @@ pub async fn vesting_claim_operator_reward( #[tauri::command] pub async fn vesting_compound_operator_reward( fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_vesting_compound_operator_reward(fee) @@ -31,7 +29,7 @@ pub async fn vesting_compound_operator_reward( pub async fn vesting_claim_delegator_reward( mix_identity: IdentityKey, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_vesting_claim_delegator_reward(mix_identity, fee) @@ -43,7 +41,7 @@ pub async fn vesting_claim_delegator_reward( pub async fn vesting_compound_delegator_reward( mix_identity: IdentityKey, fee: Option, - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { nymd_client!(state) .execute_vesting_compound_delegator_reward(mix_identity, fee) diff --git a/nym-wallet/src-tauri/src/state.rs b/nym-wallet/src-tauri/src/state.rs index 1095d872b6..114abe1a24 100644 --- a/nym-wallet/src-tauri/src/state.rs +++ b/nym-wallet/src-tauri/src/state.rs @@ -1,20 +1,21 @@ use crate::config; use crate::error::BackendError; +use crate::simulate::SimulateResult; +use itertools::Itertools; +use log::warn; +use nym_types::currency::{DecCoin, RegisteredCoins}; +use nym_types::fees::FeeDetails; use nym_wallet_types::network::Network; use nym_wallet_types::network_config; - -use strum::IntoEnumIterator; -use validator_client::nymd::{AccountId as CosmosAccountId, SigningNymdClient}; -use validator_client::Client; - -use itertools::Itertools; use once_cell::sync::Lazy; -use tokio::sync::RwLock; -use url::Url; - use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; +use strum::IntoEnumIterator; +use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +use url::Url; +use validator_client::nymd::{AccountId as CosmosAccountId, Coin, Fee, SigningNymdClient}; +use validator_client::Client; // Some hardcoded metadata overrides static METADATA_OVERRIDES: Lazy> = Lazy::new(|| { @@ -28,7 +29,7 @@ static METADATA_OVERRIDES: Lazy> = Lazy::new(|| { #[tauri::command] pub async fn load_config_from_files( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { state.write().await.load_config_files(); Ok(()) @@ -36,13 +37,30 @@ pub async fn load_config_from_files( #[tauri::command] pub async fn save_config_to_files( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { state.read().await.save_config_files() } +#[derive(Default, Clone)] +pub struct WalletState { + inner: Arc>, +} + +impl WalletState { + // not the best API, but those are exposed here for backwards compatibility with the existing + // state type assumptions so that we wouldn't need to fix it up everywhere at once + pub(crate) async fn read(&self) -> RwLockReadGuard<'_, WalletStateInner> { + self.inner.read().await + } + + pub(crate) async fn write(&self) -> RwLockWriteGuard<'_, WalletStateInner> { + self.inner.write().await + } +} + #[derive(Default)] -pub struct State { +pub struct WalletStateInner { config: config::Config, signing_clients: HashMap>, current_network: Network, @@ -56,6 +74,7 @@ pub struct State { /// We fetch (and cache) some metadata, such as names, when available validator_metadata: HashMap, + registered_coins: HashMap, } pub(crate) struct WalletAccountIds { @@ -65,7 +84,63 @@ pub(crate) struct WalletAccountIds { pub addresses: HashMap, } -impl State { +impl WalletStateInner { + // note that `Coin` is ALWAYS the base coin + pub fn attempt_convert_to_base_coin(&self, coin: DecCoin) -> Result { + let registered_coins = self + .registered_coins + .get(&self.current_network) + .ok_or_else(|| BackendError::UnknownCoinDenom(coin.denom.clone()))?; + + Ok(registered_coins.attempt_convert_to_base_coin(coin)?) + } + + pub fn attempt_convert_to_display_dec_coin(&self, coin: Coin) -> Result { + let registered_coins = self + .registered_coins + .get(&self.current_network) + .ok_or_else(|| BackendError::UnknownCoinDenom(coin.denom.clone()))?; + + Ok(registered_coins.attempt_convert_to_display_dec_coin(coin)?) + } + + pub(crate) fn registered_coins(&self) -> Result<&RegisteredCoins, BackendError> { + self.registered_coins + .get(&self.current_network) + .ok_or(BackendError::NoCoinsRegistered { + network: self.current_network, + }) + } + + pub(crate) fn convert_tx_fee(&self, fee: Option<&Fee>) -> Option { + let mut fee_amount = fee?.try_get_manual_amount()?; + if fee_amount.len() > 1 { + warn!( + "our tx fee contained more than a single denomination. using the first one for display" + ) + } + if fee_amount.is_empty() { + warn!("our tx has had an unknown fee set"); + None + } else { + self.attempt_convert_to_display_dec_coin(fee_amount.pop().unwrap()) + .ok() + } + } + + // this one is rather gnarly and I'm not 100% sure how to feel about existence of it + pub(crate) fn create_detailed_fee( + &self, + simulate_res: SimulateResult, + ) -> Result { + let amount = simulate_res + .to_fee_amount() + .map(|amount| self.attempt_convert_to_display_dec_coin(amount.into())) + .transpose()?; + + Ok(FeeDetails::new(amount, simulate_res.to_fee())) + } + pub fn client(&self, network: Network) -> Result<&Client, BackendError> { self.signing_clients .get(&network) @@ -112,6 +187,11 @@ impl State { self.signing_clients.insert(network, client); } + pub fn register_default_denoms(&mut self, network: Network) { + self.registered_coins + .insert(network, RegisteredCoins::default_denoms(network.into())); + } + pub fn set_network(&mut self, network: Network) { self.current_network = network; } @@ -390,7 +470,7 @@ mod tests { #[test] fn adding_validators_urls_prepends() { - let mut state = State::default(); + let mut state = WalletStateInner::default(); let _api_urls = state.get_api_urls(Network::MAINNET).collect::>(); state.add_validator_url( diff --git a/nym-wallet/src-tauri/src/utils.rs b/nym-wallet/src-tauri/src/utils.rs index 212bc7ad6a..40e61a317b 100644 --- a/nym-wallet/src-tauri/src/utils.rs +++ b/nym-wallet/src-tauri/src/utils.rs @@ -1,11 +1,9 @@ use crate::error::BackendError; use crate::nymd_client; -use crate::state::State; -use nym_types::currency::MajorCurrencyAmount; +use crate::state::WalletState; +use nym_types::currency::DecCoin; use nym_wallet_types::app::AppEnv; use serde::{Deserialize, Serialize}; -use std::sync::Arc; -use tokio::sync::RwLock; use validator_client::nymd::{tx, Coin, CosmosCoin, Gas, GasPrice}; fn get_env_as_option(key: &str) -> Option { @@ -24,9 +22,7 @@ pub fn get_env() -> AppEnv { } #[tauri::command] -pub async fn owns_mixnode( - state: tauri::State<'_, Arc>>, -) -> Result { +pub async fn owns_mixnode(state: tauri::State<'_, WalletState>) -> Result { Ok(nymd_client!(state) .owns_mixnode(nymd_client!(state).address()) .await? @@ -34,9 +30,7 @@ pub async fn owns_mixnode( } #[tauri::command] -pub async fn owns_gateway( - state: tauri::State<'_, Arc>>, -) -> Result { +pub async fn owns_gateway(state: tauri::State<'_, WalletState>) -> Result { Ok(nymd_client!(state) .owns_gateway(nymd_client!(state).address()) .await? @@ -144,13 +138,14 @@ impl Operation { #[tauri::command] pub async fn get_old_and_incorrect_hardcoded_fee( - state: tauri::State<'_, Arc>>, + state: tauri::State<'_, WalletState>, operation: Operation, -) -> Result { - let mut approximate_fee = operation.default_fee(nymd_client!(state).gas_price()); +) -> Result { + let guard = state.read().await; + let mut approximate_fee = operation.default_fee(guard.current_client()?.nymd.gas_price()); // on all our chains it should only ever contain a single type of currency assert_eq!(approximate_fee.amount.len(), 1); let coin: Coin = approximate_fee.amount.pop().unwrap().into(); log::info!("hardcoded fee for {:?} is {:?}", operation, coin); - Ok(coin.into()) + guard.attempt_convert_to_display_dec_coin(coin) } diff --git a/tools/ts-rs-cli/src/main.rs b/tools/ts-rs-cli/src/main.rs index 909ea574bf..c24e3d6487 100644 --- a/tools/ts-rs-cli/src/main.rs +++ b/tools/ts-rs-cli/src/main.rs @@ -4,7 +4,7 @@ use walkdir::WalkDir; use mixnet_contract_common::mixnode::RewardedSetNodeStatus; use nym_types::account::{Account, AccountEntry, AccountWithMnemonic, Balance}; -use nym_types::currency::{CurrencyDenom, MajorAmountString, MajorCurrencyAmount}; +use nym_types::currency::{CurrencyDenom, DecCoin}; use nym_types::delegation::{ Delegation, DelegationEvent, DelegationEventKind, DelegationRecord, DelegationResult, DelegationWithEverything, DelegationsSummaryResponse, PendingUndelegate, @@ -59,7 +59,6 @@ fn main() { do_export!(AccountEntry); do_export!(AccountWithMnemonic); do_export!(Balance); - do_export!(CurrencyDenom); do_export!(Delegation); do_export!(DelegationEvent); do_export!(DelegationEventKind); @@ -72,8 +71,8 @@ fn main() { do_export!(GasInfo); do_export!(Gateway); do_export!(GatewayBond); - do_export!(MajorAmountString); - do_export!(MajorCurrencyAmount); + do_export!(CurrencyDenom); + do_export!(DecCoin); do_export!(MixNode); do_export!(MixNodeBond); do_export!(OriginalVestingResponse); diff --git a/ts-packages/types/src/types/rust/Account.ts b/ts-packages/types/src/types/rust/Account.ts index 1f3c8f470a..046d22782d 100644 --- a/ts-packages/types/src/types/rust/Account.ts +++ b/ts-packages/types/src/types/rust/Account.ts @@ -1,7 +1,2 @@ -import type { CurrencyDenom } from './CurrencyDenom'; -export interface Account { - contract_address: string; - client_address: string; - denom: CurrencyDenom; -} +export interface Account { contract_address: string, client_address: string, denom: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/AccountEntry.ts b/ts-packages/types/src/types/rust/AccountEntry.ts index f6ad1b53a9..b77fa15d8c 100644 --- a/ts-packages/types/src/types/rust/AccountEntry.ts +++ b/ts-packages/types/src/types/rust/AccountEntry.ts @@ -1,4 +1,2 @@ -export interface AccountEntry { - id: string; - address: string; -} + +export interface AccountEntry { id: string, address: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/AccountWithMnemonic.ts b/ts-packages/types/src/types/rust/AccountWithMnemonic.ts index 6b3757bdab..ed0b1428e5 100644 --- a/ts-packages/types/src/types/rust/AccountWithMnemonic.ts +++ b/ts-packages/types/src/types/rust/AccountWithMnemonic.ts @@ -1,6 +1,3 @@ -import type { Account } from './Account'; +import type { Account } from "./Account"; -export interface AccountWithMnemonic { - account: Account; - mnemonic: string; -} +export interface AccountWithMnemonic { account: Account, mnemonic: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Balance.ts b/ts-packages/types/src/types/rust/Balance.ts index 80ebb917a1..e2b4ded23f 100644 --- a/ts-packages/types/src/types/rust/Balance.ts +++ b/ts-packages/types/src/types/rust/Balance.ts @@ -1,6 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface Balance { - amount: MajorCurrencyAmount; - printable_balance: string; -} +export interface Balance { amount: DecCoin, printable_balance: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/CoreNodeStatusResponse.ts b/ts-packages/types/src/types/rust/CoreNodeStatusResponse.ts index 44ac51adbe..4314f52db9 100644 --- a/ts-packages/types/src/types/rust/CoreNodeStatusResponse.ts +++ b/ts-packages/types/src/types/rust/CoreNodeStatusResponse.ts @@ -1,4 +1,2 @@ -export interface CoreNodeStatusResponse { - identity: string; - count: number; -} + +export interface CoreNodeStatusResponse { identity: string, count: number, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Currency.ts b/ts-packages/types/src/types/rust/Currency.ts deleted file mode 100644 index f0c6d57fbb..0000000000 --- a/ts-packages/types/src/types/rust/Currency.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { CurrencyDenom } from './CurrencyDenom'; -import type { MajorAmountString } from './CurrencyStringMajorAmount'; - -export interface MajorCurrencyAmount { - amount: MajorAmountString; - denom: CurrencyDenom; -} diff --git a/ts-packages/types/src/types/rust/CurrencyDenom.ts b/ts-packages/types/src/types/rust/CurrencyDenom.ts index d6a45dc3d2..e55231ccc0 100644 --- a/ts-packages/types/src/types/rust/CurrencyDenom.ts +++ b/ts-packages/types/src/types/rust/CurrencyDenom.ts @@ -1 +1,2 @@ -export type CurrencyDenom = 'NYM' | 'NYMT' | 'NYX' | 'NYXT'; + +export type CurrencyDenom = "nym" | "nymt" | "nyx" | "nyxt"; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/CurrencyStringMajorAmount.ts b/ts-packages/types/src/types/rust/CurrencyStringMajorAmount.ts deleted file mode 100644 index 9863028330..0000000000 --- a/ts-packages/types/src/types/rust/CurrencyStringMajorAmount.ts +++ /dev/null @@ -1 +0,0 @@ -export type MajorAmountString = string; diff --git a/ts-packages/types/src/types/rust/DecCoin.ts b/ts-packages/types/src/types/rust/DecCoin.ts new file mode 100644 index 0000000000..d3751d56f8 --- /dev/null +++ b/ts-packages/types/src/types/rust/DecCoin.ts @@ -0,0 +1,3 @@ +import type { CurrencyDenom } from "./CurrencyDenom"; + +export type DecCoin = { denom: CurrencyDenom, amount: string }; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Delegation.ts b/ts-packages/types/src/types/rust/Delegation.ts index 72e2ce17c7..633bf76521 100644 --- a/ts-packages/types/src/types/rust/Delegation.ts +++ b/ts-packages/types/src/types/rust/Delegation.ts @@ -1,9 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface Delegation { - owner: string; - node_identity: string; - amount: MajorCurrencyAmount; - block_height: bigint; - proxy: string | null; -} +export interface Delegation { owner: string, node_identity: string, amount: DecCoin, block_height: bigint, proxy: string | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationEvent.ts b/ts-packages/types/src/types/rust/DelegationEvent.ts index 96f0169f3e..e05ce01651 100644 --- a/ts-packages/types/src/types/rust/DelegationEvent.ts +++ b/ts-packages/types/src/types/rust/DelegationEvent.ts @@ -1,10 +1,4 @@ -import type { DelegationEventKind } from './DelegationEventKind'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { DelegationEventKind } from "./DelegationEventKind"; -export interface DelegationEvent { - kind: DelegationEventKind; - node_identity: string; - address: string; - amount: MajorCurrencyAmount | null; - block_height: bigint; -} +export interface DelegationEvent { kind: DelegationEventKind, node_identity: string, address: string, amount: DecCoin | null, block_height: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationEventKind.ts b/ts-packages/types/src/types/rust/DelegationEventKind.ts index a1db5fac12..4cff16fa5f 100644 --- a/ts-packages/types/src/types/rust/DelegationEventKind.ts +++ b/ts-packages/types/src/types/rust/DelegationEventKind.ts @@ -1 +1,2 @@ -export type DelegationEventKind = 'Delegate' | 'Undelegate'; + +export type DelegationEventKind = "Delegate" | "Undelegate"; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationRecord.ts b/ts-packages/types/src/types/rust/DelegationRecord.ts index bd432bc08d..0b86253b8e 100644 --- a/ts-packages/types/src/types/rust/DelegationRecord.ts +++ b/ts-packages/types/src/types/rust/DelegationRecord.ts @@ -1,7 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface DelegationRecord { - amount: MajorCurrencyAmount; - block_height: bigint; - delegated_on_iso_datetime: string; -} +export interface DelegationRecord { amount: DecCoin, block_height: bigint, delegated_on_iso_datetime: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationResult.ts b/ts-packages/types/src/types/rust/DelegationResult.ts index 33c6dba091..b073796646 100644 --- a/ts-packages/types/src/types/rust/DelegationResult.ts +++ b/ts-packages/types/src/types/rust/DelegationResult.ts @@ -1,7 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface DelegationResult { - source_address: string; - target_address: string; - amount: MajorCurrencyAmount | null; -} +export interface DelegationResult { source_address: string, target_address: string, amount: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts b/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts index a801d2865e..5149949bbf 100644 --- a/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts +++ b/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts @@ -1,8 +1,4 @@ -import type { DelegationWithEverything } from './DelegationWithEverything'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { DelegationWithEverything } from "./DelegationWithEverything"; -export interface DelegationsSummaryResponse { - delegations: Array; - total_delegations: MajorCurrencyAmount; - total_rewards: MajorCurrencyAmount; -} +export interface DelegationsSummaryResponse { delegations: Array, total_delegations: DecCoin, total_rewards: DecCoin, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/DelegationWithEverything.ts b/ts-packages/types/src/types/rust/DelegationWithEverything.ts index 82c5e5043c..7d033cf38e 100644 --- a/ts-packages/types/src/types/rust/DelegationWithEverything.ts +++ b/ts-packages/types/src/types/rust/DelegationWithEverything.ts @@ -1,20 +1,5 @@ -import type { DelegationEvent } from './DelegationEvent'; -import type { DelegationRecord } from './DelegationRecord'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { DelegationEvent } from "./DelegationEvent"; +import type { DelegationRecord } from "./DelegationRecord"; -export interface DelegationWithEverything { - owner: string; - node_identity: string; - amount: MajorCurrencyAmount; - total_delegation: MajorCurrencyAmount | null; - pledge_amount: MajorCurrencyAmount | null; - block_height: bigint; - delegated_on_iso_datetime: string; - profit_margin_percent: number | null; - avg_uptime_percent: number | null; - stake_saturation: number | null; - proxy: string | null; - accumulated_rewards: MajorCurrencyAmount | null; - pending_events: Array; - history: Array; -} +export interface DelegationWithEverything { owner: string, node_identity: string, amount: DecCoin, total_delegation: DecCoin | null, pledge_amount: DecCoin | null, block_height: bigint, delegated_on_iso_datetime: string, profit_margin_percent: number | null, avg_uptime_percent: number | null, stake_saturation: number | null, proxy: string | null, accumulated_rewards: DecCoin | null, pending_events: Array, history: Array, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/FeeDetails.ts b/ts-packages/types/src/types/rust/FeeDetails.ts index f01aa05f06..ca22372d3b 100644 --- a/ts-packages/types/src/types/rust/FeeDetails.ts +++ b/ts-packages/types/src/types/rust/FeeDetails.ts @@ -1,5 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface FeeDetails { - amount: MajorCurrencyAmount | null; -} +export interface FeeDetails { amount: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Gas.ts b/ts-packages/types/src/types/rust/Gas.ts index 1f9eb6f7c3..97702c900f 100644 --- a/ts-packages/types/src/types/rust/Gas.ts +++ b/ts-packages/types/src/types/rust/Gas.ts @@ -1,6 +1,2 @@ -import type { MajorCurrencyAmount } from './Currency'; -export interface Gas { - gas_units: bigint; - amount: MajorCurrencyAmount; -} +export interface Gas { gas_units: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/GasInfo.ts b/ts-packages/types/src/types/rust/GasInfo.ts index 3fbaaac7ba..b3b800abd0 100644 --- a/ts-packages/types/src/types/rust/GasInfo.ts +++ b/ts-packages/types/src/types/rust/GasInfo.ts @@ -1,7 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { Gas } from "./Gas"; -export interface GasInfo { - gas_wanted: bigint; - gas_used: bigint; - fee: MajorCurrencyAmount; -} +export interface GasInfo { gas_wanted: Gas, gas_used: Gas, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/GatewayBond.ts b/ts-packages/types/src/types/rust/GatewayBond.ts index 4ffe275186..9d8fa93bd3 100644 --- a/ts-packages/types/src/types/rust/GatewayBond.ts +++ b/ts-packages/types/src/types/rust/GatewayBond.ts @@ -1,10 +1,4 @@ -import type { Gateway } from './Gateway'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { Gateway } from "./Gateway"; -export interface GatewayBond { - pledge_amount: MajorCurrencyAmount; - owner: string; - block_height: bigint; - gateway: Gateway; - proxy: string | null; -} +export interface GatewayBond { pledge_amount: DecCoin, owner: string, block_height: bigint, gateway: Gateway, proxy: string | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts b/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts index 56d81bde41..2acfb64fd2 100644 --- a/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts +++ b/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts @@ -1,6 +1,3 @@ -import type { SelectionChance } from './SelectionChance'; +import type { SelectionChance } from "./SelectionChance"; -export interface InclusionProbabilityResponse { - in_active: SelectionChance; - in_reserve: SelectionChance; -} +export interface InclusionProbabilityResponse { in_active: SelectionChance, in_reserve: SelectionChance, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/MixNodeBond.ts b/ts-packages/types/src/types/rust/MixNodeBond.ts index 06e8cc884f..35411030a9 100644 --- a/ts-packages/types/src/types/rust/MixNodeBond.ts +++ b/ts-packages/types/src/types/rust/MixNodeBond.ts @@ -1,13 +1,4 @@ -import type { MajorCurrencyAmount } from './Currency'; -import type { MixNode } from './Mixnode'; +import type { DecCoin } from "./DecCoin"; +import type { MixNode } from "./Mixnode"; -export interface MixNodeBond { - pledge_amount: MajorCurrencyAmount; - total_delegation: MajorCurrencyAmount; - owner: string; - layer: string; - block_height: bigint; - mix_node: MixNode; - proxy: string | null; - accumulated_rewards: MajorCurrencyAmount | null; -} +export interface MixNodeBond { pledge_amount: DecCoin, total_delegation: DecCoin, owner: string, layer: string, block_height: bigint, mix_node: MixNode, proxy: string | null, accumulated_rewards: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/MixnodeStatus.ts b/ts-packages/types/src/types/rust/MixnodeStatus.ts index da89c7e8a7..a7b76b836f 100644 --- a/ts-packages/types/src/types/rust/MixnodeStatus.ts +++ b/ts-packages/types/src/types/rust/MixnodeStatus.ts @@ -1 +1,2 @@ -export type MixnodeStatus = 'active' | 'standby' | 'inactive' | 'not_found'; + +export type MixnodeStatus = "active" | "standby" | "inactive" | "not_found"; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts b/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts index 2225b26df3..4de992581a 100644 --- a/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts +++ b/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts @@ -1,5 +1,3 @@ -import type { MixnodeStatus } from './MixnodeStatus'; +import type { MixnodeStatus } from "./MixnodeStatus"; -export interface MixnodeStatusResponse { - status: MixnodeStatus; -} +export interface MixnodeStatusResponse { status: MixnodeStatus, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Operation.ts b/ts-packages/types/src/types/rust/Operation.ts deleted file mode 100644 index 7b1e769691..0000000000 --- a/ts-packages/types/src/types/rust/Operation.ts +++ /dev/null @@ -1,36 +0,0 @@ -// TODO: remove this type - -export type 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'; diff --git a/ts-packages/types/src/types/rust/OriginalVestingResponse.ts b/ts-packages/types/src/types/rust/OriginalVestingResponse.ts index 2ebbd40bb2..3f18ad35fa 100644 --- a/ts-packages/types/src/types/rust/OriginalVestingResponse.ts +++ b/ts-packages/types/src/types/rust/OriginalVestingResponse.ts @@ -1,7 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface OriginalVestingResponse { - amount: MajorCurrencyAmount; - number_of_periods: number; - period_duration: bigint; -} +export interface OriginalVestingResponse { amount: DecCoin, number_of_periods: number, period_duration: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/PendingUndelegate.ts b/ts-packages/types/src/types/rust/PendingUndelegate.ts index 70855568cf..54b4941b1d 100644 --- a/ts-packages/types/src/types/rust/PendingUndelegate.ts +++ b/ts-packages/types/src/types/rust/PendingUndelegate.ts @@ -1,6 +1,2 @@ -export interface PendingUndelegate { - mix_identity: string; - delegate: string; - proxy: string | null; - block_height: bigint; -} + +export interface PendingUndelegate { mix_identity: string, delegate: string, proxy: string | null, block_height: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/Period.ts b/ts-packages/types/src/types/rust/Period.ts index 05d9890d5f..809b6c2d87 100644 --- a/ts-packages/types/src/types/rust/Period.ts +++ b/ts-packages/types/src/types/rust/Period.ts @@ -1 +1,2 @@ -export type Period = 'Before' | { In: number } | 'After'; + +export type Period = "Before" | { In: number } | "After"; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/PledgeData.ts b/ts-packages/types/src/types/rust/PledgeData.ts index 2f82758842..26d50a5c25 100644 --- a/ts-packages/types/src/types/rust/PledgeData.ts +++ b/ts-packages/types/src/types/rust/PledgeData.ts @@ -1,6 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface PledgeData { - amount: MajorCurrencyAmount; - block_time: bigint; -} +export interface PledgeData { amount: DecCoin, block_time: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/RpcTransactionResponse.ts b/ts-packages/types/src/types/rust/RpcTransactionResponse.ts index 65cc61702a..e938c00efa 100644 --- a/ts-packages/types/src/types/rust/RpcTransactionResponse.ts +++ b/ts-packages/types/src/types/rust/RpcTransactionResponse.ts @@ -1,11 +1,4 @@ -import type { GasInfo } from './GasInfo'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { Gas } from "./Gas"; -export interface RpcTransactionResponse { - index: number; - tx_result_json: string; - block_height: bigint; - transaction_hash: string; - gas_info: GasInfo; - fee: MajorCurrencyAmount; -} +export interface RpcTransactionResponse { index: number, tx_result_json: string, block_height: bigint, transaction_hash: string, gas_used: Gas, gas_wanted: Gas, fee: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/SelectionChance.ts b/ts-packages/types/src/types/rust/SelectionChance.ts index a9e7e4797b..d01e33a4ce 100644 --- a/ts-packages/types/src/types/rust/SelectionChance.ts +++ b/ts-packages/types/src/types/rust/SelectionChance.ts @@ -1 +1,2 @@ -export type SelectionChance = 'VeryHigh' | 'High' | 'Moderate' | 'Low' | 'VeryLow'; + +export type SelectionChance = "VeryHigh" | "High" | "Moderate" | "Low" | "VeryLow"; \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/SendTxResult.ts b/ts-packages/types/src/types/rust/SendTxResult.ts index 7ea8859ed5..2ff7f3995f 100644 --- a/ts-packages/types/src/types/rust/SendTxResult.ts +++ b/ts-packages/types/src/types/rust/SendTxResult.ts @@ -1,12 +1,5 @@ -import type { MajorCurrencyAmount } from './Currency'; -import type { TransactionDetails } from './TransactionDetails'; +import type { DecCoin } from "./DecCoin"; +import type { Gas } from "./Gas"; +import type { TransactionDetails } from "./TransactionDetails"; -export interface SendTxResult { - block_height: bigint; - code: number; - details: TransactionDetails; - gas_used: bigint; - gas_wanted: bigint; - fee: MajorCurrencyAmount; - tx_hash: string; -} +export interface SendTxResult { block_height: bigint, code: number, details: TransactionDetails, gas_used: Gas, gas_wanted: Gas, tx_hash: string, fee: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/StakeSaturationResponse.ts b/ts-packages/types/src/types/rust/StakeSaturationResponse.ts index 8f399885a4..7f651f89cc 100644 --- a/ts-packages/types/src/types/rust/StakeSaturationResponse.ts +++ b/ts-packages/types/src/types/rust/StakeSaturationResponse.ts @@ -1,4 +1,2 @@ -export interface StakeSaturationResponse { - saturation: number; - as_at: bigint; -} + +export interface StakeSaturationResponse { saturation: number, as_at: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/TransactionDetails.ts b/ts-packages/types/src/types/rust/TransactionDetails.ts index 8e26480c19..46ace159c9 100644 --- a/ts-packages/types/src/types/rust/TransactionDetails.ts +++ b/ts-packages/types/src/types/rust/TransactionDetails.ts @@ -1,7 +1,3 @@ -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; -export interface TransactionDetails { - amount: MajorCurrencyAmount; - from_address: string; - to_address: string; -} +export interface TransactionDetails { amount: DecCoin, from_address: string, to_address: string, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/TransactionExecuteResult.ts b/ts-packages/types/src/types/rust/TransactionExecuteResult.ts index fd67980be6..4e23cd992b 100644 --- a/ts-packages/types/src/types/rust/TransactionExecuteResult.ts +++ b/ts-packages/types/src/types/rust/TransactionExecuteResult.ts @@ -1,10 +1,4 @@ -import type { GasInfo } from './GasInfo'; -import type { MajorCurrencyAmount } from './Currency'; +import type { DecCoin } from "./DecCoin"; +import type { GasInfo } from "./GasInfo"; -export interface TransactionExecuteResult { - logs_json: string; - data_json: string; - transaction_hash: string; - gas_info: GasInfo; - fee: MajorCurrencyAmount; -} +export interface TransactionExecuteResult { logs_json: string, data_json: string, transaction_hash: string, gas_info: GasInfo, fee: DecCoin | null, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/VestingAccountInfo.ts b/ts-packages/types/src/types/rust/VestingAccountInfo.ts index 793431c215..55cc750936 100644 --- a/ts-packages/types/src/types/rust/VestingAccountInfo.ts +++ b/ts-packages/types/src/types/rust/VestingAccountInfo.ts @@ -1,10 +1,4 @@ -import type { MajorCurrencyAmount } from './Currency'; -import type { VestingPeriod } from './VestingPeriod'; +import type { DecCoin } from "./DecCoin"; +import type { VestingPeriod } from "./VestingPeriod"; -export interface VestingAccountInfo { - owner_address: string; - staking_address: string | null; - start_time: bigint; - periods: Array; - amount: MajorCurrencyAmount; -} +export interface VestingAccountInfo { owner_address: string, staking_address: string | null, start_time: bigint, periods: Array, amount: DecCoin, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/VestingPeriod.ts b/ts-packages/types/src/types/rust/VestingPeriod.ts index de1089005f..fb3cf1c7b2 100644 --- a/ts-packages/types/src/types/rust/VestingPeriod.ts +++ b/ts-packages/types/src/types/rust/VestingPeriod.ts @@ -1,4 +1,2 @@ -export interface VestingPeriod { - start_time: bigint; - period_seconds: bigint; -} + +export interface VestingPeriod { start_time: bigint, period_seconds: bigint, } \ No newline at end of file diff --git a/ts-packages/types/src/types/rust/index.ts b/ts-packages/types/src/types/rust/index.ts deleted file mode 100644 index e3421a9b32..0000000000 --- a/ts-packages/types/src/types/rust/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -export * from './Account'; -export * from './AccountEntry'; -export * from './AccountWithMnemonic'; -export * from './Balance'; -export * from './CoreNodeStatusResponse'; -export * from './Currency'; -export * from './CurrencyDenom'; -export * from './CurrencyStringMajorAmount'; -export * from './Delegation'; -export * from './DelegationEvent'; -export * from './DelegationEventKind'; -export * from './DelegationRecord'; -export * from './DelegationResult'; -export * from './DelegationSummaryResponse'; -export * from './DelegationWithEverything'; -export * from './FeeDetails'; -export * from './Gas'; -export * from './GasInfo'; -export * from './Gateway'; -export * from './GatewayBond'; -export * from './InclusionProbabilityResponse'; -export * from './Mixnode'; -export * from './MixNodeBond'; -export * from './MixnodeStatus'; -export * from './MixnodeStatusResponse'; -export * from './Operation'; -export * from './OriginalVestingResponse'; -export * from './PendingUndelegate'; -export * from './Period'; -export * from './PledgeData'; -export * from './RewardedSetNodeStatus'; -export * from './RpcTransactionResponse'; -export * from './SendTxResult'; -export * from './SelectionChance'; -export * from './StakeSaturationResponse'; -export * from './SendTxResult'; -export * from './TransactionDetails'; -export * from './TransactionExecuteResult'; -export * from './VestingAccountInfo'; -export * from './VestingPeriod';