From 1bc17abbaad98e1aee3ebf2bfd944e1c47506a1e Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Wed, 25 Aug 2021 11:18:16 +0200 Subject: [PATCH] Add connect_with_mnemonic and get_balance tauri functions --- Cargo.lock | 34 +++---- .../nymd/cosmwasm_client/signing_client.rs | 1 + .../validator-client/src/nymd/mod.rs | 1 + .../validator-client/src/nymd/wallet/mod.rs | 2 + tauri-wallet/src-tauri/Cargo.toml | 9 +- tauri-wallet/src-tauri/src/config/mod.rs | 26 +++--- tauri-wallet/src-tauri/src/error.rs | 21 +++++ tauri-wallet/src-tauri/src/main.rs | 88 ++++++++++++++++++- tauri-wallet/src-tauri/src/nymd_client.rs | 2 +- 9 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 tauri-wallet/src-tauri/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 53c618bd7e..764b18d5b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,22 +4,6 @@ # SPDX-License-Identifier: Apache-2.0 version = 3 -[[package]] -name = "Nym-Wallet" -version = "0.1.0" -dependencies = [ - "config", - "dirs", - "mixnet-contract", - "serde", - "serde_json", - "tauri", - "tauri-build", - "tokio", - "url", - "validator-client", -] - [[package]] name = "addr2line" version = "0.16.0" @@ -3520,6 +3504,24 @@ dependencies = [ "version-checker", ] +[[package]] +name = "nym_wallet" +version = "0.1.0" +dependencies = [ + "bip39", + "config", + "dirs", + "mixnet-contract", + "serde", + "serde_json", + "tauri", + "tauri-build", + "tendermint-rpc", + "thiserror", + "tokio", + "validator-client", +] + [[package]] name = "nymsphinx" version = "0.1.0" diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs index bb9a0e588b..afd1392680 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs @@ -442,6 +442,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { } } +#[derive(Debug)] pub struct Client { rpc_client: HttpClient, signer: DirectSecp256k1HdWallet, diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 32bde42a8e..ff57978983 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -36,6 +36,7 @@ pub(crate) mod fee_helpers; pub mod gas_price; pub mod wallet; +#[derive(Debug)] pub struct NymdClient { client: C, contract_address: Option, diff --git a/common/client-libs/validator-client/src/nymd/wallet/mod.rs b/common/client-libs/validator-client/src/nymd/wallet/mod.rs index ef43a65f84..c1e53631db 100644 --- a/common/client-libs/validator-client/src/nymd/wallet/mod.rs +++ b/common/client-libs/validator-client/src/nymd/wallet/mod.rs @@ -10,6 +10,7 @@ use cosmos_sdk::tx::SignDoc; use cosmos_sdk::{tx, AccountId}; /// Derivation information required to derive a keypair and an address from a mnemonic. +#[derive(Debug)] struct Secp256k1Derivation { hd_path: DerivationPath, prefix: String, @@ -25,6 +26,7 @@ pub struct AccountData { type Secp256k1Keypair = (SigningKey, PublicKey); +#[derive(Debug)] pub struct DirectSecp256k1HdWallet { /// Base secret secret: bip39::Mnemonic, diff --git a/tauri-wallet/src-tauri/Cargo.toml b/tauri-wallet/src-tauri/Cargo.toml index 34b8494a87..25af97aa32 100644 --- a/tauri-wallet/src-tauri/Cargo.toml +++ b/tauri-wallet/src-tauri/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "Nym-Wallet" +name = "nym_wallet" version = "0.1.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" -default-run = "Nym-Wallet" +default-run = "nym_wallet" edition = "2018" build = "src/build.rs" @@ -20,7 +20,10 @@ serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.0.0-beta.6", features = [] } tokio = { version = "1.10", features = ["sync"] } dirs = "3.0" -url = "2.2" +# url = "2.2" +bip39 = "1.0" +thiserror = "1.0" +tendermint-rpc = "0.21.0" validator-client = { path = "../../common/client-libs/validator-client", features = [ "nymd-client", diff --git a/tauri-wallet/src-tauri/src/config/mod.rs b/tauri-wallet/src-tauri/src/config/mod.rs index 0c1fb9d2c0..52ff55b940 100644 --- a/tauri-wallet/src-tauri/src/config/mod.rs +++ b/tauri-wallet/src-tauri/src/config/mod.rs @@ -7,12 +7,15 @@ use config::defaults::{ use config::NymConfig; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use url::Url; +use std::str::FromStr; +use tendermint_rpc::Url; mod template; use template::config_template; +use crate::error::BackendError; + #[derive(Debug, Default, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { @@ -71,20 +74,23 @@ impl NymConfig for Config { } impl Config { - pub fn get_nymd_validator_url(&self) -> Url { + pub fn get_nymd_validator_url(&self) -> Result { // TODO make this a random choice if let Some(validator_details) = self.base.validators.first() { - validator_details.nymd_url() + match tendermint_rpc::Url::from_str(&validator_details.nymd_url().to_string()) { + Ok(url) => Ok(url), + Err(e) => Err(e.into()), + } } else { - panic!("No validators found in config") + panic!("No validators found in config") } } - pub fn get_mixnet_contract_address(&self) -> String { - self.base.mixnet_contract_address.clone() - } + // pub fn get_mixnet_contract_address(&self) -> String { + // self.base.mixnet_contract_address.clone() + // } - pub fn get_mnemonic(&self) -> String { - self.base.mnemonic.clone() - } + // pub fn get_mnemonic(&self) -> String { + // self.base.mnemonic.clone() + // } } diff --git a/tauri-wallet/src-tauri/src/error.rs b/tauri-wallet/src-tauri/src/error.rs new file mode 100644 index 0000000000..bac80998ad --- /dev/null +++ b/tauri-wallet/src-tauri/src/error.rs @@ -0,0 +1,21 @@ +use thiserror::Error; +use validator_client::nymd::error::NymdError; + +#[derive(Error, Debug)] +pub enum BackendError { + #[error("Error parsing bip39 mnemonic")] + Bip39Error { + #[from] + source: bip39::Error + }, + #[error("Error parsing into tendermint Url")] + TendermintError { + #[from] + source: tendermint_rpc::Error + }, + #[error("Error getting balances")] + NymdError { + #[from] + source: NymdError + } +} \ No newline at end of file diff --git a/tauri-wallet/src-tauri/src/main.rs b/tauri-wallet/src-tauri/src/main.rs index b4c6877c1a..eb69704546 100644 --- a/tauri-wallet/src-tauri/src/main.rs +++ b/tauri-wallet/src-tauri/src/main.rs @@ -3,11 +3,97 @@ windows_subsystem = "windows" )] -mod nymd_client; +use bip39::Mnemonic; +use error::BackendError; +use std::collections::HashMap; +use std::str::FromStr; +use validator_client::nymd::{NymdClient, SigningNymdClient}; + mod config; +mod error; +// mod nymd_client; + +use std::sync::Arc; +use tokio::sync::RwLock; + +use crate::config::Config; + +#[derive(Debug, Default)] +struct State { + config: Config, + signing_client: Option>, +} + +#[tauri::command] +async fn connect_with_mnemonic( + mnemonic: String, + state: tauri::State<'_, Arc>>, +) -> Result { + let mnemonic = match Mnemonic::from_str(&mnemonic) { + Ok(mnemonic) => mnemonic, + Err(e) => return Err(BackendError::from(e).to_string()), + }; + let r_state = state.read().await; + let client = _connect_with_mnemonic(mnemonic, &r_state.config); + let mut w_state = state.write().await; + w_state.signing_client = Some(client); + Ok(true) +} + +#[tauri::command] +async fn get_balance( + state: tauri::State<'_, Arc>>, +) -> Result, String> { + let r_state = state.read().await; + if let Some(client) = &r_state.signing_client { + match client.get_balance(client.address()).await { + Ok(Some(coin)) => { + let mut balance = HashMap::new(); + balance.insert("amount", coin.amount.to_string()); + balance.insert("denom", coin.denom.to_string()); + Ok(balance) + }, + Ok(None) => Err(format!("No balance available for address {}", client.address())), + Err(e) => Err(BackendError::from(e).to_string()), + } + } else { + Err(String::from("Client has not been initialized yet")) + } +} + +fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> NymdClient { + match NymdClient::connect_with_mnemonic(config.get_nymd_validator_url().unwrap(), None, mnemonic) + { + Ok(client) => client, + Err(e) => panic!("{}", e), + } +} fn main() { tauri::Builder::default() + .manage(Arc::new(RwLock::new(State::default()))) + .invoke_handler(tauri::generate_handler![connect_with_mnemonic, get_balance]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } + + +mod test { + #![allow(unused_imports)] + use crate::Config; + use crate::_connect_with_mnemonic; + use bip39::Mnemonic; + use std::str::FromStr; + + #[test] + fn test_connect_with_mnemonic() { + let config = Config::default(); + assert_eq!( + "https://testnet-milhon-validator1.nymtech.net/", + config.get_nymd_validator_url().unwrap().to_string() + ); + let mnemonic = Mnemonic::from_str("riot worth swear negative toward hood absent crater release net detect weasel profit wash market key smart member prize cancel awkward famous sauce sport").unwrap(); + let client = _connect_with_mnemonic(mnemonic, &config); + assert!(client.contract_address().is_ok()); + } +} diff --git a/tauri-wallet/src-tauri/src/nymd_client.rs b/tauri-wallet/src-tauri/src/nymd_client.rs index 9bf510bc9d..08e0ac5929 100644 --- a/tauri-wallet/src-tauri/src/nymd_client.rs +++ b/tauri-wallet/src-tauri/src/nymd_client.rs @@ -6,7 +6,7 @@ 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}; +use validator_client::nymd::{CosmWasmClient, QueryNymdClient, SigningNymdClient, NymdClient}; use validator_client::ValidatorClientError; #[derive(Clone)]