wip
This commit is contained in:
Generated
+1
@@ -4885,6 +4885,7 @@ dependencies = [
|
||||
"colored",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"cw3",
|
||||
"cw4",
|
||||
"eyre",
|
||||
|
||||
@@ -45,6 +45,7 @@ cosmrs = { workspace = true, features = ["bip32", "cosmwasm"] }
|
||||
tendermint-rpc = { workspace = true }
|
||||
|
||||
eyre = { version = "0.6", optional = true }
|
||||
cw-utils = { workspace = true }
|
||||
cw3 = { workspace = true }
|
||||
cw4 = { workspace = true }
|
||||
prost = { version = "0.11", default-features = false }
|
||||
|
||||
@@ -16,9 +16,8 @@ pub use nym_mixnet_contract_common::{
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
use crate::nyxd::contract_traits::{DkgQueryClient, MixnetQueryClient};
|
||||
#[cfg(feature = "http-client")]
|
||||
use crate::nyxd::QueryNyxdClient;
|
||||
// use crate::nyxd::contract_traits::{DkgQueryClient, MixnetQueryClient};
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{self, CosmWasmClient, NyxdClient};
|
||||
use nym_api_requests::models::MixNodeBondAnnotated;
|
||||
use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare};
|
||||
@@ -31,11 +30,11 @@ use nym_mixnet_contract_common::{
|
||||
};
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use std::str::FromStr;
|
||||
use tendermint_rpc::HttpClient;
|
||||
|
||||
#[cfg(all(feature = "signing", feature = "http-client"))]
|
||||
use crate::nyxd::SigningNyxdClient;
|
||||
#[cfg(all(feature = "signing", feature = "http-client"))]
|
||||
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||
use crate::signing::signer::NoSigner;
|
||||
|
||||
#[must_use]
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -116,29 +115,32 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Client<C> {
|
||||
pub struct Client<C, S = NoSigner> {
|
||||
#[deprecated]
|
||||
mixnode_page_limit: Option<u32>,
|
||||
#[deprecated]
|
||||
gateway_page_limit: Option<u32>,
|
||||
#[deprecated]
|
||||
mixnode_delegations_page_limit: Option<u32>,
|
||||
#[deprecated]
|
||||
rewarded_set_page_limit: Option<u32>,
|
||||
|
||||
// ideally they would have been read-only, but unfortunately rust doesn't have such features
|
||||
pub nym_api: nym_api::Client,
|
||||
pub nyxd: NyxdClient<C>,
|
||||
pub nyxd: NyxdClient<C, S>,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "signing", feature = "http-client"))]
|
||||
impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
|
||||
impl Client<HttpClient, DirectSecp256k1HdWallet> {
|
||||
pub fn new_signing(
|
||||
config: Config,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
) -> Result<Client<SigningNyxdClient<DirectSecp256k1HdWallet>>, ValidatorClientError> {
|
||||
) -> Result<Client<HttpClient, DirectSecp256k1HdWallet>, ValidatorClientError> {
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone());
|
||||
let nyxd_client = NyxdClient::connect_with_mnemonic(
|
||||
config.nyxd_config.clone(),
|
||||
config.nyxd_url.as_str(),
|
||||
mnemonic,
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(Client {
|
||||
@@ -157,13 +159,14 @@ impl Client<SigningNyxdClient<DirectSecp256k1HdWallet>> {
|
||||
}
|
||||
|
||||
pub fn set_nyxd_simulated_gas_multiplier(&mut self, multiplier: f32) {
|
||||
self.nyxd.set_simulated_gas_multiplier(multiplier)
|
||||
todo!()
|
||||
// self.nyxd.set_simulated_gas_multiplier(multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
impl Client<QueryNyxdClient> {
|
||||
pub fn new_query(config: Config) -> Result<Client<QueryNyxdClient>, ValidatorClientError> {
|
||||
impl Client<HttpClient> {
|
||||
pub fn new_query(config: Config) -> Result<Client<HttpClient>, ValidatorClientError> {
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone());
|
||||
let nyxd_client =
|
||||
NyxdClient::connect(config.nyxd_config.clone(), config.nyxd_url.as_str())?;
|
||||
@@ -195,375 +198,379 @@ impl<C> Client<C> {
|
||||
}
|
||||
|
||||
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
|
||||
self.nyxd.mixnet_contract_address().clone()
|
||||
// TODO: deal with the expect
|
||||
self.nyxd
|
||||
.mixnet_contract_address()
|
||||
.expect("mixnet contract address is not available")
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub async fn get_all_node_families(&self) -> Result<Vec<Family>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut families = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let paged_response = self
|
||||
.nyxd
|
||||
.get_all_node_families_paged(start_after.take(), None)
|
||||
.await?;
|
||||
families.extend(paged_response.families);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(families)
|
||||
}
|
||||
|
||||
pub async fn get_all_family_members(
|
||||
&self,
|
||||
) -> Result<Vec<(IdentityKey, FamilyHead)>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut members = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let paged_response = self
|
||||
.nyxd
|
||||
.get_all_family_members_paged(start_after.take(), None)
|
||||
.await?;
|
||||
members.extend(paged_response.members);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(members)
|
||||
}
|
||||
|
||||
// basically handles paging for us
|
||||
pub async fn get_all_nyxd_rewarded_set_mixnodes(
|
||||
&self,
|
||||
) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut identities = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_rewarded_set_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
.await?;
|
||||
identities.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(identities)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut mixnodes = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_mixnode_bonds_paged(self.mixnode_page_limit, start_after.take())
|
||||
.await?;
|
||||
mixnodes.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mixnodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_mixnodes_detailed(
|
||||
&self,
|
||||
) -> Result<Vec<MixNodeDetails>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut mixnodes = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_mixnodes_detailed_paged(self.mixnode_page_limit, start_after.take())
|
||||
.await?;
|
||||
mixnodes.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mixnodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_unbonded_mixnodes(
|
||||
&self,
|
||||
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut mixnodes = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_unbonded_paged(self.mixnode_page_limit, start_after.take())
|
||||
.await?;
|
||||
mixnodes.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mixnodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_unbonded_mixnodes_by_owner(
|
||||
&self,
|
||||
owner: &cosmrs::AccountId,
|
||||
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut mixnodes = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_unbonded_by_owner_paged(owner, self.mixnode_page_limit, start_after.take())
|
||||
.await?;
|
||||
mixnodes.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mixnodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_unbonded_mixnodes_by_identity(
|
||||
&self,
|
||||
identity_key: String,
|
||||
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut mixnodes = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_unbonded_by_identity_paged(
|
||||
identity_key.clone(),
|
||||
self.mixnode_page_limit,
|
||||
start_after.take(),
|
||||
)
|
||||
.await?;
|
||||
mixnodes.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mixnodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut gateways = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_gateways_paged(start_after.take(), self.gateway_page_limit)
|
||||
.await?;
|
||||
gateways.append(&mut paged_response.nodes);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(gateways)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_single_mixnode_delegations(
|
||||
&self,
|
||||
mix_id: MixId,
|
||||
) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut delegations = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_mixnode_delegations_paged(
|
||||
mix_id,
|
||||
start_after.take(),
|
||||
self.mixnode_delegations_page_limit,
|
||||
)
|
||||
.await?;
|
||||
delegations.append(&mut paged_response.delegations);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(delegations)
|
||||
}
|
||||
|
||||
pub async fn get_all_delegator_delegations(
|
||||
&self,
|
||||
delegation_owner: &cosmrs::AccountId,
|
||||
) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut delegations = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_delegator_delegations_paged(
|
||||
delegation_owner.to_string(),
|
||||
start_after.take(),
|
||||
self.mixnode_delegations_page_limit,
|
||||
)
|
||||
.await?;
|
||||
delegations.append(&mut paged_response.delegations);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(delegations)
|
||||
}
|
||||
|
||||
pub async fn get_all_network_delegations(&self) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut delegations = Vec::new();
|
||||
let mut start_after = None;
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_all_network_delegations_paged(
|
||||
start_after.take(),
|
||||
self.mixnode_delegations_page_limit,
|
||||
)
|
||||
.await?;
|
||||
delegations.append(&mut paged_response.delegations);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(delegations)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_pending_epoch_events(
|
||||
&self,
|
||||
) -> Result<Vec<PendingEpochEvent>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut events = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_pending_epoch_events_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
.await?;
|
||||
events.append(&mut paged_response.events);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
pub async fn get_all_nyxd_pending_interval_events(
|
||||
&self,
|
||||
) -> Result<Vec<PendingIntervalEvent>, ValidatorClientError>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
let mut events = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let mut paged_response = self
|
||||
.nyxd
|
||||
.get_pending_interval_events_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
.await?;
|
||||
events.append(&mut paged_response.events);
|
||||
|
||||
if let Some(start_after_res) = paged_response.start_next_after {
|
||||
start_after = Some(start_after_res)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
// pub async fn get_all_node_families(&self) -> Result<Vec<Family>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut families = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let paged_response = self
|
||||
// .nyxd
|
||||
// .get_all_node_families_paged(start_after.take(), None)
|
||||
// .await?;
|
||||
// families.extend(paged_response.families);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(families)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_family_members(
|
||||
// &self,
|
||||
// ) -> Result<Vec<(IdentityKey, FamilyHead)>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut members = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let paged_response = self
|
||||
// .nyxd
|
||||
// .get_all_family_members_paged(start_after.take(), None)
|
||||
// .await?;
|
||||
// members.extend(paged_response.members);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(members)
|
||||
// }
|
||||
//
|
||||
// // basically handles paging for us
|
||||
// pub async fn get_all_nyxd_rewarded_set_mixnodes(
|
||||
// &self,
|
||||
// ) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut identities = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_rewarded_set_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
// .await?;
|
||||
// identities.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(identities)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut mixnodes = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_mixnode_bonds_paged(self.mixnode_page_limit, start_after.take())
|
||||
// .await?;
|
||||
// mixnodes.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(mixnodes)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_mixnodes_detailed(
|
||||
// &self,
|
||||
// ) -> Result<Vec<MixNodeDetails>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut mixnodes = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_mixnodes_detailed_paged(self.mixnode_page_limit, start_after.take())
|
||||
// .await?;
|
||||
// mixnodes.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(mixnodes)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_unbonded_mixnodes(
|
||||
// &self,
|
||||
// ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut mixnodes = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_unbonded_paged(self.mixnode_page_limit, start_after.take())
|
||||
// .await?;
|
||||
// mixnodes.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(mixnodes)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_unbonded_mixnodes_by_owner(
|
||||
// &self,
|
||||
// owner: &cosmrs::AccountId,
|
||||
// ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut mixnodes = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_unbonded_by_owner_paged(owner, self.mixnode_page_limit, start_after.take())
|
||||
// .await?;
|
||||
// mixnodes.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(mixnodes)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_unbonded_mixnodes_by_identity(
|
||||
// &self,
|
||||
// identity_key: String,
|
||||
// ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut mixnodes = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_unbonded_by_identity_paged(
|
||||
// identity_key.clone(),
|
||||
// self.mixnode_page_limit,
|
||||
// start_after.take(),
|
||||
// )
|
||||
// .await?;
|
||||
// mixnodes.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(mixnodes)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut gateways = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_gateways_paged(start_after.take(), self.gateway_page_limit)
|
||||
// .await?;
|
||||
// gateways.append(&mut paged_response.nodes);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(gateways)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_single_mixnode_delegations(
|
||||
// &self,
|
||||
// mix_id: MixId,
|
||||
// ) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut delegations = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_mixnode_delegations_paged(
|
||||
// mix_id,
|
||||
// start_after.take(),
|
||||
// self.mixnode_delegations_page_limit,
|
||||
// )
|
||||
// .await?;
|
||||
// delegations.append(&mut paged_response.delegations);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(delegations)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_delegator_delegations(
|
||||
// &self,
|
||||
// delegation_owner: &cosmrs::AccountId,
|
||||
// ) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut delegations = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_delegator_delegations_paged(
|
||||
// delegation_owner.to_string(),
|
||||
// start_after.take(),
|
||||
// self.mixnode_delegations_page_limit,
|
||||
// )
|
||||
// .await?;
|
||||
// delegations.append(&mut paged_response.delegations);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(delegations)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_network_delegations(&self) -> Result<Vec<Delegation>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut delegations = Vec::new();
|
||||
// let mut start_after = None;
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_all_network_delegations_paged(
|
||||
// start_after.take(),
|
||||
// self.mixnode_delegations_page_limit,
|
||||
// )
|
||||
// .await?;
|
||||
// delegations.append(&mut paged_response.delegations);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(delegations)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_pending_epoch_events(
|
||||
// &self,
|
||||
// ) -> Result<Vec<PendingEpochEvent>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut events = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_pending_epoch_events_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
// .await?;
|
||||
// events.append(&mut paged_response.events);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(events)
|
||||
// }
|
||||
//
|
||||
// pub async fn get_all_nyxd_pending_interval_events(
|
||||
// &self,
|
||||
// ) -> Result<Vec<PendingIntervalEvent>, ValidatorClientError>
|
||||
// where
|
||||
// C: CosmWasmClient + Sync + Send,
|
||||
// {
|
||||
// let mut events = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let mut paged_response = self
|
||||
// .nyxd
|
||||
// .get_pending_interval_events_paged(start_after.take(), self.rewarded_set_page_limit)
|
||||
// .await?;
|
||||
// events.append(&mut paged_response.events);
|
||||
//
|
||||
// if let Some(start_after_res) = paged_response.start_next_after {
|
||||
// start_after = Some(start_after_res)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(events)
|
||||
// }
|
||||
}
|
||||
|
||||
// validator-api wrappers
|
||||
@@ -633,20 +640,20 @@ pub struct CoconutApiClient {
|
||||
}
|
||||
|
||||
impl CoconutApiClient {
|
||||
pub async fn all_coconut_api_clients<C>(
|
||||
client: &C,
|
||||
epoch_id: EpochId,
|
||||
) -> Result<Vec<Self>, ValidatorClientError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
{
|
||||
Ok(client
|
||||
.get_all_verification_key_shares(epoch_id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter_map(Self::try_from)
|
||||
.collect())
|
||||
}
|
||||
// pub async fn all_coconut_api_clients<C>(
|
||||
// client: &C,
|
||||
// epoch_id: EpochId,
|
||||
// ) -> Result<Vec<Self>, ValidatorClientError>
|
||||
// where
|
||||
// C: DkgQueryClient + Sync + Send,
|
||||
// {
|
||||
// Ok(client
|
||||
// .get_all_verification_key_shares(epoch_id)
|
||||
// .await?
|
||||
// .into_iter()
|
||||
// .filter_map(Self::try_from)
|
||||
// .collect())
|
||||
// }
|
||||
|
||||
fn try_from(share: ContractVKShare) -> Option<Self> {
|
||||
if share.verified {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Config as ClientConfig, NyxdClient, QueryNyxdClient};
|
||||
use crate::nyxd::{Config as ClientConfig, QueryHttpNyxdClient};
|
||||
use crate::{NymApiClient, ValidatorClientError};
|
||||
|
||||
// use crate::nyxd::contract_traits::MixnetQueryClient;
|
||||
use crate::nyxd::contract_traits::MixnetQueryClient;
|
||||
use colored::Colorize;
|
||||
use core::fmt;
|
||||
@@ -53,7 +54,7 @@ pub async fn test_nyxd_url_connection(
|
||||
let config = ClientConfig::try_from_nym_network_details(&network)
|
||||
.expect("failed to create valid nyxd client config");
|
||||
|
||||
let mut nyxd_client = NyxdClient::<QueryNyxdClient>::connect(config, nyxd_url.as_str())?;
|
||||
let mut nyxd_client = QueryHttpNyxdClient::connect(config, nyxd_url.as_str())?;
|
||||
// possibly redundant, but lets just leave it here
|
||||
nyxd_client.set_mixnet_contract_address(address);
|
||||
match test_nyxd_connection(network, &nyxd_url, &nyxd_client).await {
|
||||
@@ -75,7 +76,7 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
|
||||
let config = ClientConfig::try_from_nym_network_details(&network)
|
||||
.expect("failed to create valid nyxd client config");
|
||||
|
||||
if let Ok(mut client) = NyxdClient::<QueryNyxdClient>::connect(config, url.as_str()) {
|
||||
if let Ok(mut client) = QueryHttpNyxdClient::connect(config, url.as_str()) {
|
||||
// possibly redundant, but lets just leave it here
|
||||
client.set_mixnet_contract_address(address);
|
||||
Some(ClientForConnectionTest::Nyxd(
|
||||
@@ -112,7 +113,7 @@ fn extract_and_collect_results_into_map(
|
||||
async fn test_nyxd_connection(
|
||||
network: NymNetworkDetails,
|
||||
url: &Url,
|
||||
client: &NyxdClient<QueryNyxdClient>,
|
||||
client: &QueryHttpNyxdClient,
|
||||
) -> ConnectionResult {
|
||||
let result = match timeout(
|
||||
Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC),
|
||||
@@ -186,7 +187,7 @@ async fn test_nym_api_connection(
|
||||
}
|
||||
|
||||
enum ClientForConnectionTest {
|
||||
Nyxd(NymNetworkDetails, Url, Box<NyxdClient<QueryNyxdClient>>),
|
||||
Nyxd(NymNetworkDetails, Url, Box<QueryHttpNyxdClient>),
|
||||
Api(NymNetworkDetails, Url, NymApiClient),
|
||||
}
|
||||
|
||||
|
||||
+45
-13
@@ -1,33 +1,65 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{CosmWasmClient, NyxdClient};
|
||||
|
||||
use nym_coconut_bandwidth_contract_common::msg::QueryMsg;
|
||||
use nym_coconut_bandwidth_contract_common::msg::QueryMsg as CoconutBandwidthQueryMsg;
|
||||
use nym_coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse;
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use async_trait::async_trait;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[async_trait]
|
||||
pub trait CoconutBandwidthQueryClient {
|
||||
async fn get_spent_credential(
|
||||
async fn query_coconut_bandwidth_contract<T>(
|
||||
&self,
|
||||
blinded_serial_number: String,
|
||||
) -> Result<SpendCredentialResponse, NyxdError>;
|
||||
}
|
||||
query: CoconutBandwidthQueryMsg,
|
||||
) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
#[async_trait]
|
||||
impl<C: CosmWasmClient + Sync + Send> CoconutBandwidthQueryClient for NyxdClient<C> {
|
||||
async fn get_spent_credential(
|
||||
&self,
|
||||
blinded_serial_number: String,
|
||||
) -> Result<SpendCredentialResponse, NyxdError> {
|
||||
let request = QueryMsg::GetSpentCredential {
|
||||
self.query_coconut_bandwidth_contract(CoconutBandwidthQueryMsg::GetSpentCredential {
|
||||
blinded_serial_number,
|
||||
};
|
||||
self.client
|
||||
.query_contract_smart(self.coconut_bandwidth_contract_address(), &request)
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> CoconutBandwidthQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_coconut_bandwidth_contract<T>(
|
||||
&self,
|
||||
query: CoconutBandwidthQueryMsg,
|
||||
) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let coconut_bandwidth_contract_address = self
|
||||
.coconut_bandwidth_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;
|
||||
self.query_contract_smart(coconut_bandwidth_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: CoconutBandwidthQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: CoconutBandwidthQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{CosmWasmClient, NyxdClient};
|
||||
use async_trait::async_trait;
|
||||
@@ -176,29 +177,32 @@ pub trait DkgQueryClient {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> DkgQueryClient for NyxdClient<C>
|
||||
impl<C> DkgQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.client
|
||||
.query_contract_smart(self.coconut_dkg_contract_address(), &query)
|
||||
let dkg_contract_address = &self
|
||||
.dkg_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("dkg contract"))?;
|
||||
self.query_contract_smart(dkg_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> DkgQueryClient for crate::Client<C>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.nyxd.query_dkg_contract(query).await
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: DkgQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: DkgQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
+43
-14
@@ -1,28 +1,57 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{CosmWasmClient, NyxdClient};
|
||||
|
||||
use nym_group_contract_common::msg::QueryMsg;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cw4::MemberResponse;
|
||||
use nym_group_contract_common::msg::QueryMsg as GroupQueryMsg;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[async_trait]
|
||||
pub trait GroupQueryClient {
|
||||
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError>;
|
||||
}
|
||||
async fn query_group_contract<T>(&self, query: GroupQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
#[async_trait]
|
||||
impl<C: CosmWasmClient + Sync + Send> GroupQueryClient for NyxdClient<C> {
|
||||
async fn member(&self, addr: String) -> Result<MemberResponse, NyxdError> {
|
||||
let request = QueryMsg::Member {
|
||||
addr,
|
||||
at_height: None,
|
||||
};
|
||||
self.client
|
||||
.query_contract_smart(self.group_contract_address(), &request)
|
||||
async fn member(
|
||||
&self,
|
||||
addr: String,
|
||||
at_height: Option<u64>,
|
||||
) -> Result<MemberResponse, NyxdError> {
|
||||
self.query_group_contract(GroupQueryMsg::Member { addr, at_height })
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> GroupQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_group_contract<T>(&self, query: GroupQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let group_contract_address = &self
|
||||
.group_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("group contract"))?;
|
||||
self.query_contract_smart(group_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: GroupQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: GroupQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
+163
-31
@@ -1,9 +1,10 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
|
||||
use crate::define_paged_response;
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::NyxdClient;
|
||||
use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::Nonce;
|
||||
@@ -93,8 +94,8 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_all_family_members_paged(
|
||||
&self,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
start_after: Option<String>,
|
||||
) -> Result<PagedMembersResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetAllMembersPaged { limit, start_after })
|
||||
.await
|
||||
@@ -435,46 +436,177 @@ pub trait MixnetQueryClient {
|
||||
|
||||
async fn get_node_family_by_label(
|
||||
&self,
|
||||
label: &str,
|
||||
label: String,
|
||||
) -> Result<FamilyByLabelResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel {
|
||||
label: label.to_string(),
|
||||
})
|
||||
.await
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel { label })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_family_by_head(&self, head: &str) -> Result<FamilyByHeadResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead {
|
||||
head: head.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> MixnetQueryClient for NyxdClient<C>
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
{
|
||||
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.client
|
||||
.query_contract_smart(self.mixnet_contract_address(), &query)
|
||||
async fn get_node_family_by_head(
|
||||
&self,
|
||||
head: String,
|
||||
) -> Result<FamilyByHeadResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByHead { head })
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// extension trait to the query client to deal with the paged queries
|
||||
// (it didn't feel appropriate to combine it with the existing trait
|
||||
#[async_trait]
|
||||
impl<C> MixnetQueryClient for crate::Client<C>
|
||||
pub trait PagedMixnetClient: MixnetQueryClient + Send + Sync {
|
||||
// async fn get_all_node_families(&self) -> Result<Vec<Family>, NyxdError> {
|
||||
// let mut res = Vec::new();
|
||||
// let mut start_after = None;
|
||||
//
|
||||
// loop {
|
||||
// let paged_response = self
|
||||
// .get_all_node_families_paged(start_after.take(), None)
|
||||
// .await?;
|
||||
// res.extend(paged_response.families);
|
||||
//
|
||||
// if let Some(start_next_after) = paged_response.start_next_after {
|
||||
// start_after = Some(start_next_after)
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ok(res)
|
||||
// }
|
||||
|
||||
// define_paged_response!(
|
||||
// get_all_node_families,
|
||||
// Family,
|
||||
// get_all_node_families_paged,
|
||||
// families
|
||||
// );
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> PagedMixnetClient for T where T: MixnetQueryClient {}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> MixnetQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + Sync + Send,
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.nyxd.query_mixnet_contract(query).await
|
||||
let mixnet_contract_address = &self
|
||||
.mixnet_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("mixnet contract"))?;
|
||||
self.query_contract_smart(mixnet_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: MixnetQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: MixnetQueryMsg,
|
||||
) {
|
||||
todo!()
|
||||
// match msg {
|
||||
// MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after } => client
|
||||
// .get_all_family_members_paged(limit, start_after)
|
||||
// .await
|
||||
// .map(|_| ()),
|
||||
// MixnetQueryMsg::GetAllMembersPaged { limit, start_after } => client
|
||||
// .get_all_family_members_paged(limit, start_after)
|
||||
// .await
|
||||
// .map(|_| ()),
|
||||
// MixnetQueryMsg::GetFamilyByHead { head } => {
|
||||
// client.get_node_family_by_head(head).await.map(|_| ())
|
||||
// }
|
||||
// MixnetQueryMsg::GetFamilyByLabel { label } => {
|
||||
// client.get_node_family_by_label(label).await.map(|_| ())
|
||||
// }
|
||||
// MixnetQueryMsg::GetFamilyMembersByHead { head } => todo!(),
|
||||
// MixnetQueryMsg::GetFamilyMembersByLabel { label } => todo!(),
|
||||
// MixnetQueryMsg::GetContractVersion {} => {
|
||||
// client.get_mixnet_contract_version().await.map(|_| ())
|
||||
// }
|
||||
// MixnetQueryMsg::GetCW2ContractVersion {} => todo!(),
|
||||
// MixnetQueryMsg::GetRewardingValidatorAddress {} => {
|
||||
// client.get_rewarding_validator_address().await.map(|_| ())
|
||||
// }
|
||||
// MixnetQueryMsg::GetStateParams {} => todo!(),
|
||||
// MixnetQueryMsg::GetState {} => client.get_mixnet_contract_state().await.map(|_| ()),
|
||||
// MixnetQueryMsg::GetRewardingParams {} => {}
|
||||
// MixnetQueryMsg::GetEpochStatus {} => {}
|
||||
// MixnetQueryMsg::GetCurrentIntervalDetails {} => {}
|
||||
// MixnetQueryMsg::GetRewardedSet { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetMixNodeBonds { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetMixNodesDetailed { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetUnbondedMixNodesByOwner {
|
||||
// owner,
|
||||
// limit,
|
||||
// start_after,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetUnbondedMixNodesByIdentityKey {
|
||||
// identity_key,
|
||||
// limit,
|
||||
// start_after,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetOwnedMixnode { address } => {}
|
||||
// MixnetQueryMsg::GetMixnodeDetails { mix_id } => {}
|
||||
// MixnetQueryMsg::GetMixnodeRewardingDetails { mix_id } => {}
|
||||
// MixnetQueryMsg::GetStakeSaturation { mix_id } => {}
|
||||
// MixnetQueryMsg::GetUnbondedMixNodeInformation { mix_id } => {}
|
||||
// MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity { mix_identity } => {}
|
||||
// MixnetQueryMsg::GetLayerDistribution {} => {}
|
||||
// MixnetQueryMsg::GetGateways { start_after, limit } => {}
|
||||
// MixnetQueryMsg::GetGatewayBond { identity } => {}
|
||||
// MixnetQueryMsg::GetOwnedGateway { address } => {}
|
||||
// MixnetQueryMsg::GetMixnodeDelegations {
|
||||
// mix_id,
|
||||
// start_after,
|
||||
// limit,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetDelegatorDelegations {
|
||||
// delegator,
|
||||
// start_after,
|
||||
// limit,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetDelegationDetails {
|
||||
// mix_id,
|
||||
// delegator,
|
||||
// proxy,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetAllDelegations { start_after, limit } => {}
|
||||
// MixnetQueryMsg::GetPendingOperatorReward { address } => {}
|
||||
// MixnetQueryMsg::GetPendingMixNodeOperatorReward { mix_id } => {}
|
||||
// MixnetQueryMsg::GetPendingDelegatorReward {
|
||||
// address,
|
||||
// mix_id,
|
||||
// proxy,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetEstimatedCurrentEpochOperatorReward {
|
||||
// mix_id,
|
||||
// estimated_performance,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetEstimatedCurrentEpochDelegatorReward {
|
||||
// address,
|
||||
// mix_id,
|
||||
// proxy,
|
||||
// estimated_performance,
|
||||
// } => {}
|
||||
// MixnetQueryMsg::GetPendingEpochEvents { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetPendingIntervalEvents { limit, start_after } => {}
|
||||
// MixnetQueryMsg::GetPendingEpochEvent { event_id } => {}
|
||||
// MixnetQueryMsg::GetPendingIntervalEvent { event_id } => {}
|
||||
// MixnetQueryMsg::GetNumberOfPendingEvents {} => {}
|
||||
// MixnetQueryMsg::GetSigningNonce { address } => {}
|
||||
// }
|
||||
// .expect("ignore error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// TODO: expose query-related capabilities to wasm client...
|
||||
use cosmrs::AccountId;
|
||||
use nym_network_defaults::NymContracts;
|
||||
use std::str::FromStr;
|
||||
|
||||
// TODO: all of those could/should be derived via a macro
|
||||
|
||||
mod coconut_bandwidth_query_client;
|
||||
mod dkg_query_client;
|
||||
@@ -12,20 +16,20 @@ mod name_service_query_client;
|
||||
mod sp_directory_query_client;
|
||||
mod vesting_query_client;
|
||||
|
||||
#[cfg(feature = "signing")]
|
||||
mod coconut_bandwidth_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod dkg_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod mixnet_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod multisig_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod name_service_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod sp_directory_signing_client;
|
||||
#[cfg(feature = "signing")]
|
||||
mod vesting_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod coconut_bandwidth_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod dkg_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod mixnet_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod multisig_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod name_service_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod sp_directory_signing_client;
|
||||
// #[cfg(feature = "signing")]
|
||||
// mod vesting_signing_client;
|
||||
|
||||
pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
|
||||
pub use dkg_query_client::DkgQueryClient;
|
||||
@@ -36,17 +40,112 @@ pub use name_service_query_client::NameServiceQueryClient;
|
||||
pub use sp_directory_query_client::SpDirectoryQueryClient;
|
||||
pub use vesting_query_client::VestingQueryClient;
|
||||
|
||||
#[cfg(feature = "signing")]
|
||||
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use dkg_signing_client::DkgSigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use mixnet_signing_client::MixnetSigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use multisig_signing_client::MultisigSigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use name_service_signing_client::NameServiceSigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use sp_directory_signing_client::SpDirectorySigningClient;
|
||||
#[cfg(feature = "signing")]
|
||||
pub use vesting_signing_client::VestingSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use dkg_signing_client::DkgSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use mixnet_signing_client::MixnetSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use multisig_signing_client::MultisigSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use name_service_signing_client::NameServiceSigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use sp_directory_signing_client::SpDirectorySigningClient;
|
||||
// #[cfg(feature = "signing")]
|
||||
// pub use vesting_signing_client::VestingSigningClient;
|
||||
|
||||
pub trait NymContractsProvider {
|
||||
// main
|
||||
fn mixnet_contract_address(&self) -> Option<&AccountId>;
|
||||
fn vesting_contract_address(&self) -> Option<&AccountId>;
|
||||
|
||||
// coconut-related
|
||||
fn coconut_bandwidth_contract_address(&self) -> Option<&AccountId>;
|
||||
fn dkg_contract_address(&self) -> Option<&AccountId>;
|
||||
fn group_contract_address(&self) -> Option<&AccountId>;
|
||||
fn multisig_contract_address(&self) -> Option<&AccountId>;
|
||||
|
||||
// SPs
|
||||
fn name_service_contract_address(&self) -> Option<&AccountId>;
|
||||
fn service_provider_contract_address(&self) -> Option<&AccountId>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypedNymContracts {
|
||||
pub mixnet_contract_address: Option<AccountId>,
|
||||
pub vesting_contract_address: Option<AccountId>,
|
||||
|
||||
pub coconut_bandwidth_contract_address: Option<AccountId>,
|
||||
pub group_contract_address: Option<AccountId>,
|
||||
pub multisig_contract_address: Option<AccountId>,
|
||||
pub coconut_dkg_contract_address: Option<AccountId>,
|
||||
|
||||
pub service_provider_directory_contract_address: Option<AccountId>,
|
||||
pub name_service_contract_address: Option<AccountId>,
|
||||
}
|
||||
|
||||
impl TryFrom<NymContracts> for TypedNymContracts {
|
||||
type Error = <AccountId as FromStr>::Err;
|
||||
|
||||
fn try_from(value: NymContracts) -> Result<Self, Self::Error> {
|
||||
Ok(TypedNymContracts {
|
||||
mixnet_contract_address: value
|
||||
.mixnet_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
vesting_contract_address: value
|
||||
.vesting_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
coconut_bandwidth_contract_address: value
|
||||
.coconut_bandwidth_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
group_contract_address: value
|
||||
.group_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
multisig_contract_address: value
|
||||
.multisig_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
coconut_dkg_contract_address: value
|
||||
.coconut_dkg_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
service_provider_directory_contract_address: value
|
||||
.service_provider_directory_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
name_service_contract_address: value
|
||||
.name_service_contract_address
|
||||
.map(|addr| addr.parse())
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// a simple helper macro to define a function to repeatedly call a paged query until a full response is constructed
|
||||
#[macro_export]
|
||||
macro_rules! define_paged_response {
|
||||
( $f: ident, $r: ty, $fc: ident, $field: ident ) => {
|
||||
async fn $f(&self) -> Result<Vec<$r>, NyxdError> {
|
||||
let mut res = Vec::new();
|
||||
let mut start_after = None;
|
||||
|
||||
loop {
|
||||
let paged_response = self.$fc(start_after.take(), None).await?;
|
||||
res.extend(paged_response.$field);
|
||||
|
||||
if let Some(start_next_after) = paged_response.start_next_after {
|
||||
start_after = Some(start_next_after)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+135
-24
@@ -1,23 +1,93 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{CosmWasmClient, NyxdClient};
|
||||
|
||||
use cw3::{ProposalListResponse, ProposalResponse};
|
||||
use nym_multisig_contract_common::msg::QueryMsg;
|
||||
|
||||
use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cw3::{
|
||||
ProposalListResponse, ProposalResponse, VoteListResponse, VoteResponse, VoterListResponse,
|
||||
VoterResponse,
|
||||
};
|
||||
use cw_utils::ThresholdResponse;
|
||||
use nym_multisig_contract_common::msg::QueryMsg as MultisigQueryMsg;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[async_trait]
|
||||
pub trait MultisigQueryClient {
|
||||
async fn get_proposal(&self, proposal_id: u64) -> Result<ProposalResponse, NyxdError>;
|
||||
async fn query_multisig_contract<T>(&self, query: MultisigQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
async fn query_threshold(&self) -> Result<ThresholdResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::Threshold {})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn query_proposal(&self, proposal_id: u64) -> Result<ProposalResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::Proposal { proposal_id })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_proposals(
|
||||
&self,
|
||||
start_after: Option<u64>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<ProposalListResponse, NyxdError>;
|
||||
) -> Result<ProposalListResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::ListProposals { start_after, limit })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn reverse_proposals(
|
||||
&self,
|
||||
start_before: Option<u64>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<ProposalListResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::ReverseProposals {
|
||||
start_before,
|
||||
limit,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn query_vote(&self, proposal_id: u64, voter: String) -> Result<VoteResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::Vote { proposal_id, voter })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_votes(
|
||||
&self,
|
||||
proposal_id: u64,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<VoteListResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::ListVotes {
|
||||
proposal_id,
|
||||
start_after,
|
||||
limit,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn query_voter(&self, address: String) -> Result<VoterResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::Voter { address })
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_voters(
|
||||
&self,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<VoterListResponse, NyxdError> {
|
||||
self.query_multisig_contract(MultisigQueryMsg::ListVoters { start_after, limit })
|
||||
.await
|
||||
}
|
||||
|
||||
// technically it's not deprecated, just not implemented, but I need clippy to point it out to me before I make a PR
|
||||
#[deprecated]
|
||||
async fn query_config(&self) -> Result<(), NyxdError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn get_all_proposals(&self) -> Result<Vec<ProposalResponse>, NyxdError> {
|
||||
let mut proposals = Vec::new();
|
||||
@@ -41,22 +111,63 @@ pub trait MultisigQueryClient {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: CosmWasmClient + Sync + Send> MultisigQueryClient for NyxdClient<C> {
|
||||
async fn get_proposal(&self, proposal_id: u64) -> Result<ProposalResponse, NyxdError> {
|
||||
let request = QueryMsg::Proposal { proposal_id };
|
||||
self.client
|
||||
.query_contract_smart(self.multisig_contract_address(), &request)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_proposals(
|
||||
&self,
|
||||
start_after: Option<u64>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<ProposalListResponse, NyxdError> {
|
||||
let request = QueryMsg::ListProposals { start_after, limit };
|
||||
self.client
|
||||
.query_contract_smart(self.multisig_contract_address(), &request)
|
||||
impl<C> MultisigQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_multisig_contract<T>(&self, query: MultisigQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
let multisig_contract_address = &self
|
||||
.multisig_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("multisig contract"))?;
|
||||
self.query_contract_smart(multisig_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
async fn all_query_variants_are_covered<C: MultisigQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: MultisigQueryMsg,
|
||||
) {
|
||||
match msg {
|
||||
MultisigQueryMsg::Threshold {} => client.query_threshold().await.map(|_| ()),
|
||||
MultisigQueryMsg::Proposal { proposal_id } => {
|
||||
client.query_proposal(proposal_id).await.map(|_| ())
|
||||
}
|
||||
MultisigQueryMsg::ListProposals { start_after, limit } => {
|
||||
client.list_proposals(start_after, limit).await.map(|_| ())
|
||||
}
|
||||
MultisigQueryMsg::ReverseProposals {
|
||||
start_before,
|
||||
limit,
|
||||
} => client
|
||||
.reverse_proposals(start_before, limit)
|
||||
.await
|
||||
.map(|_| ()),
|
||||
MultisigQueryMsg::Vote { proposal_id, voter } => {
|
||||
client.query_vote(proposal_id, voter).await.map(|_| ())
|
||||
}
|
||||
MultisigQueryMsg::ListVotes {
|
||||
proposal_id,
|
||||
start_after,
|
||||
limit,
|
||||
} => client
|
||||
.list_votes(proposal_id, start_after, limit)
|
||||
.await
|
||||
.map(|_| ()),
|
||||
MultisigQueryMsg::Voter { address } => client.query_voter(address).await.map(|_| ()),
|
||||
MultisigQueryMsg::ListVoters { start_after, limit } => {
|
||||
client.list_voters(start_after, limit).await.map(|_| ())
|
||||
}
|
||||
MultisigQueryMsg::Config {} => client.query_config().await.map(|_| ()),
|
||||
}
|
||||
.expect("ignore error")
|
||||
}
|
||||
}
|
||||
|
||||
+22
-22
@@ -1,3 +1,8 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{error::NyxdError, CosmWasmClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::{signing::Nonce, ContractBuildInformation};
|
||||
@@ -8,8 +13,6 @@ use nym_name_service_common::{
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::nyxd::{error::NyxdError, CosmWasmClient, NyxdClient};
|
||||
|
||||
#[async_trait]
|
||||
pub trait NameServiceQueryClient {
|
||||
async fn query_name_service_contract<T>(&self, query: NameQueryMsg) -> Result<T, NyxdError>
|
||||
@@ -81,36 +84,33 @@ pub trait NameServiceQueryClient {
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> NameServiceQueryClient for NyxdClient<C>
|
||||
impl<C> NameServiceQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_name_service_contract<T>(&self, query: NameQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.client
|
||||
.query_contract_smart(
|
||||
self.name_service_contract_address().ok_or(
|
||||
NyxdError::NoContractAddressAvailable("name service contract".to_string()),
|
||||
)?,
|
||||
&query,
|
||||
)
|
||||
let name_service_contract_address = &self
|
||||
.name_service_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("name service contract"))?;
|
||||
self.query_contract_smart(name_service_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> NameServiceQueryClient for crate::Client<C>
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
{
|
||||
async fn query_name_service_contract<T>(&self, query: NameQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.nyxd.query_name_service_contract(query).await
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: NameServiceQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: NameQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
+19
-21
@@ -10,6 +10,7 @@ use nym_service_provider_directory_common::{
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::{error::NyxdError, CosmWasmClient, NyxdClient};
|
||||
|
||||
#[async_trait]
|
||||
@@ -89,36 +90,33 @@ pub trait SpDirectoryQueryClient {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> SpDirectoryQueryClient for NyxdClient<C>
|
||||
impl<C> SpDirectoryQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_service_provider_contract<T>(&self, query: SpQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.client
|
||||
.query_contract_smart(
|
||||
self.service_provider_contract_address().ok_or(
|
||||
NyxdError::NoContractAddressAvailable(
|
||||
"service provider directory contract".to_string(),
|
||||
),
|
||||
)?,
|
||||
&query,
|
||||
)
|
||||
let sp_directory_contract_address =
|
||||
&self.service_provider_contract_address().ok_or_else(|| {
|
||||
NyxdError::unavailable_contract_address("service provider directory contract")
|
||||
})?;
|
||||
self.query_contract_smart(sp_directory_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C> SpDirectoryQueryClient for crate::Client<C>
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
{
|
||||
async fn query_service_provider_contract<T>(&self, query: SpQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.nyxd.query_service_provider_contract(query).await
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: SpDirectoryQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: SpQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
+25
-6
@@ -1,10 +1,10 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::coin::Coin;
|
||||
pub use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
|
||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::NyxdClient;
|
||||
use crate::nyxd::{CosmWasmClient, NyxdClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::{Coin as CosmWasmCoin, Timestamp};
|
||||
use nym_contracts_common::ContractBuildInformation;
|
||||
@@ -334,13 +334,32 @@ pub trait VestingQueryClient {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NyxdClient<C> {
|
||||
impl<C> VestingQueryClient for C
|
||||
where
|
||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
||||
{
|
||||
async fn query_vesting_contract<T>(&self, query: VestingQueryMsg) -> Result<T, NyxdError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.client
|
||||
.query_contract_smart(self.vesting_contract_address(), &query)
|
||||
let vesting_contract_address = &self
|
||||
.vesting_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("vesting contract"))?;
|
||||
self.query_contract_smart(vesting_contract_address, &query)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// it's enough that this compiles
|
||||
#[deprecated]
|
||||
async fn all_query_variants_are_covered<C: VestingQueryClient + Send + Sync>(
|
||||
client: C,
|
||||
msg: VestingQueryMsg,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod query_client;
|
||||
|
||||
#[cfg(feature = "signing")]
|
||||
pub mod signing_client;
|
||||
|
||||
pub use query_client::CosmWasmClient;
|
||||
|
||||
#[cfg(feature = "signing")]
|
||||
pub use signing_client::SigningCosmWasmClient;
|
||||
+19
-19
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd;
|
||||
@@ -39,25 +39,15 @@ use tendermint_rpc::{
|
||||
Order,
|
||||
};
|
||||
|
||||
pub const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
|
||||
pub const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[async_trait]
|
||||
impl CosmWasmClient for cosmrs::rpc::HttpClient {
|
||||
fn broadcast_polling_rate(&self) -> Duration {
|
||||
Duration::from_secs(4)
|
||||
}
|
||||
|
||||
fn broadcast_timeout(&self) -> Duration {
|
||||
Duration::from_secs(60)
|
||||
}
|
||||
}
|
||||
impl CosmWasmClient for cosmrs::rpc::HttpClient {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait CosmWasmClient: TendermintClient {
|
||||
// this should probably get redesigned, but I'm leaving those like that temporarily to fix
|
||||
// the underlying issue more quickly
|
||||
fn broadcast_polling_rate(&self) -> Duration;
|
||||
fn broadcast_timeout(&self) -> Duration;
|
||||
|
||||
// helper method to remove duplicate code involved in making abci requests with protobuf messages
|
||||
// TODO: perhaps it should have an additional argument to determine whether the response should
|
||||
// require proof?
|
||||
@@ -268,10 +258,20 @@ pub trait CosmWasmClient: TendermintClient {
|
||||
Ok(tendermint_rpc::client::Client::broadcast_tx_commit(self, tx).await?)
|
||||
}
|
||||
|
||||
async fn broadcast_tx<T>(&self, tx: T) -> Result<TxResponse, NyxdError>
|
||||
async fn broadcast_tx<T>(
|
||||
&self,
|
||||
tx: T,
|
||||
timeout: impl Into<Option<Duration>> + Send,
|
||||
poll_interval: impl Into<Option<Duration>> + Send,
|
||||
) -> Result<TxResponse, NyxdError>
|
||||
where
|
||||
T: Into<Vec<u8>> + Send,
|
||||
{
|
||||
let timeout = timeout.into().unwrap_or(DEFAULT_BROADCAST_TIMEOUT);
|
||||
let poll_interval = poll_interval
|
||||
.into()
|
||||
.unwrap_or(DEFAULT_BROADCAST_POLLING_RATE);
|
||||
|
||||
let broadcasted = CosmWasmClient::broadcast_tx_sync(self, tx).await?;
|
||||
|
||||
if broadcasted.code.is_err() {
|
||||
@@ -292,10 +292,10 @@ pub trait CosmWasmClient: TendermintClient {
|
||||
"Polling for result of including {} in a block...",
|
||||
broadcasted.hash
|
||||
);
|
||||
if tokio::time::Instant::now().duration_since(start) >= self.broadcast_timeout() {
|
||||
if tokio::time::Instant::now().duration_since(start) >= timeout {
|
||||
return Err(NyxdError::BroadcastTimeout {
|
||||
hash: tx_hash,
|
||||
timeout: self.broadcast_timeout(),
|
||||
timeout,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ pub trait CosmWasmClient: TendermintClient {
|
||||
return Ok(poll_res);
|
||||
}
|
||||
|
||||
tokio::time::sleep(self.broadcast_polling_rate()).await;
|
||||
tokio::time::sleep(poll_interval).await;
|
||||
}
|
||||
}
|
||||
|
||||
+23
-180
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nyxd::cosmwasm_client::types::*;
|
||||
@@ -9,6 +9,7 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
use crate::nyxd::{Coin, GasAdjustable, GasPrice, TxResponse};
|
||||
use crate::signing::signer::OfflineSigner;
|
||||
use crate::signing::tx_signer::TxSigner;
|
||||
use crate::signing::SignerData;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::abci::GasInfo;
|
||||
@@ -26,21 +27,9 @@ use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
use std::convert::TryInto;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::time::SystemTime;
|
||||
use tendermint_rpc::endpoint::broadcast;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use crate::signing::tx_signer::TxSigner;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use tendermint_rpc::{Error as TendermintRpcError, SimpleRequest};
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
||||
|
||||
pub const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
|
||||
pub const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
fn empty_fee() -> tx::Fee {
|
||||
tx::Fee {
|
||||
amount: vec![],
|
||||
@@ -65,15 +54,16 @@ fn single_unspecified_signer_auth(
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
type Signer: OfflineSigner + Send + Sync;
|
||||
|
||||
fn signer(&self) -> &Self::Signer;
|
||||
|
||||
pub trait SigningCosmWasmClient: CosmWasmClient + TxSigner
|
||||
where
|
||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
||||
{
|
||||
// TODO: would it somehow be possible to get rid of this method and allow for
|
||||
// blanket implementation for anything that provides CosmWasmClient + TxSigner?
|
||||
fn gas_price(&self) -> &GasPrice;
|
||||
|
||||
fn signer_public_key(&self, signer_address: &AccountId) -> Option<tx::SignerPublicKey> {
|
||||
let account = self.signer().find_account(signer_address).ok()?;
|
||||
let account = self.find_account(signer_address).ok()?;
|
||||
Some(account.public_key().into())
|
||||
}
|
||||
|
||||
@@ -587,9 +577,9 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
let multiplier = multiplier.unwrap_or(DEFAULT_SIMULATED_GAS_MULTIPLIER);
|
||||
let gas = gas_estimation.adjust_gas(multiplier);
|
||||
|
||||
debug!("Gas estimation: {}", gas_estimation);
|
||||
debug!("Multiplying the estimation by {}", multiplier);
|
||||
debug!("Final gas limit used: {}", gas);
|
||||
debug!("Gas estimation: {gas_estimation}");
|
||||
debug!("Multiplying the estimation by {multiplier}");
|
||||
debug!("Final gas limit used: {gas}");
|
||||
|
||||
let fee = self.gas_price() * gas;
|
||||
Ok::<tx::Fee, NyxdError>(tx::Fee::from_amount_and_gas(fee, gas))
|
||||
@@ -687,7 +677,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.to_bytes()
|
||||
.map_err(|_| NyxdError::SerializationError("Tx".to_owned()))?;
|
||||
|
||||
self.broadcast_tx(tx_bytes).await
|
||||
self.broadcast_tx(tx_bytes, None, None).await
|
||||
}
|
||||
|
||||
async fn sign(
|
||||
@@ -710,161 +700,14 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
}
|
||||
};
|
||||
|
||||
self.sign_direct(signer_address, messages, fee, memo, signer_data)
|
||||
}
|
||||
|
||||
fn sign_amino(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, NyxdError>;
|
||||
|
||||
fn sign_direct(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, NyxdError>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[derive(Debug)]
|
||||
pub struct Client<S> {
|
||||
// TODO: somehow nicely hide this guy if we decide to use our client in offline mode,
|
||||
// maybe just convert it into an option?
|
||||
// or maybe we need another level of indirection. tbd.
|
||||
rpc_client: HttpClient,
|
||||
tx_signer: TxSigner<S>,
|
||||
gas_price: GasPrice,
|
||||
|
||||
broadcast_polling_rate: Duration,
|
||||
broadcast_timeout: Duration,
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
impl<S> Client<S> {
|
||||
pub fn connect_with_signer<U: Clone>(
|
||||
endpoint: U,
|
||||
signer: S,
|
||||
gas_price: GasPrice,
|
||||
) -> Result<Self, NyxdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let rpc_client = HttpClient::new(endpoint)?;
|
||||
Ok(Client {
|
||||
rpc_client,
|
||||
tx_signer: TxSigner::new(signer),
|
||||
gas_price,
|
||||
broadcast_polling_rate: DEFAULT_BROADCAST_POLLING_RATE,
|
||||
broadcast_timeout: DEFAULT_BROADCAST_TIMEOUT,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn offline(signer: S) -> TxSigner<S>
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
TxSigner::new(signer)
|
||||
}
|
||||
|
||||
pub fn change_endpoint<U>(&mut self, new_endpoint: U) -> Result<(), NyxdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let new_rpc_client = HttpClient::new(new_endpoint)?;
|
||||
self.rpc_client = new_rpc_client;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn into_signer(self) -> S {
|
||||
self.tx_signer.into_inner_signer()
|
||||
}
|
||||
|
||||
pub fn set_broadcast_polling_rate(&mut self, broadcast_polling_rate: Duration) {
|
||||
self.broadcast_polling_rate = broadcast_polling_rate
|
||||
}
|
||||
|
||||
pub fn set_broadcast_timeout(&mut self, broadcast_timeout: Duration) {
|
||||
self.broadcast_timeout = broadcast_timeout
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[async_trait]
|
||||
impl<S> tendermint_rpc::client::Client for Client<S>
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
async fn perform<R>(&self, request: R) -> Result<R::Output, tendermint_rpc::Error>
|
||||
where
|
||||
R: SimpleRequest,
|
||||
{
|
||||
self.rpc_client.perform(request).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[async_trait]
|
||||
impl<S> CosmWasmClient for Client<S>
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
fn broadcast_polling_rate(&self) -> Duration {
|
||||
self.broadcast_polling_rate
|
||||
}
|
||||
|
||||
fn broadcast_timeout(&self) -> Duration {
|
||||
self.broadcast_timeout
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[async_trait]
|
||||
impl<S> SigningCosmWasmClient for Client<S>
|
||||
where
|
||||
S: OfflineSigner + Send + Sync,
|
||||
NyxdError: From<S::Error>,
|
||||
{
|
||||
type Signer = S;
|
||||
|
||||
fn signer(&self) -> &Self::Signer {
|
||||
self.tx_signer.signer()
|
||||
}
|
||||
|
||||
fn gas_price(&self) -> &GasPrice {
|
||||
&self.gas_price
|
||||
}
|
||||
|
||||
fn sign_amino(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, NyxdError> {
|
||||
Ok(self
|
||||
.tx_signer
|
||||
.sign_amino(signer_address, messages, fee, memo, signer_data)?)
|
||||
}
|
||||
|
||||
fn sign_direct(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, NyxdError> {
|
||||
Ok(self
|
||||
.tx_signer
|
||||
.sign_direct(signer_address, messages, fee, memo, signer_data)?)
|
||||
Ok(<Self as TxSigner>::sign_direct(
|
||||
self,
|
||||
signer_address,
|
||||
messages,
|
||||
fee,
|
||||
memo,
|
||||
signer_data,
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,153 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use crate::nyxd::cosmwasm_client::client_traits::{CosmWasmClient, SigningCosmWasmClient};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
#[cfg(feature = "http-client")]
|
||||
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl};
|
||||
#[cfg(feature = "http-client")]
|
||||
use std::convert::TryInto;
|
||||
use crate::nyxd::{Config, GasPrice, TendermintClient};
|
||||
use crate::signing::signer::{NoSigner, OfflineSigner};
|
||||
use crate::signing::tx_signer::TxSigner;
|
||||
use crate::signing::AccountData;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::rpc::Error as TendermintRpcError;
|
||||
use cosmrs::AccountId;
|
||||
use tendermint_rpc::SimpleRequest;
|
||||
|
||||
pub mod client;
|
||||
pub mod client_traits;
|
||||
mod helpers;
|
||||
pub mod logs;
|
||||
pub mod types;
|
||||
|
||||
#[cfg(feature = "signing")]
|
||||
pub mod signing_client;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
pub fn connect<U>(endpoint: U) -> Result<HttpClient, NyxdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
Ok(HttpClient::new(endpoint)?)
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct SigningClientOptions {
|
||||
gas_price: GasPrice,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "signing", feature = "http-client"))]
|
||||
pub fn connect_with_signer<S, U: Clone>(
|
||||
endpoint: U,
|
||||
impl<'a> From<&'a Config> for SigningClientOptions {
|
||||
fn from(value: &'a Config) -> Self {
|
||||
SigningClientOptions {
|
||||
gas_price: value.gas_price.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convenience wrapper around query client to allow for optional signing
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MaybeSigningClient<C, S = NoSigner> {
|
||||
client: C,
|
||||
signer: S,
|
||||
gas_price: crate::nyxd::GasPrice,
|
||||
) -> Result<signing_client::Client<S>, NyxdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
signing_client::Client::connect_with_signer(endpoint, signer, gas_price)
|
||||
opts: SigningClientOptions,
|
||||
derived_addresses: Option<Vec<AccountId>>,
|
||||
}
|
||||
|
||||
impl<C> MaybeSigningClient<C> {
|
||||
pub(crate) fn new(client: C, opts: SigningClientOptions) -> Self {
|
||||
MaybeSigningClient {
|
||||
client,
|
||||
signer: Default::default(),
|
||||
opts,
|
||||
derived_addresses: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, S> MaybeSigningClient<C, S> {
|
||||
pub(crate) fn new_signing(
|
||||
client: C,
|
||||
signer: S,
|
||||
opts: SigningClientOptions,
|
||||
) -> Result<Self, S::Error>
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
let derived_addresses = signer
|
||||
.get_accounts()?
|
||||
.into_iter()
|
||||
.map(|account| account.address)
|
||||
.collect();
|
||||
Ok(MaybeSigningClient {
|
||||
client,
|
||||
signer,
|
||||
opts,
|
||||
derived_addresses: Some(derived_addresses),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn derived_addresses(&self) -> &[AccountId] {
|
||||
// the unwrap is fine here as you can't construct a signing client without setting the addresses
|
||||
self.derived_addresses.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> TendermintClient for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: TendermintClient + Send + Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
async fn perform<R>(&self, request: R) -> Result<R::Output, TendermintRpcError>
|
||||
where
|
||||
R: SimpleRequest,
|
||||
{
|
||||
self.client.perform(request).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> CosmWasmClient for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
impl<C, S> OfflineSigner for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: CosmWasmClient,
|
||||
S: OfflineSigner,
|
||||
{
|
||||
type Error = S::Error;
|
||||
|
||||
fn get_accounts(&self) -> Result<Vec<AccountData>, Self::Error> {
|
||||
self.signer.get_accounts()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, S> TxSigner for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: CosmWasmClient,
|
||||
S: OfflineSigner,
|
||||
{
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> SigningCosmWasmClient for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: CosmWasmClient + Send + Sync,
|
||||
S: OfflineSigner + Send + Sync,
|
||||
NyxdError: From<S::Error>,
|
||||
{
|
||||
fn gas_price(&self) -> &GasPrice {
|
||||
&self.opts.gas_price
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// #[cfg(feature = "http-client")]
|
||||
// pub fn connect<U>(endpoint: U) -> Result<MaybeSigningClient<HttpClient>, NyxdError>
|
||||
// where
|
||||
// U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
// {
|
||||
// Ok(HttpClient::new(endpoint)?)
|
||||
// }
|
||||
//
|
||||
// #[cfg(all(feature = "signing", feature = "http-client"))]
|
||||
// pub fn connect_with_signer<S, U: Clone>(
|
||||
// endpoint: U,
|
||||
// signer: S,
|
||||
// gas_price: crate::nyxd::GasPrice,
|
||||
// ) -> Result<MaybeSigningClient<HttpClient, S>, NyxdError>
|
||||
// where
|
||||
// U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
// {
|
||||
// signing_client::Client::connect_with_signer(endpoint, signer, gas_price)
|
||||
// }
|
||||
|
||||
@@ -224,4 +224,8 @@ impl NyxdError {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unavailable_contract_address<S: Into<String>>(contract_type: S) -> Self {
|
||||
NyxdError::NoContractAddressAvailable(contract_type.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use cosmrs::Coin;
|
||||
use cosmrs::Gas;
|
||||
use cosmwasm_std::{Decimal, Fraction, Uint128};
|
||||
use nym_config::defaults;
|
||||
use nym_network_defaults::{ChainDetails, NymNetworkDetails};
|
||||
use std::ops::Mul;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -73,6 +74,19 @@ impl FromStr for GasPrice {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a NymNetworkDetails> for GasPrice {
|
||||
type Error = NyxdError;
|
||||
|
||||
fn try_from(value: &'a NymNetworkDetails) -> Result<Self, Self::Error> {
|
||||
format!(
|
||||
"{}{}",
|
||||
value.default_gas_price_amount(),
|
||||
value.chain_details.mix_denom.base
|
||||
)
|
||||
.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl GasPrice {
|
||||
pub fn new_with_default_price(denom: &str) -> Result<Self, NyxdError> {
|
||||
format!("{}{}", defaults::GAS_PRICE_AMOUNT, denom).parse()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ pub enum DirectSecp256k1HdWalletError {
|
||||
AccountDerivationError { source: eyre::Report },
|
||||
}
|
||||
|
||||
// TODO: maybe lock this one behind feature flag?
|
||||
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
|
||||
pub struct DirectSecp256k1HdWallet {
|
||||
/// Base secret
|
||||
|
||||
@@ -94,3 +94,25 @@ pub trait OfflineSigner {
|
||||
|
||||
// fn sign_amino_with_account(&self, signer: &AccountData, sign_doc: AminoSignDoc) -> Result<tx::Raw, Self::Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct NoSigner;
|
||||
|
||||
// #[derive(Debug, Copy, Clone, Error)]
|
||||
// #[error("no signer is available")]
|
||||
// struct SignerUnavailable;
|
||||
//
|
||||
// // trait bound requirements
|
||||
// impl From<SigningError> for SignerUnavailable {
|
||||
// fn from(_: SigningError) -> Self {
|
||||
// SignerUnavailable
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl OfflineSigner for NoSigner {
|
||||
// type Error = SignerUnavailable;
|
||||
//
|
||||
// fn get_accounts(&self) -> Result<Vec<AccountData>, Self::Error> {
|
||||
// return Err(SignerUnavailable);
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -5,54 +5,98 @@ use crate::signing::signer::{OfflineSigner, SigningError};
|
||||
use crate::signing::SignerData;
|
||||
use cosmrs::tx::{SignDoc, SignerInfo};
|
||||
use cosmrs::{tx, AccountId, Any};
|
||||
//
|
||||
// #[derive(Debug)]
|
||||
// /// A client that has only one responsibility - sign transactions
|
||||
// /// and not touch chain.
|
||||
// pub struct TxSigner<S> {
|
||||
// signer: S,
|
||||
// }
|
||||
//
|
||||
// impl<S> TxSigner<S> {
|
||||
// pub fn new(signer: S) -> Self {
|
||||
// TxSigner { signer }
|
||||
// }
|
||||
//
|
||||
// pub fn signer(&self) -> &S {
|
||||
// &self.signer
|
||||
// }
|
||||
//
|
||||
// pub fn into_inner_signer(self) -> S {
|
||||
// self.signer
|
||||
// }
|
||||
//
|
||||
// pub fn sign_amino(
|
||||
// &self,
|
||||
// _signer_address: &AccountId,
|
||||
// _messages: Vec<Any>,
|
||||
// _fee: tx::Fee,
|
||||
// _memo: impl Into<String> + Send + 'static,
|
||||
// _signer_data: SignerData,
|
||||
// ) -> Result<tx::Raw, S::Error>
|
||||
// where
|
||||
// S: OfflineSigner,
|
||||
// {
|
||||
// unimplemented!()
|
||||
// }
|
||||
//
|
||||
// // TODO: change this sucker to use the trait better
|
||||
// pub fn sign_direct(
|
||||
// &self,
|
||||
// signer_address: &AccountId,
|
||||
// messages: Vec<Any>,
|
||||
// fee: tx::Fee,
|
||||
// memo: impl Into<String> + Send + 'static,
|
||||
// signer_data: SignerData,
|
||||
// ) -> Result<tx::Raw, S::Error>
|
||||
// where
|
||||
// S: OfflineSigner,
|
||||
// {
|
||||
// let account_from_signer = self.signer.find_account(signer_address)?;
|
||||
//
|
||||
// // TODO: experiment with this field
|
||||
// let timeout_height = 0u32;
|
||||
//
|
||||
// let tx_body = tx::Body::new(messages, memo, timeout_height);
|
||||
// let signer_info =
|
||||
// SignerInfo::single_direct(Some(account_from_signer.public_key), signer_data.sequence);
|
||||
// let auth_info = signer_info.auth_info(fee);
|
||||
//
|
||||
// let sign_doc = SignDoc::new(
|
||||
// &tx_body,
|
||||
// &auth_info,
|
||||
// &signer_data.chain_id,
|
||||
// signer_data.account_number,
|
||||
// )
|
||||
// .map_err(|source| SigningError::SignDocFailure { source })?;
|
||||
//
|
||||
// self.signer
|
||||
// .sign_direct_with_account(&account_from_signer, sign_doc)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A client that has only one responsibility - sign transactions
|
||||
/// and not touch chain.
|
||||
pub struct TxSigner<S> {
|
||||
signer: S,
|
||||
}
|
||||
|
||||
impl<S> TxSigner<S> {
|
||||
pub fn new(signer: S) -> Self {
|
||||
TxSigner { signer }
|
||||
}
|
||||
|
||||
pub fn signer(&self) -> &S {
|
||||
&self.signer
|
||||
}
|
||||
|
||||
pub fn into_inner_signer(self) -> S {
|
||||
self.signer
|
||||
}
|
||||
|
||||
pub fn sign_amino(
|
||||
// extension trait for the OfflineSigner to allow to sign transactions
|
||||
pub trait TxSigner: OfflineSigner {
|
||||
fn sign_amino(
|
||||
&self,
|
||||
_signer_address: &AccountId,
|
||||
_messages: Vec<Any>,
|
||||
_fee: tx::Fee,
|
||||
_memo: impl Into<String> + Send + 'static,
|
||||
_signer_data: SignerData,
|
||||
) -> Result<tx::Raw, S::Error>
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
) -> Result<tx::Raw, <Self as OfflineSigner>::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// TODO: change this sucker to use the trait better
|
||||
pub fn sign_direct(
|
||||
fn sign_direct(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, S::Error>
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
let account_from_signer = self.signer.find_account(signer_address)?;
|
||||
) -> Result<tx::Raw, <Self as OfflineSigner>::Error> {
|
||||
let account_from_signer = self.find_account(signer_address)?;
|
||||
|
||||
// TODO: experiment with this field
|
||||
let timeout_height = 0u32;
|
||||
@@ -70,7 +114,6 @@ impl<S> TxSigner<S> {
|
||||
)
|
||||
.map_err(|source| SigningError::SignDocFailure { source })?;
|
||||
|
||||
self.signer
|
||||
.sign_direct_with_account(&account_from_signer, sign_doc)
|
||||
self.sign_direct_with_account(&account_from_signer, sign_doc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,10 @@ impl NymNetworkDetails {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Generated
+1
@@ -4561,6 +4561,7 @@ dependencies = [
|
||||
"colored 2.0.4",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"cw3",
|
||||
"cw4",
|
||||
"eyre",
|
||||
|
||||
Generated
+1
@@ -3415,6 +3415,7 @@ dependencies = [
|
||||
"colored 2.0.4",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"cw3",
|
||||
"cw4",
|
||||
"eyre",
|
||||
|
||||
Reference in New Issue
Block a user