diff --git a/Cargo.lock b/Cargo.lock index afac5848cb..e4855d7cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,10 +8,16 @@ version = 3 name = "Nym-Wallet" version = "0.1.0" dependencies = [ + "config", + "dirs 3.0.2", + "mixnet-contract", "serde", "serde_json", "tauri", "tauri-build", + "tokio", + "url", + "validator-client", ] [[package]] @@ -3292,6 +3298,7 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" name = "network-defaults" version = "0.1.0" dependencies = [ + "serde", "url", ] @@ -6410,9 +6417,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ "autocfg 1.0.1", "bytes", diff --git a/common/network-defaults/Cargo.toml b/common/network-defaults/Cargo.toml index 94e5c6d126..17ebf56249 100644 --- a/common/network-defaults/Cargo.toml +++ b/common/network-defaults/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +serde = {version = "1.0", features = ["derive"]} url = "2.2" diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index 072f1845ff..2066a5878f 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -1,19 +1,24 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 - +use serde::{Deserialize, Serialize}; use url::Url; -pub struct ValidatorDetails<'a> { +#[derive(Debug, Serialize, Deserialize)] +pub struct ValidatorDetails { // it is assumed those values are always valid since they're being provided in our defaults file - pub nymd_url: &'a str, + pub nymd_url: String, // Right now api_url is optional as we are not running the api reliably on all validators // however, later on it should be a mandatory field - pub api_url: Option<&'a str>, + pub api_url: Option, } -impl<'a> ValidatorDetails<'a> { - pub const fn new(nymd_url: &'a str, api_url: Option<&'a str>) -> Self { - ValidatorDetails { nymd_url, api_url } +impl ValidatorDetails { + pub fn new(nymd_url: &str, api_url: Option<&str>) -> Self { + let api_url = api_url.map(|api_url_str| api_url_str.to_string()); + ValidatorDetails { + nymd_url: nymd_url.to_string(), + api_url, + } } pub fn nymd_url(&self) -> Url { @@ -24,27 +29,30 @@ impl<'a> ValidatorDetails<'a> { pub fn api_url(&self) -> Option { self.api_url + .as_ref() .map(|url| url.parse().expect("the provided api url is invalid!")) } } -pub const DEFAULT_VALIDATORS: &[ValidatorDetails] = &[ - ValidatorDetails::new( - "https://testnet-milhon-validator1.nymtech.net", - Some("https://testnet-milhon-validator1.nymtech.net/api"), - ), - ValidatorDetails::new("https://testnet-milhon-validator2.nymtech.net", None), -]; +pub fn default_validators() -> Vec { + vec![ + ValidatorDetails::new( + "https://testnet-milhon-validator1.nymtech.net", + Some("https://testnet-milhon-validator1.nymtech.net/api"), + ), + ValidatorDetails::new("https://testnet-milhon-validator2.nymtech.net", None), + ] +} pub fn default_nymd_endpoints() -> Vec { - DEFAULT_VALIDATORS + default_validators() .iter() .map(|validator| validator.nymd_url()) .collect() } pub fn default_api_endpoints() -> Vec { - DEFAULT_VALIDATORS + default_validators() .iter() .filter_map(|validator| validator.api_url()) .collect() diff --git a/tauri-wallet/src-tauri/Cargo.toml b/tauri-wallet/src-tauri/Cargo.toml index 49bd880425..4558ede657 100644 --- a/tauri-wallet/src-tauri/Cargo.toml +++ b/tauri-wallet/src-tauri/Cargo.toml @@ -18,7 +18,16 @@ tauri-build = { version = "1.0.0-beta.4" } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.0.0-beta.6", features = ["api-all"] } +tokio = { version = "1.10", features = ["sync"] } +dirs = "3.0" +url = "2.2" + +validator-client = { path = "../../common/client-libs/validator-client", features = [ + "nymd-client", +] } +mixnet-contract = { path = "../../common/mixnet-contract" } +config = { path = "../../common/config" } [features] -default = [ "custom-protocol" ] -custom-protocol = [ "tauri/custom-protocol" ] +default = ["custom-protocol"] +custom-protocol = ["tauri/custom-protocol"] diff --git a/tauri-wallet/src-tauri/src/config/mod.rs b/tauri-wallet/src-tauri/src/config/mod.rs new file mode 100644 index 0000000000..0c1fb9d2c0 --- /dev/null +++ b/tauri-wallet/src-tauri/src/config/mod.rs @@ -0,0 +1,90 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use config::defaults::{ + default_api_endpoints, default_validators, ValidatorDetails, DEFAULT_MIXNET_CONTRACT_ADDRESS, +}; +use config::NymConfig; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use url::Url; + +mod template; + +use template::config_template; + +#[derive(Debug, Default, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Config { + base: Base, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Base { + validators: Vec, + + /// Address of the validator contract managing the network + mixnet_contract_address: String, + + /// Mnemonic (currently of the network monitor) used for rewarding + mnemonic: String, + + // Avoid breaking derives for now + keypair_bs58: String, +} + +impl Default for Base { + fn default() -> Self { + Base { + validators: default_validators(), + mixnet_contract_address: DEFAULT_MIXNET_CONTRACT_ADDRESS.to_string(), + mnemonic: String::default(), + keypair_bs58: String::default(), + } + } +} + +impl NymConfig for Config { + fn template() -> &'static str { + config_template() + } + + fn default_root_directory() -> PathBuf { + dirs::home_dir() + .expect("Failed to evaluate $HOME value") + .join(".nym") + .join("wallet") + } + + fn root_directory(&self) -> PathBuf { + Self::default_root_directory() + } + + fn config_directory(&self) -> PathBuf { + self.root_directory().join("config") + } + + fn data_directory(&self) -> PathBuf { + self.root_directory().join("data") + } +} + +impl Config { + pub fn get_nymd_validator_url(&self) -> Url { + // TODO make this a random choice + if let Some(validator_details) = self.base.validators.first() { + validator_details.nymd_url() + } else { + panic!("No validators found in config") + } + } + + pub fn get_mixnet_contract_address(&self) -> String { + self.base.mixnet_contract_address.clone() + } + + pub fn get_mnemonic(&self) -> String { + self.base.mnemonic.clone() + } +} diff --git a/tauri-wallet/src-tauri/src/config/template.rs b/tauri-wallet/src-tauri/src/config/template.rs new file mode 100644 index 0000000000..3242277b83 --- /dev/null +++ b/tauri-wallet/src-tauri/src/config/template.rs @@ -0,0 +1,17 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub(crate) fn config_template() -> &'static str { + r#" +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +##### main base tauri-wallet config options ##### + +[base] + +# Validator server to which the API will be getting information about the network. +validator_url = '{{ base.validator_url }}' + +"# +} diff --git a/tauri-wallet/src-tauri/src/main.rs b/tauri-wallet/src-tauri/src/main.rs index e994ea4d19..b4c6877c1a 100644 --- a/tauri-wallet/src-tauri/src/main.rs +++ b/tauri-wallet/src-tauri/src/main.rs @@ -3,6 +3,9 @@ windows_subsystem = "windows" )] +mod nymd_client; +mod config; + fn main() { tauri::Builder::default() .run(tauri::generate_context!()) diff --git a/tauri-wallet/src-tauri/src/nymd_client.rs b/tauri-wallet/src-tauri/src/nymd_client.rs new file mode 100644 index 0000000000..9bf510bc9d --- /dev/null +++ b/tauri-wallet/src-tauri/src/nymd_client.rs @@ -0,0 +1,80 @@ +// Copyright 2021 - Nym Technologies SA +// 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}; +use validator_client::ValidatorClientError; + +#[derive(Clone)] +pub(crate) struct Client(Arc>>); + +impl Client { + 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 { + 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 Client { + pub(crate) async fn get_mixnodes(&self) -> Result, ValidatorClientError> + where + C: CosmWasmClient + Sync, + { + self.0.read().await.get_all_nymd_mixnodes().await + } + + pub(crate) async fn get_gateways(&self) -> Result, 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!() + } +} diff --git a/tauri-wallet/src-tauri/tauri.conf.json b/tauri-wallet/src-tauri/tauri.conf.json index a84e385103..54c03151fe 100644 --- a/tauri-wallet/src-tauri/tauri.conf.json +++ b/tauri-wallet/src-tauri/tauri.conf.json @@ -48,9 +48,7 @@ "updater": { "active": false }, - "allowlist": { - "all": true - }, + "allowlist": {}, "windows": [ { "title": "nym-wallet",