Admin functions, reorganize code
This commit is contained in:
@@ -11,7 +11,7 @@ use std::fmt;
|
|||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
use validator_client::nymd::{GasPrice, CosmosCoin};
|
use validator_client::nymd::{CosmosCoin, GasPrice};
|
||||||
|
|
||||||
use crate::format_err;
|
use crate::format_err;
|
||||||
|
|
||||||
@@ -96,25 +96,25 @@ impl Add for Coin {
|
|||||||
|
|
||||||
// Allows adding minor and major denominations, output will have the LHS denom.
|
// Allows adding minor and major denominations, output will have the LHS denom.
|
||||||
impl Sub for Coin {
|
impl Sub for Coin {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn sub(self, rhs: Self) -> Self {
|
fn sub(self, rhs: Self) -> Self {
|
||||||
let denom = self.denom.clone();
|
let denom = self.denom.clone();
|
||||||
let lhs = self.to_minor();
|
let lhs = self.to_minor();
|
||||||
let rhs = rhs.to_minor();
|
let rhs = rhs.to_minor();
|
||||||
let lhs_amount = lhs.amount.parse::<i64>().unwrap();
|
let lhs_amount = lhs.amount.parse::<i64>().unwrap();
|
||||||
let rhs_amount = rhs.amount.parse::<i64>().unwrap();
|
let rhs_amount = rhs.amount.parse::<i64>().unwrap();
|
||||||
let amount = lhs_amount - rhs_amount;
|
let amount = lhs_amount - rhs_amount;
|
||||||
let coin = Coin {
|
let coin = Coin {
|
||||||
amount: amount.to_string(),
|
amount: amount.to_string(),
|
||||||
denom: Denom::Minor,
|
denom: Denom::Minor,
|
||||||
};
|
};
|
||||||
match denom {
|
match denom {
|
||||||
Denom::Major => coin.to_major(),
|
Denom::Major => coin.to_major(),
|
||||||
Denom::Minor => coin,
|
Denom::Minor => coin,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Coin {
|
impl Coin {
|
||||||
pub fn major<T: ToString>(amount: T) -> Coin {
|
pub fn major<T: ToString>(amount: T) -> Coin {
|
||||||
@@ -212,7 +212,7 @@ impl From<CosmWasmCoin> for Coin {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{Coin, Denom};
|
use crate::coin::{Coin, Denom};
|
||||||
use cosmrs::Coin as CosmosCoin;
|
use cosmrs::Coin as CosmosCoin;
|
||||||
use cosmrs::Decimal;
|
use cosmrs::Decimal;
|
||||||
use cosmrs::Denom as CosmosDenom;
|
use cosmrs::Denom as CosmosDenom;
|
||||||
@@ -273,7 +273,7 @@ mod test {
|
|||||||
"1000000000000000",
|
"1000000000000000",
|
||||||
"10000000000000000",
|
"10000000000000000",
|
||||||
"100000000000000000",
|
"100000000000000000",
|
||||||
"1000000000000000000"
|
"1000000000000000000",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,10 +333,10 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add() {
|
fn test_add() {
|
||||||
assert_eq!(Coin::minor("1") + Coin::minor("1"), Coin::minor("2"));
|
assert_eq!(Coin::minor("1") + Coin::minor("1"), Coin::minor("2"));
|
||||||
assert_eq!(Coin::major("1") + Coin::major("1"), Coin::major("2"));
|
assert_eq!(Coin::major("1") + Coin::major("1"), Coin::major("2"));
|
||||||
assert_eq!(Coin::minor("1") + Coin::major("1"), Coin::minor("1000001"));
|
assert_eq!(Coin::minor("1") + Coin::major("1"), Coin::minor("1000001"));
|
||||||
assert_eq!(Coin::major("1") + Coin::minor("1"), Coin::major("1.000001"));
|
assert_eq!(Coin::major("1") + Coin::minor("1"), Coin::major("1.000001"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -345,5 +345,5 @@ mod test {
|
|||||||
assert_eq!(Coin::major("1") - Coin::major("1"), Coin::major("0"));
|
assert_eq!(Coin::major("1") - Coin::major("1"), Coin::major("0"));
|
||||||
assert_eq!(Coin::minor("1") - Coin::major("1"), Coin::minor("-999999"));
|
assert_eq!(Coin::minor("1") - Coin::major("1"), Coin::minor("-999999"));
|
||||||
assert_eq!(Coin::major("1") - Coin::minor("1"), Coin::major("0.999999"));
|
assert_eq!(Coin::major("1") - Coin::minor("1"), Coin::major("0.999999"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,30 @@
|
|||||||
windows_subsystem = "windows"
|
windows_subsystem = "windows"
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use bip39::{Language, Mnemonic};
|
|
||||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
|
||||||
use error::BackendError;
|
|
||||||
use mixnet_contract::{Gateway, MixNode};
|
use mixnet_contract::{Gateway, MixNode};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tendermint_rpc::endpoint::broadcast::tx_commit::Response;
|
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use ts_rs::{export, TS};
|
use ts_rs::export;
|
||||||
use validator_client::nymd::fee_helpers::Operation;
|
use validator_client::nymd::fee_helpers::Operation;
|
||||||
use validator_client::nymd::{NymdClient, SigningNymdClient, AccountId, CosmosCoin};
|
|
||||||
|
|
||||||
mod coin;
|
mod coin;
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod operations;
|
||||||
mod state;
|
mod state;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
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::state::State;
|
use crate::state::State;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
use crate::coin::{Coin, Denom};
|
use crate::coin::{Coin, Denom};
|
||||||
use crate::config::Config;
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! format_err {
|
macro_rules! format_err {
|
||||||
@@ -35,346 +35,6 @@ macro_rules! format_err {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(TS, Serialize, Deserialize)]
|
|
||||||
struct DelegationResult {
|
|
||||||
source_address: String,
|
|
||||||
target_address: String,
|
|
||||||
amount: Option<Coin>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(TS, Serialize, Deserialize)]
|
|
||||||
struct Balance {
|
|
||||||
coin: Coin,
|
|
||||||
printable_balance: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, TS)]
|
|
||||||
struct TauriTxResult {
|
|
||||||
code: u32,
|
|
||||||
gas_wanted: u64,
|
|
||||||
gas_used: u64,
|
|
||||||
block_height: u64,
|
|
||||||
details: TransactionDetails,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, TS)]
|
|
||||||
struct TransactionDetails {
|
|
||||||
from_address: String,
|
|
||||||
to_address: String,
|
|
||||||
amount: Coin,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TauriTxResult {
|
|
||||||
fn new(t: Response, details: TransactionDetails) -> TauriTxResult {
|
|
||||||
TauriTxResult {
|
|
||||||
code: t.check_tx.code.value(),
|
|
||||||
gas_wanted: t.check_tx.gas_wanted.value(),
|
|
||||||
gas_used: t.check_tx.gas_used.value(),
|
|
||||||
block_height: t.height.value(),
|
|
||||||
details,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO these should be more explicit
|
|
||||||
#[tauri::command]
|
|
||||||
fn major_to_minor(amount: &str) -> Result<Coin, String> {
|
|
||||||
let coin = Coin::new(amount, &Denom::Major);
|
|
||||||
Ok(coin.to_minor())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
fn minor_to_major(amount: &str) -> Result<Coin, String> {
|
|
||||||
let coin = Coin::new(amount, &Denom::Minor);
|
|
||||||
Ok(coin.to_major())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn connect_with_mnemonic(
|
|
||||||
mnemonic: String,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<HashMap<&str, String>, String> {
|
|
||||||
let mnemonic = match Mnemonic::from_str(&mnemonic) {
|
|
||||||
Ok(mnemonic) => mnemonic,
|
|
||||||
Err(e) => return Err(BackendError::from(e).to_string()),
|
|
||||||
};
|
|
||||||
let client;
|
|
||||||
{
|
|
||||||
let r_state = state.read().await;
|
|
||||||
client = _connect_with_mnemonic(mnemonic, &r_state.config());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ret = HashMap::new();
|
|
||||||
ret.insert(
|
|
||||||
"contract_address",
|
|
||||||
match client.contract_address() {
|
|
||||||
Ok(address) => address.to_string(),
|
|
||||||
Err(e) => format_err!(e),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
ret.insert("client_address", client.address().to_string());
|
|
||||||
ret.insert(
|
|
||||||
"denom",
|
|
||||||
match client.denom() {
|
|
||||||
Ok(denom) => denom.to_string(),
|
|
||||||
Err(e) => format_err!(e),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let mut w_state = state.write().await;
|
|
||||||
w_state.set_client(client);
|
|
||||||
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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 {
|
|
||||||
Ok(Some(coin)) => {
|
|
||||||
let coin = Coin::new(
|
|
||||||
&coin.amount.to_string(),
|
|
||||||
&Denom::from_str(&coin.denom.to_string())?,
|
|
||||||
);
|
|
||||||
Ok(Balance {
|
|
||||||
coin: coin.clone(),
|
|
||||||
printable_balance: coin.to_major().to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Ok(None) => Err(format!(
|
|
||||||
"No balance available for address {}",
|
|
||||||
client.address()
|
|
||||||
)),
|
|
||||||
Err(e) => Err(BackendError::from(e).to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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]
|
|
||||||
async fn bond_mixnode(
|
|
||||||
mixnode: MixNode,
|
|
||||||
bond: Coin,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let r_state = state.read().await;
|
|
||||||
let bond: CosmWasmCoin = match bond.try_into() {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => return Err(format_err!(e)),
|
|
||||||
};
|
|
||||||
let client = r_state.client()?;
|
|
||||||
match client.bond_mixnode(mixnode, bond).await {
|
|
||||||
Ok(_result) => Ok(()),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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 bond: 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, &bond).await {
|
|
||||||
Ok(_result) => Ok(DelegationResult {
|
|
||||||
source_address: client.address().to_string(),
|
|
||||||
target_address: identity.to_string(),
|
|
||||||
amount: Some(bond.into()),
|
|
||||||
}),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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]
|
|
||||||
async fn delegate_to_gateway(
|
|
||||||
identity: &str,
|
|
||||||
amount: Coin,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<DelegationResult, String> {
|
|
||||||
let r_state = state.read().await;
|
|
||||||
let bond: CosmWasmCoin = match amount.try_into() {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => return Err(format_err!(e)),
|
|
||||||
};
|
|
||||||
let client = r_state.client()?;
|
|
||||||
match client.delegate_to_gateway(identity, &bond).await {
|
|
||||||
Ok(_result) => Ok(DelegationResult {
|
|
||||||
source_address: client.address().to_string(),
|
|
||||||
target_address: identity.to_string(),
|
|
||||||
amount: Some(bond.into()),
|
|
||||||
}),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn undelegate_from_gateway(
|
|
||||||
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_gateway_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]
|
|
||||||
async fn bond_gateway(
|
|
||||||
gateway: Gateway,
|
|
||||||
bond: Coin,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let r_state = state.read().await;
|
|
||||||
let bond: CosmWasmCoin = match bond.try_into() {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => return Err(format_err!(e)),
|
|
||||||
};
|
|
||||||
let client = r_state.client()?;
|
|
||||||
match client.bond_gateway(gateway, bond).await {
|
|
||||||
Ok(_result) => Ok(()),
|
|
||||||
Err(e) => Err(format_err!(e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
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]
|
|
||||||
async fn send(
|
|
||||||
address: &str,
|
|
||||||
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)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn get_fee(
|
|
||||||
operation: Operation,
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<Coin, String> {
|
|
||||||
let r_state = state.read().await;
|
|
||||||
let client = r_state.client()?;
|
|
||||||
let fee = client.get_fee(operation);
|
|
||||||
let mut coin = Coin::new("0", &Denom::Major);
|
|
||||||
for f in fee.amount {
|
|
||||||
coin = coin + f.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(coin)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn create_new_account(
|
|
||||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
|
||||||
) -> Result<HashMap<&str, String>, String> {
|
|
||||||
let mnemonic = random_mnemonic();
|
|
||||||
let mut client = connect_with_mnemonic(mnemonic.to_string(), state).await?;
|
|
||||||
client.insert("mnemonic", mnemonic.to_string());
|
|
||||||
Ok(client)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random_mnemonic() -> Mnemonic {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> NymdClient<SigningNymdClient> {
|
|
||||||
match NymdClient::connect_with_mnemonic(
|
|
||||||
config.get_nymd_validator_url().unwrap(),
|
|
||||||
Some(AccountId::from_str(&config.get_mixnet_contract_address()).unwrap()),
|
|
||||||
mnemonic,
|
|
||||||
) {
|
|
||||||
Ok(client) => client,
|
|
||||||
Err(e) => panic!("{}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.manage(Arc::new(RwLock::new(State::default())))
|
.manage(Arc::new(RwLock::new(State::default())))
|
||||||
@@ -395,7 +55,9 @@ fn main() {
|
|||||||
undelegate_from_gateway,
|
undelegate_from_gateway,
|
||||||
send,
|
send,
|
||||||
create_new_account,
|
create_new_account,
|
||||||
get_fee
|
get_fee,
|
||||||
|
get_state_params,
|
||||||
|
update_state_params
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
@@ -410,5 +72,7 @@ export! {
|
|||||||
TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
||||||
Operation => "../src/types/rust/operation.ts",
|
Operation => "../src/types/rust/operation.ts",
|
||||||
Denom => "../src/types/rust/denom.ts",
|
Denom => "../src/types/rust/denom.ts",
|
||||||
DelegationResult => "../src/types/rust/delegationresult.ts"
|
DelegationResult => "../src/types/rust/delegationresult.ts",
|
||||||
|
Account => "../src/types/rust/account.ts",
|
||||||
|
TauriStateParams => "../src/types/rust/stateparams.ts"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
use config::defaults::DEFAULT_VALIDATOR_API_PORT;
|
|
||||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
use validator_client::nymd::{CosmWasmClient, QueryNymdClient, SigningNymdClient, NymdClient};
|
|
||||||
use validator_client::ValidatorClientError;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub(crate) struct Client<C>(Arc<RwLock<validator_client::Client<C>>>);
|
|
||||||
|
|
||||||
impl Client<QueryNymdClient> {
|
|
||||||
pub(crate) fn new_query(config: &Config) -> Self {
|
|
||||||
// the api address is irrelevant here as **WE ARE THE API**
|
|
||||||
let api_url = format!("http://localhost:{}", DEFAULT_VALIDATOR_API_PORT)
|
|
||||||
.parse()
|
|
||||||
.unwrap();
|
|
||||||
let nymd_url = config.get_nymd_validator_url();
|
|
||||||
|
|
||||||
let mixnet_contract = config
|
|
||||||
.get_mixnet_contract_address()
|
|
||||||
.parse()
|
|
||||||
.expect("the mixnet contract address is invalid!");
|
|
||||||
|
|
||||||
let client_config = validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract));
|
|
||||||
let inner =
|
|
||||||
validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!");
|
|
||||||
|
|
||||||
Client(Arc::new(RwLock::new(inner)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Client<SigningNymdClient> {
|
|
||||||
pub(crate) fn new_signing(config: &Config) -> Self {
|
|
||||||
// the api address is irrelevant here as **WE ARE THE API**
|
|
||||||
let api_url = format!("http://localhost:{}", DEFAULT_VALIDATOR_API_PORT)
|
|
||||||
.parse()
|
|
||||||
.unwrap();
|
|
||||||
let nymd_url = config.get_nymd_validator_url();
|
|
||||||
|
|
||||||
let mixnet_contract = config
|
|
||||||
.get_mixnet_contract_address()
|
|
||||||
.parse()
|
|
||||||
.expect("the mixnet contract address is invalid!");
|
|
||||||
let mnemonic = config
|
|
||||||
.get_mnemonic()
|
|
||||||
.parse()
|
|
||||||
.expect("the mnemonic is invalid!");
|
|
||||||
|
|
||||||
let client_config = validator_client::Config::new(nymd_url, api_url, Some(mixnet_contract));
|
|
||||||
let inner = validator_client::Client::new_signing(client_config, mnemonic)
|
|
||||||
.expect("Failed to connect to nymd!");
|
|
||||||
|
|
||||||
Client(Arc::new(RwLock::new(inner)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> Client<C> {
|
|
||||||
pub(crate) async fn get_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
|
|
||||||
where
|
|
||||||
C: CosmWasmClient + Sync,
|
|
||||||
{
|
|
||||||
self.0.read().await.get_all_nymd_mixnodes().await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn get_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError>
|
|
||||||
where
|
|
||||||
C: CosmWasmClient + Sync,
|
|
||||||
{
|
|
||||||
self.0.read().await.get_all_nymd_gateways().await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) async fn some_rewarding_stuff_here(&self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
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};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use ts_rs::TS;
|
||||||
|
use validator_client::nymd::{AccountId, NymdClient, SigningNymdClient};
|
||||||
|
|
||||||
|
#[derive(TS, Serialize, Deserialize)]
|
||||||
|
pub struct Account {
|
||||||
|
contract_address: String,
|
||||||
|
client_address: String,
|
||||||
|
denom: Denom,
|
||||||
|
mnemonmic: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TS, Serialize, Deserialize)]
|
||||||
|
pub struct Balance {
|
||||||
|
coin: Coin,
|
||||||
|
printable_balance: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
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;
|
||||||
|
{
|
||||||
|
let r_state = state.read().await;
|
||||||
|
client = _connect_with_mnemonic(mnemonic, &r_state.config());
|
||||||
|
}
|
||||||
|
|
||||||
|
let contract_address = match client.contract_address() {
|
||||||
|
Ok(address) => address.to_string(),
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
let client_address = client.address().to_string();
|
||||||
|
let denom = match client.denom() {
|
||||||
|
Ok(denom) => denom,
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let account = Account {
|
||||||
|
contract_address,
|
||||||
|
client_address,
|
||||||
|
denom: Denom::from_str(&denom.to_string())?,
|
||||||
|
mnemonmic: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut w_state = state.write().await;
|
||||||
|
w_state.set_client(client);
|
||||||
|
|
||||||
|
Ok(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 {
|
||||||
|
Ok(Some(coin)) => {
|
||||||
|
let coin = Coin::new(
|
||||||
|
&coin.amount.to_string(),
|
||||||
|
&Denom::from_str(&coin.denom.to_string())?,
|
||||||
|
);
|
||||||
|
Ok(Balance {
|
||||||
|
coin: coin.clone(),
|
||||||
|
printable_balance: coin.to_major().to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Ok(None) => Err(format!(
|
||||||
|
"No balance available for address {}",
|
||||||
|
client.address()
|
||||||
|
)),
|
||||||
|
Err(e) => Err(BackendError::from(e).to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn create_new_account(
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<Account, String> {
|
||||||
|
let mnemonic = random_mnemonic();
|
||||||
|
let mut client = connect_with_mnemonic(mnemonic.to_string(), state).await?;
|
||||||
|
client.mnemonmic = Some(mnemonic.to_string());
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_mnemonic() -> Mnemonic {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> NymdClient<SigningNymdClient> {
|
||||||
|
match NymdClient::connect_with_mnemonic(
|
||||||
|
config.get_nymd_validator_url().unwrap(),
|
||||||
|
Some(AccountId::from_str(&config.get_mixnet_contract_address()).unwrap()),
|
||||||
|
mnemonic,
|
||||||
|
) {
|
||||||
|
Ok(client) => client,
|
||||||
|
Err(e) => panic!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
use crate::format_err;
|
||||||
|
use crate::state::State;
|
||||||
|
use cosmwasm_std::Decimal;
|
||||||
|
use cosmwasm_std::Uint128;
|
||||||
|
use mixnet_contract::StateParams;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, TS)]
|
||||||
|
pub struct TauriStateParams {
|
||||||
|
epoch_length: u32,
|
||||||
|
minimum_mixnode_bond: String,
|
||||||
|
minimum_gateway_bond: String,
|
||||||
|
mixnode_bond_reward_rate: String,
|
||||||
|
gateway_bond_reward_rate: String,
|
||||||
|
mixnode_delegation_reward_rate: String,
|
||||||
|
gateway_delegation_reward_rate: String,
|
||||||
|
mixnode_active_set_size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StateParams> for TauriStateParams {
|
||||||
|
fn from(p: StateParams) -> TauriStateParams {
|
||||||
|
TauriStateParams {
|
||||||
|
epoch_length: p.epoch_length,
|
||||||
|
minimum_mixnode_bond: p.minimum_mixnode_bond.to_string(),
|
||||||
|
minimum_gateway_bond: p.minimum_gateway_bond.to_string(),
|
||||||
|
mixnode_bond_reward_rate: p.mixnode_bond_reward_rate.to_string(),
|
||||||
|
gateway_bond_reward_rate: p.gateway_bond_reward_rate.to_string(),
|
||||||
|
mixnode_delegation_reward_rate: p.mixnode_delegation_reward_rate.to_string(),
|
||||||
|
gateway_delegation_reward_rate: p.gateway_delegation_reward_rate.to_string(),
|
||||||
|
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<TauriStateParams> for StateParams {
|
||||||
|
type Error = Box<dyn std::error::Error>;
|
||||||
|
|
||||||
|
fn try_from(p: TauriStateParams) -> Result<StateParams, Self::Error> {
|
||||||
|
Ok(StateParams {
|
||||||
|
epoch_length: p.epoch_length,
|
||||||
|
minimum_mixnode_bond: Uint128::try_from(p.minimum_mixnode_bond.as_str())?,
|
||||||
|
minimum_gateway_bond: Uint128::try_from(p.minimum_gateway_bond.as_str())?,
|
||||||
|
mixnode_bond_reward_rate: Decimal::from_str(p.mixnode_bond_reward_rate.as_str())?,
|
||||||
|
gateway_bond_reward_rate: Decimal::from_str(p.gateway_bond_reward_rate.as_str())?,
|
||||||
|
mixnode_delegation_reward_rate: Decimal::from_str(p.mixnode_delegation_reward_rate.as_str())?,
|
||||||
|
gateway_delegation_reward_rate: Decimal::from_str(p.gateway_delegation_reward_rate.as_str())?,
|
||||||
|
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_state_params(
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<TauriStateParams, String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let client = r_state.client()?;
|
||||||
|
match client.get_state_params().await {
|
||||||
|
Ok(params) => Ok(params.into()),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn update_state_params(
|
||||||
|
params: TauriStateParams,
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<TauriStateParams, String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let client = r_state.client()?;
|
||||||
|
let state_params: StateParams = match params.try_into() {
|
||||||
|
Ok(state_params) => state_params,
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
match client.update_state_params(state_params.clone()).await {
|
||||||
|
Ok(_) => Ok(state_params.into()),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
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,
|
||||||
|
bond: Coin,
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let bond: CosmWasmCoin = match bond.try_into() {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
let client = r_state.client()?;
|
||||||
|
match client.bond_gateway(gateway, bond).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,
|
||||||
|
bond: Coin,
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let bond: CosmWasmCoin = match bond.try_into() {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
let client = r_state.client()?;
|
||||||
|
match client.bond_mixnode(mixnode, bond).await {
|
||||||
|
Ok(_result) => Ok(()),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
use crate::coin::Coin;
|
||||||
|
use crate::format_err;
|
||||||
|
use crate::state::State;
|
||||||
|
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
#[derive(TS, 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 bond: 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, &bond).await {
|
||||||
|
Ok(_result) => Ok(DelegationResult {
|
||||||
|
source_address: client.address().to_string(),
|
||||||
|
target_address: identity.to_string(),
|
||||||
|
amount: Some(bond.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 delegate_to_gateway(
|
||||||
|
identity: &str,
|
||||||
|
amount: Coin,
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<DelegationResult, String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let bond: CosmWasmCoin = match amount.try_into() {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => return Err(format_err!(e)),
|
||||||
|
};
|
||||||
|
let client = r_state.client()?;
|
||||||
|
match client.delegate_to_gateway(identity, &bond).await {
|
||||||
|
Ok(_result) => Ok(DelegationResult {
|
||||||
|
source_address: client.address().to_string(),
|
||||||
|
target_address: identity.to_string(),
|
||||||
|
amount: Some(bond.into()),
|
||||||
|
}),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn undelegate_from_gateway(
|
||||||
|
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_gateway_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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod account;
|
||||||
|
pub mod admin;
|
||||||
|
pub mod bond;
|
||||||
|
pub mod delegate;
|
||||||
|
pub mod send;
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
use crate::coin::Coin;
|
||||||
|
use crate::format_err;
|
||||||
|
use crate::state::State;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tendermint_rpc::endpoint::broadcast::tx_commit::Response;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use ts_rs::TS;
|
||||||
|
use validator_client::nymd::{AccountId, CosmosCoin};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, TS)]
|
||||||
|
pub struct TauriTxResult {
|
||||||
|
code: u32,
|
||||||
|
gas_wanted: u64,
|
||||||
|
gas_used: u64,
|
||||||
|
block_height: u64,
|
||||||
|
details: TransactionDetails,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, TS)]
|
||||||
|
pub struct TransactionDetails {
|
||||||
|
from_address: String,
|
||||||
|
to_address: String,
|
||||||
|
amount: Coin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TauriTxResult {
|
||||||
|
fn new(t: Response, details: TransactionDetails) -> TauriTxResult {
|
||||||
|
TauriTxResult {
|
||||||
|
code: t.check_tx.code.value(),
|
||||||
|
gas_wanted: t.check_tx.gas_wanted.value(),
|
||||||
|
gas_used: t.check_tx.gas_used.value(),
|
||||||
|
block_height: t.height.value(),
|
||||||
|
details,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn send(
|
||||||
|
address: &str,
|
||||||
|
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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
use crate::coin::{Coin, Denom};
|
||||||
|
use crate::format_err;
|
||||||
|
use crate::state::State;
|
||||||
|
use crate::Operation;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn major_to_minor(amount: &str) -> Result<Coin, String> {
|
||||||
|
let coin = Coin::new(amount, &Denom::Major);
|
||||||
|
Ok(coin.to_minor())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn minor_to_major(amount: &str) -> Result<Coin, String> {
|
||||||
|
let coin = Coin::new(amount, &Denom::Minor);
|
||||||
|
Ok(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),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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),
|
||||||
|
Err(e) => Err(format_err!(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_fee(
|
||||||
|
operation: Operation,
|
||||||
|
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||||
|
) -> Result<Coin, String> {
|
||||||
|
let r_state = state.read().await;
|
||||||
|
let client = r_state.client()?;
|
||||||
|
let fee = client.get_fee(operation);
|
||||||
|
let mut coin = Coin::new("0", &Denom::Major);
|
||||||
|
for f in fee.amount {
|
||||||
|
coin = coin + f.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(coin)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Denom } from "./denom";
|
||||||
|
|
||||||
|
export interface Account {
|
||||||
|
contract_address: string;
|
||||||
|
client_address: string;
|
||||||
|
denom: Denom;
|
||||||
|
mnemonmic: string | null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export interface TauriStateParams {
|
||||||
|
epoch_length: number;
|
||||||
|
minimum_mixnode_bond: string;
|
||||||
|
minimum_gateway_bond: string;
|
||||||
|
mixnode_bond_reward_rate: string;
|
||||||
|
gateway_bond_reward_rate: string;
|
||||||
|
mixnode_delegation_reward_rate: string;
|
||||||
|
gateway_delegation_reward_rate: string;
|
||||||
|
mixnode_active_set_size: number;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user