Merge pull request #1033 from nymtech/feature/configurable_wallet

Feature/configurable wallet
This commit is contained in:
Tommy Verrall
2022-01-19 10:36:17 +00:00
committed by GitHub
22 changed files with 456 additions and 150 deletions
Generated
+1
View File
@@ -3549,6 +3549,7 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
name = "network-defaults"
version = "0.1.0"
dependencies = [
"cfg-if 1.0.0",
"hex-literal",
"serde",
"time 0.3.3",
+1
View File
@@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cfg-if = "1.0.0"
hex-literal = "0.3.3"
serde = {version = "1.0", features = ["derive"]}
url = "2.2"
+130
View File
@@ -0,0 +1,130 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::{milhon, qa, sandbox, ValidatorDetails};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum Network {
MILHON,
QA,
SANDBOX,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkDetails {
bech32_prefix: String,
denom: String,
mixnet_contract_address: String,
vesting_contract_address: String,
bandwidth_claim_contract_address: String,
rewarding_validator_address: String,
validators: Vec<ValidatorDetails>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SupportedNetworks {
networks: HashMap<Network, NetworkDetails>,
}
impl SupportedNetworks {
pub fn new(support: Vec<Network>) -> Self {
let mut networks = HashMap::new();
for network in support {
match network {
Network::MILHON => networks.insert(
Network::MILHON,
NetworkDetails {
bech32_prefix: String::from(milhon::BECH32_PREFIX),
denom: String::from(milhon::DENOM),
mixnet_contract_address: String::from(milhon::MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: String::from(milhon::VESTING_CONTRACT_ADDRESS),
bandwidth_claim_contract_address: String::from(
milhon::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
),
rewarding_validator_address: String::from(
milhon::REWARDING_VALIDATOR_ADDRESS,
),
validators: milhon::validators(),
},
),
Network::QA => networks.insert(
Network::QA,
NetworkDetails {
bech32_prefix: String::from(qa::BECH32_PREFIX),
denom: String::from(qa::DENOM),
mixnet_contract_address: String::from(qa::MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: String::from(qa::VESTING_CONTRACT_ADDRESS),
bandwidth_claim_contract_address: String::from(
qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
),
rewarding_validator_address: String::from(qa::REWARDING_VALIDATOR_ADDRESS),
validators: qa::validators(),
},
),
Network::SANDBOX => networks.insert(
Network::SANDBOX,
NetworkDetails {
bech32_prefix: String::from(sandbox::BECH32_PREFIX),
denom: String::from(sandbox::DENOM),
mixnet_contract_address: String::from(sandbox::MIXNET_CONTRACT_ADDRESS),
vesting_contract_address: String::from(sandbox::VESTING_CONTRACT_ADDRESS),
bandwidth_claim_contract_address: String::from(
sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
),
rewarding_validator_address: String::from(
sandbox::REWARDING_VALIDATOR_ADDRESS,
),
validators: sandbox::validators(),
},
),
};
}
SupportedNetworks { networks }
}
pub fn bech32_prefix(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.bech32_prefix.as_str())
}
pub fn denom(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.denom.as_str())
}
pub fn mixnet_contract_address(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.mixnet_contract_address.as_str())
}
pub fn vesting_contract_address(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.vesting_contract_address.as_str())
}
pub fn bandwidth_claim_contract_address(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.bandwidth_claim_contract_address.as_str())
}
pub fn rewarding_validator_address(&self, network: Network) -> Option<&str> {
self.networks
.get(&network)
.map(|network_details| network_details.rewarding_validator_address.as_str())
}
pub fn validators(&self, network: Network) -> Option<&Vec<ValidatorDetails>> {
self.networks
.get(&network)
.map(|network_details| &network_details.validators)
}
}
+62 -39
View File
@@ -5,20 +5,63 @@ use std::time::Duration;
use time::OffsetDateTime;
use url::Url;
pub mod all;
pub mod eth_contract;
#[cfg(network = "milhon")]
pub mod milhon;
#[cfg(network = "qa")]
pub mod qa;
#[cfg(network = "sandbox")]
pub mod sandbox;
mod milhon;
mod qa;
mod sandbox;
#[cfg(network = "milhon")]
pub use milhon::*;
#[cfg(network = "qa")]
pub use qa::*;
#[cfg(network = "sandbox")]
pub use sandbox::*;
cfg_if::cfg_if! {
if #[cfg(network = "milhon")] {
pub const BECH32_PREFIX: &str = milhon::BECH32_PREFIX;
pub const DENOM: &str = milhon::DENOM;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = milhon::MIXNET_CONTRACT_ADDRESS;
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = milhon::VESTING_CONTRACT_ADDRESS;
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = milhon::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
pub const DEFAULT_REWARDING_VALIDATOR_ADDRESS: &str = milhon::REWARDING_VALIDATOR_ADDRESS;
pub fn default_validators() -> Vec<ValidatorDetails> {
milhon::validators()
}
pub fn default_network() -> all::Network {
all::Network::MILHON
}
} else if #[cfg(network = "qa")] {
pub const BECH32_PREFIX: &str = qa::BECH32_PREFIX;
pub const DENOM: &str = qa::DENOM;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = qa::MIXNET_CONTRACT_ADDRESS;
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = qa::VESTING_CONTRACT_ADDRESS;
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
pub const DEFAULT_REWARDING_VALIDATOR: &str = qa::REWARDING_VALIDATOR_ADDRESS;
pub fn default_validators() -> Vec<ValidatorDetails> {
qa::validators()
}
pub fn default_network() -> all::Network {
all::Network::QA
}
} else if #[cfg(network = "sandbox")] {
pub const BECH32_PREFIX: &str = sandbox::BECH32_PREFIX;
pub const DENOM: &str = sandbox::DENOM;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = sandbox::MIXNET_CONTRACT_ADDRESS;
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = sandbox::VESTING_CONTRACT_ADDRESS;
pub const DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS;
pub const DEFAULT_REWARDING_VALIDATOR: &str = sandbox::REWARDING_VALIDATOR_ADDRESS;
pub fn default_validators() -> Vec<ValidatorDetails> {
sandbox::validators()
}
pub fn default_network() -> all::Network {
all::Network::SANDBOX
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ValidatorDetails {
@@ -51,33 +94,6 @@ impl ValidatorDetails {
}
}
#[cfg(network = "milhon")]
pub fn default_validators() -> Vec<ValidatorDetails> {
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),
]
}
#[cfg(network = "qa")]
pub fn default_validators() -> Vec<ValidatorDetails> {
vec![ValidatorDetails::new(
"https://qa-validator.nymtech.net",
Some("https://qa-validator.nymtech.net/api"),
)]
}
#[cfg(network = "sandbox")]
pub fn default_validators() -> Vec<ValidatorDetails> {
vec![ValidatorDetails::new(
"https://sandbox-validator.nymtech.net",
Some("https://sandbox-validator.nymtech.net/api"),
)]
}
pub fn default_nymd_endpoints() -> Vec<Url> {
default_validators()
.iter()
@@ -92,6 +108,13 @@ pub fn default_api_endpoints() -> Vec<Url> {
.collect()
}
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
// Name of the event triggered by the eth contract. If the event name is changed,
// this would also need to be changed; It is currently tested against the json abi
pub const ETH_EVENT_NAME: &str = "Burned";
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
// Ethereum constants used for token bridge
/// How much bandwidth (in bytes) one token can buy
const BYTES_PER_TOKEN: u64 = 1024 * 1024 * 1024;
+18 -12
View File
@@ -1,17 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub const BECH32_PREFIX: &str = "punk";
pub const DENOM: &str = "upunk";
use crate::ValidatorDetails;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "punk10pyejy66429refv3g35g2t7am0was7yalwrzen";
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = "";
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "punk1jld76tqw4wnpfenmay2xkv86nr3j0w426eka82";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "punk1v9qauwdq5terag6uvfsdytcs2d0sdmfdy7hgk3";
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
pub(crate) const BECH32_PREFIX: &str = "punk";
pub(crate) const DENOM: &str = "upunk";
// Name of the event triggered by the eth contract. If the event name is changed,
// this would also need to be changed; It is currently tested against the json abi
pub const ETH_EVENT_NAME: &str = "Burned";
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "punk10pyejy66429refv3g35g2t7am0was7yalwrzen";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "";
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
"punk1jld76tqw4wnpfenmay2xkv86nr3j0w426eka82";
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "punk1v9qauwdq5terag6uvfsdytcs2d0sdmfdy7hgk3";
pub(crate) fn validators() -> Vec<ValidatorDetails> {
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),
]
}
+15 -12
View File
@@ -1,17 +1,20 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub const BECH32_PREFIX: &str = "nymt";
pub const DENOM: &str = "unymt";
use crate::ValidatorDetails;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "nymt14hj2tavq8fpesdwxxcu44rty3hh90vhuysqrsr";
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "nymt1dn52nx8wv9wkqmrvj6tcmdzh4es6jt8tr7f6j9";
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
pub(crate) const BECH32_PREFIX: &str = "nymt";
pub(crate) const DENOM: &str = "unymt";
// Name of the event triggered by the eth contract. If the event name is changed,
// this would also need to be changed; It is currently tested against the json abi
pub const ETH_EVENT_NAME: &str = "Burned";
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt14hj2tavq8fpesdwxxcu44rty3hh90vhuysqrsr";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
"nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "nymt1dn52nx8wv9wkqmrvj6tcmdzh4es6jt8tr7f6j9";
pub(crate) fn validators() -> Vec<ValidatorDetails> {
vec![ValidatorDetails::new(
"https://qa-validator.nymtech.net",
Some("https://qa-validator.nymtech.net/api"),
)]
}
+15 -12
View File
@@ -1,17 +1,20 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub const BECH32_PREFIX: &str = "nymt";
pub const DENOM: &str = "unymt";
use crate::ValidatorDetails;
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
pub const DEFAULT_VESTING_CONTRACT_ADDRESS: &str = "nymt1nc5tatafv6eyq7llkr2gv50ff9e22mnfp9pc5s";
pub const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "nymt17zujduc46wvkwvp6f062mm5xhr7jc3fewvqu9e";
pub const ETH_CONTRACT_ADDRESS: [u8; 20] =
hex_literal::hex!("9fEE3e28c17dbB87310A51F13C4fbf4331A6f102");
pub(crate) const BECH32_PREFIX: &str = "nymt";
pub(crate) const DENOM: &str = "unymt";
// Name of the event triggered by the eth contract. If the event name is changed,
// this would also need to be changed; It is currently tested against the json abi
pub const ETH_EVENT_NAME: &str = "Burned";
pub const ETH_BURN_FUNCTION_NAME: &str = "burnTokenForAccessCode";
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt1nc5tatafv6eyq7llkr2gv50ff9e22mnfp9pc5s";
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
"nymt17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9f8xzkv";
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "nymt17zujduc46wvkwvp6f062mm5xhr7jc3fewvqu9e";
pub(crate) fn validators() -> Vec<ValidatorDetails> {
vec![ValidatorDetails::new(
"https://sandbox-validator.nymtech.net",
Some("https://sandbox-validator.nymtech.net/api"),
)]
}
+1
View File
@@ -877,6 +877,7 @@ dependencies = [
name = "network-defaults"
version = "0.1.0"
dependencies = [
"cfg-if",
"hex-literal",
"serde",
"time 0.3.5",
+1 -1
View File
@@ -309,7 +309,7 @@ pub mod tests {
let mut deps = mock_dependencies();
let env = mock_env();
let msg = InstantiateMsg {
rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(),
rewarding_validator_address: config::defaults::DEFAULT_REWARDING_VALIDATOR.to_string(),
};
let info = mock_info("creator", &[]);
+1 -1
View File
@@ -81,7 +81,7 @@ pub mod test_helpers {
pub fn init_contract() -> OwnedDeps<MemoryStorage, MockApi, MockQuerier<Empty>> {
let mut deps = mock_dependencies();
let msg = InstantiateMsg {
rewarding_validator_address: config::defaults::REWARDING_VALIDATOR_ADDRESS.to_string(),
rewarding_validator_address: config::defaults::DEFAULT_REWARDING_VALIDATOR.to_string(),
};
let env = mock_env();
let info = mock_info("creator", &[]);
@@ -20,7 +20,7 @@ use credentials::token::bandwidth::TokenCredential;
use crypto::asymmetric::identity::{PublicKey, Signature};
use gateway_client::bandwidth::eth_contract;
use network_defaults::{
BANDWIDTH_CLAIM_CONTRACT_ADDRESS, DENOM, ETH_EVENT_NAME, ETH_MIN_BLOCK_DEPTH,
DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS, DENOM, ETH_EVENT_NAME, ETH_MIN_BLOCK_DEPTH,
};
use validator_client::nymd::{
AccountId, CosmosCoin, Decimal, Denom, NymdClient, SigningNymdClient,
@@ -44,7 +44,7 @@ impl ERC20Bridge {
Mnemonic::from_str(&cosmos_mnemonic).expect("Invalid Cosmos mnemonic provided");
let nymd_client = NymdClient::connect_with_mnemonic(
nymd_url.as_ref(),
AccountId::from_str(BANDWIDTH_CLAIM_CONTRACT_ADDRESS).ok(),
AccountId::from_str(DEFAULT_BANDWIDTH_CLAIM_CONTRACT_ADDRESS).ok(),
None,
mnemonic,
None,
+24
View File
@@ -2680,6 +2680,7 @@ checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
name = "network-defaults"
version = "0.1.0"
dependencies = [
"cfg-if 1.0.0",
"hex-literal",
"serde",
"time 0.3.5",
@@ -2809,6 +2810,7 @@ dependencies = [
"rand 0.6.5",
"serde",
"serde_json",
"strum 0.23.0",
"tauri",
"tauri-build",
"tendermint-rpc",
@@ -4400,6 +4402,15 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
[[package]]
name = "strum"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
dependencies = [
"strum_macros 0.23.1",
]
[[package]]
name = "strum_macros"
version = "0.18.0"
@@ -4424,6 +4435,19 @@ dependencies = [
"syn",
]
[[package]]
name = "strum_macros"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "subtle"
version = "1.0.0"
+1
View File
@@ -18,6 +18,7 @@ tauri-build = { version = "1.0.0-beta.4" }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
strum = { version = "0.23", features = ["derive"] }
tauri = { version = "1.0.0-beta.8", features = ["shell-open"] }
tokio = { version = "1.10", features = ["sync"] }
dirs = "4.0"
+33 -19
View File
@@ -1,10 +1,12 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use config::defaults::{default_validators, ValidatorDetails, DEFAULT_MIXNET_CONTRACT_ADDRESS};
use crate::network::Network;
use config::defaults::all::SupportedNetworks;
use config::NymConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use strum::IntoEnumIterator;
use url::Url;
mod template;
@@ -20,21 +22,15 @@ pub struct Config {
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Base {
validators: Vec<ValidatorDetails>,
/// Address of the validator contract managing the network
mixnet_contract_address: String,
/// Mnemonic (currently of the network monitor) used for rewarding
mnemonic: String,
/// Information on all the networks that the wallet connects to.
networks: SupportedNetworks,
}
impl Default for Base {
fn default() -> Self {
let networks = Network::iter().map(|network| network.into()).collect();
Base {
validators: default_validators(),
mixnet_contract_address: DEFAULT_MIXNET_CONTRACT_ADDRESS.to_string(),
mnemonic: String::default(),
networks: SupportedNetworks::new(networks),
}
}
}
@@ -65,33 +61,51 @@ impl NymConfig for Config {
}
impl Config {
pub fn get_nymd_validator_url(&self) -> Url {
pub fn get_nymd_validator_url(&self, network: Network) -> Url {
// TODO make this a random choice
if let Some(validator_details) = self.base.validators.first() {
if let Some(Some(validator_details)) = self
.base
.networks
.validators(network.into())
.map(|validators| validators.first())
{
validator_details.nymd_url()
} else {
panic!("No validators found in config")
}
}
pub fn get_validator_api_url(&self) -> Url {
pub fn get_validator_api_url(&self, network: Network) -> Url {
// TODO make this a random choice
if let Some(validator_details) = self.base.validators.first() {
if let Some(Some(validator_details)) = self
.base
.networks
.validators(network.into())
.map(|validators| validators.first())
{
validator_details.api_url().expect("no api url provided")
} else {
panic!("No validators found in config")
}
}
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
pub fn get_mixnet_contract_address(&self, network: Network) -> cosmrs::AccountId {
self
.base
.mixnet_contract_address
.networks
.mixnet_contract_address(network.into())
.expect("No mixnet contract address found in config")
.parse()
.expect("stored mixnet contract address is not a valid account address")
}
pub fn get_vesting_contract_address(&self) -> Option<cosmrs::AccountId> {
None
pub fn get_vesting_contract_address(&self, network: Network) -> cosmrs::AccountId {
self
.base
.networks
.vesting_contract_address(network.into())
.expect("No vesting contract address found in config")
.parse()
.expect("stored vesting contract address is not a valid account address")
}
}
+2
View File
@@ -41,6 +41,8 @@ pub enum BackendError {
NoBalance(String),
#[error("{0} is not a valid denomination string")]
InvalidDenom(String),
#[error("The provided network is not supported (yet)")]
NetworkNotSupported(config::defaults::all::Network),
}
impl Serialize for BackendError {
+3
View File
@@ -13,6 +13,7 @@ mod coin;
mod config;
mod error;
mod menu;
mod network;
mod operations;
mod state;
mod utils;
@@ -30,6 +31,7 @@ fn main() {
.invoke_handler(tauri::generate_handler![
mixnet::account::connect_with_mnemonic,
mixnet::account::create_new_account,
mixnet::account::switch_network,
mixnet::account::get_balance,
mixnet::admin::get_contract_settings,
mixnet::admin::update_contract_settings,
@@ -80,6 +82,7 @@ mod test {
ts_rs::export! {
mixnet_contract_common::MixNode => "../src/types/rust/mixnode.ts",
crate::coin::Coin => "../src/types/rust/coin.ts",
crate::network::Network => "../src/types/rust/network.ts",
crate::mixnet::account::Balance => "../src/types/rust/balance.ts",
mixnet_contract_common::Gateway => "../src/types/rust/gateway.ts",
crate::mixnet::send::TauriTxResult => "../src/types/rust/tauritxresult.ts",
+43
View File
@@ -0,0 +1,43 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use strum::EnumIter;
use crate::error::BackendError;
use config::defaults::all::Network as ConfigNetwork;
#[cfg_attr(test, derive(ts_rs::TS))]
#[derive(Copy, Clone, Debug, Deserialize, EnumIter, Eq, Hash, PartialEq, Serialize)]
pub enum Network {
QA,
SANDBOX,
}
impl Default for Network {
fn default() -> Self {
Network::SANDBOX
}
}
impl Into<ConfigNetwork> for Network {
fn into(self) -> ConfigNetwork {
match self {
Network::QA => ConfigNetwork::QA,
Network::SANDBOX => ConfigNetwork::SANDBOX,
}
}
}
impl TryFrom<ConfigNetwork> for Network {
type Error = BackendError;
fn try_from(value: ConfigNetwork) -> Result<Self, Self::Error> {
match value {
ConfigNetwork::QA => Ok(Network::QA),
ConfigNetwork::SANDBOX => Ok(Network::SANDBOX),
_ => Err(BackendError::NetworkNotSupported(value)),
}
}
}
@@ -1,16 +1,16 @@
use crate::coin::{Coin, Denom};
use crate::config::Config;
use crate::error::BackendError;
use crate::network::Network;
use crate::nymd_client;
use crate::state::State;
use bip39::{Language, Mnemonic};
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::convert::{TryFrom, TryInto};
use std::str::FromStr;
use std::sync::Arc;
use strum::IntoEnumIterator;
use tokio::sync::RwLock;
use validator_client::nymd::SigningNymdClient;
use validator_client::Client;
#[cfg_attr(test, derive(ts_rs::TS))]
#[derive(Serialize, Deserialize)]
@@ -18,7 +18,16 @@ pub struct Account {
contract_address: String,
client_address: String,
denom: Denom,
mnemonic: Option<String>,
}
impl Account {
pub fn new(contract_address: String, client_address: String, denom: Denom) -> Self {
Account {
contract_address,
client_address,
denom,
}
}
}
#[cfg_attr(test, derive(ts_rs::TS))]
@@ -34,26 +43,7 @@ pub async fn connect_with_mnemonic(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<Account, BackendError> {
let mnemonic = Mnemonic::from_str(&mnemonic)?;
let client = {
let r_state = state.read().await;
_connect_with_mnemonic(mnemonic, &r_state.config())
};
let contract_address = client.nymd.mixnet_contract_address()?.to_string();
let client_address = client.nymd.address().to_string();
let denom = client.nymd.denom()?;
let account = Account {
contract_address,
client_address,
denom: denom.try_into()?,
mnemonic: None,
};
let mut w_state = state.write().await;
w_state.set_client(client);
Ok(account)
_connect_with_mnemonic(mnemonic, state).await
}
#[tauri::command]
@@ -86,9 +76,30 @@ pub async fn create_new_account(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> 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());
Ok(client)
let account = connect_with_mnemonic(rand_mnemonic.to_string(), state).await?;
Ok(account)
}
#[tauri::command]
pub async fn switch_network(
state: tauri::State<'_, Arc<RwLock<State>>>,
network: Network,
) -> Result<Account, BackendError> {
let account = {
let r_state = state.read().await;
let client = r_state.client(network)?;
Account::new(
client.nymd.mixnet_contract_address()?.to_string(),
client.nymd.address().to_string(),
client.nymd.denom()?.try_into()?,
)
};
let mut w_state = state.write().await;
w_state.set_network(network);
Ok(account)
}
fn random_mnemonic() -> Mnemonic {
@@ -96,17 +107,42 @@ fn random_mnemonic() -> Mnemonic {
Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap()
}
fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> Client<SigningNymdClient> {
match validator_client::Client::new_signing(
validator_client::Config::new(
config.get_nymd_validator_url(),
config.get_validator_api_url(),
Some(config.get_mixnet_contract_address()),
config.get_vesting_contract_address(),
),
mnemonic,
) {
Ok(client) => client,
Err(e) => panic!("{}", e),
async fn _connect_with_mnemonic(
mnemonic: Mnemonic,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<Account, BackendError> {
let default_network = Network::try_from(config::defaults::default_network())?;
let mut default_account = None;
for network in Network::iter() {
let client = {
let config = state.read().await.config();
match validator_client::Client::new_signing(
validator_client::Config::new(
config.get_nymd_validator_url(network),
config.get_validator_api_url(network),
Some(config.get_mixnet_contract_address(network)),
Some(config.get_vesting_contract_address(network)),
),
mnemonic.clone(),
) {
Ok(client) => client,
Err(e) => panic!("{}", e),
}
};
if network == default_network {
default_account = Some(Account::new(
client.nymd.mixnet_contract_address()?.to_string(),
client.nymd.address().to_string(),
client.nymd.denom()?.try_into()?,
));
}
let mut w_state = state.write().await;
w_state.add_client(network, client);
}
default_account.ok_or(BackendError::NetworkNotSupported(
config::defaults::default_network(),
))
}
@@ -66,7 +66,7 @@ pub async fn mixnode_bond_details(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<Option<MixNodeBond>, BackendError> {
let guard = state.read().await;
let client = guard.client()?;
let client = guard.current_client()?;
let bond = client.nymd.owns_mixnode(client.nymd.address()).await?;
Ok(bond)
}
@@ -76,7 +76,7 @@ pub async fn gateway_bond_details(
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<Option<GatewayBond>, BackendError> {
let guard = state.read().await;
let client = guard.client()?;
let client = guard.current_client()?;
let bond = client.nymd.owns_gateway(client.nymd.address()).await?;
Ok(bond)
}
+24 -9
View File
@@ -1,19 +1,30 @@
use crate::config::Config;
use crate::error::BackendError;
use crate::network::Network;
use validator_client::nymd::SigningNymdClient;
use validator_client::Client;
use std::collections::HashMap;
#[derive(Default)]
pub struct State {
config: Config,
signing_client: Option<Client<SigningNymdClient>>,
signing_clients: HashMap<Network, Client<SigningNymdClient>>,
current_network: Network,
}
impl State {
pub fn client(&self) -> Result<&Client<SigningNymdClient>, BackendError> {
pub fn client(&self, network: Network) -> Result<&Client<SigningNymdClient>, BackendError> {
self
.signing_client
.as_ref()
.signing_clients
.get(&network)
.ok_or(BackendError::ClientNotInitialized)
}
pub fn current_client(&self) -> Result<&Client<SigningNymdClient>, BackendError> {
self
.signing_clients
.get(&self.current_network)
.ok_or(BackendError::ClientNotInitialized)
}
@@ -21,28 +32,32 @@ impl State {
self.config.clone()
}
pub fn set_client(&mut self, signing_client: Client<SigningNymdClient>) {
self.signing_client = Some(signing_client)
pub fn add_client(&mut self, network: Network, client: Client<SigningNymdClient>) {
self.signing_clients.insert(network, client);
}
pub fn set_network(&mut self, network: Network) {
self.current_network = network;
}
}
#[macro_export]
macro_rules! client {
($state:ident) => {
$state.read().await.client()?
$state.read().await.current_client()?
};
}
#[macro_export]
macro_rules! nymd_client {
($state:ident) => {
$state.read().await.client()?.nymd
$state.read().await.current_client()?.nymd
};
}
#[macro_export]
macro_rules! api_client {
($state:ident) => {
$state.read().await.client()?.validator_api
$state.read().await.current_client()?.validator_api
};
}
-1
View File
@@ -4,5 +4,4 @@ export interface Account {
contract_address: string;
client_address: string;
denom: Denom;
mnemonic: string | null;
}
+1
View File
@@ -0,0 +1 @@
export type Network = "QA" | "SANDBOX";