use super::*;
use std::ops::Not;
#[cfg(feature = "network")]
pub mod mainnet {
use crate::ApiUrlConst;
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
#[cfg(feature = "network")]
pub const NYM_APIS: &[ApiUrlConst] = &[
ApiUrlConst {
url: NYM_API,
front_hosts: None,
},
ApiUrlConst {
url: "https://nym-frontdoor.global.ssl.fastly.net/api/",
front_hosts: Some(&["yelp.global.ssl.fastly.net"]),
},
ApiUrlConst {
url: "https://cdn1.media-platform.net/api/",
front_hosts: None,
},
];
pub const NYM_VPN_API: &str = "https://nymvpn.com/api/";
#[cfg(feature = "network")]
pub const NYM_VPN_APIS: &[ApiUrlConst] = &[
ApiUrlConst {
url: NYM_VPN_API,
front_hosts: None,
},
ApiUrlConst {
url: "https://nymvpn-frontdoor.global.ssl.fastly.net/api/",
front_hosts: Some(&["yelp.global.ssl.fastly.net"]),
},
ApiUrlConst {
url: "https://edge1.streaming-gateway.com/api/",
front_hosts: None,
},
];
}
#[cfg(feature = "network")]
pub mod sandbox {
use crate::ApiUrlConst;
pub const NYM_VPN_API: &str =
"https://nym-vpn-api-git-deploy-sandbox-nyx-network-staging.vercel.app/api/";
pub const NYM_VPN_APIS: &[ApiUrlConst] = &[
ApiUrlConst {
url: NYM_VPN_API,
front_hosts: Some(&["vercel.app", "vercel.com"]),
},
ApiUrlConst {
url: "https://nym-frontdoor.vercel.app/sandbox/nym-vpn-api/",
front_hosts: Some(&["vercel.app", "vercel.com"]),
},
];
pub const NYM_APIS: &[ApiUrlConst] = &[
ApiUrlConst {
url: "https://sandbox-nym-api1.nymtech.net/api/",
front_hosts: None,
},
ApiUrlConst {
url: "https://nym-frontdoor.vercel.app/sandbox/nym-api/",
front_hosts: Some(&["vercel.app", "vercel.com"]),
},
];
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct NymNetworkDetails {
pub network_name: String,
pub chain_details: ChainDetails,
pub endpoints: Vec<ValidatorDetails>,
pub contracts: NymContracts,
pub nym_api_urls: Option<Vec<ApiUrl>>,
pub nym_vpn_api_urls: Option<Vec<ApiUrl>>,
pub nym_vpn_api_url: Option<String>,
}
impl Default for NymNetworkDetails {
fn default() -> Self {
NymNetworkDetails::new_mainnet()
}
}
impl NymNetworkDetails {
pub fn new_empty() -> Self {
v2::NymNetworkDetails::new_empty().into()
}
#[cfg(feature = "env")]
pub fn new_from_env() -> Self {
v2::NymNetworkDetails::new_from_env().into()
}
pub fn new_mainnet() -> Self {
let out: NymNetworkDetails = v2::NymNetworkDetails::new_mainnet().into();
out.with_pinned_api_urls(crate::mainnet::NETWORK_NAME)
}
#[must_use]
pub fn with_pinned_api_urls(mut self, network_name: &str) -> Self {
fn parse_optional_str(raw: &str) -> Option<String> {
raw.is_empty().not().then(|| raw.into())
}
let (vpn_api, apis, vpn_apis) = match network_name {
crate::mainnet::NETWORK_NAME => (
mainnet::NYM_VPN_API,
mainnet::NYM_APIS,
mainnet::NYM_VPN_APIS,
),
crate::sandbox::NETWORK_NAME => (
sandbox::NYM_VPN_API,
sandbox::NYM_APIS,
sandbox::NYM_VPN_APIS,
),
_ => return self,
};
self.nym_vpn_api_url = parse_optional_str(vpn_api);
self.nym_api_urls = Some(apis.iter().copied().map(Into::into).collect());
self.nym_vpn_api_urls = Some(vpn_apis.iter().copied().map(Into::into).collect());
self
}
#[cfg(feature = "env")]
pub fn export_to_env(self) {
let v2: v2::NymNetworkDetails = self.into();
v2.export_to_env();
}
pub fn default_gas_price_amount(&self) -> f64 {
GAS_PRICE_AMOUNT
}
#[must_use]
pub fn with_network_name(mut self, network_name: String) -> Self {
self.network_name = network_name;
self
}
#[must_use]
pub fn with_chain_details(mut self, chain_details: ChainDetails) -> Self {
self.chain_details = chain_details;
self
}
#[must_use]
pub fn with_bech32_account_prefix<S: Into<String>>(mut self, prefix: S) -> Self {
self.chain_details.bech32_account_prefix = prefix.into();
self
}
#[must_use]
pub fn with_mix_denom(mut self, mix_denom: DenomDetailsOwned) -> Self {
self.chain_details.mix_denom = mix_denom;
self
}
#[must_use]
pub fn with_stake_denom(mut self, stake_denom: DenomDetailsOwned) -> Self {
self.chain_details.stake_denom = stake_denom;
self
}
#[must_use]
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
}
#[must_use]
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
}
#[must_use]
pub fn with_additional_validator_endpoint(mut self, endpoint: ValidatorDetails) -> Self {
self.endpoints.push(endpoint);
self
}
#[must_use]
pub fn with_validator_endpoint(mut self, endpoint: ValidatorDetails) -> Self {
self.endpoints = vec![endpoint];
self
}
#[must_use]
pub fn with_contracts(mut self, contracts: NymContracts) -> Self {
self.contracts = contracts;
self
}
#[must_use]
pub fn with_mixnet_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.mixnet_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_vesting_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.vesting_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_node_families_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.node_families_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_directory_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.directory_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_geolocation_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.geolocation_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_ecash_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.ecash_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_group_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.group_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_multisig_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.multisig_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_coconut_dkg_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.coconut_dkg_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_performance_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.performance_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_network_monitors_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.network_monitors_contract_address = contract.map(Into::into);
self
}
pub fn set_nym_api_urls<U: Into<ApiUrl>>(&mut self, urls: Vec<U>) {
let urls: Vec<ApiUrl> = urls.into_iter().map(Into::into).collect();
self.nym_api_urls = (!urls.is_empty()).then_some(urls);
}
#[must_use]
pub fn with_nym_api_urls<U: Into<ApiUrl>>(mut self, urls: Vec<U>) -> Self {
self.set_nym_api_urls(urls);
self
}
pub fn set_nym_vpn_api_urls<U: Into<ApiUrl>>(&mut self, urls: Vec<U>) {
let urls: Vec<ApiUrl> = urls.into_iter().map(Into::into).collect();
if urls.is_empty() {
self.nym_vpn_api_urls = None;
self.nym_vpn_api_url = None
} else {
self.nym_vpn_api_url = Some(urls.first().expect("checked non-empty above").url.clone());
self.nym_vpn_api_urls = Some(urls);
}
}
#[must_use]
pub fn with_nym_vpn_api_urls<U: Into<ApiUrl>>(mut self, urls: Vec<U>) -> Self {
self.set_nym_vpn_api_urls(urls);
self
}
pub fn nym_api_urls(&self) -> Vec<ApiUrl> {
if let Some(urls) = &self.nym_api_urls
&& !urls.is_empty()
{
return urls.clone();
}
self.endpoints
.iter()
.filter_map(|e| e.api_url())
.map(ApiUrl::from)
.collect()
}
pub fn nym_vpn_api_urls(&self) -> Vec<ApiUrl> {
self.nym_vpn_api_urls.clone().unwrap_or_default()
}
}