nym_validator_client/coconut/
mod.rs1use crate::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient};
5use crate::nyxd::error::NyxdError;
6use nym_coconut_dkg_common::types::{EpochId, NodeIndex};
7use nym_coconut_dkg_common::verification_key::ContractVKShare;
8use nym_compact_ecash::error::CompactEcashError;
9use nym_compact_ecash::{Base58, VerificationKeyAuth};
10use std::fmt::{Display, Formatter};
11use thiserror::Error;
12use url::Url;
13
14#[derive(Clone)]
16pub struct EcashApiClient {
17 pub api_client: nym_http_api_client::Client,
18 pub verification_key: VerificationKeyAuth,
19 pub node_id: NodeIndex,
20 pub cosmos_address: cosmrs::AccountId,
21}
22
23impl EcashApiClient {
24 pub fn try_construct_from_share(share: ContractVKShare) -> Result<Self, EcashApiError> {
25 if !share.verified {
26 return Err(EcashApiError::UnverifiedShare);
27 }
28
29 let url_address = Url::parse(&share.announce_address)?;
30
31 let api_client = nym_http_api_client::Client::builder(url_address)
38 .map_err(|e| EcashApiError::ClientError(e.to_string()))?
39 .build()
40 .map_err(|e| EcashApiError::ClientError(e.to_string()))?;
41
42 Ok(EcashApiClient {
43 api_client,
44 verification_key: VerificationKeyAuth::try_from_bs58(&share.share)?,
45 node_id: share.node_index,
46 cosmos_address: share.owner.as_str().parse()?,
47 })
48 }
49}
50
51impl Display for EcashApiClient {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 write!(
54 f,
55 "[id: {}] {} @ ({})",
56 self.node_id,
57 self.cosmos_address,
58 self.api_client
59 .base_urls()
60 .iter()
61 .map(|url| url.to_string())
62 .collect::<Vec<String>>()
63 .join(", ")
64 )
65 }
66}
67
68#[derive(Debug, Error)]
72pub enum EcashApiError {
73 #[error("the provided key share hasn't been verified")]
75 UnverifiedShare,
76
77 #[error("failed to query the contract: {source}")]
78 ContractQueryFailure {
79 #[from]
80 source: NyxdError,
81 },
82
83 #[error("the provided announce address is malformed: {source}")]
84 MalformedAnnounceAddress {
85 #[from]
86 source: url::ParseError,
87 },
88
89 #[error("the provided verification key is malformed: {source}")]
90 MalformedVerificationKey {
91 #[from]
92 source: CompactEcashError,
93 },
94
95 #[error("failed to create API client: {0}")]
96 ClientError(String),
97
98 #[error("the provided account address is malformed: {source}")]
99 MalformedAccountAddress {
100 #[from]
101 source: cosmrs::ErrorReport,
102 },
103
104 #[error("nym api error")]
105 NymApi {
106 #[from]
107 source: crate::ValidatorClientError,
108 },
109}
110
111pub async fn all_ecash_api_clients<C>(
112 client: &C,
113 epoch_id: EpochId,
114) -> Result<Vec<EcashApiClient>, EcashApiError>
115where
116 C: DkgQueryClient,
117{
118 client
120 .get_all_verification_key_shares(epoch_id)
121 .await?
122 .into_iter()
123 .map(EcashApiClient::try_construct_from_share)
124 .collect::<Result<Vec<_>, _>>()
125
126 }