1use crate::collect_paged;
5use crate::nyxd::contract_traits::NymContractsProvider;
6use crate::nyxd::error::NyxdError;
7use crate::nyxd::CosmWasmClient;
8use async_trait::async_trait;
9use cosmrs::AccountId;
10use cosmwasm_std::Addr;
11use nym_coconut_dkg_common::dealer::RegisteredDealerDetails;
12use nym_coconut_dkg_common::types::{ChunkIndex, NodeIndex, StateAdvanceResponse};
13use serde::Deserialize;
14use tracing::trace;
15
16pub use nym_coconut_dkg_common::{
17 dealer::{DealerDetailsResponse, PagedDealerIndexResponse, PagedDealerResponse},
18 dealing::{
19 DealerDealingsStatusResponse, DealingChunkResponse, DealingChunkStatusResponse,
20 DealingMetadataResponse, DealingStatusResponse,
21 },
22 msg::QueryMsg as DkgQueryMsg,
23 types::{DealerDetails, DealingIndex, Epoch, EpochId, EpochState, State},
24 verification_key::{
25 ContractVKShare, PagedVKSharesResponse, VerificationKeyShare, VkShareResponse,
26 },
27};
28
29#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
30#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
31pub trait DkgQueryClient: Send + Sync {
32 async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
33 where
34 for<'a> T: Deserialize<'a>;
35
36 async fn get_state(&self) -> Result<State, NyxdError> {
37 let request = DkgQueryMsg::GetState {};
38 self.query_dkg_contract(request).await
39 }
40
41 async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
42 let request = DkgQueryMsg::GetCurrentEpochState {};
43 self.query_dkg_contract(request).await
44 }
45
46 async fn get_epoch_at_height(&self, height: u64) -> Result<Option<Epoch>, NyxdError> {
47 let request = DkgQueryMsg::GetEpochStateAtHeight { height };
48 self.query_dkg_contract(request).await
49 }
50
51 async fn can_advance_state(&self) -> Result<StateAdvanceResponse, NyxdError> {
52 let request = DkgQueryMsg::CanAdvanceState {};
53 self.query_dkg_contract(request).await
54 }
55
56 async fn get_current_epoch_threshold(&self) -> Result<Option<u64>, NyxdError> {
57 let request = DkgQueryMsg::GetCurrentEpochThreshold {};
58 self.query_dkg_contract(request).await
59 }
60
61 async fn get_epoch_threshold(&self, epoch_id: EpochId) -> Result<Option<u64>, NyxdError> {
62 let request = DkgQueryMsg::GetEpochThreshold { epoch_id };
63 self.query_dkg_contract(request).await
64 }
65
66 async fn get_registered_dealer_details(
67 &self,
68 address: &AccountId,
69 epoch_id: Option<EpochId>,
70 ) -> Result<RegisteredDealerDetails, NyxdError> {
71 let request = DkgQueryMsg::GetRegisteredDealer {
72 dealer_address: address.to_string(),
73 epoch_id,
74 };
75 self.query_dkg_contract(request).await
76 }
77
78 async fn get_dealer_details(
79 &self,
80 address: &AccountId,
81 ) -> Result<DealerDetailsResponse, NyxdError> {
82 let request = DkgQueryMsg::GetDealerDetails {
83 dealer_address: address.to_string(),
84 };
85 self.query_dkg_contract(request).await
86 }
87
88 async fn get_current_dealers_paged(
89 &self,
90 start_after: Option<String>,
91 limit: Option<u32>,
92 ) -> Result<PagedDealerResponse, NyxdError> {
93 let request = DkgQueryMsg::GetCurrentDealers { start_after, limit };
94 self.query_dkg_contract(request).await
95 }
96
97 async fn get_epoch_dealers_paged(
98 &self,
99 epoch_id: EpochId,
100 start_after: Option<String>,
101 limit: Option<u32>,
102 ) -> Result<PagedDealerResponse, NyxdError> {
103 let request = DkgQueryMsg::GetEpochDealers {
104 epoch_id,
105 start_after,
106 limit,
107 };
108 self.query_dkg_contract(request).await
109 }
110
111 async fn get_epoch_dealers_addresses_paged(
112 &self,
113 epoch_id: EpochId,
114 start_after: Option<String>,
115 limit: Option<u32>,
116 ) -> Result<PagedDealerResponse, NyxdError> {
117 let request = DkgQueryMsg::GetEpochDealersAddresses {
118 epoch_id,
119 start_after,
120 limit,
121 };
122 self.query_dkg_contract(request).await
123 }
124
125 async fn get_dealer_indices_paged(
126 &self,
127 start_after: Option<String>,
128 limit: Option<u32>,
129 ) -> Result<PagedDealerIndexResponse, NyxdError> {
130 let request = DkgQueryMsg::GetDealerIndices { start_after, limit };
131 self.query_dkg_contract(request).await
132 }
133
134 async fn get_dealings_metadata(
135 &self,
136 epoch_id: EpochId,
137 dealer: String,
138 dealing_index: DealingIndex,
139 ) -> Result<DealingMetadataResponse, NyxdError> {
140 let request = DkgQueryMsg::GetDealingsMetadata {
141 epoch_id,
142 dealer,
143 dealing_index,
144 };
145
146 self.query_dkg_contract(request).await
147 }
148
149 async fn get_dealer_dealings_status(
150 &self,
151 epoch_id: EpochId,
152 dealer: String,
153 ) -> Result<DealerDealingsStatusResponse, NyxdError> {
154 let request = DkgQueryMsg::GetDealerDealingsStatus { epoch_id, dealer };
155
156 self.query_dkg_contract(request).await
157 }
158
159 async fn get_dealing_status(
160 &self,
161 epoch_id: EpochId,
162 dealer: String,
163 dealing_index: DealingIndex,
164 ) -> Result<DealingStatusResponse, NyxdError> {
165 let request = DkgQueryMsg::GetDealingStatus {
166 epoch_id,
167 dealer,
168 dealing_index,
169 };
170
171 self.query_dkg_contract(request).await
172 }
173
174 async fn get_dealing_chunk_status(
175 &self,
176 epoch_id: EpochId,
177 dealer: String,
178 dealing_index: DealingIndex,
179 chunk_index: ChunkIndex,
180 ) -> Result<DealingChunkStatusResponse, NyxdError> {
181 let request = DkgQueryMsg::GetDealingChunkStatus {
182 epoch_id,
183 dealer,
184 dealing_index,
185 chunk_index,
186 };
187
188 self.query_dkg_contract(request).await
189 }
190
191 async fn get_dealing_chunk(
192 &self,
193 epoch_id: EpochId,
194 dealer: String,
195 dealing_index: DealingIndex,
196 chunk_index: ChunkIndex,
197 ) -> Result<DealingChunkResponse, NyxdError> {
198 let request = DkgQueryMsg::GetDealingChunk {
199 epoch_id,
200 dealer,
201 dealing_index,
202 chunk_index,
203 };
204
205 self.query_dkg_contract(request).await
206 }
207
208 async fn get_vk_share(
209 &self,
210 epoch_id: EpochId,
211 owner: String,
212 ) -> Result<VkShareResponse, NyxdError> {
213 let request = DkgQueryMsg::GetVerificationKey { epoch_id, owner };
214 self.query_dkg_contract(request).await
215 }
216
217 async fn get_vk_shares_paged(
218 &self,
219 epoch_id: EpochId,
220 start_after: Option<String>,
221 limit: Option<u32>,
222 ) -> Result<PagedVKSharesResponse, NyxdError> {
223 let request = DkgQueryMsg::GetVerificationKeys {
224 epoch_id,
225 limit,
226 start_after,
227 };
228 self.query_dkg_contract(request).await
229 }
230
231 async fn get_contract_cw2_version(&self) -> Result<cw2::ContractVersion, NyxdError> {
232 self.query_dkg_contract(DkgQueryMsg::GetCW2ContractVersion {})
233 .await
234 }
235}
236
237#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
240#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
241pub trait PagedDkgQueryClient: DkgQueryClient {
242 async fn get_all_current_dealers(&self) -> Result<Vec<DealerDetails>, NyxdError> {
243 collect_paged!(self, get_current_dealers_paged, dealers)
244 }
245
246 async fn get_all_epoch_dealers(
247 &self,
248 epoch_id: EpochId,
249 ) -> Result<Vec<DealerDetails>, NyxdError> {
250 collect_paged!(self, get_epoch_dealers_paged, dealers, epoch_id)
251 }
252
253 async fn get_all_epoch_dealers_addresses(
254 &self,
255 epoch_id: EpochId,
256 ) -> Result<Vec<DealerDetails>, NyxdError> {
257 collect_paged!(self, get_epoch_dealers_addresses_paged, dealers, epoch_id)
258 }
259
260 async fn get_all_dealer_indices(&self) -> Result<Vec<(Addr, NodeIndex)>, NyxdError> {
261 collect_paged!(self, get_dealer_indices_paged, indices)
262 }
263
264 async fn get_all_verification_key_shares(
265 &self,
266 epoch_id: EpochId,
267 ) -> Result<Vec<ContractVKShare>, NyxdError> {
268 collect_paged!(self, get_vk_shares_paged, shares, epoch_id)
269 }
270}
271
272#[async_trait]
273impl<T> PagedDkgQueryClient for T where T: DkgQueryClient {}
274
275#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
276#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
277impl<C> DkgQueryClient for C
278where
279 C: CosmWasmClient + NymContractsProvider + Send + Sync,
280{
281 async fn query_dkg_contract<T>(&self, query: DkgQueryMsg) -> Result<T, NyxdError>
282 where
283 for<'a> T: Deserialize<'a>,
284 {
285 let dkg_contract_address = &self
286 .dkg_contract_address()
287 .ok_or_else(|| NyxdError::unavailable_contract_address("dkg contract"))?;
288 trace!("using the following dkg contract: {dkg_contract_address}");
289 self.query_contract_smart(dkg_contract_address, &query)
290 .await
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297 use crate::nyxd::contract_traits::tests::IgnoreValue;
298 use nym_coconut_dkg_common::msg::QueryMsg;
299
300 #[allow(dead_code)]
302 fn all_query_variants_are_covered<C: DkgQueryClient>(client: C, msg: DkgQueryMsg) {
303 match msg {
304 DkgQueryMsg::GetState {} => client.get_state().ignore(),
305 DkgQueryMsg::GetCurrentEpochState {} => client.get_current_epoch().ignore(),
306 DkgQueryMsg::GetEpochStateAtHeight { height } => {
307 client.get_epoch_at_height(height).ignore()
308 }
309 DkgQueryMsg::CanAdvanceState {} => client.can_advance_state().ignore(),
310 DkgQueryMsg::GetCurrentEpochThreshold {} => {
311 client.get_current_epoch_threshold().ignore()
312 }
313 DkgQueryMsg::GetEpochThreshold { epoch_id } => {
314 client.get_epoch_threshold(epoch_id).ignore()
315 }
316 DkgQueryMsg::GetRegisteredDealer {
317 dealer_address,
318 epoch_id,
319 } => client
320 .get_registered_dealer_details(&dealer_address.parse().unwrap(), epoch_id)
321 .ignore(),
322 DkgQueryMsg::GetDealerDetails { dealer_address } => client
323 .get_dealer_details(&dealer_address.parse().unwrap())
324 .ignore(),
325 DkgQueryMsg::GetCurrentDealers { limit, start_after } => client
326 .get_current_dealers_paged(start_after, limit)
327 .ignore(),
328 QueryMsg::GetEpochDealers {
329 epoch_id,
330 limit,
331 start_after,
332 } => client
333 .get_epoch_dealers_paged(epoch_id, start_after, limit)
334 .ignore(),
335 QueryMsg::GetEpochDealersAddresses {
336 epoch_id,
337 limit,
338 start_after,
339 } => client
340 .get_epoch_dealers_addresses_paged(epoch_id, start_after, limit)
341 .ignore(),
342 DkgQueryMsg::GetDealerIndices { limit, start_after } => {
343 client.get_dealer_indices_paged(start_after, limit).ignore()
344 }
345 DkgQueryMsg::GetDealingStatus {
346 epoch_id,
347 dealer,
348 dealing_index,
349 } => client
350 .get_dealing_status(epoch_id, dealer, dealing_index)
351 .ignore(),
352 DkgQueryMsg::GetDealingsMetadata {
353 epoch_id,
354 dealer,
355 dealing_index,
356 } => client
357 .get_dealings_metadata(epoch_id, dealer, dealing_index)
358 .ignore(),
359 QueryMsg::GetDealerDealingsStatus { epoch_id, dealer } => {
360 client.get_dealer_dealings_status(epoch_id, dealer).ignore()
361 }
362 DkgQueryMsg::GetDealingChunkStatus {
363 epoch_id,
364 dealer,
365 dealing_index,
366 chunk_index,
367 } => client
368 .get_dealing_chunk_status(epoch_id, dealer, dealing_index, chunk_index)
369 .ignore(),
370 DkgQueryMsg::GetDealingChunk {
371 epoch_id,
372 dealer,
373 dealing_index,
374 chunk_index,
375 } => client
376 .get_dealing_chunk(epoch_id, dealer, dealing_index, chunk_index)
377 .ignore(),
378 DkgQueryMsg::GetVerificationKey { epoch_id, owner } => {
379 client.get_vk_share(epoch_id, owner).ignore()
380 }
381 DkgQueryMsg::GetVerificationKeys {
382 epoch_id,
383 limit,
384 start_after,
385 } => client
386 .get_vk_shares_paged(epoch_id, start_after, limit)
387 .ignore(),
388 DkgQueryMsg::GetCW2ContractVersion {} => client.get_contract_cw2_version().ignore(),
389 };
390 }
391}