From 87e8666b863a12f1850863ded9103ec5090a45f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 1 Jun 2022 16:52:26 +0100 Subject: [PATCH] 'New' API on 'send' --- .../validator-client/src/nymd/fee/mod.rs | 10 +++ common/types/src/gas.rs | 80 ++++++------------ common/types/src/transaction.rs | 84 +++++++++++-------- .../src-tauri/src/operations/mixnet/send.rs | 30 ++++--- 4 files changed, 100 insertions(+), 104 deletions(-) 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..aefb953900 100644 --- a/common/client-libs/validator-client/src/nymd/fee/mod.rs +++ b/common/client-libs/validator-client/src/nymd/fee/mod.rs @@ -1,6 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::nymd::Coin; use cosmrs::tx; use serde::{Deserialize, Serialize}; @@ -14,6 +15,15 @@ pub enum Fee { Auto(Option), } +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/types/src/gas.rs b/common/types/src/gas.rs index a6f18c6376..22cf8ba6dc 100644 --- a/common/types/src/gas.rs +++ b/common/types/src/gas.rs @@ -10,36 +10,23 @@ use validator_client::nymd::GasPrice; 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, } 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(), + } } } @@ -48,44 +35,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/transaction.rs b/common/types/src/transaction.rs index 956e8cfc92..b62a6db3f4 100644 --- a/common/types/src/transaction.rs +++ b/common/types/src/transaction.rs @@ -1,9 +1,10 @@ -use crate::currency::MajorCurrencyAmount; +use crate::currency::{DecCoin, MajorCurrencyAmount}; use crate::error::TypesError; -use crate::gas::GasInfo; +use crate::gas::{Gas, GasInfo}; +use log::warn; use serde::{Deserialize, Serialize}; use validator_client::nymd::cosmwasm_client::types::ExecuteResult; -use validator_client::nymd::TxResponse; +use validator_client::nymd::{Coin, TxResponse}; #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( @@ -15,31 +16,37 @@ 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 { + let fee = match fee { + None => None, + Some(mut fee) => { + if fee.len() > 1 { + warn!("our tx fee contained more than a single denomination. using the first one for display") + } + if fee.is_empty() { + warn!("our tx has had an unknown fee set"); + None + } else { + Some(fee.pop().unwrap().into()) + } + } + }; + 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 +57,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", @@ -74,8 +91,9 @@ impl TransactionExecuteResult { value: ExecuteResult, denom_minor: &str, ) -> Result { - let gas_info = GasInfo::from_validator_client_gas_info(value.gas_info, denom_minor)?; - let fee = gas_info.fee.clone(); + let gas_info = GasInfo::from(value.gas_info); + // let fee = gas_info.fee.clone(); + let fee = todo!(); Ok(TransactionExecuteResult { gas_info, transaction_hash: value.transaction_hash.to_string(), @@ -97,25 +115,23 @@ pub struct RpcTransactionResponse { pub tx_result_json: String, pub block_height: u64, pub transaction_hash: String, - pub gas_info: GasInfo, + pub gas_used: Gas, + pub gas_wanted: Gas, // pub fee: MajorCurrencyAmount, } impl RpcTransactionResponse { pub fn from_tx_response( - value: &TxResponse, + t: &TxResponse, denom_minor: &str, ) -> 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(), + 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(), // wrong // fee: MajorCurrencyAmount::from_decimal_and_denom( // Decimal::new(Uint128::from(value.tx_result.gas_used.value())), diff --git a/nym-wallet/src-tauri/src/operations/mixnet/send.rs b/nym-wallet/src-tauri/src/operations/mixnet/send.rs index 30efde8566..ec4845a23f 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/send.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/send.rs @@ -1,7 +1,7 @@ use crate::error::BackendError; use crate::nymd_client; use crate::state::State; -use nym_types::currency::MajorCurrencyAmount; +use nym_types::currency::DecCoin; use nym_types::transaction::{SendTxResult, TransactionDetails}; use std::str::FromStr; use std::sync::Arc; @@ -11,36 +11,34 @@ 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>>, ) -> Result { - let denom_minor = state.read().await.current_network().denom(); - let address = AccountId::from_str(address)?; + 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 = nymd_client!(state).address().to_string(); - let amount2 = amount.clone().into(); + let fee_amount = fee.as_ref().and_then(|fee| fee.try_get_manual_amount()); 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) + .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) }