Feature/vesting to wallet (#954)
* Better code structure, proper error handling, VestingSigningClient for wallet * Add vesting contract queries to wallet * Address review comments Co-authored-by: Drazen Urch <durch@users.noreply.guthub.com>
This commit is contained in:
@@ -29,7 +29,3 @@ fmt-contracts:
|
||||
|
||||
fmt-wallet:
|
||||
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -636,7 +636,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
rpc_client: HttpClient,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
|
||||
@@ -52,8 +52,8 @@ pub trait VestingQueryClient {
|
||||
|
||||
async fn delegated_vesting(
|
||||
&self,
|
||||
block_time: Option<Timestamp>,
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<Timestamp>,
|
||||
) -> Result<Coin, NymdError>;
|
||||
}
|
||||
|
||||
@@ -162,8 +162,8 @@ impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NymdClient<C> {
|
||||
|
||||
async fn delegated_vesting(
|
||||
&self,
|
||||
block_time: Option<Timestamp>,
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<Timestamp>,
|
||||
) -> Result<Coin, NymdError> {
|
||||
let request = VestingQueryMsg::GetDelegatedVesting {
|
||||
vesting_account_address: vesting_account_address.to_string(),
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::nymd::fee::helpers::Operation;
|
||||
use crate::nymd::{cosmwasm_coin_to_cosmos_coin, NymdClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::Coin;
|
||||
use mixnet_contract::{Gateway, IdentityKey, MixNode};
|
||||
use mixnet_contract::{Gateway, IdentityKey, IdentityKeyRef, MixNode};
|
||||
use vesting_contract::messages::ExecuteMsg as VestingExecuteMsg;
|
||||
|
||||
#[async_trait]
|
||||
@@ -16,8 +16,8 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_bond_gateway(
|
||||
&self,
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_unbond_gateway(&self) -> Result<ExecuteResult, NymdError>;
|
||||
@@ -31,8 +31,8 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
async fn vesting_unbond_mixnode(&self) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
@@ -51,15 +51,15 @@ pub trait VestingSigningClient {
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_delegate_to_mixnode(
|
||||
async fn vesting_delegate_to_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
amount: Coin,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
amount: &Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_undelegate_from_mixnode(
|
||||
async fn vesting_undelegate_from_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn create_periodic_vesting_account(
|
||||
@@ -75,8 +75,8 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
async fn vesting_bond_gateway(
|
||||
&self,
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.operation_fee(Operation::BondGateway);
|
||||
let req = VestingExecuteMsg::BondGateway {
|
||||
@@ -135,8 +135,8 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
async fn vesting_bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.operation_fee(Operation::BondMixnode);
|
||||
let req = VestingExecuteMsg::BondMixnode {
|
||||
@@ -230,13 +230,15 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
)
|
||||
.await
|
||||
}
|
||||
async fn vesting_delegate_to_mixnode(
|
||||
async fn vesting_delegate_to_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
amount: Coin,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
amount: &Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.operation_fee(Operation::DelegateToMixnode);
|
||||
let req = VestingExecuteMsg::DelegateToMixnode { mix_identity };
|
||||
let req = VestingExecuteMsg::DelegateToMixnode {
|
||||
mix_identity: mix_identity.into(),
|
||||
};
|
||||
self.client
|
||||
.execute(
|
||||
self.address(),
|
||||
@@ -244,16 +246,18 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
&req,
|
||||
fee,
|
||||
"VestingContract::DeledateToMixnode",
|
||||
vec![cosmwasm_coin_to_cosmos_coin(amount)],
|
||||
vec![cosmwasm_coin_to_cosmos_coin(amount.to_owned())],
|
||||
)
|
||||
.await
|
||||
}
|
||||
async fn vesting_undelegate_from_mixnode(
|
||||
async fn vesting_undelegate_from_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.operation_fee(Operation::UndelegateFromMixnode);
|
||||
let req = VestingExecuteMsg::UndelegateFromMixnode { mix_identity };
|
||||
let req = VestingExecuteMsg::UndelegateFromMixnode {
|
||||
mix_identity: mix_identity.into(),
|
||||
};
|
||||
self.client
|
||||
.execute(
|
||||
self.address(),
|
||||
|
||||
@@ -10,7 +10,7 @@ use cosmrs::tx::SignDoc;
|
||||
use cosmrs::{tx, AccountId};
|
||||
|
||||
/// Derivation information required to derive a keypair and an address from a mnemonic.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct Secp256k1Derivation {
|
||||
hd_path: DerivationPath,
|
||||
prefix: String,
|
||||
@@ -40,7 +40,7 @@ impl AccountData {
|
||||
|
||||
type Secp256k1Keypair = (SigningKey, PublicKey);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DirectSecp256k1HdWallet {
|
||||
/// Base secret
|
||||
secret: bip39::Mnemonic,
|
||||
|
||||
Generated
+1
@@ -2709,6 +2709,7 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"credentials",
|
||||
"dirs",
|
||||
"eyre",
|
||||
"mixnet-contract",
|
||||
"rand 0.6.5",
|
||||
"serde",
|
||||
|
||||
@@ -26,6 +26,7 @@ thiserror = "1.0"
|
||||
tendermint-rpc = "0.23.0"
|
||||
url = "2.0"
|
||||
rand = "0.6.5"
|
||||
eyre = "0.6.5"
|
||||
|
||||
|
||||
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev="e5a1872083abb3d88fa62dda966e7f5408deba58", features = ["rpc", "bip32", "cosmwasm"] }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// This should be moved out of the wallet, and used as a primary coin type throughout the codebase
|
||||
|
||||
use crate::error::BackendError;
|
||||
use ::config::defaults::DENOM;
|
||||
use cosmrs::Decimal;
|
||||
use cosmrs::Denom as CosmosDenom;
|
||||
@@ -12,8 +13,6 @@ use std::ops::{Add, Sub};
|
||||
use std::str::FromStr;
|
||||
use validator_client::nymd::{CosmosCoin, GasPrice};
|
||||
|
||||
use crate::format_err;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub enum Denom {
|
||||
@@ -33,19 +32,16 @@ impl fmt::Display for Denom {
|
||||
}
|
||||
|
||||
impl FromStr for Denom {
|
||||
type Err = String;
|
||||
type Err = BackendError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Denom, String> {
|
||||
fn from_str(s: &str) -> Result<Denom, BackendError> {
|
||||
let s = s.to_lowercase();
|
||||
if s == DENOM.to_lowercase() || s == "minor" {
|
||||
Ok(Denom::Minor)
|
||||
} else if s == DENOM[1..].to_lowercase() || s == "major" {
|
||||
Ok(Denom::Major)
|
||||
} else {
|
||||
Err(format_err!(format!(
|
||||
"{} is not a valid denomination string",
|
||||
s
|
||||
)))
|
||||
Err(BackendError::InvalidDenom(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,9 +165,9 @@ impl Coin {
|
||||
}
|
||||
|
||||
impl TryFrom<Coin> for CosmWasmCoin {
|
||||
type Error = String;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(coin: Coin) -> Result<CosmWasmCoin, String> {
|
||||
fn try_from(coin: Coin) -> Result<CosmWasmCoin, Self::Error> {
|
||||
Ok(CosmWasmCoin::new(
|
||||
Uint128::try_from(coin.amount.as_str()).unwrap().u128(),
|
||||
coin.denom.to_string(),
|
||||
@@ -180,15 +176,15 @@ impl TryFrom<Coin> for CosmWasmCoin {
|
||||
}
|
||||
|
||||
impl TryFrom<Coin> for CosmosCoin {
|
||||
type Error = String;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(coin: Coin) -> Result<CosmosCoin, String> {
|
||||
fn try_from(coin: Coin) -> Result<CosmosCoin, BackendError> {
|
||||
match Decimal::from_str(&coin.amount) {
|
||||
Ok(d) => Ok(CosmosCoin {
|
||||
amount: d,
|
||||
denom: CosmosDenom::from_str(&coin.denom.to_string()).unwrap(),
|
||||
denom: CosmosDenom::from_str(&coin.denom.to_string())?,
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,47 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
use thiserror::Error;
|
||||
use validator_client::nymd::error::NymdError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BackendError {
|
||||
#[error("Error parsing bip39 mnemonic")]
|
||||
#[error("{source}")]
|
||||
Bip39Error {
|
||||
#[from]
|
||||
source: bip39::Error,
|
||||
},
|
||||
#[error("Error parsing into tendermint Url")]
|
||||
#[error("{source}")]
|
||||
TendermintError {
|
||||
#[from]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
#[error("Error getting balances")]
|
||||
#[error("{source}")]
|
||||
NymdError {
|
||||
#[from]
|
||||
source: NymdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
CosmwasmStd {
|
||||
#[from]
|
||||
source: cosmwasm_std::StdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ErrorReport {
|
||||
#[from]
|
||||
source: eyre::Report,
|
||||
},
|
||||
#[error("Client has not been initialized yet, connect with mnemonic to initialize")]
|
||||
ClientNotInitialized,
|
||||
#[error("No balance available for address {0}")]
|
||||
NoBalance(String),
|
||||
#[error("{0} is not a valid denomination string")]
|
||||
InvalidDenom(String),
|
||||
}
|
||||
|
||||
impl Serialize for BackendError {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,47 +18,48 @@ mod state;
|
||||
mod utils;
|
||||
|
||||
use crate::menu::AddDefaultSubmenus;
|
||||
use crate::operations::account::*;
|
||||
use crate::operations::admin::*;
|
||||
use crate::operations::bond::*;
|
||||
use crate::operations::delegate::*;
|
||||
use crate::operations::send::*;
|
||||
use crate::utils::*;
|
||||
use crate::operations::mixnet;
|
||||
use crate::operations::vesting;
|
||||
|
||||
use crate::state::State;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::coin::{Coin, Denom};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! format_err {
|
||||
($e:expr) => {
|
||||
format!("line {}: {}", line!(), $e)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(RwLock::new(State::default())))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
connect_with_mnemonic,
|
||||
get_balance,
|
||||
minor_to_major,
|
||||
major_to_minor,
|
||||
owns_gateway,
|
||||
owns_mixnode,
|
||||
bond_mixnode,
|
||||
unbond_mixnode,
|
||||
bond_gateway,
|
||||
unbond_gateway,
|
||||
delegate_to_mixnode,
|
||||
undelegate_from_mixnode,
|
||||
send,
|
||||
create_new_account,
|
||||
get_approximate_fee,
|
||||
get_contract_settings,
|
||||
update_contract_settings,
|
||||
get_reverse_mix_delegations_paged,
|
||||
mixnet::account::connect_with_mnemonic,
|
||||
mixnet::account::create_new_account,
|
||||
mixnet::account::get_balance,
|
||||
mixnet::admin::get_contract_settings,
|
||||
mixnet::admin::update_contract_settings,
|
||||
mixnet::bond::bond_gateway,
|
||||
mixnet::bond::bond_mixnode,
|
||||
mixnet::bond::unbond_gateway,
|
||||
mixnet::bond::unbond_mixnode,
|
||||
mixnet::delegate::delegate_to_mixnode,
|
||||
mixnet::delegate::get_reverse_mix_delegations_paged,
|
||||
mixnet::delegate::undelegate_from_mixnode,
|
||||
mixnet::send::send,
|
||||
utils::get_approximate_fee,
|
||||
utils::major_to_minor,
|
||||
utils::minor_to_major,
|
||||
utils::owns_gateway,
|
||||
utils::owns_mixnode,
|
||||
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,
|
||||
])
|
||||
.menu(Menu::new().add_default_app_submenu_if_macos())
|
||||
.run(tauri::generate_context!())
|
||||
@@ -69,15 +70,15 @@ fn main() {
|
||||
mod test {
|
||||
ts_rs::export! {
|
||||
mixnet_contract::MixNode => "../src/types/rust/mixnode.ts",
|
||||
crate::Coin => "../src/types/rust/coin.ts",
|
||||
crate::Balance => "../src/types/rust/balance.ts",
|
||||
crate::coin::Coin => "../src/types/rust/coin.ts",
|
||||
crate::mixnet::account::Balance => "../src/types/rust/balance.ts",
|
||||
mixnet_contract::Gateway => "../src/types/rust/gateway.ts",
|
||||
crate::TauriTxResult => "../src/types/rust/tauritxresult.ts",
|
||||
crate::TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
||||
crate::mixnet::send::TauriTxResult => "../src/types/rust/tauritxresult.ts",
|
||||
crate::mixnet::send::TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
||||
validator_client::nymd::fee::helpers::Operation => "../src/types/rust/operation.ts",
|
||||
crate::Denom => "../src/types/rust/denom.ts",
|
||||
crate::DelegationResult => "../src/types/rust/delegationresult.ts",
|
||||
crate::Account => "../src/types/rust/account.ts",
|
||||
crate::TauriContractStateParams => "../src/types/rust/stateparams.ts"
|
||||
crate::coin::Denom => "../src/types/rust/denom.ts",
|
||||
crate::utils::DelegationResult => "../src/types/rust/delegationresult.ts",
|
||||
crate::mixnet::account::Account => "../src/types/rust/account.ts",
|
||||
crate::mixnet::admin::TauriContractStateParams => "../src/types/rust/stateparams.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let pledge: CosmWasmCoin = match pledge.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.bond_gateway(gateway, owner_signature, pledge).await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.unbond_gateway().await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.unbond_mixnode().await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let pledge: CosmWasmCoin = match pledge.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.bond_mixnode(mixnode, owner_signature, pledge).await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use mixnet_contract::PagedDelegatorDelegationsResponse;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct DelegationResult {
|
||||
source_address: String,
|
||||
target_address: String,
|
||||
amount: Option<Coin>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, String> {
|
||||
let r_state = state.read().await;
|
||||
let delegation: CosmWasmCoin = match amount.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.delegate_to_mixnode(identity, &delegation).await {
|
||||
Ok(_result) => Ok(DelegationResult {
|
||||
source_address: client.address().to_string(),
|
||||
target_address: identity.to_string(),
|
||||
amount: Some(delegation.into()),
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.remove_mixnode_delegation(identity).await {
|
||||
Ok(_result) => Ok(DelegationResult {
|
||||
source_address: client.address().to_string(),
|
||||
target_address: identity.to_string(),
|
||||
amount: None,
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_reverse_mix_delegations_paged(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
client
|
||||
.get_delegator_delegations_paged(client.address().to_string(), None, None)
|
||||
.await
|
||||
.map_err(|err| format_err!(err))
|
||||
}
|
||||
+16
-27
@@ -1,7 +1,7 @@
|
||||
use crate::client;
|
||||
use crate::coin::{Coin, Denom};
|
||||
use crate::config::Config;
|
||||
use crate::error::BackendError;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use bip39::{Language, Mnemonic};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -30,26 +30,16 @@ pub struct Balance {
|
||||
pub async fn connect_with_mnemonic(
|
||||
mnemonic: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Account, String> {
|
||||
let mnemonic = match Mnemonic::from_str(&mnemonic) {
|
||||
Ok(mnemonic) => mnemonic,
|
||||
Err(e) => return Err(BackendError::from(e).to_string()),
|
||||
};
|
||||
let client;
|
||||
{
|
||||
) -> Result<Account, BackendError> {
|
||||
let mnemonic = Mnemonic::from_str(&mnemonic)?;
|
||||
let client = {
|
||||
let r_state = state.read().await;
|
||||
client = _connect_with_mnemonic(mnemonic, &r_state.config());
|
||||
}
|
||||
_connect_with_mnemonic(mnemonic, &r_state.config())
|
||||
};
|
||||
|
||||
let contract_address = match client.mixnet_contract_address() {
|
||||
Ok(address) => address.to_string(),
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let contract_address = client.mixnet_contract_address()?.to_string();
|
||||
let client_address = client.address().to_string();
|
||||
let denom = match client.denom() {
|
||||
Ok(denom) => denom,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let denom = client.denom()?;
|
||||
|
||||
let account = Account {
|
||||
contract_address,
|
||||
@@ -65,10 +55,10 @@ pub async fn connect_with_mnemonic(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_balance(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<Balance, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.get_balance(client.address()).await {
|
||||
pub async fn get_balance(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Balance, BackendError> {
|
||||
match client!(state).get_balance(client!(state).address()).await {
|
||||
Ok(Some(coin)) => {
|
||||
let coin = Coin::new(
|
||||
&coin.amount.to_string(),
|
||||
@@ -79,18 +69,17 @@ pub async fn get_balance(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<
|
||||
printable_balance: coin.to_major().to_string(),
|
||||
})
|
||||
}
|
||||
Ok(None) => Err(format!(
|
||||
"No balance available for address {}",
|
||||
client.address()
|
||||
Ok(None) => Err(BackendError::NoBalance(
|
||||
client!(state).address().to_string(),
|
||||
)),
|
||||
Err(e) => Err(BackendError::from(e).to_string()),
|
||||
Err(e) => Err(BackendError::from(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_new_account(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Account, String> {
|
||||
) -> Result<Account, BackendError> {
|
||||
let rand_mnemonic = random_mnemonic();
|
||||
let mut client = connect_with_mnemonic(rand_mnemonic.to_string(), state).await?;
|
||||
client.mnemonic = Some(rand_mnemonic.to_string());
|
||||
+10
-22
@@ -1,4 +1,5 @@
|
||||
use crate::format_err;
|
||||
use crate::client;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Uint128;
|
||||
use mixnet_contract::ContractStateParams;
|
||||
@@ -30,7 +31,7 @@ impl From<ContractStateParams> for TauriContractStateParams {
|
||||
}
|
||||
|
||||
impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(p: TauriContractStateParams) -> Result<ContractStateParams, Self::Error> {
|
||||
Ok(ContractStateParams {
|
||||
@@ -46,31 +47,18 @@ impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
#[tauri::command]
|
||||
pub async fn get_contract_settings(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriContractStateParams, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.get_contract_settings().await {
|
||||
Ok(params) => Ok(params.into()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
Ok(client!(state).get_contract_settings().await?.into())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_contract_settings(
|
||||
params: TauriContractStateParams,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriContractStateParams, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
let mixnet_contract_settings_params: ContractStateParams = match params.try_into() {
|
||||
Ok(mixnet_contract_settings_params) => mixnet_contract_settings_params,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
match client
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
|
||||
client!(state)
|
||||
.update_contract_settings(mixnet_contract_settings_params.clone())
|
||||
.await
|
||||
{
|
||||
Ok(_) => Ok(mixnet_contract_settings_params.into()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
.await?;
|
||||
Ok(mixnet_contract_settings_params.into())
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.bond_gateway(gateway, owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).unbond_gateway().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).unbond_mixnode().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.bond_mixnode(mixnode, owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationResult;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use mixnet_contract::PagedDelegatorDelegationsResponse;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation: CosmWasmCoin = amount.try_into()?;
|
||||
client!(state)
|
||||
.delegate_to_mixnode(identity, &delegation)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
client!(state).remove_mixnode_delegation(identity).await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_reverse_mix_delegations_paged(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.get_delegator_delegations_paged(client!(state).address().to_string(), None, None)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
pub mod account;
|
||||
pub mod admin;
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod send;
|
||||
+16
-23
@@ -1,5 +1,6 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
@@ -47,26 +48,18 @@ pub async fn send(
|
||||
amount: Coin,
|
||||
memo: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriTxResult, String> {
|
||||
let address = match AccountId::from_str(address) {
|
||||
Ok(addy) => addy,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let cosmos_amount: CosmosCoin = match amount.clone().try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.send(&address, vec![cosmos_amount], memo).await {
|
||||
Ok(result) => Ok(TauriTxResult::new(
|
||||
result,
|
||||
TransactionDetails {
|
||||
from_address: client.address().to_string(),
|
||||
to_address: address.to_string(),
|
||||
amount,
|
||||
},
|
||||
)),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
) -> Result<TauriTxResult, BackendError> {
|
||||
let address = AccountId::from_str(address)?;
|
||||
let cosmos_amount: CosmosCoin = amount.clone().try_into()?;
|
||||
let result = client!(state)
|
||||
.send(&address, vec![cosmos_amount], memo)
|
||||
.await?;
|
||||
Ok(TauriTxResult::new(
|
||||
result,
|
||||
TransactionDetails {
|
||||
from_address: client!(state).address().to_string(),
|
||||
to_address: address.to_string(),
|
||||
amount,
|
||||
},
|
||||
))
|
||||
}
|
||||
@@ -1,5 +1,2 @@
|
||||
pub mod account;
|
||||
pub mod admin;
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod send;
|
||||
pub mod mixnet;
|
||||
pub mod vesting;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingSigningClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.vesting_bond_gateway(gateway, &owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).vesting_unbond_gateway().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).vesting_unbond_mixnode().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.vesting_bond_mixnode(mixnode, &owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationResult;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingSigningClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation: CosmWasmCoin = amount.try_into()?;
|
||||
client!(state)
|
||||
.vesting_delegate_to_mixnode(identity, &delegation)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
client!(state)
|
||||
.vesting_undelegate_from_mixnode(identity)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod queries;
|
||||
@@ -0,0 +1,146 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Timestamp;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingQueryClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn locked_coins(
|
||||
address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.locked_coins(address, block_time.map(Timestamp::from_seconds))
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn spendable_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.spendable_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vested_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vested_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_start_time(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<u64, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_start_time(vesting_account_address)
|
||||
.await?
|
||||
.seconds(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_end_time(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<u64, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_end_time(vesting_account_address)
|
||||
.await?
|
||||
.seconds(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn original_vesting(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.original_vesting(vesting_account_address)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegated_free(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.delegated_free(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegated_vesting(
|
||||
block_time: Option<u64>,
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.delegated_vesting(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::config::Config;
|
||||
use crate::error::BackendError;
|
||||
use validator_client::nymd::{NymdClient, SigningNymdClient};
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -8,10 +9,11 @@ pub struct State {
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn client(&self) -> Result<&NymdClient<SigningNymdClient>, String> {
|
||||
self.signing_client.as_ref().ok_or_else(|| {
|
||||
"Client has not been initialized yet, connect with mnemonic to initialize".to_string()
|
||||
})
|
||||
pub fn client(&self) -> Result<&NymdClient<SigningNymdClient>, BackendError> {
|
||||
self
|
||||
.signing_client
|
||||
.as_ref()
|
||||
.ok_or(BackendError::ClientNotInitialized)
|
||||
}
|
||||
|
||||
pub fn config(&self) -> Config {
|
||||
@@ -22,3 +24,10 @@ impl State {
|
||||
self.signing_client = Some(signing_client)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! client {
|
||||
($state:ident) => {
|
||||
$state.read().await.client()?
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
use crate::client;
|
||||
use crate::coin::{Coin, Denom};
|
||||
use crate::format_err;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::Operation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn major_to_minor(amount: &str) -> Result<Coin, String> {
|
||||
pub fn major_to_minor(amount: &str) -> Coin {
|
||||
let coin = Coin::new(amount, &Denom::Major);
|
||||
Ok(coin.to_minor())
|
||||
coin.to_minor()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn minor_to_major(amount: &str) -> Result<Coin, String> {
|
||||
pub fn minor_to_major(amount: &str) -> Coin {
|
||||
let coin = Coin::new(amount, &Denom::Minor);
|
||||
Ok(coin.to_major())
|
||||
coin.to_major()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn owns_mixnode(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<bool, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.owns_mixnode(client.address()).await {
|
||||
Ok(o) => Ok(o.is_some()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
pub async fn owns_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<bool, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.owns_mixnode(client!(state).address())
|
||||
.await?
|
||||
.is_some(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn owns_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<bool, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.owns_gateway(client.address()).await {
|
||||
Ok(o) => Ok(o.is_some()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
pub async fn owns_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<bool, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.owns_gateway(client!(state).address())
|
||||
.await?
|
||||
.is_some(),
|
||||
)
|
||||
}
|
||||
|
||||
// NOTE: this uses OUTDATED defaults that might have no resemblance with the reality
|
||||
@@ -43,14 +49,29 @@ pub async fn owns_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result
|
||||
pub async fn get_approximate_fee(
|
||||
operation: Operation,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
let approximate_fee = operation.default_fee(client.gas_price());
|
||||
) -> Result<Coin, BackendError> {
|
||||
let approximate_fee = operation.default_fee(client!(state).gas_price());
|
||||
let mut coin = Coin::new("0", &Denom::Major);
|
||||
for f in approximate_fee.amount {
|
||||
coin = coin + f.into();
|
||||
}
|
||||
|
||||
Ok(coin)
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct DelegationResult {
|
||||
source_address: String,
|
||||
target_address: String,
|
||||
amount: Option<Coin>,
|
||||
}
|
||||
|
||||
impl DelegationResult {
|
||||
pub fn new(source_address: &str, target_address: &str, amount: Option<Coin>) -> DelegationResult {
|
||||
DelegationResult {
|
||||
source_address: source_address.to_string(),
|
||||
target_address: target_address.to_string(),
|
||||
amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user