diff --git a/Cargo.lock b/Cargo.lock index f3d0b5aa78..2905637e37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7741,6 +7741,7 @@ dependencies = [ "mixnet-contract-common", "schemars", "serde", + "ts-rs", ] [[package]] diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 24a0753d6e..c3e173b0f2 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -39,7 +39,8 @@ flate2 = { version = "1.0.20", optional = true } sha2 = { version = "0.9.5", optional = true } itertools = { version = "0.10", optional = true } cosmwasm-std = { version = "1.0.0-beta3", optional = true } -ts-rs = { version = "5.1", optional = true } +# Leaving it as * so that it inherits whatever the wallet is using +ts-rs = { version = "*", optional = true } [features] nymd-client = [ diff --git a/common/client-libs/validator-client/src/nymd/traits/vesting_query_client.rs b/common/client-libs/validator-client/src/nymd/traits/vesting_query_client.rs index b6bd534ccb..3101850b7c 100644 --- a/common/client-libs/validator-client/src/nymd/traits/vesting_query_client.rs +++ b/common/client-libs/validator-client/src/nymd/traits/vesting_query_client.rs @@ -6,8 +6,10 @@ use crate::nymd::error::NymdError; use crate::nymd::NymdClient; use async_trait::async_trait; use cosmwasm_std::{Coin, Timestamp}; -use vesting_contract::vesting::{Account, PledgeData}; -use vesting_contract_common::messages::QueryMsg as VestingQueryMsg; +use vesting_contract::vesting::Account; +use vesting_contract_common::{ + messages::QueryMsg as VestingQueryMsg, OriginalVestingResponse, Period, PledgeData, +}; #[async_trait] pub trait VestingQueryClient { @@ -43,7 +45,10 @@ pub trait VestingQueryClient { async fn vesting_end_time(&self, vesting_account_address: &str) -> Result; - async fn original_vesting(&self, vesting_account_address: &str) -> Result; + async fn original_vesting( + &self, + vesting_account_address: &str, + ) -> Result; async fn delegated_free( &self, @@ -60,6 +65,10 @@ pub trait VestingQueryClient { async fn get_account(&self, address: &str) -> Result; async fn get_mixnode_pledge(&self, address: &str) -> Result, NymdError>; async fn get_gateway_pledge(&self, address: &str) -> Result, NymdError>; + async fn get_current_vesting_period( + &self, + vesting_account_address: &str, + ) -> Result; } #[async_trait] @@ -142,7 +151,10 @@ impl VestingQueryClient for NymdClient { .await } - async fn original_vesting(&self, vesting_account_address: &str) -> Result { + async fn original_vesting( + &self, + vesting_account_address: &str, + ) -> Result { let request = VestingQueryMsg::GetOriginalVesting { vesting_account_address: vesting_account_address.to_string(), }; @@ -203,4 +215,13 @@ impl VestingQueryClient for NymdClient { .query_contract_smart(self.vesting_contract_address()?, &request) .await } + + async fn get_current_vesting_period(&self, address: &str) -> Result { + let request = VestingQueryMsg::GetCurrentVestingPeriod { + address: address.to_string(), + }; + self.client + .query_contract_smart(self.vesting_contract_address()?, &request) + .await + } } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 248036d804..1989c2c0dd 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -12,7 +12,8 @@ cosmwasm-std = "1.0.0-beta3" serde = { version = "1.0", features = ["derive"] } serde_repr = "0.1" schemars = "0.8" -ts-rs = { version = "5.1", optional = true } +# Leaving it as * so that it inherits whatever the wallet is using +ts-rs = { version = "*", optional = true } thiserror = "1.0" network-defaults = { path = "../../network-defaults" } fixed = { version = "1.1", features = ["serde"] } diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index c5829ec703..1e4e25342b 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -11,4 +11,5 @@ mixnet-contract-common = { path = "../mixnet-contract" } serde = { version = "1.0", features = ["derive"] } schemars = "0.8" cw-storage-plus = "0.11.1" -config = {path = "../../config"} +config = { path = "../../config" } +ts-rs = { version = "*", optional = true } diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs index f985260a76..4e8b951506 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs @@ -1,7 +1,9 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use config::defaults::DENOM; -use cosmwasm_std::Coin; +use cosmwasm_std::{Coin, Timestamp}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; pub mod events; pub mod messages; @@ -9,3 +11,60 @@ pub mod messages; pub fn one_ucoin() -> Coin { Coin::new(1, DENOM) } + +#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))] +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, JsonSchema)] +pub enum Period { + Before, + In(usize), + After, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct PledgeData { + amount: Coin, + block_time: Timestamp, +} + +impl PledgeData { + pub fn amount(&self) -> Coin { + self.amount.clone() + } + + pub fn block_time(&self) -> Timestamp { + self.block_time + } + + pub fn new(amount: Coin, block_time: Timestamp) -> Self { + Self { amount, block_time } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct OriginalVestingResponse { + amount: Coin, + number_of_periods: usize, + period_duration: u64, +} + +impl OriginalVestingResponse { + pub fn amount(&self) -> Coin { + self.amount.clone() + } + + pub fn number_of_periods(&self) -> usize { + self.number_of_periods + } + + pub fn period_duration(&self) -> u64 { + self.period_duration + } + + pub fn new(amount: Coin, number_of_periods: usize, period_duration: u64) -> Self { + Self { + amount, + number_of_periods, + period_duration, + } + } +} diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs index 18983ff982..dc478ed751 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs @@ -148,4 +148,7 @@ pub enum QueryMsg { GetGateway { address: String, }, + GetCurrentVestingPeriod { + address: String, + }, } diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 0b174b2a64..493cb4dd6a 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -3,7 +3,7 @@ use crate::storage::{account_from_address, ADMIN, MIXNET_CONTRACT_ADDRESS}; use crate::traits::{ DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount, }; -use crate::vesting::{populate_vesting_periods, Account, PledgeData}; +use crate::vesting::{populate_vesting_periods, Account}; use config::defaults::DENOM; use cosmwasm_std::{ coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse, @@ -18,6 +18,7 @@ use vesting_contract_common::events::{ use vesting_contract_common::messages::{ ExecuteMsg, InitMsg, MigrateMsg, QueryMsg, VestingSpecification, }; +use vesting_contract_common::{OriginalVestingResponse, Period, PledgeData}; #[entry_point] pub fn instantiate( @@ -443,11 +444,23 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result to_binary(&try_get_account(&address, deps)?), QueryMsg::GetMixnode { address } => to_binary(&try_get_mixnode(&address, deps)?), QueryMsg::GetGateway { address } => to_binary(&try_get_gateway(&address, deps)?), + QueryMsg::GetCurrentVestingPeriod { address } => { + to_binary(&try_get_current_vesting_period(&address, deps, env)?) + } }; Ok(query_res?) } +pub fn try_get_current_vesting_period( + address: &str, + deps: Deps<'_>, + env: Env, +) -> Result { + let account = account_from_address(address, deps.storage, deps.api)?; + Ok(account.get_current_vesting_period(env.block.time)) +} + pub fn try_get_mixnode(address: &str, deps: Deps<'_>) -> Result, ContractError> { let account = account_from_address(address, deps.storage, deps.api)?; account.load_mixnode_pledge(deps.storage) @@ -521,7 +534,7 @@ pub fn try_get_end_time( pub fn try_get_original_vesting( vesting_account_address: &str, deps: Deps<'_>, -) -> Result { +) -> Result { let account = account_from_address(vesting_account_address, deps.storage, deps.api)?; Ok(account.get_original_vesting()) } diff --git a/contracts/vesting/src/storage.rs b/contracts/vesting/src/storage.rs index 190f4cb565..1915b5c826 100644 --- a/contracts/vesting/src/storage.rs +++ b/contracts/vesting/src/storage.rs @@ -1,9 +1,9 @@ use crate::errors::ContractError; use crate::vesting::Account; -use crate::vesting::PledgeData; use cosmwasm_std::{Addr, Api, Storage, Uint128}; use cw_storage_plus::{Item, Map}; use mixnet_contract_common::IdentityKey; +use vesting_contract_common::PledgeData; type BlockHeight = u64; diff --git a/contracts/vesting/src/traits/vesting_account.rs b/contracts/vesting/src/traits/vesting_account.rs index a564cfd2f5..b1d6687e47 100644 --- a/contracts/vesting/src/traits/vesting_account.rs +++ b/contracts/vesting/src/traits/vesting_account.rs @@ -1,5 +1,6 @@ use crate::errors::ContractError; use cosmwasm_std::{Addr, Coin, Env, Storage, Timestamp}; +use vesting_contract_common::OriginalVestingResponse; pub trait VestingAccount { // locked_coins returns the set of coins that are not spendable (can still be delegated tough) (i.e. locked), @@ -37,7 +38,7 @@ pub trait VestingAccount { fn get_start_time(&self) -> Timestamp; fn get_end_time(&self) -> Timestamp; - fn get_original_vesting(&self) -> Coin; + fn get_original_vesting(&self) -> OriginalVestingResponse; fn get_delegated_free( &self, block_time: Option, diff --git a/contracts/vesting/src/vesting/account/gateway_bonding_account.rs b/contracts/vesting/src/vesting/account/gateway_bonding_account.rs index c76c9d9385..c9b411d965 100644 --- a/contracts/vesting/src/vesting/account/gateway_bonding_account.rs +++ b/contracts/vesting/src/vesting/account/gateway_bonding_account.rs @@ -34,10 +34,7 @@ impl GatewayBondingAccount for Account { self.owner_address().as_str().to_string(), )); } else { - PledgeData { - block_time: env.block.time, - amount: pledge.amount, - } + PledgeData::new(pledge.clone(), env.block.time) }; let msg = MixnetExecuteMsg::BondGatewayOnBehalf { diff --git a/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs b/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs index 0416a1fbd9..ad34223f6d 100644 --- a/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs +++ b/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs @@ -1,4 +1,3 @@ -use super::PledgeData; use crate::errors::ContractError; use crate::storage::MIXNET_CONTRACT_ADDRESS; use crate::traits::MixnodeBondingAccount; @@ -8,7 +7,9 @@ use vesting_contract_common::events::{ new_vesting_mixnode_bonding_event, new_vesting_mixnode_unbonding_event, new_vesting_update_mixnode_config_event, }; + use vesting_contract_common::one_ucoin; +use vesting_contract_common::PledgeData; use super::Account; @@ -56,10 +57,7 @@ impl MixnodeBondingAccount for Account { self.owner_address().as_str().to_string(), )); } else { - PledgeData { - block_time: env.block.time, - amount: pledge.amount, - } + PledgeData::new(pledge.clone(), env.block.time) }; let msg = MixnetExecuteMsg::BondMixnodeOnBehalf { diff --git a/contracts/vesting/src/vesting/account/mod.rs b/contracts/vesting/src/vesting/account/mod.rs index 5c14cbba42..ee09f37ab2 100644 --- a/contracts/vesting/src/vesting/account/mod.rs +++ b/contracts/vesting/src/vesting/account/mod.rs @@ -1,4 +1,4 @@ -use super::{PledgeData, VestingPeriod}; +use super::VestingPeriod; use crate::errors::ContractError; use crate::storage::{ load_balance, load_bond_pledge, load_gateway_pledge, remove_bond_pledge, remove_delegation, @@ -10,6 +10,7 @@ use cw_storage_plus::Bound; use mixnet_contract_common::IdentityKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use vesting_contract_common::{Period, PledgeData}; mod delegating_account; mod gateway_bonding_account; @@ -22,13 +23,6 @@ fn generate_storage_key(storage: &mut dyn Storage) -> Result Ok(key) } -#[derive(Debug, PartialEq)] -pub enum Period { - Before, - In(usize), - After, -} - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Account { owner_address: Addr, @@ -67,6 +61,10 @@ impl Account { self.periods.len() } + pub fn period_duration(&self) -> u64 { + self.periods.get(0).unwrap().period_seconds + } + pub fn storage_key(&self) -> u32 { self.storage_key } diff --git a/contracts/vesting/src/vesting/account/vesting_account.rs b/contracts/vesting/src/vesting/account/vesting_account.rs index 0c3832b382..7648724b3c 100644 --- a/contracts/vesting/src/vesting/account/vesting_account.rs +++ b/contracts/vesting/src/vesting/account/vesting_account.rs @@ -3,8 +3,9 @@ use crate::storage::{delete_account, save_account, DELEGATIONS}; use crate::traits::VestingAccount; use config::defaults::DENOM; use cosmwasm_std::{Addr, Coin, Env, Order, Storage, Timestamp, Uint128}; +use vesting_contract_common::{OriginalVestingResponse, Period}; -use super::{Account, Period}; +use super::Account; impl VestingAccount for Account { fn locked_coins( @@ -83,7 +84,7 @@ impl VestingAccount for Account { env: &Env, ) -> Result { Ok(Coin { - amount: self.get_original_vesting().amount + amount: self.get_original_vesting().amount().amount - self.get_vested_coins(block_time, env)?.amount, denom: DENOM.to_string(), }) @@ -97,8 +98,12 @@ impl VestingAccount for Account { self.periods[(self.num_vesting_periods() - 1) as usize].end_time() } - fn get_original_vesting(&self) -> Coin { - self.coin.clone() + fn get_original_vesting(&self) -> OriginalVestingResponse { + OriginalVestingResponse::new( + self.coin.clone(), + self.num_vesting_periods(), + self.period_duration(), + ) } fn get_delegated_free( @@ -170,8 +175,8 @@ impl VestingAccount for Account { .load_mixnode_pledge(storage)? .or(self.load_gateway_pledge(storage)?) { - if bond.block_time.seconds() < start_time { - bond.amount + if bond.block_time().seconds() < start_time { + bond.amount().amount } else { Uint128::zero() } @@ -200,7 +205,7 @@ impl VestingAccount for Account { .load_mixnode_pledge(storage)? .or(self.load_gateway_pledge(storage)?) { - let amount = bond.amount - bonded_free.amount; + let amount = bond.amount().amount - bonded_free.amount; Ok(Coin { amount, denom: DENOM.to_string(), diff --git a/contracts/vesting/src/vesting/mod.rs b/contracts/vesting/src/vesting/mod.rs index 8293ef2063..d3851daa31 100644 --- a/contracts/vesting/src/vesting/mod.rs +++ b/contracts/vesting/src/vesting/mod.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Timestamp, Uint128}; +use cosmwasm_std::Timestamp; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -19,12 +19,6 @@ impl VestingPeriod { } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct PledgeData { - amount: Uint128, - block_time: Timestamp, -} - pub fn populate_vesting_periods( start_time: u64, vesting_spec: VestingSpecification, @@ -48,12 +42,12 @@ mod tests { use crate::traits::DelegatingAccount; use crate::traits::VestingAccount; use crate::traits::{GatewayBondingAccount, MixnodeBondingAccount}; - use crate::vesting::Period; use config::defaults::DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, Addr, Coin, Timestamp, Uint128}; use mixnet_contract_common::{Gateway, MixNode}; use vesting_contract_common::messages::ExecuteMsg; + use vesting_contract_common::Period; #[test] fn test_account_creation() { @@ -194,14 +188,15 @@ mod tests { assert_eq!( vested_coins.amount, Uint128::new( - account.get_original_vesting().amount.u128() / num_vesting_periods as u128 + account.get_original_vesting().amount().amount.u128() / num_vesting_periods as u128 ) ); assert_eq!( vesting_coins.amount, Uint128::new( - account.get_original_vesting().amount.u128() - - account.get_original_vesting().amount.u128() / num_vesting_periods as u128 + account.get_original_vesting().amount().amount.u128() + - account.get_original_vesting().amount().amount.u128() + / num_vesting_periods as u128 ) ); @@ -214,14 +209,15 @@ mod tests { assert_eq!( vested_coins.amount, Uint128::new( - 5 * account.get_original_vesting().amount.u128() / num_vesting_periods as u128 + 5 * account.get_original_vesting().amount().amount.u128() + / num_vesting_periods as u128 ) ); assert_eq!( vesting_coins.amount, Uint128::new( - account.get_original_vesting().amount.u128() - - 5 * account.get_original_vesting().amount.u128() + account.get_original_vesting().amount().amount.u128() + - 5 * account.get_original_vesting().amount().amount.u128() / num_vesting_periods as u128 ) ); @@ -235,7 +231,7 @@ mod tests { let vesting_coins = account.get_vesting_coins(Some(block_time), &env).unwrap(); assert_eq!( vested_coins.amount, - Uint128::new(account.get_original_vesting().amount.u128()) + Uint128::new(account.get_original_vesting().amount().amount.u128()) ); assert_eq!(vesting_coins.amount, Uint128::zero()); } @@ -410,7 +406,7 @@ mod tests { assert!(err.is_err()); let pledge = account.load_mixnode_pledge(&deps.storage).unwrap().unwrap(); - assert_eq!(Uint128::new(500_000_000_000), pledge.amount); + assert_eq!(Uint128::new(500_000_000_000), pledge.amount().amount); // Current period -> block_time: None let bonded_free = account.get_pledged_free(None, &env, &deps.storage).unwrap(); @@ -419,7 +415,10 @@ mod tests { let bonded_vesting = account .get_pledged_vesting(None, &env, &deps.storage) .unwrap(); - assert_eq!(pledge.amount - bonded_free.amount, bonded_vesting.amount); + assert_eq!( + pledge.amount().amount - bonded_free.amount, + bonded_vesting.amount + ); // All periods for (i, period) in account.periods().iter().enumerate() { @@ -431,7 +430,8 @@ mod tests { ) .unwrap(); assert_eq!( - (account.tokens_per_period().unwrap() * i as u128).min(pledge.amount.u128()), + (account.tokens_per_period().unwrap() * i as u128) + .min(pledge.amount().amount.u128()), bonded_free.amount.u128() ); @@ -442,7 +442,10 @@ mod tests { &deps.storage, ) .unwrap(); - assert_eq!(pledge.amount - bonded_free.amount, bonded_vesting.amount); + assert_eq!( + pledge.amount().amount - bonded_free.amount, + bonded_vesting.amount + ); } let bonded_free = account @@ -452,7 +455,7 @@ mod tests { &deps.storage, ) .unwrap(); - assert_eq!(pledge.amount, bonded_free.amount); + assert_eq!(pledge.amount().amount, bonded_free.amount); let bonded_vesting = account .get_pledged_vesting( @@ -523,7 +526,7 @@ mod tests { assert!(err.is_err()); let pledge = account.load_gateway_pledge(&deps.storage).unwrap().unwrap(); - assert_eq!(Uint128::new(500_000_000_000), pledge.amount); + assert_eq!(Uint128::new(500_000_000_000), pledge.amount().amount); // Current period -> block_time: None let bonded_free = account.get_pledged_free(None, &env, &deps.storage).unwrap(); @@ -532,7 +535,10 @@ mod tests { let bonded_vesting = account .get_pledged_vesting(None, &env, &deps.storage) .unwrap(); - assert_eq!(pledge.amount - bonded_free.amount, bonded_vesting.amount); + assert_eq!( + pledge.amount().amount - bonded_free.amount, + bonded_vesting.amount + ); // All periods for (i, period) in account.periods().iter().enumerate() { @@ -544,7 +550,8 @@ mod tests { ) .unwrap(); assert_eq!( - (account.tokens_per_period().unwrap() * i as u128).min(pledge.amount.u128()), + (account.tokens_per_period().unwrap() * i as u128) + .min(pledge.amount().amount.u128()), bonded_free.amount.u128() ); @@ -555,7 +562,10 @@ mod tests { &deps.storage, ) .unwrap(); - assert_eq!(pledge.amount - bonded_free.amount, bonded_vesting.amount); + assert_eq!( + pledge.amount().amount - bonded_free.amount, + bonded_vesting.amount + ); } let bonded_free = account @@ -565,7 +575,7 @@ mod tests { &deps.storage, ) .unwrap(); - assert_eq!(pledge.amount, bonded_free.amount); + assert_eq!(pledge.amount().amount, bonded_free.amount); let bonded_vesting = account .get_pledged_vesting( diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 2f6f0133ce..699363132a 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -2915,6 +2915,7 @@ dependencies = [ "ts-rs", "url", "validator-client", + "vesting-contract-common", "zeroize", ] @@ -5510,6 +5511,7 @@ dependencies = [ "mixnet-contract-common", "schemars", "serde", + "ts-rs", ] [[package]] diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 7063375b8a..a364b1e93b 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -41,6 +41,7 @@ validator-client = { path = "../../common/client-libs/validator-client", feature "nymd-client", ] } mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } +vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config" } coconut-interface = { path = "../../common/coconut-interface" } credentials = { path = "../../common/credentials" } @@ -57,6 +58,10 @@ features = ["ts-rs"] path = "../../common/client-libs/validator-client" features = ["typescript-types"] +[dev-dependencies.vesting-contract-common] +path = "../../common/cosmwasm-smart-contracts/vesting-contract" +features = ["ts-rs"] + [features] default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 2f1328c434..94cc2ec29a 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -34,48 +34,51 @@ fn main() { .invoke_handler(tauri::generate_handler![ mixnet::account::connect_with_mnemonic, mixnet::account::create_new_account, - mixnet::account::switch_network, mixnet::account::get_balance, mixnet::account::logout, + mixnet::account::switch_network, mixnet::admin::get_contract_settings, mixnet::admin::update_contract_settings, mixnet::bond::bond_gateway, mixnet::bond::bond_mixnode, + mixnet::bond::gateway_bond_details, + mixnet::bond::mixnode_bond_details, mixnet::bond::unbond_gateway, mixnet::bond::unbond_mixnode, mixnet::bond::update_mixnode, - mixnet::bond::mixnode_bond_details, - mixnet::bond::gateway_bond_details, mixnet::delegate::delegate_to_mixnode, mixnet::delegate::get_reverse_mix_delegations_paged, mixnet::delegate::undelegate_from_mixnode, mixnet::send::send, - utils::outdated_get_approximate_fee, utils::major_to_minor, utils::minor_to_major, + utils::outdated_get_approximate_fee, utils::owns_gateway, utils::owns_mixnode, + validator_api::status::gateway_core_node_status, + validator_api::status::mixnode_core_node_status, + validator_api::status::mixnode_inclusion_probability, + validator_api::status::mixnode_reward_estimation, + validator_api::status::mixnode_stake_saturation, + validator_api::status::mixnode_status, vesting::bond::vesting_bond_gateway, vesting::bond::vesting_bond_mixnode, vesting::bond::vesting_unbond_gateway, vesting::bond::vesting_unbond_mixnode, vesting::delegate::vesting_delegate_to_mixnode, vesting::delegate::vesting_undelegate_from_mixnode, - vesting::queries::locked_coins, - vesting::queries::spendable_coins, - vesting::queries::vesting_coins, - vesting::queries::vested_coins, - vesting::queries::vesting_start_time, - vesting::queries::vesting_end_time, - vesting::queries::original_vesting, vesting::queries::delegated_free, vesting::queries::delegated_vesting, - validator_api::status::mixnode_core_node_status, - validator_api::status::gateway_core_node_status, - validator_api::status::mixnode_status, - validator_api::status::mixnode_reward_estimation, - validator_api::status::mixnode_stake_saturation, - validator_api::status::mixnode_inclusion_probability, + vesting::queries::get_current_vesting_period, + vesting::queries::locked_coins, + vesting::queries::original_vesting, + vesting::queries::spendable_coins, + vesting::queries::vested_coins, + vesting::queries::vesting_coins, + vesting::queries::vesting_end_time, + vesting::queries::vesting_get_gateway_pledge, + vesting::queries::vesting_get_mixnode_pledge, + vesting::queries::vesting_start_time, ]) .menu(Menu::new().add_default_app_submenu_if_macos()) .run(tauri::generate_context!()) @@ -104,5 +107,8 @@ mod test { validator_client::models::RewardEstimationResponse => "../src/types/rust/rewardestimationresponse.ts", validator_client::models::StakeSaturationResponse => "../src/types/rust/stakesaturaionresponse.ts", validator_client::models::InclusionProbabilityResponse => "../src/types/rust/inclusionprobabilityresponse.ts", + vesting_contract_common::Period => "../src/types/rust/period.ts", + crate::vesting::PledgeData => "../src/types/rust/pledgedata.ts", + crate::vesting::OriginalVestingResponse => "../src/types/rust/originalvestingresponse.ts", } } diff --git a/nym-wallet/src-tauri/src/operations/vesting/mod.rs b/nym-wallet/src-tauri/src/operations/vesting/mod.rs index 361dd44ae6..7abfabf28a 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/mod.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/mod.rs @@ -1,3 +1,48 @@ +use crate::coin::Coin; +use serde::{Deserialize, Serialize}; +use vesting_contract_common::OriginalVestingResponse as VestingOriginalVestingResponse; +use vesting_contract_common::PledgeData as VestingPledgeData; + pub mod bond; pub mod delegate; pub mod queries; + +#[cfg_attr(test, derive(ts_rs::TS))] +#[derive(Serialize, Deserialize, Debug)] +pub struct PledgeData { + pub amount: Coin, + pub block_time: u64, +} + +impl From for PledgeData { + fn from(data: VestingPledgeData) -> Self { + Self { + amount: data.amount().into(), + block_time: data.block_time().seconds(), + } + } +} + +impl PledgeData { + fn and_then(data: VestingPledgeData) -> Option { + Some(data.into()) + } +} + +#[cfg_attr(test, derive(ts_rs::TS))] +#[derive(Serialize, Deserialize, Debug)] +pub struct OriginalVestingResponse { + amount: Coin, + number_of_periods: usize, + period_duration: u64, +} + +impl From for OriginalVestingResponse { + fn from(data: VestingOriginalVestingResponse) -> Self { + Self { + amount: data.amount().into(), + number_of_periods: data.number_of_periods(), + period_duration: data.period_duration(), + } + } +} diff --git a/nym-wallet/src-tauri/src/operations/vesting/queries.rs b/nym-wallet/src-tauri/src/operations/vesting/queries.rs index be6e68d663..bb3d91f1f9 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/queries.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/queries.rs @@ -6,6 +6,9 @@ use cosmwasm_std::Timestamp; use std::sync::Arc; use tokio::sync::RwLock; use validator_client::nymd::VestingQueryClient; +use vesting_contract_common::Period; + +use super::{OriginalVestingResponse, PledgeData}; #[tauri::command] pub async fn locked_coins( @@ -102,7 +105,7 @@ pub async fn vesting_end_time( pub async fn original_vesting( vesting_account_address: &str, state: tauri::State<'_, Arc>>, -) -> Result { +) -> Result { Ok( nymd_client!(state) .original_vesting(vesting_account_address) @@ -144,3 +147,41 @@ pub async fn delegated_vesting( .into(), ) } + +#[tauri::command] +pub async fn vesting_get_mixnode_pledge( + address: &str, + state: tauri::State<'_, Arc>>, +) -> Result, BackendError> { + Ok( + nymd_client!(state) + .get_mixnode_pledge(address) + .await? + .and_then(PledgeData::and_then), + ) +} + +#[tauri::command] +pub async fn vesting_get_gateway_pledge( + address: &str, + state: tauri::State<'_, Arc>>, +) -> Result, BackendError> { + Ok( + nymd_client!(state) + .get_gateway_pledge(address) + .await? + .and_then(PledgeData::and_then), + ) +} + +#[tauri::command] +pub async fn get_current_vesting_period( + address: &str, + state: tauri::State<'_, Arc>>, +) -> Result { + Ok( + nymd_client!(state) + .get_current_vesting_period(address) + .await?, + ) +} diff --git a/nym-wallet/src/types/rust/originalvestingresponse.ts b/nym-wallet/src/types/rust/originalvestingresponse.ts new file mode 100644 index 0000000000..058640ea39 --- /dev/null +++ b/nym-wallet/src/types/rust/originalvestingresponse.ts @@ -0,0 +1,7 @@ +import { Coin } from "./coin"; + +export interface OriginalVestingResponse { + amount: Coin; + number_of_periods: number; + period_duration: bigint; +} \ No newline at end of file diff --git a/nym-wallet/src/types/rust/period.ts b/nym-wallet/src/types/rust/period.ts new file mode 100644 index 0000000000..86a901216f --- /dev/null +++ b/nym-wallet/src/types/rust/period.ts @@ -0,0 +1 @@ +export type Period = "Before" | number | "After"; \ No newline at end of file diff --git a/nym-wallet/src/types/rust/pledgedata.ts b/nym-wallet/src/types/rust/pledgedata.ts new file mode 100644 index 0000000000..6527ebe1cf --- /dev/null +++ b/nym-wallet/src/types/rust/pledgedata.ts @@ -0,0 +1,6 @@ +import { Coin } from "./coin"; + +export interface PledgeData { + amount: Coin; + block_time: bigint; +} \ No newline at end of file