Feature/wallet sim gas adjustment (#1388)
* Incorporating GasAdjustment into wallet fee simulation * Adjusting the gas only a single time * Hacky implementation of ts_rs on FeeDetails * changelog
This commit is contained in:
committed by
GitHub
parent
bfcc49ab78
commit
aa3310fb9c
@@ -20,6 +20,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- validator-api: Added new endpoints for coconut spending flow and communications with coconut & multisig contracts ([#1261])
|
||||
- validator-api: add `uptime`, `estimated_operator_apy`, `estimated_delegators_apy` to `/mixnodes/detailed` endpoint ([#1393])
|
||||
- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328])
|
||||
- wallet: when simulating gas costs, an automatic adjustment is being used ([#1388]).
|
||||
- mixnode: Added basic mixnode hardware reporting to the HTTP API ([#1308]).
|
||||
|
||||
### Fixed
|
||||
@@ -54,6 +55,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
[#1329]: https://github.com/nymtech/nym/pull/1329
|
||||
[#1353]: https://github.com/nymtech/nym/pull/1353
|
||||
[#1376]: https://github.com/nymtech/nym/pull/1376
|
||||
[#1388]: https://github.com/nymtech/nym/pull/1388
|
||||
[#1393]: https://github.com/nymtech/nym/pull/1393
|
||||
|
||||
## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22)
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::nymd::cosmwasm_client::types::*;
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
use crate::nymd::wallet::DirectSecp256k1HdWallet;
|
||||
use crate::nymd::{Coin, GasPrice, TxResponse};
|
||||
use crate::nymd::{Coin, GasAdjustable, GasPrice, TxResponse};
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::bank::MsgSend;
|
||||
use cosmrs::distribution::MsgWithdrawDelegatorReward;
|
||||
@@ -504,7 +504,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.gas_used;
|
||||
|
||||
let multiplier = multiplier.unwrap_or(DEFAULT_SIMULATED_GAS_MULTIPLIER);
|
||||
let gas = ((gas_estimation.value() as f32 * multiplier) as u64).into();
|
||||
let gas = gas_estimation.adjust_gas(multiplier);
|
||||
|
||||
debug!("Gas estimation: {}", gas_estimation);
|
||||
debug!("Multiplying the estimation by {}", multiplier);
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nymd::Gas;
|
||||
use cosmrs::tx;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod gas_price;
|
||||
|
||||
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: f32 = 1.3;
|
||||
pub type GasAdjustment = f32;
|
||||
|
||||
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: GasAdjustment = 1.3;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Fee {
|
||||
Manual(#[serde(with = "sealed::TxFee")] tx::Fee),
|
||||
Auto(Option<f32>),
|
||||
Auto(Option<GasAdjustment>),
|
||||
}
|
||||
|
||||
impl From<tx::Fee> for Fee {
|
||||
@@ -20,8 +23,8 @@ impl From<tx::Fee> for Fee {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Fee {
|
||||
fn from(multiplier: f32) -> Self {
|
||||
impl From<GasAdjustment> for Fee {
|
||||
fn from(multiplier: GasAdjustment) -> Self {
|
||||
Fee::Auto(Some(multiplier))
|
||||
}
|
||||
}
|
||||
@@ -32,6 +35,21 @@ impl Default for Fee {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GasAdjustable {
|
||||
fn adjust_gas(&self, adjustment: GasAdjustment) -> Self;
|
||||
}
|
||||
|
||||
impl GasAdjustable for Gas {
|
||||
fn adjust_gas(&self, adjustment: GasAdjustment) -> Self {
|
||||
if adjustment == 1.0 {
|
||||
*self
|
||||
} else {
|
||||
let adjusted = (self.value() as f32 * adjustment).ceil();
|
||||
(adjusted as u64).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a workaround to provide serde implementation for tx::Fee. We don't want to ever expose any of those
|
||||
// types to the public and ideally they will get replaced by proper implementation inside comrs
|
||||
mod sealed {
|
||||
|
||||
@@ -15,7 +15,6 @@ use cosmrs::rpc::HttpClientUrl;
|
||||
use cosmrs::tx::Msg;
|
||||
use cosmwasm_std::Uint128;
|
||||
use execute::execute;
|
||||
pub use fee::gas_price::GasPrice;
|
||||
use mixnet_contract_common::mixnode::DelegationEvent;
|
||||
use mixnet_contract_common::{
|
||||
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayBondResponse,
|
||||
@@ -50,6 +49,7 @@ pub use cosmrs::tx::{self, Gas};
|
||||
pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
|
||||
pub use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||
pub use signing_client::Client as SigningNymdClient;
|
||||
pub use traits::{VestingQueryClient, VestingSigningClient};
|
||||
|
||||
@@ -270,6 +270,10 @@ impl<C> NymdClient<C> {
|
||||
self.client.gas_price()
|
||||
}
|
||||
|
||||
pub fn gas_adjustment(&self) -> GasAdjustment {
|
||||
self.simulated_gas_multiplier
|
||||
}
|
||||
|
||||
pub async fn account_sequence(&self) -> Result<SequenceResponse, NymdError>
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
|
||||
@@ -1,18 +1,84 @@
|
||||
use crate::currency::MajorCurrencyAmount;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use validator_client::nymd::Fee;
|
||||
|
||||
use crate::currency::MajorCurrencyAmount;
|
||||
#[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/FeeDetails.ts")
|
||||
)]
|
||||
#[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<MajorCurrencyAmount>,
|
||||
#[cfg_attr(feature = "generate-ts", ts(skip))]
|
||||
pub fee: Fee,
|
||||
}
|
||||
|
||||
#[cfg(feature = "generate-ts")]
|
||||
impl TS for FeeDetails {
|
||||
const EXPORT_TO: Option<&'static str> = Some("ts-packages/types/src/types/rust/FeeDetails.ts");
|
||||
|
||||
fn decl() -> String {
|
||||
format!("type {} = {};", Self::name(), Self::inline())
|
||||
}
|
||||
|
||||
fn name() -> String {
|
||||
"FeeDetails".into()
|
||||
}
|
||||
|
||||
fn inline() -> String {
|
||||
"{ amount: MajorCurrencyAmount | null, fee: Fee }".into()
|
||||
}
|
||||
|
||||
fn dependencies() -> Vec<Dependency> {
|
||||
vec![
|
||||
Dependency::from_ty::<MajorCurrencyAmount>()
|
||||
.expect("TS was incorrectly defined on `CurrencyDenom`"),
|
||||
Dependency::from_ty::<ts_type_helpers::Fee>()
|
||||
.expect("TS was incorrectly defined on `ts_type_helpers::Fee`"),
|
||||
]
|
||||
}
|
||||
|
||||
fn transparent() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// this should really be sealed and NEVER EVER used as "normal" types,
|
||||
// but due to our typescript requirements, we have to expose it to generate
|
||||
// the types...
|
||||
#[cfg(feature = "generate-ts")]
|
||||
pub mod ts_type_helpers {
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::GasAdjustment;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
|
||||
#[ts(export_to = "ts-packages/types/src/types/rust/Fee.ts")]
|
||||
pub enum Fee {
|
||||
Manual(CosmosFee),
|
||||
Auto(Option<GasAdjustment>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
|
||||
#[ts(export_to = "ts-packages/types/src/types/rust/CosmosFee.ts")]
|
||||
// this should corresponds to cosmrs::tx::Fee
|
||||
// IMPORTANT NOTE: this should work as of cosmrs 0.7.1 due to their `FromStr` implementations
|
||||
// on the type. The below struct might have to get readjusted if we update cosmrs!!
|
||||
pub struct CosmosFee {
|
||||
amount: Vec<Coin>,
|
||||
gas_limit: u64,
|
||||
payer: Option<String>,
|
||||
granter: Option<String>,
|
||||
}
|
||||
|
||||
// Note: I've got a feeling this one will bite us hard at some point...
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
|
||||
#[ts(export_to = "ts-packages/types/src/types/rust/Coin.ts")]
|
||||
// this should corresponds to cosmrs::Coin
|
||||
// IMPORTANT NOTE: this should work as of cosmrs 0.7.1 due to their `FromStr` implementations
|
||||
// on the type. The below struct might have to get readjusted if we update cosmrs!!
|
||||
pub struct Coin {
|
||||
denom: String,
|
||||
// this is not entirely true, but for the purposes
|
||||
// of ts_rs, it's sufficient for the time being
|
||||
amount: u64,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::simulate::detailed_fee;
|
||||
use crate::State;
|
||||
use mixnet_contract_common::{ContractStateParams, ExecuteMsg};
|
||||
use nym_wallet_types::admin::TauriContractStateParams;
|
||||
@@ -19,7 +20,6 @@ pub async fn simulate_update_contract_settings(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -28,5 +28,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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::simulate::detailed_fee;
|
||||
use crate::state::State;
|
||||
use nym_types::currency::MajorCurrencyAmount;
|
||||
use std::str::FromStr;
|
||||
@@ -23,7 +24,6 @@ pub async fn simulate_send(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let from_address = client.nymd.address().clone();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
// TODO: I'm still not 100% convinced whether this should be exposed here or handled somewhere else in the client code
|
||||
let msg = MsgSend {
|
||||
@@ -33,5 +33,5 @@ pub async fn simulate_send(
|
||||
};
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::simulate::detailed_fee;
|
||||
use crate::State;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode};
|
||||
@@ -23,7 +23,6 @@ pub async fn simulate_bond_gateway(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
// TODO: I'm still not 100% convinced whether this should be exposed here or handled somewhere else in the client code
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
@@ -36,7 +35,7 @@ pub async fn simulate_bond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -44,10 +43,8 @@ pub async fn simulate_unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -56,7 +53,7 @@ pub async fn simulate_unbond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -71,7 +68,6 @@ pub async fn simulate_bond_mixnode(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -83,7 +79,7 @@ pub async fn simulate_bond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -91,10 +87,8 @@ pub async fn simulate_unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -103,7 +97,7 @@ pub async fn simulate_unbond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -112,10 +106,8 @@ pub async fn simulate_update_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -126,7 +118,7 @@ pub async fn simulate_update_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -140,7 +132,6 @@ pub async fn simulate_delegate_to_mixnode(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -151,7 +142,7 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -160,10 +151,8 @@ pub async fn simulate_undelegate_from_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
mixnet_contract,
|
||||
@@ -174,29 +163,27 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_claim_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
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())
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client.nymd.simulate_claim_operator_reward(None).await?;
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_compound_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
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())
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client.nymd.simulate_compound_operator_reward(None).await?;
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -204,11 +191,13 @@ pub async fn simulate_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -216,9 +205,11 @@ pub async fn simulate_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmrs::tx;
|
||||
use cosmrs::tx::Gas;
|
||||
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};
|
||||
use validator_client::nymd::cosmwasm_client::types::{GasInfo, SimulateResponse};
|
||||
use validator_client::nymd::{
|
||||
CosmosCoin, Fee, GasAdjustable, GasAdjustment, GasPrice, SigningNymdClient,
|
||||
};
|
||||
use validator_client::Client;
|
||||
|
||||
pub mod admin;
|
||||
pub mod cosmos;
|
||||
pub mod mixnet;
|
||||
pub mod vesting;
|
||||
|
||||
pub(crate) fn detailed_fee(
|
||||
client: &Client<SigningNymdClient>,
|
||||
simulate_response: SimulateResponse,
|
||||
) -> FeeDetails {
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
let gas_adjustment = client.nymd.gas_adjustment();
|
||||
|
||||
SimulateResult::new(simulate_response.gas_info, gas_price, gas_adjustment).detailed_fee()
|
||||
}
|
||||
|
||||
// technically we could have also exposed a result: Option<AbciResult> field from the SimulateResponse,
|
||||
// but in the context of the wallet it's really irrelevant and useless for the time being
|
||||
pub(crate) struct SimulateResult {
|
||||
@@ -19,13 +34,19 @@ pub(crate) struct SimulateResult {
|
||||
// for example if you attempt to send a 'BondMixnode' with invalid signature
|
||||
pub gas_info: Option<GasInfo>,
|
||||
pub gas_price: GasPrice,
|
||||
pub gas_adjustment: GasAdjustment,
|
||||
}
|
||||
|
||||
impl SimulateResult {
|
||||
pub fn new(gas_info: Option<GasInfo>, gas_price: GasPrice) -> Self {
|
||||
pub fn new(
|
||||
gas_info: Option<GasInfo>,
|
||||
gas_price: GasPrice,
|
||||
gas_adjustment: GasAdjustment,
|
||||
) -> Self {
|
||||
SimulateResult {
|
||||
gas_info,
|
||||
gas_price,
|
||||
gas_adjustment,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,18 +58,20 @@ impl SimulateResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_fee_amount(&self) -> Option<CosmosCoin> {
|
||||
fn adjusted_gas(&self) -> Option<Gas> {
|
||||
self.gas_info
|
||||
.map(|gas_info| &self.gas_price * gas_info.gas_used)
|
||||
.map(|gas_info| gas_info.gas_used.adjust_gas(self.gas_adjustment))
|
||||
}
|
||||
|
||||
fn to_fee_amount(&self) -> Option<CosmosCoin> {
|
||||
self.adjusted_gas().map(|gas| &self.gas_price * gas)
|
||||
}
|
||||
|
||||
fn to_fee(&self) -> Fee {
|
||||
self.to_fee_amount()
|
||||
.and_then(|fee_amount| {
|
||||
self.gas_info.map(|gas_info| {
|
||||
let gas_limit = gas_info.gas_used;
|
||||
tx::Fee::from_amount_and_gas(fee_amount, gas_limit).into()
|
||||
})
|
||||
self.adjusted_gas()
|
||||
.map(|gas| {
|
||||
let fee_amount = &self.gas_price * gas;
|
||||
tx::Fee::from_amount_and_gas(fee_amount, gas).into()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::simulate::detailed_fee;
|
||||
use crate::State;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{Gateway, MixNode};
|
||||
@@ -24,7 +24,6 @@ pub async fn simulate_vesting_bond_gateway(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -37,7 +36,7 @@ pub async fn simulate_vesting_bond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -48,7 +47,6 @@ pub async fn simulate_vesting_unbond_gateway(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -57,7 +55,7 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -72,7 +70,6 @@ pub async fn simulate_vesting_bond_mixnode(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -85,7 +82,7 @@ pub async fn simulate_vesting_bond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -96,7 +93,6 @@ pub async fn simulate_vesting_unbond_mixnode(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -105,7 +101,7 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -117,7 +113,6 @@ pub async fn simulate_vesting_update_mixnode(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -128,7 +123,7 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -141,7 +136,6 @@ pub async fn simulate_withdraw_vested_coins(
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
@@ -150,29 +144,33 @@ 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())
|
||||
Ok(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_claim_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_compound_operator_reward(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -180,11 +178,13 @@ pub async fn simulate_vesting_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -192,9 +192,11 @@ pub async fn simulate_vesting_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let result = nymd_client!(state)
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let result = client
|
||||
.nymd
|
||||
.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(detailed_fee(client, result))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use nym_types::delegation::{
|
||||
Delegation, DelegationEvent, DelegationEventKind, DelegationRecord, DelegationResult,
|
||||
DelegationWithEverything, DelegationsSummaryResponse, PendingUndelegate,
|
||||
};
|
||||
use nym_types::fees::FeeDetails;
|
||||
use nym_types::fees::{self, FeeDetails};
|
||||
use nym_types::gas::{Gas, GasInfo};
|
||||
use nym_types::gateway::{Gateway, GatewayBond};
|
||||
use nym_types::mixnode::{MixNode, MixNodeBond};
|
||||
@@ -68,6 +68,11 @@ fn main() {
|
||||
do_export!(DelegationsSummaryResponse);
|
||||
do_export!(DelegationWithEverything);
|
||||
do_export!(FeeDetails);
|
||||
// I'm explicitly using full(-ish) path as to indicate
|
||||
// those are not "proper" types to be used elsewhere
|
||||
do_export!(fees::ts_type_helpers::Fee);
|
||||
do_export!(fees::ts_type_helpers::CosmosFee);
|
||||
do_export!(fees::ts_type_helpers::Coin);
|
||||
do_export!(Gas);
|
||||
do_export!(GasInfo);
|
||||
do_export!(Gateway);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export interface Coin { denom: string, amount: bigint, }
|
||||
@@ -0,0 +1,3 @@
|
||||
import type { Coin } from "./Coin";
|
||||
|
||||
export interface CosmosFee { amount: Array<Coin>, gas_limit: bigint, payer: string | null, granter: string | null, }
|
||||
@@ -0,0 +1,3 @@
|
||||
import type { CosmosFee } from "./CosmosFee";
|
||||
|
||||
export type Fee = { Manual: CosmosFee } | { Auto: number | null };
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { MajorCurrencyAmount } from './Currency';
|
||||
import type { Fee } from "./Fee";
|
||||
import type { MajorCurrencyAmount } from "./Currency";
|
||||
|
||||
export interface FeeDetails {
|
||||
amount: MajorCurrencyAmount | null;
|
||||
}
|
||||
export type FeeDetails = { amount: MajorCurrencyAmount | null, fee: Fee };
|
||||
Reference in New Issue
Block a user