Chore/network config (#1335)
* Definition of NymNetworkDetails * Initial attempt at changing network usage for nymd client * Removed deprecated denom call and added constructor for custom network * Cargo fmt
This commit is contained in:
committed by
GitHub
parent
a646f84221
commit
a2409c0a84
@@ -1,14 +1,13 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use bip39::Mnemonic;
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::{MNEMONIC, NYMD_URL};
|
||||
|
||||
use bip39::Mnemonic;
|
||||
use network_defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO};
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
use validator_client::nymd;
|
||||
use validator_client::nymd::traits::CoconutBandwidthSigningClient;
|
||||
use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient};
|
||||
|
||||
@@ -20,9 +19,10 @@ impl Client {
|
||||
pub fn new() -> Self {
|
||||
let nymd_url = Url::from_str(NYMD_URL).unwrap();
|
||||
let mnemonic = Mnemonic::from_str(MNEMONIC).unwrap();
|
||||
let config = nymd::Config::try_from_nym_network_details(&DEFAULT_NETWORK.details())
|
||||
.expect("failed to construct valid validator client config with the provided network");
|
||||
let nymd_client =
|
||||
NymdClient::connect_with_mnemonic(DEFAULT_NETWORK, nymd_url.as_ref(), mnemonic, None)
|
||||
.unwrap();
|
||||
NymdClient::connect_with_mnemonic(config, nymd_url.as_ref(), mnemonic, None).unwrap();
|
||||
|
||||
Client { nymd_client }
|
||||
}
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@
|
||||
},
|
||||
"../pkg": {
|
||||
"name": "@nymproject/nym-client-wasm",
|
||||
"version": "0.0.1"
|
||||
"version": "1.0.1",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
|
||||
@@ -9,20 +9,17 @@ use validator_api_requests::coconut::{
|
||||
ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, VerificationKeyResponse,
|
||||
VerifyCredentialBody, VerifyCredentialResponse,
|
||||
};
|
||||
|
||||
use validator_api_requests::models::{
|
||||
CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse,
|
||||
};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use validator_api_requests::models::{MixNodeBondAnnotated, UptimeResponse};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use network_defaults::DEFAULT_NETWORK;
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use crate::nymd::{
|
||||
error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient,
|
||||
self, error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient,
|
||||
};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
@@ -31,19 +28,20 @@ use mixnet_contract_common::{
|
||||
MixnetContractVersion, MixnodeRewardingStatusResponse, RewardedSetNodeStatus,
|
||||
RewardedSetUpdateDetails,
|
||||
};
|
||||
use network_defaults::all::Network;
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use network_defaults::NymNetworkDetails;
|
||||
#[cfg(feature = "nymd-client")]
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
#[must_use]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
network: network_defaults::all::Network,
|
||||
api_url: Url,
|
||||
nymd_url: Url,
|
||||
mixnet_contract_address: cosmrs::AccountId,
|
||||
vesting_contract_address: cosmrs::AccountId,
|
||||
bandwidth_claim_contract_address: cosmrs::AccountId,
|
||||
|
||||
nymd_config: nymd::Config,
|
||||
|
||||
mixnode_page_limit: Option<u32>,
|
||||
gateway_page_limit: Option<u32>,
|
||||
@@ -53,42 +51,44 @@ pub struct Config {
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
impl Config {
|
||||
pub fn new(network: network_defaults::all::Network, nymd_url: Url, api_url: Url) -> Self {
|
||||
Config {
|
||||
network,
|
||||
nymd_url,
|
||||
mixnet_contract_address: DEFAULT_NETWORK
|
||||
.mixnet_contract_address()
|
||||
pub fn try_from_nym_network_details(
|
||||
details: &NymNetworkDetails,
|
||||
) -> Result<Self, ValidatorClientError> {
|
||||
let mut api_url = details
|
||||
.endpoints
|
||||
.iter()
|
||||
.filter_map(|d| d.api_url.as_ref())
|
||||
.map(|url| Url::parse(url))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
if api_url.is_empty() {
|
||||
return Err(ValidatorClientError::NoAPIUrlAvailable);
|
||||
}
|
||||
|
||||
Ok(Config {
|
||||
api_url: api_url.pop().unwrap(),
|
||||
nymd_url: details.endpoints[0]
|
||||
.nymd_url
|
||||
.parse()
|
||||
.expect("Error parsing mixnet contract address"),
|
||||
vesting_contract_address: DEFAULT_NETWORK
|
||||
.vesting_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing vesting contract address"),
|
||||
bandwidth_claim_contract_address: DEFAULT_NETWORK
|
||||
.bandwidth_claim_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing bandwidth claim contract address"),
|
||||
api_url,
|
||||
.map_err(ValidatorClientError::MalformedUrlProvided)?,
|
||||
nymd_config: nymd::Config::try_from_nym_network_details(details)?,
|
||||
mixnode_page_limit: None,
|
||||
gateway_page_limit: None,
|
||||
mixnode_delegations_page_limit: None,
|
||||
rewarded_set_page_limit: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_mixnode_contract_address(mut self, address: cosmrs::AccountId) -> Self {
|
||||
self.mixnet_contract_address = address;
|
||||
// TODO: this method shouldn't really exist as all information should be included immediately
|
||||
// via `from_nym_network_details`, but it's here for, you guessed it, legacy compatibility
|
||||
pub fn with_urls(mut self, nymd_url: Url, api_url: Url) -> Self {
|
||||
self.nymd_url = nymd_url;
|
||||
self.api_url = api_url;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_vesting_contract_address(mut self, address: cosmrs::AccountId) -> Self {
|
||||
self.vesting_contract_address = address;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_bandwidth_claim_contract_address(mut self, address: cosmrs::AccountId) -> Self {
|
||||
self.bandwidth_claim_contract_address = address;
|
||||
pub fn with_nymd_url(mut self, nymd_url: Url) -> Self {
|
||||
self.nymd_url = nymd_url;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -115,10 +115,11 @@ impl Config {
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
pub struct Client<C> {
|
||||
pub network: network_defaults::all::Network,
|
||||
mixnet_contract_address: cosmrs::AccountId,
|
||||
vesting_contract_address: cosmrs::AccountId,
|
||||
bandwidth_claim_contract_address: cosmrs::AccountId,
|
||||
// compatibility : (
|
||||
pub network: Network,
|
||||
|
||||
// TODO: we really shouldn't be storing a mnemonic here, but removing it would be
|
||||
// non-trivial amount of work and it's out of scope of the current branch
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
mixnode_page_limit: Option<u32>,
|
||||
@@ -135,29 +136,26 @@ pub struct Client<C> {
|
||||
impl Client<SigningNymdClient> {
|
||||
pub fn new_signing(
|
||||
config: Config,
|
||||
// we need to provide network argument due to compatibility with other components (wallet...)
|
||||
// that rely on its existence...
|
||||
network: Network,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
) -> Result<Client<SigningNymdClient>, ValidatorClientError> {
|
||||
let validator_api_client = validator_api::Client::new(config.api_url.clone());
|
||||
let nymd_client = NymdClient::connect_with_mnemonic(
|
||||
config.network,
|
||||
config.nymd_config.clone(),
|
||||
config.nymd_url.as_str(),
|
||||
mnemonic.clone(),
|
||||
None,
|
||||
)?
|
||||
.with_mixnet_contract_address(config.mixnet_contract_address.clone())
|
||||
.with_vesting_contract_address(config.vesting_contract_address.clone())
|
||||
.with_bandwidth_claim_contract_address(config.bandwidth_claim_contract_address.clone());
|
||||
)?;
|
||||
|
||||
Ok(Client {
|
||||
network: config.network,
|
||||
mixnet_contract_address: config.mixnet_contract_address,
|
||||
vesting_contract_address: config.vesting_contract_address,
|
||||
bandwidth_claim_contract_address: config.bandwidth_claim_contract_address,
|
||||
network,
|
||||
mnemonic: Some(mnemonic),
|
||||
mixnode_page_limit: config.mixnode_page_limit,
|
||||
gateway_page_limit: config.gateway_page_limit,
|
||||
mixnode_delegations_page_limit: config.mixnode_delegations_page_limit,
|
||||
rewarded_set_page_limit: None,
|
||||
rewarded_set_page_limit: config.rewarded_set_page_limit,
|
||||
validator_api: validator_api_client,
|
||||
nymd: nymd_client,
|
||||
})
|
||||
@@ -165,14 +163,11 @@ impl Client<SigningNymdClient> {
|
||||
|
||||
pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
|
||||
self.nymd = NymdClient::connect_with_mnemonic(
|
||||
self.network,
|
||||
self.nymd.current_config().clone(),
|
||||
new_endpoint.as_ref(),
|
||||
self.mnemonic.clone().unwrap(),
|
||||
None,
|
||||
)?
|
||||
.with_mixnet_contract_address(self.mixnet_contract_address.clone())
|
||||
.with_vesting_contract_address(self.vesting_contract_address.clone())
|
||||
.with_bandwidth_claim_contract_address(self.bandwidth_claim_contract_address.clone());
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -183,17 +178,18 @@ impl Client<SigningNymdClient> {
|
||||
|
||||
#[cfg(feature = "nymd-client")]
|
||||
impl Client<QueryNymdClient> {
|
||||
pub fn new_query(config: Config) -> Result<Client<QueryNymdClient>, ValidatorClientError> {
|
||||
pub fn new_query(
|
||||
config: Config,
|
||||
// we need to provide network argument due to compatibility with other components (wallet...)
|
||||
// that rely on its existence...
|
||||
network: Network,
|
||||
) -> Result<Client<QueryNymdClient>, ValidatorClientError> {
|
||||
let validator_api_client = validator_api::Client::new(config.api_url.clone());
|
||||
let nymd_client = NymdClient::connect(config.nymd_url.as_str())?
|
||||
.with_mixnet_contract_address(config.mixnet_contract_address.clone())
|
||||
.with_vesting_contract_address(config.vesting_contract_address.clone());
|
||||
let nymd_client =
|
||||
NymdClient::connect(config.nymd_config.clone(), config.nymd_url.as_str())?;
|
||||
|
||||
Ok(Client {
|
||||
network: config.network,
|
||||
mixnet_contract_address: config.mixnet_contract_address,
|
||||
vesting_contract_address: config.vesting_contract_address,
|
||||
bandwidth_claim_contract_address: config.bandwidth_claim_contract_address,
|
||||
network,
|
||||
mnemonic: None,
|
||||
mixnode_page_limit: config.mixnode_page_limit,
|
||||
gateway_page_limit: config.gateway_page_limit,
|
||||
@@ -205,10 +201,7 @@ impl Client<QueryNymdClient> {
|
||||
}
|
||||
|
||||
pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
|
||||
self.nymd = NymdClient::connect(new_endpoint.as_ref())?
|
||||
.with_mixnet_contract_address(self.mixnet_contract_address.clone())
|
||||
.with_vesting_contract_address(self.vesting_contract_address.clone())
|
||||
.with_bandwidth_claim_contract_address(self.bandwidth_claim_contract_address.clone());
|
||||
self.nymd = NymdClient::connect(self.nymd.current_config().clone(), new_endpoint.as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -222,11 +215,12 @@ impl<C> Client<C> {
|
||||
// use case: somebody initialised client without a contract in order to upload and initialise one
|
||||
// and now they want to actually use it without making new client
|
||||
pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) {
|
||||
self.mixnet_contract_address = mixnet_contract_address
|
||||
self.nymd
|
||||
.set_mixnet_contract_address(mixnet_contract_address)
|
||||
}
|
||||
|
||||
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
|
||||
self.mixnet_contract_address.clone()
|
||||
self.nymd.mixnet_contract_address().clone()
|
||||
}
|
||||
|
||||
pub async fn get_cached_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::{NymdClient, QueryNymdClient};
|
||||
use crate::nymd::{Config as ClientConfig, NymdClient, QueryNymdClient};
|
||||
use crate::ApiClient;
|
||||
use network_defaults::all::Network;
|
||||
|
||||
@@ -54,10 +54,20 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
|
||||
.get(&network)
|
||||
.expect("No configured contract address")
|
||||
.clone();
|
||||
NymdClient::<QueryNymdClient>::connect(url.as_str())
|
||||
.map(|client| client.with_mixnet_contract_address(address))
|
||||
.map(move |client| ClientForConnectionTest::Nymd(network, url, Box::new(client)))
|
||||
.ok()
|
||||
let config = ClientConfig::try_from_nym_network_details(&network.details())
|
||||
.expect("failed to create valid nymd client config");
|
||||
|
||||
if let Ok(mut client) = NymdClient::<QueryNymdClient>::connect(config, url.as_str()) {
|
||||
// possibly redundant, but lets just leave it here
|
||||
client.set_mixnet_contract_address(address);
|
||||
Some(ClientForConnectionTest::Nymd(
|
||||
network,
|
||||
url,
|
||||
Box::new(client),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let api_connection_test_clients = api_urls.map(|(network, url)| {
|
||||
@@ -76,7 +86,7 @@ fn extract_and_collect_results_into_map(
|
||||
.filter(|c| &c.url_type() == url_type)
|
||||
.map(|c| {
|
||||
let (network, url, result) = c.result();
|
||||
(*network, (url.clone(), *result))
|
||||
(network.clone(), (url.clone(), *result))
|
||||
})
|
||||
.into_group_map()
|
||||
}
|
||||
|
||||
@@ -18,4 +18,7 @@ pub enum ValidatorClientError {
|
||||
#[cfg(feature = "nymd-client")]
|
||||
#[error("There was an issue with the Nymd client - {0}")]
|
||||
NymdError(#[from] crate::nymd::error::NymdError),
|
||||
|
||||
#[error("No validator API url has been provided")]
|
||||
NoAPIUrlAvailable,
|
||||
}
|
||||
|
||||
@@ -130,6 +130,9 @@ pub enum NymdError {
|
||||
|
||||
#[error("Coconut interface error: {0}")]
|
||||
CoconutInterfaceError(#[from] coconut_interface::error::CoconutInterfaceError),
|
||||
|
||||
#[error("Account had an unexpected bech32 prefix. Expected: {expected}, got: {got}")]
|
||||
UnexpectedBech32Prefix { got: String, expected: String },
|
||||
}
|
||||
|
||||
impl NymdError {
|
||||
|
||||
@@ -24,7 +24,6 @@ use mixnet_contract_common::{
|
||||
PagedMixDelegationsResponse, PagedMixnodeResponse, PagedRewardedSetResponse, QueryMsg,
|
||||
RewardedSetUpdateDetails,
|
||||
};
|
||||
use network_defaults::DEFAULT_NETWORK;
|
||||
use serde::Serialize;
|
||||
use std::convert::TryInto;
|
||||
use vesting_contract_common::ExecuteMsg as VestingExecuteMsg;
|
||||
@@ -50,6 +49,7 @@ pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
|
||||
pub use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||
use network_defaults::{ChainDetails, NymNetworkDetails};
|
||||
pub use signing_client::Client as SigningNymdClient;
|
||||
pub use traits::{VestingQueryClient, VestingSigningClient};
|
||||
|
||||
@@ -60,67 +60,92 @@ pub mod fee;
|
||||
pub mod traits;
|
||||
pub mod wallet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub(crate) chain_details: ChainDetails,
|
||||
|
||||
// I'd love to have used `NymContracts` struct directly here instead,
|
||||
// however, I'd really prefer to use something more strongly typed (i.e. AccountId vs String)
|
||||
pub(crate) mixnet_contract_address: Option<AccountId>,
|
||||
pub(crate) vesting_contract_address: Option<AccountId>,
|
||||
pub(crate) bandwidth_claim_contract_address: Option<AccountId>,
|
||||
pub(crate) coconut_bandwidth_contract_address: Option<AccountId>,
|
||||
pub(crate) multisig_contract_address: Option<AccountId>,
|
||||
// TODO: add this in later commits
|
||||
// pub(crate) gas_price: GasPrice,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn parse_optional_account(
|
||||
raw: Option<&String>,
|
||||
expected_prefix: &str,
|
||||
) -> Result<Option<AccountId>, NymdError> {
|
||||
if let Some(address) = raw {
|
||||
let parsed: AccountId = address
|
||||
.parse()
|
||||
.map_err(|_| NymdError::MalformedAccountAddress(address.clone()))?;
|
||||
if parsed.prefix() != expected_prefix {
|
||||
Err(NymdError::UnexpectedBech32Prefix {
|
||||
got: parsed.prefix().into(),
|
||||
expected: expected_prefix.into(),
|
||||
})
|
||||
} else {
|
||||
Ok(Some(parsed))
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_nym_network_details(details: &NymNetworkDetails) -> Result<Self, NymdError> {
|
||||
let prefix = &details.chain_details.bech32_account_prefix;
|
||||
Ok(Config {
|
||||
chain_details: details.chain_details.clone(),
|
||||
mixnet_contract_address: Self::parse_optional_account(
|
||||
details.contracts.mixnet_contract_address.as_ref(),
|
||||
prefix,
|
||||
)?,
|
||||
vesting_contract_address: Self::parse_optional_account(
|
||||
details.contracts.vesting_contract_address.as_ref(),
|
||||
prefix,
|
||||
)?,
|
||||
bandwidth_claim_contract_address: Self::parse_optional_account(
|
||||
details.contracts.bandwidth_claim_contract_address.as_ref(),
|
||||
prefix,
|
||||
)?,
|
||||
coconut_bandwidth_contract_address: Self::parse_optional_account(
|
||||
details
|
||||
.contracts
|
||||
.coconut_bandwidth_contract_address
|
||||
.as_ref(),
|
||||
prefix,
|
||||
)?,
|
||||
multisig_contract_address: Self::parse_optional_account(
|
||||
details.contracts.multisig_contract_address.as_ref(),
|
||||
prefix,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NymdClient<C> {
|
||||
client: C,
|
||||
mixnet_contract_address: AccountId,
|
||||
vesting_contract_address: AccountId,
|
||||
bandwidth_claim_contract_address: AccountId,
|
||||
coconut_bandwidth_contract_address: AccountId,
|
||||
multisig_contract_address: AccountId,
|
||||
config: Config,
|
||||
client_address: Option<Vec<AccountId>>,
|
||||
simulated_gas_multiplier: f32,
|
||||
}
|
||||
|
||||
impl<C> NymdClient<C> {
|
||||
pub fn with_mixnet_contract_address(mut self, address: AccountId) -> Self {
|
||||
self.mixnet_contract_address = address;
|
||||
self
|
||||
}
|
||||
pub fn with_vesting_contract_address(mut self, address: AccountId) -> Self {
|
||||
self.vesting_contract_address = address;
|
||||
self
|
||||
}
|
||||
pub fn with_bandwidth_claim_contract_address(mut self, address: AccountId) -> Self {
|
||||
self.bandwidth_claim_contract_address = address;
|
||||
self
|
||||
}
|
||||
pub fn with_coconut_bandwidth_contract_address(mut self, address: AccountId) -> Self {
|
||||
self.coconut_bandwidth_contract_address = address;
|
||||
self
|
||||
}
|
||||
pub fn with_multisig_contract_address(mut self, address: AccountId) -> Self {
|
||||
self.multisig_contract_address = address;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl NymdClient<QueryNymdClient> {
|
||||
pub fn connect<U>(endpoint: U) -> Result<NymdClient<QueryNymdClient>, NymdError>
|
||||
pub fn connect<U>(config: Config, endpoint: U) -> Result<NymdClient<QueryNymdClient>, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
Ok(NymdClient {
|
||||
client: QueryNymdClient::new(endpoint)?,
|
||||
config,
|
||||
client_address: None,
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
mixnet_contract_address: DEFAULT_NETWORK
|
||||
.mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing mixnet contract address"),
|
||||
vesting_contract_address: DEFAULT_NETWORK
|
||||
.vesting_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing vesting contract address"),
|
||||
bandwidth_claim_contract_address: DEFAULT_NETWORK
|
||||
.bandwidth_claim_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing bandwidth claim contract address"),
|
||||
coconut_bandwidth_contract_address: DEFAULT_NETWORK
|
||||
.coconut_bandwidth_contract_address()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -128,6 +153,7 @@ impl NymdClient<QueryNymdClient> {
|
||||
impl NymdClient<SigningNymdClient> {
|
||||
// maybe the wallet could be made into a generic, but for now, let's just have this one implementation
|
||||
pub fn connect_with_signer<U: Clone>(
|
||||
config: Config,
|
||||
network: config::defaults::all::Network,
|
||||
endpoint: U,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
@@ -136,40 +162,24 @@ impl NymdClient<SigningNymdClient> {
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let denom = network.mix_denom().base;
|
||||
let denom = network.base_mix_denom();
|
||||
let client_address = signer
|
||||
.try_derive_accounts()?
|
||||
.into_iter()
|
||||
.map(|account| account.address)
|
||||
.collect();
|
||||
let gas_price = gas_price.unwrap_or(GasPrice::new_with_default_price(denom)?);
|
||||
let gas_price = gas_price.unwrap_or(GasPrice::new_with_default_price(&denom)?);
|
||||
|
||||
Ok(NymdClient {
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, signer, gas_price)?,
|
||||
config,
|
||||
client_address: Some(client_address),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
mixnet_contract_address: DEFAULT_NETWORK
|
||||
.mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing mixnet contract address"),
|
||||
vesting_contract_address: DEFAULT_NETWORK
|
||||
.vesting_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing vesting contract address"),
|
||||
bandwidth_claim_contract_address: DEFAULT_NETWORK
|
||||
.bandwidth_claim_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing bandwidth claim contract address"),
|
||||
coconut_bandwidth_contract_address: DEFAULT_NETWORK
|
||||
.coconut_bandwidth_contract_address()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connect_with_mnemonic<U: Clone>(
|
||||
network: config::defaults::all::Network,
|
||||
config: Config,
|
||||
endpoint: U,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
gas_price: Option<GasPrice>,
|
||||
@@ -177,8 +187,8 @@ impl NymdClient<SigningNymdClient> {
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let prefix = network.bech32_prefix();
|
||||
let denom = network.mix_denom().base;
|
||||
let prefix = &config.chain_details.bech32_account_prefix;
|
||||
let denom = &config.chain_details.mix_denom.base;
|
||||
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?;
|
||||
let client_address = wallet
|
||||
.try_derive_accounts()?
|
||||
@@ -189,48 +199,82 @@ impl NymdClient<SigningNymdClient> {
|
||||
|
||||
Ok(NymdClient {
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, wallet, gas_price)?,
|
||||
config,
|
||||
client_address: Some(client_address),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
mixnet_contract_address: network
|
||||
.mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing mixnet contract address"),
|
||||
vesting_contract_address: network
|
||||
.vesting_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing vesting contract address"),
|
||||
bandwidth_claim_contract_address: network
|
||||
.bandwidth_claim_contract_address()
|
||||
.parse()
|
||||
.expect("Error parsing bandwidth claim contract address"),
|
||||
coconut_bandwidth_contract_address: network
|
||||
.coconut_bandwidth_contract_address()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
multisig_contract_address: network.multisig_contract_address().parse().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> NymdClient<C> {
|
||||
pub fn current_config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
|
||||
self.config.mixnet_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_vesting_contract_address(&mut self, address: AccountId) {
|
||||
self.config.vesting_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_bandwidth_claim_contract_address(&mut self, address: AccountId) {
|
||||
self.config.bandwidth_claim_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_coconut_bandwidth_contract_address(&mut self, address: AccountId) {
|
||||
self.config.coconut_bandwidth_contract_address = Some(address);
|
||||
}
|
||||
|
||||
pub fn set_multisig_contract_address(&mut self, address: AccountId) {
|
||||
self.config.multisig_contract_address = Some(address);
|
||||
}
|
||||
|
||||
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
|
||||
// note: what unwrap is doing here is just moving a failure that would have normally
|
||||
// occurred in `connect` when attempting to parse an empty address,
|
||||
// so it's not introducing new source of failure (just moves it)
|
||||
pub fn mixnet_contract_address(&self) -> &AccountId {
|
||||
&self.mixnet_contract_address
|
||||
self.config.mixnet_contract_address.as_ref().unwrap()
|
||||
}
|
||||
|
||||
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
|
||||
// note: what unwrap is doing here is just moving a failure that would have normally
|
||||
// occurred in `connect` when attempting to parse an empty address,
|
||||
// so it's not introducing new source of failure (just moves it)
|
||||
pub fn vesting_contract_address(&self) -> &AccountId {
|
||||
&self.vesting_contract_address
|
||||
self.config.vesting_contract_address.as_ref().unwrap()
|
||||
}
|
||||
|
||||
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
|
||||
// note: what unwrap is doing here is just moving a failure that would have normally
|
||||
// occurred in `connect` when attempting to parse an empty address,
|
||||
// so it's not introducing new source of failure (just moves it)
|
||||
pub fn bandwidth_claim_contract_address(&self) -> &AccountId {
|
||||
&self.bandwidth_claim_contract_address
|
||||
self.config
|
||||
.bandwidth_claim_contract_address
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
|
||||
// note: what unwrap is doing here is just moving a failure that would have normally
|
||||
// occurred in `connect` when attempting to parse an empty address,
|
||||
// so it's not introducing new source of failure (just moves it)
|
||||
pub fn coconut_bandwidth_contract_address(&self) -> &AccountId {
|
||||
&self.coconut_bandwidth_contract_address
|
||||
self.config
|
||||
.coconut_bandwidth_contract_address
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// TODO: this should get changed into Result<&AccountId, NymdError> (or Option<&AccountId> in future commits
|
||||
// note: what unwrap is doing here is just moving a failure that would have normally
|
||||
// occurred in `connect` when attempting to parse an empty address,
|
||||
// so it's not introducing new source of failure (just moves it)
|
||||
pub fn multisig_contract_address(&self) -> &AccountId {
|
||||
&self.multisig_contract_address
|
||||
self.config.multisig_contract_address.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
|
||||
|
||||
@@ -214,7 +214,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for prefix in prefixes {
|
||||
let addrs = match prefix {
|
||||
let addrs = match prefix.as_ref() {
|
||||
"nymt" => vec![
|
||||
"nymt1jw6mp7d5xqc7w6xm79lha27glmd0vdt339me94",
|
||||
"nymt1h5hgn94nsq4kh99rjj794hr5h5q6yfm23rjshv",
|
||||
@@ -229,7 +229,7 @@ mod tests {
|
||||
};
|
||||
for (idx, mnemonic) in mnemonics.iter().enumerate() {
|
||||
let wallet =
|
||||
DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.parse().unwrap())
|
||||
DirectSecp256k1HdWallet::from_mnemonic(&prefix, mnemonic.parse().unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
wallet.try_derive_accounts().unwrap()[0].address,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
DefaultNetworkDetails, DenomDetailsOwned, NymNetworkDetails, ValidatorDetails,
|
||||
MAINNET_DEFAULTS, QA_DEFAULTS, SANDBOX_DEFAULTS,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
DefaultNetworkDetails, DenomDetails, DenomDetailsOwned, ValidatorDetails, MAINNET_DEFAULTS,
|
||||
QA_DEFAULTS, SANDBOX_DEFAULTS,
|
||||
};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@@ -17,64 +15,95 @@ pub enum NetworkDefaultsError {
|
||||
MalformedNetworkProvided(String),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
// the reason for allowing it is that this is just a temporary solution
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum Network {
|
||||
QA,
|
||||
SANDBOX,
|
||||
MAINNET,
|
||||
CUSTOM { details: NymNetworkDetails },
|
||||
}
|
||||
|
||||
impl Network {
|
||||
fn details(&self) -> &DefaultNetworkDetails {
|
||||
pub fn new_custom(details: NymNetworkDetails) -> Self {
|
||||
Network::CUSTOM { details }
|
||||
}
|
||||
|
||||
pub fn details(&self) -> NymNetworkDetails {
|
||||
match self {
|
||||
Self::QA => &QA_DEFAULTS,
|
||||
Self::SANDBOX => &SANDBOX_DEFAULTS,
|
||||
Self::MAINNET => &MAINNET_DEFAULTS,
|
||||
Self::QA => (&*QA_DEFAULTS).into(),
|
||||
Self::SANDBOX => (&*SANDBOX_DEFAULTS).into(),
|
||||
Self::MAINNET => (&*MAINNET_DEFAULTS).into(),
|
||||
// I dislike the clone here, but for compatibility reasons we cannot define other networks with `NymNetworkDetails` directly yet
|
||||
Self::CUSTOM { details } => details.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bech32_prefix(&self) -> &str {
|
||||
self.details().bech32_prefix
|
||||
pub fn bech32_prefix(&self) -> String {
|
||||
self.details().chain_details.bech32_account_prefix
|
||||
}
|
||||
|
||||
pub fn mix_denom(&self) -> &DenomDetails {
|
||||
&self.details().mix_denom
|
||||
pub fn mix_denom(&self) -> DenomDetailsOwned {
|
||||
self.details().chain_details.mix_denom
|
||||
}
|
||||
|
||||
pub fn stake_denom(&self) -> &DenomDetails {
|
||||
&self.details().stake_denom
|
||||
pub fn stake_denom(&self) -> DenomDetailsOwned {
|
||||
self.details().chain_details.stake_denom
|
||||
}
|
||||
|
||||
pub fn mixnet_contract_address(&self) -> &str {
|
||||
self.details().mixnet_contract_address
|
||||
pub fn base_mix_denom(&self) -> String {
|
||||
self.details().chain_details.mix_denom.base
|
||||
}
|
||||
|
||||
pub fn vesting_contract_address(&self) -> &str {
|
||||
self.details().vesting_contract_address
|
||||
pub fn base_stake_denom(&self) -> String {
|
||||
self.details().chain_details.stake_denom.base
|
||||
}
|
||||
|
||||
pub fn bandwidth_claim_contract_address(&self) -> &str {
|
||||
self.details().bandwidth_claim_contract_address
|
||||
pub fn mixnet_contract_address(&self) -> Option<String> {
|
||||
self.details().contracts.mixnet_contract_address
|
||||
}
|
||||
|
||||
pub fn coconut_bandwidth_contract_address(&self) -> &str {
|
||||
self.details().coconut_bandwidth_contract_address
|
||||
pub fn vesting_contract_address(&self) -> Option<String> {
|
||||
self.details().contracts.vesting_contract_address
|
||||
}
|
||||
|
||||
pub fn multisig_contract_address(&self) -> &str {
|
||||
self.details().multisig_contract_address
|
||||
pub fn bandwidth_claim_contract_address(&self) -> Option<String> {
|
||||
self.details().contracts.bandwidth_claim_contract_address
|
||||
}
|
||||
|
||||
pub fn coconut_bandwidth_contract_address(&self) -> Option<String> {
|
||||
self.details().contracts.coconut_bandwidth_contract_address
|
||||
}
|
||||
|
||||
pub fn multisig_contract_address(&self) -> Option<String> {
|
||||
self.details().contracts.multisig_contract_address
|
||||
}
|
||||
|
||||
pub fn validators(&self) -> Vec<ValidatorDetails> {
|
||||
self.details().endpoints
|
||||
}
|
||||
|
||||
// only used in mixnet contract tests, but I don't want to be messing with that code now
|
||||
pub fn rewarding_validator_address(&self) -> &str {
|
||||
self.details().rewarding_validator_address
|
||||
match self {
|
||||
Network::QA => crate::qa::REWARDING_VALIDATOR_ADDRESS,
|
||||
Network::SANDBOX => crate::sandbox::REWARDING_VALIDATOR_ADDRESS,
|
||||
Network::MAINNET => crate::mainnet::REWARDING_VALIDATOR_ADDRESS,
|
||||
Network::CUSTOM { .. } => {
|
||||
panic!("rewarding validator address is unavailable for a custom network")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this should be handled differently, but I don't want to break compatibility
|
||||
pub fn statistics_service_url(&self) -> &str {
|
||||
self.details().statistics_service_url
|
||||
}
|
||||
|
||||
pub fn validators(&self) -> impl Iterator<Item = &ValidatorDetails> {
|
||||
self.details().validators.iter()
|
||||
match self {
|
||||
Network::MAINNET => crate::mainnet::STATISTICS_SERVICE_DOMAIN_ADDRESS,
|
||||
_ => {
|
||||
panic!("statistics service url is only available for mainnet!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +128,7 @@ impl fmt::Display for Network {
|
||||
Network::QA => f.write_str("QA"),
|
||||
Network::SANDBOX => f.write_str("Sandbox"),
|
||||
Network::MAINNET => f.write_str("Mainnet"),
|
||||
Network::CUSTOM { .. } => f.write_str("Custom"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,6 +160,31 @@ impl From<&DefaultNetworkDetails> for NetworkDetails {
|
||||
}
|
||||
}
|
||||
|
||||
// this also has to exist for compatibility reasons since I don't want to be touching the wallet now
|
||||
impl From<NymNetworkDetails> for NetworkDetails {
|
||||
fn from(details: NymNetworkDetails) -> Self {
|
||||
NetworkDetails {
|
||||
bech32_prefix: details.chain_details.bech32_account_prefix,
|
||||
mix_denom: details.chain_details.mix_denom,
|
||||
stake_denom: details.chain_details.stake_denom,
|
||||
mixnet_contract_address: details
|
||||
.contracts
|
||||
.mixnet_contract_address
|
||||
.unwrap_or_default(),
|
||||
vesting_contract_address: details
|
||||
.contracts
|
||||
.vesting_contract_address
|
||||
.unwrap_or_default(),
|
||||
bandwidth_claim_contract_address: details
|
||||
.contracts
|
||||
.bandwidth_claim_contract_address
|
||||
.unwrap_or_default(),
|
||||
statistics_service_url: "".to_string(),
|
||||
validators: details.endpoints,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkDetails {
|
||||
pub fn base_mix_denom(&self) -> &str {
|
||||
&self.mix_denom.base
|
||||
@@ -146,7 +201,10 @@ impl SupportedNetworks {
|
||||
SupportedNetworks {
|
||||
networks: support
|
||||
.into_iter()
|
||||
.map(|n| (n, n.details().into()))
|
||||
.map(|n| {
|
||||
let details = n.details().into();
|
||||
(n, details)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub mod sandbox;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(network = "mainnet")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::MAINNET;
|
||||
pub const MIX_DENOM: DenomDetails = mainnet::MIX_DENOM;
|
||||
pub const MIX_DENOM: DenomDetails = mainnet::MIX_DENOM;
|
||||
pub const STAKE_DENOM: DenomDetails = mainnet::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_CONTRACT_ADDRESS;
|
||||
@@ -25,7 +25,7 @@ cfg_if::cfg_if! {
|
||||
|
||||
} else if #[cfg(network = "qa")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::QA;
|
||||
pub const MIX_DENOM: DenomDetails = qa::MIX_DENOM;
|
||||
pub const MIX_DENOM: DenomDetails = qa::MIX_DENOM;
|
||||
pub const STAKE_DENOM: DenomDetails = qa::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_CONTRACT_ADDRESS;
|
||||
@@ -41,10 +41,157 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ChainDetails {
|
||||
pub bech32_account_prefix: String,
|
||||
pub mix_denom: DenomDetailsOwned,
|
||||
pub stake_denom: DenomDetailsOwned,
|
||||
}
|
||||
|
||||
// by default we assume the same defaults as mainnet, i.e. same prefixes and denoms
|
||||
impl Default for ChainDetails {
|
||||
fn default() -> Self {
|
||||
ChainDetails {
|
||||
bech32_account_prefix: mainnet::BECH32_PREFIX.into(),
|
||||
mix_denom: mainnet::MIX_DENOM.into(),
|
||||
stake_denom: mainnet::STAKE_DENOM.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct NymContracts {
|
||||
pub mixnet_contract_address: Option<String>,
|
||||
pub vesting_contract_address: Option<String>,
|
||||
pub bandwidth_claim_contract_address: Option<String>,
|
||||
pub coconut_bandwidth_contract_address: Option<String>,
|
||||
pub multisig_contract_address: Option<String>,
|
||||
}
|
||||
|
||||
// I wanted to use the simpler `NetworkDetails` name, but there's a clash
|
||||
// with `NetworkDetails` defined in all.rs...
|
||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct NymNetworkDetails {
|
||||
pub chain_details: ChainDetails,
|
||||
pub endpoints: Vec<ValidatorDetails>,
|
||||
pub contracts: NymContracts,
|
||||
}
|
||||
|
||||
impl NymNetworkDetails {
|
||||
pub fn new() -> Self {
|
||||
NymNetworkDetails::default()
|
||||
}
|
||||
|
||||
pub fn new_qa() -> Self {
|
||||
(&*QA_DEFAULTS).into()
|
||||
}
|
||||
|
||||
pub fn new_sandbox() -> Self {
|
||||
(&*SANDBOX_DEFAULTS).into()
|
||||
}
|
||||
|
||||
pub fn new_mainnet() -> Self {
|
||||
(&*MAINNET_DEFAULTS).into()
|
||||
}
|
||||
|
||||
pub fn current_default() -> Self {
|
||||
// backwards compatibility reasons
|
||||
DEFAULT_NETWORK.details()
|
||||
}
|
||||
|
||||
pub fn with_bech32_account_prefix<S: Into<String>>(mut self, prefix: S) -> Self {
|
||||
self.chain_details.bech32_account_prefix = prefix.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_mix_denom(mut self, mix_denom: DenomDetailsOwned) -> Self {
|
||||
self.chain_details.mix_denom = mix_denom;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_stake_denom(mut self, stake_denom: DenomDetailsOwned) -> Self {
|
||||
self.chain_details.stake_denom = stake_denom;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_base_mix_denom<S: Into<String>>(mut self, base_mix_denom: S) -> Self {
|
||||
self.chain_details.mix_denom = DenomDetailsOwned::base_only(base_mix_denom.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_base_stake_denom<S: Into<String>>(mut self, base_stake_denom: S) -> Self {
|
||||
self.chain_details.stake_denom = DenomDetailsOwned::base_only(base_stake_denom.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_validator_endpoint(mut self, endpoint: ValidatorDetails) -> Self {
|
||||
self.endpoints.push(endpoint);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_mixnet_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
|
||||
self.contracts.mixnet_contract_address = contract.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_vesting_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
|
||||
self.contracts.vesting_contract_address = contract.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_bandwidth_claim_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
|
||||
self.contracts.bandwidth_claim_contract_address = contract.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_coconut_bandwidth_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
|
||||
self.contracts.coconut_bandwidth_contract_address = contract.map(Into::into);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_multisig_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
|
||||
self.contracts.multisig_contract_address = contract.map(Into::into);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// This conversion only exists for convenience reasons until
|
||||
// we can completely phase out `DefaultNetworkDetails`
|
||||
impl<'a> From<&'a DefaultNetworkDetails> for NymNetworkDetails {
|
||||
fn from(details: &'a DefaultNetworkDetails) -> Self {
|
||||
fn parse_optional_str(raw: &str) -> Option<String> {
|
||||
if raw.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(raw.into())
|
||||
}
|
||||
}
|
||||
|
||||
NymNetworkDetails {
|
||||
chain_details: ChainDetails {
|
||||
bech32_account_prefix: details.bech32_prefix.into(),
|
||||
mix_denom: details.mix_denom.into(),
|
||||
stake_denom: details.stake_denom.into(),
|
||||
},
|
||||
endpoints: details.validators.clone(),
|
||||
contracts: NymContracts {
|
||||
mixnet_contract_address: parse_optional_str(details.mixnet_contract_address),
|
||||
vesting_contract_address: parse_optional_str(details.vesting_contract_address),
|
||||
bandwidth_claim_contract_address: parse_optional_str(
|
||||
details.bandwidth_claim_contract_address,
|
||||
),
|
||||
coconut_bandwidth_contract_address: parse_optional_str(
|
||||
details.coconut_bandwidth_contract_address,
|
||||
),
|
||||
multisig_contract_address: parse_optional_str(details.multisig_contract_address),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Since these are lazily constructed, we can afford to switch some of them to stronger types in the
|
||||
// future. If we do this, and also get rid of the references we could potentially unify with
|
||||
// `NetworkDetails`.
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultNetworkDetails {
|
||||
bech32_prefix: &'static str,
|
||||
mix_denom: DenomDetails,
|
||||
@@ -54,6 +201,7 @@ pub struct DefaultNetworkDetails {
|
||||
bandwidth_claim_contract_address: &'static str,
|
||||
coconut_bandwidth_contract_address: &'static str,
|
||||
multisig_contract_address: &'static str,
|
||||
#[allow(dead_code)]
|
||||
rewarding_validator_address: &'static str,
|
||||
statistics_service_url: &'static str,
|
||||
validators: Vec<ValidatorDetails>,
|
||||
@@ -119,7 +267,7 @@ impl DenomDetails {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct DenomDetailsOwned {
|
||||
pub base: String,
|
||||
pub display: String,
|
||||
@@ -137,27 +285,38 @@ impl From<DenomDetails> for DenomDetailsOwned {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
impl DenomDetailsOwned {
|
||||
pub fn base_only(base: String) -> Self {
|
||||
DenomDetailsOwned {
|
||||
base: base.clone(),
|
||||
display: base,
|
||||
display_exponent: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ValidatorDetails {
|
||||
// it is assumed those values are always valid since they're being provided in our defaults file
|
||||
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<String>,
|
||||
// TODO: I'd argue this one should also have a field like `gas_price` since its a validator-specific setting
|
||||
}
|
||||
|
||||
impl ValidatorDetails {
|
||||
pub fn new(nymd_url: &str, api_url: Option<&str>) -> Self {
|
||||
pub fn new<S: Into<String>>(nymd_url: S, api_url: Option<S>) -> Self {
|
||||
ValidatorDetails {
|
||||
nymd_url: nymd_url.to_string(),
|
||||
api_url: api_url.map(ToString::to_string),
|
||||
nymd_url: nymd_url.into(),
|
||||
api_url: api_url.map(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_name(nymd_url: &str, api_url: Option<&str>) -> Self {
|
||||
pub fn new_nymd_only<S: Into<String>>(nymd_url: S) -> Self {
|
||||
ValidatorDetails {
|
||||
nymd_url: nymd_url.to_string(),
|
||||
api_url: api_url.map(ToString::to_string),
|
||||
nymd_url: nymd_url.into(),
|
||||
api_url: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +343,7 @@ pub fn default_statistics_service_url() -> Url {
|
||||
pub fn default_nymd_endpoints() -> Vec<Url> {
|
||||
DEFAULT_NETWORK
|
||||
.validators()
|
||||
.iter()
|
||||
.map(ValidatorDetails::nymd_url)
|
||||
.collect()
|
||||
}
|
||||
@@ -191,6 +351,7 @@ pub fn default_nymd_endpoints() -> Vec<Url> {
|
||||
pub fn default_api_endpoints() -> Vec<Url> {
|
||||
DEFAULT_NETWORK
|
||||
.validators()
|
||||
.iter()
|
||||
.filter_map(ValidatorDetails::api_url)
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ pub enum TypesError {
|
||||
#[from]
|
||||
source: cosmwasm_std::DecimalRangeExceeded,
|
||||
},
|
||||
#[error("No validator API URL configured")]
|
||||
NoValidatorApiUrlConfigured,
|
||||
#[error("{0} is not a valid amount string")]
|
||||
InvalidAmount(String),
|
||||
#[error("{0} is not a valid denomination string")]
|
||||
@@ -78,6 +80,7 @@ impl From<ValidatorClientError> for TypesError {
|
||||
ValidatorClientError::ValidatorAPIError { source } => source.into(),
|
||||
ValidatorClientError::MalformedUrlProvided(e) => e.into(),
|
||||
ValidatorClientError::NymdError(e) => e.into(),
|
||||
ValidatorClientError::NoAPIUrlAvailable => TypesError::NoValidatorApiUrlConfigured,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub mod helpers {
|
||||
let env = mock_env();
|
||||
let info = mock_info("creator", &[]);
|
||||
instantiate(deps.as_mut(), env.clone(), info, msg).unwrap();
|
||||
return deps;
|
||||
deps
|
||||
}
|
||||
|
||||
pub fn mock_app(init_funds: &[Coin]) -> App {
|
||||
|
||||
@@ -26,9 +26,13 @@ pub(crate) fn new_validator_client() -> ThreadsafeValidatorClient {
|
||||
let nymd_url = default_nymd_endpoints()[0].clone();
|
||||
let api_url = default_api_endpoints()[0].clone();
|
||||
|
||||
let client_config = validator_client::Config::new(DEFAULT_NETWORK, nymd_url, api_url);
|
||||
let client_config =
|
||||
validator_client::Config::try_from_nym_network_details(&DEFAULT_NETWORK.details())
|
||||
.expect("failed to construct valid validator client config with the provided network")
|
||||
.with_urls(nymd_url, api_url);
|
||||
|
||||
ThreadsafeValidatorClient(Arc::new(
|
||||
validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!"),
|
||||
validator_client::Client::new_query(client_config, DEFAULT_NETWORK)
|
||||
.expect("Failed to connect to nymd!"),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::str::FromStr;
|
||||
use web3::contract::tokens::Detokenize;
|
||||
use web3::contract::{Contract, Error};
|
||||
use web3::ethabi::Token;
|
||||
use web3::transports::Http;
|
||||
use web3::types::{BlockNumber, FilterBuilder, H256};
|
||||
use web3::Web3;
|
||||
|
||||
use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError;
|
||||
use bandwidth_claim_contract::msg::ExecuteMsg;
|
||||
use bandwidth_claim_contract::payment::LinkPaymentData;
|
||||
@@ -16,7 +8,14 @@ use credentials::token::bandwidth::TokenCredential;
|
||||
use crypto::asymmetric::identity::{PublicKey, Signature, SIGNATURE_LENGTH};
|
||||
use gateway_client::bandwidth::eth_contract;
|
||||
use network_defaults::{ETH_EVENT_NAME, ETH_MIN_BLOCK_DEPTH};
|
||||
use std::str::FromStr;
|
||||
use validator_client::nymd::{AccountId, NymdClient, SigningNymdClient};
|
||||
use web3::contract::tokens::Detokenize;
|
||||
use web3::contract::{Contract, Error};
|
||||
use web3::ethabi::Token;
|
||||
use web3::transports::Http;
|
||||
use web3::types::{BlockNumber, FilterBuilder, H256};
|
||||
use web3::Web3;
|
||||
|
||||
pub(crate) struct ERC20Bridge {
|
||||
// This is needed because web3's Contract doesn't sufficiently expose it's eth interface
|
||||
|
||||
@@ -27,6 +27,7 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
|
||||
use crate::node::client_handling::websocket::connection_handler::eth_events::ERC20Bridge;
|
||||
#[cfg(feature = "coconut")]
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use validator_client::nymd;
|
||||
|
||||
use self::storage::PersistentStorage;
|
||||
|
||||
@@ -248,8 +249,11 @@ where
|
||||
.choose(&mut thread_rng())
|
||||
.expect("The list of validators is empty");
|
||||
|
||||
let client_config = nymd::Config::try_from_nym_network_details(&DEFAULT_NETWORK.details())
|
||||
.expect("failed to construct valid validator client config with the provided network");
|
||||
|
||||
validator_client::nymd::NymdClient::connect_with_mnemonic(
|
||||
DEFAULT_NETWORK,
|
||||
client_config,
|
||||
validator_nymd.as_ref(),
|
||||
self.config.get_cosmos_mnemonic(),
|
||||
None,
|
||||
|
||||
Generated
+4
@@ -5508,6 +5508,10 @@ dependencies = [
|
||||
name = "validator-api-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"coconut-interface",
|
||||
"cosmrs",
|
||||
"getset",
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
|
||||
@@ -65,6 +65,7 @@ impl From<ConfigNetwork> for Network {
|
||||
ConfigNetwork::QA => Network::QA,
|
||||
ConfigNetwork::SANDBOX => Network::SANDBOX,
|
||||
ConfigNetwork::MAINNET => Network::MAINNET,
|
||||
ConfigNetwork::CUSTOM { .. } => panic!("custom network is not supported"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,9 @@ impl From<ValidatorClientError> for BackendError {
|
||||
ValidatorClientError::ValidatorAPIError { source } => source.into(),
|
||||
ValidatorClientError::MalformedUrlProvided(e) => e.into(),
|
||||
ValidatorClientError::NymdError(e) => e.into(),
|
||||
ValidatorClientError::NoAPIUrlAvailable => {
|
||||
TypesError::NoValidatorApiUrlConfigured.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ async fn _connect_with_mnemonic(
|
||||
let default_network: WalletNetwork = config::defaults::DEFAULT_NETWORK.into();
|
||||
let client_for_default_network = clients
|
||||
.iter()
|
||||
.find(|client| WalletNetwork::from(client.network) == default_network);
|
||||
.find(|client| WalletNetwork::from(client.network.clone()) == default_network);
|
||||
let account_for_default_network = match client_for_default_network {
|
||||
Some(client) => Ok(Account::new(
|
||||
client.nymd.mixnet_contract_address().to_string(),
|
||||
@@ -175,7 +175,7 @@ async fn _connect_with_mnemonic(
|
||||
w_state.logout();
|
||||
}
|
||||
for client in clients {
|
||||
let network: WalletNetwork = client.network.into();
|
||||
let network: WalletNetwork = client.network.clone().into();
|
||||
let mut w_state = state.write().await;
|
||||
w_state.add_client(network, client);
|
||||
}
|
||||
@@ -252,15 +252,21 @@ fn create_clients(
|
||||
log::info!("Connecting to: nymd_url: {nymd_url} for {network}");
|
||||
log::info!("Connecting to: api_url: {api_url} for {network}");
|
||||
|
||||
let mut client = validator_client::Client::new_signing(
|
||||
validator_client::Config::new(network.into(), nymd_url, api_url)
|
||||
.with_mixnode_contract_address(config.get_mixnet_contract_address(network))
|
||||
.with_vesting_contract_address(config.get_vesting_contract_address(network))
|
||||
.with_bandwidth_claim_contract_address(
|
||||
config.get_bandwidth_claim_contract_address(network),
|
||||
),
|
||||
mnemonic.clone(),
|
||||
)?;
|
||||
let network_details = Network::from(network)
|
||||
.details()
|
||||
.with_mixnet_contract(Some(config.get_mixnet_contract_address(network).as_ref()))
|
||||
.with_vesting_contract(Some(config.get_vesting_contract_address(network).as_ref()))
|
||||
.with_bandwidth_claim_contract(Some(
|
||||
config
|
||||
.get_bandwidth_claim_contract_address(network)
|
||||
.as_ref(),
|
||||
));
|
||||
|
||||
let config = validator_client::Config::try_from_nym_network_details(&network_details)?
|
||||
.with_urls(nymd_url, api_url);
|
||||
|
||||
let mut client =
|
||||
validator_client::Client::new_signing(config, network.into(), mnemonic.clone())?;
|
||||
client.set_nymd_simulated_gas_multiplier(CUSTOM_SIMULATED_GAS_MULTIPLIER);
|
||||
clients.push(client);
|
||||
}
|
||||
@@ -435,7 +441,7 @@ pub async fn add_account_for_password(
|
||||
let address = {
|
||||
let state = state.read().await;
|
||||
let network: Network = state.current_network().into();
|
||||
derive_address(mnemonic, network.bech32_prefix())?.to_string()
|
||||
derive_address(mnemonic, &network.bech32_prefix())?.to_string()
|
||||
};
|
||||
|
||||
// Re-read all the acccounts from the wallet to reset the state, rather than updating it
|
||||
@@ -477,7 +483,7 @@ async fn set_state_with_all_accounts(
|
||||
let config_network: Network = network.into();
|
||||
(
|
||||
network,
|
||||
derive_address(mnemonic.clone(), config_network.bech32_prefix()).unwrap(),
|
||||
derive_address(mnemonic.clone(), &config_network.bech32_prefix()).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -71,6 +71,9 @@ impl OptionalStatsProviderConfig {
|
||||
network_defaults::all::Network::MAINNET => self.mainnet.clone(),
|
||||
network_defaults::all::Network::SANDBOX => self.sandbox.clone(),
|
||||
network_defaults::all::Network::QA => self.qa.clone(),
|
||||
network_defaults::all::Network::CUSTOM { .. } => {
|
||||
panic!("custom network is not supported")
|
||||
}
|
||||
};
|
||||
entry_config.map(|e| e.stats_client_address)
|
||||
}
|
||||
|
||||
@@ -108,7 +108,9 @@ impl Default for Base {
|
||||
local_validator: DEFAULT_LOCAL_VALIDATOR
|
||||
.parse()
|
||||
.expect("default local validator is malformed!"),
|
||||
mixnet_contract_address: DEFAULT_NETWORK.mixnet_contract_address().to_string(),
|
||||
mixnet_contract_address: DEFAULT_NETWORK
|
||||
.mixnet_contract_address()
|
||||
.expect("mixnet contract address is unavailable"),
|
||||
mnemonic: "exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,16 +53,16 @@ impl Client<QueryNymdClient> {
|
||||
.unwrap();
|
||||
let nymd_url = config.get_nymd_validator_url();
|
||||
let network = DEFAULT_NETWORK;
|
||||
let details = network
|
||||
.details()
|
||||
.with_mixnet_contract(Some(config.get_mixnet_contract_address()));
|
||||
|
||||
let mixnet_contract = config
|
||||
.get_mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("the mixnet contract address is invalid!");
|
||||
let client_config = validator_client::Config::try_from_nym_network_details(&details)
|
||||
.expect("failed to construct valid validator client config with the provided network")
|
||||
.with_urls(nymd_url, api_url);
|
||||
|
||||
let client_config = validator_client::Config::new(network, nymd_url, api_url)
|
||||
.with_mixnode_contract_address(mixnet_contract);
|
||||
let inner =
|
||||
validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!");
|
||||
let inner = validator_client::Client::new_query(client_config, network)
|
||||
.expect("Failed to connect to nymd!");
|
||||
|
||||
Client(Arc::new(RwLock::new(inner)))
|
||||
}
|
||||
@@ -76,20 +76,22 @@ impl Client<SigningNymdClient> {
|
||||
.parse()
|
||||
.unwrap();
|
||||
let nymd_url = config.get_nymd_validator_url();
|
||||
let network = DEFAULT_NETWORK;
|
||||
|
||||
let mixnet_contract = config
|
||||
.get_mixnet_contract_address()
|
||||
.parse()
|
||||
.expect("the mixnet contract address is invalid!");
|
||||
let network = DEFAULT_NETWORK;
|
||||
let details = network
|
||||
.details()
|
||||
.with_mixnet_contract(Some(config.get_mixnet_contract_address()));
|
||||
|
||||
let client_config = validator_client::Config::try_from_nym_network_details(&details)
|
||||
.expect("failed to construct valid validator client config with the provided network")
|
||||
.with_urls(nymd_url, api_url);
|
||||
|
||||
let mnemonic = config
|
||||
.get_mnemonic()
|
||||
.parse()
|
||||
.expect("the mnemonic is invalid!");
|
||||
|
||||
let client_config = validator_client::Config::new(network, nymd_url, api_url)
|
||||
.with_mixnode_contract_address(mixnet_contract);
|
||||
let inner = validator_client::Client::new_signing(client_config, mnemonic)
|
||||
let inner = validator_client::Client::new_signing(client_config, network, mnemonic)
|
||||
.expect("Failed to connect to nymd!");
|
||||
|
||||
Client(Arc::new(RwLock::new(inner)))
|
||||
|
||||
Reference in New Issue
Block a user