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 nym_contracts_common::signing::Nonce;
11use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
12use nym_mixnet_contract_common::nym_node::{
13 EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeDetailsResponse,
14 NodeOwnershipResponse, NodeRewardingDetailsResponse, PagedNymNodeBondsResponse,
15 PagedNymNodeDetailsResponse, PagedUnbondedNymNodesResponse, RewardedSetMetadata, Role,
16 RolesMetadataResponse, StakeSaturationResponse, UnbondedNodeResponse, UnbondedNymNode,
17};
18use nym_mixnet_contract_common::reward_params::WorkFactor;
19use nym_mixnet_contract_common::{
20 delegation,
21 delegation::{NodeDelegationResponse, OwnerProxySubKey},
22 mixnode::{
23 MixStakeSaturationResponse, MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
24 PagedUnbondedMixnodesResponse, UnbondedMixnodeResponse,
25 },
26 reward_params::{Performance, RewardingParams},
27 rewarding::{EstimatedCurrentEpochRewardResponse, PendingRewardResponse},
28 ContractBuildInformation, ContractState, ContractStateParams, CurrentIntervalResponse,
29 CurrentNymNodeVersionResponse, Delegation, EpochEventId, EpochRewardedSet, EpochStatus,
30 GatewayBond, GatewayBondResponse, GatewayOwnershipResponse, HistoricalNymNodeVersionEntry,
31 IdentityKey, IdentityKeyRef, IntervalEventId, KeyRotationIdResponse, KeyRotationState,
32 MixNodeBond, MixNodeDetails, MixOwnershipResponse, MixnodeDetailsByIdentityResponse,
33 MixnodeDetailsResponse, NodeId, NumberOfPendingEventsResponse, NymNodeBond, NymNodeDetails,
34 NymNodeVersionHistoryResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
35 PagedGatewayResponse, PagedMixnodeBondsResponse, PagedNodeDelegationsResponse,
36 PendingEpochEvent, PendingEpochEventResponse, PendingEpochEventsResponse, PendingIntervalEvent,
37 PendingIntervalEventResponse, PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg,
38 RewardedSet, UnbondedMixnode,
39};
40use serde::Deserialize;
41
42#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
43#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
44pub trait MixnetQueryClient {
45 async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
46 where
47 for<'a> T: Deserialize<'a>;
48
49 async fn admin(&self) -> Result<cw_controllers::AdminResponse, NyxdError> {
52 self.query_mixnet_contract(MixnetQueryMsg::Admin {}).await
53 }
54
55 async fn get_mixnet_contract_version(&self) -> Result<ContractBuildInformation, NyxdError> {
56 self.query_mixnet_contract(MixnetQueryMsg::GetContractVersion {})
57 .await
58 }
59
60 async fn get_mixnet_contract_cw2_version(&self) -> Result<cw2::ContractVersion, NyxdError> {
61 self.query_mixnet_contract(MixnetQueryMsg::GetCW2ContractVersion {})
62 .await
63 }
64
65 async fn get_rewarding_validator_address(&self) -> Result<AccountId, NyxdError> {
66 self.query_mixnet_contract(MixnetQueryMsg::GetRewardingValidatorAddress {})
67 .await
68 }
69
70 async fn get_mixnet_contract_state_params(&self) -> Result<ContractStateParams, NyxdError> {
71 self.query_mixnet_contract(MixnetQueryMsg::GetStateParams {})
72 .await
73 }
74
75 async fn get_nym_node_version_history_paged(
76 &self,
77 start_after: Option<u32>,
78 limit: Option<u32>,
79 ) -> Result<NymNodeVersionHistoryResponse, NyxdError> {
80 self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeVersionHistory { limit, start_after })
81 .await
82 }
83
84 async fn get_current_nym_node_version(
85 &self,
86 ) -> Result<CurrentNymNodeVersionResponse, NyxdError> {
87 self.query_mixnet_contract(MixnetQueryMsg::GetCurrentNymNodeVersion {})
88 .await
89 }
90
91 async fn get_mixnet_contract_state(&self) -> Result<ContractState, NyxdError> {
92 self.query_mixnet_contract(MixnetQueryMsg::GetState {})
93 .await
94 }
95
96 async fn get_rewarding_parameters(&self) -> Result<RewardingParams, NyxdError> {
97 self.query_mixnet_contract(MixnetQueryMsg::GetRewardingParams {})
98 .await
99 }
100
101 async fn get_current_epoch_status(&self) -> Result<EpochStatus, NyxdError> {
102 self.query_mixnet_contract(MixnetQueryMsg::GetEpochStatus {})
103 .await
104 }
105
106 async fn get_current_interval_details(&self) -> Result<CurrentIntervalResponse, NyxdError> {
107 self.query_mixnet_contract(MixnetQueryMsg::GetCurrentIntervalDetails {})
108 .await
109 }
110
111 async fn get_mixnode_bonds_paged(
114 &self,
115 start_after: Option<NodeId>,
116 limit: Option<u32>,
117 ) -> Result<PagedMixnodeBondsResponse, NyxdError> {
118 self.query_mixnet_contract(MixnetQueryMsg::GetMixNodeBonds { limit, start_after })
119 .await
120 }
121
122 async fn get_mixnodes_detailed_paged(
123 &self,
124 start_after: Option<NodeId>,
125 limit: Option<u32>,
126 ) -> Result<PagedMixnodesDetailsResponse, NyxdError> {
127 self.query_mixnet_contract(MixnetQueryMsg::GetMixNodesDetailed { limit, start_after })
128 .await
129 }
130
131 async fn get_unbonded_mixnodes_paged(
132 &self,
133 start_after: Option<NodeId>,
134 limit: Option<u32>,
135 ) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
136 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after })
137 .await
138 }
139
140 async fn get_unbonded_mixnodes_by_owner_paged(
141 &self,
142 owner: &AccountId,
143 start_after: Option<NodeId>,
144 limit: Option<u32>,
145 ) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
146 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodesByOwner {
147 owner: owner.to_string(),
148 limit,
149 start_after,
150 })
151 .await
152 }
153
154 async fn get_unbonded_mixnodes_by_identity_paged(
155 &self,
156 identity_key: IdentityKeyRef<'_>,
157 start_after: Option<NodeId>,
158 limit: Option<u32>,
159 ) -> Result<PagedUnbondedMixnodesResponse, NyxdError> {
160 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodesByIdentityKey {
161 identity_key: identity_key.to_string(),
162 limit,
163 start_after,
164 })
165 .await
166 }
167
168 async fn get_owned_mixnode(
169 &self,
170 address: &AccountId,
171 ) -> Result<MixOwnershipResponse, NyxdError> {
172 self.query_mixnet_contract(MixnetQueryMsg::GetOwnedMixnode {
173 address: address.to_string(),
174 })
175 .await
176 }
177
178 async fn get_mixnode_details(
179 &self,
180 mix_id: NodeId,
181 ) -> Result<MixnodeDetailsResponse, NyxdError> {
182 self.query_mixnet_contract(MixnetQueryMsg::GetMixnodeDetails { mix_id })
183 .await
184 }
185
186 async fn get_mixnode_details_by_identity(
187 &self,
188 mix_identity: IdentityKey,
189 ) -> Result<MixnodeDetailsByIdentityResponse, NyxdError> {
190 self.query_mixnet_contract(MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity {
191 mix_identity,
192 })
193 .await
194 }
195
196 async fn get_mixnode_rewarding_details(
197 &self,
198 mix_id: NodeId,
199 ) -> Result<MixnodeRewardingDetailsResponse, NyxdError> {
200 self.query_mixnet_contract(MixnetQueryMsg::GetMixnodeRewardingDetails { mix_id })
201 .await
202 }
203
204 async fn get_mixnode_stake_saturation(
205 &self,
206 mix_id: NodeId,
207 ) -> Result<MixStakeSaturationResponse, NyxdError> {
208 self.query_mixnet_contract(MixnetQueryMsg::GetStakeSaturation { mix_id })
209 .await
210 }
211
212 async fn get_unbonded_mixnode_information(
213 &self,
214 mix_id: NodeId,
215 ) -> Result<UnbondedMixnodeResponse, NyxdError> {
216 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedMixNodeInformation { mix_id })
217 .await
218 }
219
220 async fn get_gateways_paged(
228 &self,
229 start_after: Option<IdentityKey>,
230 limit: Option<u32>,
231 ) -> Result<PagedGatewayResponse, NyxdError> {
232 self.query_mixnet_contract(MixnetQueryMsg::GetGateways { start_after, limit })
233 .await
234 }
235
236 async fn get_gateway_bond(
238 &self,
239 identity: IdentityKey,
240 ) -> Result<GatewayBondResponse, NyxdError> {
241 self.query_mixnet_contract(MixnetQueryMsg::GetGatewayBond { identity })
242 .await
243 }
244
245 async fn get_owned_gateway(
247 &self,
248 address: &AccountId,
249 ) -> Result<GatewayOwnershipResponse, NyxdError> {
250 self.query_mixnet_contract(MixnetQueryMsg::GetOwnedGateway {
251 address: address.to_string(),
252 })
253 .await
254 }
255
256 async fn get_preassigned_gateway_ids_paged(
257 &self,
258 start_after: Option<IdentityKey>,
259 limit: Option<u32>,
260 ) -> Result<PreassignedGatewayIdsResponse, NyxdError> {
261 self.query_mixnet_contract(MixnetQueryMsg::GetPreassignedGatewayIds { start_after, limit })
262 .await
263 }
264
265 async fn get_nymnode_bonds_paged(
267 &self,
268 start_after: Option<NodeId>,
269 limit: Option<u32>,
270 ) -> Result<PagedNymNodeBondsResponse, NyxdError> {
271 self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeBondsPaged { limit, start_after })
272 .await
273 }
274
275 async fn get_nymnodes_detailed_paged(
276 &self,
277 start_after: Option<NodeId>,
278 limit: Option<u32>,
279 ) -> Result<PagedNymNodeDetailsResponse, NyxdError> {
280 self.query_mixnet_contract(MixnetQueryMsg::GetNymNodesDetailedPaged { limit, start_after })
281 .await
282 }
283
284 async fn get_unbonded_nymnodes_paged(
285 &self,
286 start_after: Option<NodeId>,
287 limit: Option<u32>,
288 ) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
289 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesPaged { limit, start_after })
290 .await
291 }
292
293 async fn get_unbonded_nymnodes_by_owner_paged(
294 &self,
295 owner: &AccountId,
296 start_after: Option<NodeId>,
297 limit: Option<u32>,
298 ) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
299 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesByOwnerPaged {
300 owner: owner.to_string(),
301 limit,
302 start_after,
303 })
304 .await
305 }
306
307 async fn get_unbonded_nymnodes_by_identity_paged(
308 &self,
309 identity_key: IdentityKeyRef<'_>,
310 start_after: Option<NodeId>,
311 limit: Option<u32>,
312 ) -> Result<PagedUnbondedNymNodesResponse, NyxdError> {
313 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNodesByIdentityKeyPaged {
314 identity_key: identity_key.to_string(),
315 limit,
316 start_after,
317 })
318 .await
319 }
320
321 async fn get_owned_nymnode(
322 &self,
323 address: &AccountId,
324 ) -> Result<NodeOwnershipResponse, NyxdError> {
325 self.query_mixnet_contract(MixnetQueryMsg::GetOwnedNymNode {
326 address: address.to_string(),
327 })
328 .await
329 }
330
331 async fn get_nymnode_details(&self, node_id: NodeId) -> Result<NodeDetailsResponse, NyxdError> {
332 self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
333 .await
334 }
335
336 async fn get_nymnode_details_by_identity(
337 &self,
338 node_identity: IdentityKey,
339 ) -> Result<NodeDetailsByIdentityResponse, NyxdError> {
340 self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetailsByIdentityKey { node_identity })
341 .await
342 }
343
344 async fn get_nymnode_rewarding_details(
345 &self,
346 node_id: NodeId,
347 ) -> Result<NodeRewardingDetailsResponse, NyxdError> {
348 self.query_mixnet_contract(MixnetQueryMsg::GetNodeRewardingDetails { node_id })
349 .await
350 }
351
352 async fn get_node_stake_saturation(
353 &self,
354 node_id: NodeId,
355 ) -> Result<StakeSaturationResponse, NyxdError> {
356 self.query_mixnet_contract(MixnetQueryMsg::GetNodeStakeSaturation { node_id })
357 .await
358 }
359
360 async fn get_unbonded_nymnode_information(
361 &self,
362 node_id: NodeId,
363 ) -> Result<UnbondedNodeResponse, NyxdError> {
364 self.query_mixnet_contract(MixnetQueryMsg::GetUnbondedNymNode { node_id })
365 .await
366 }
367
368 async fn get_role_assignment(&self, role: Role) -> Result<EpochAssignmentResponse, NyxdError> {
369 self.query_mixnet_contract(MixnetQueryMsg::GetRoleAssignment { role })
370 .await
371 }
372
373 async fn get_rewarded_set_metadata(&self) -> Result<RolesMetadataResponse, NyxdError> {
374 self.query_mixnet_contract(MixnetQueryMsg::GetRewardedSetMetadata {})
375 .await
376 }
377
378 async fn get_mixnode_delegations_paged(
382 &self,
383 node_id: NodeId,
384 start_after: Option<String>,
385 limit: Option<u32>,
386 ) -> Result<PagedNodeDelegationsResponse, NyxdError> {
387 self.query_mixnet_contract(MixnetQueryMsg::GetNodeDelegations {
388 node_id,
389 start_after,
390 limit,
391 })
392 .await
393 }
394
395 async fn get_delegator_delegations_paged(
397 &self,
398 delegator: &AccountId,
399 start_after: Option<(NodeId, OwnerProxySubKey)>,
400 limit: Option<u32>,
401 ) -> Result<PagedDelegatorDelegationsResponse, NyxdError> {
402 self.query_mixnet_contract(MixnetQueryMsg::GetDelegatorDelegations {
403 delegator: delegator.to_string(),
404 start_after,
405 limit,
406 })
407 .await
408 }
409
410 async fn get_delegation_details(
412 &self,
413 node_id: NodeId,
414 delegator: &AccountId,
415 proxy: Option<String>,
416 ) -> Result<NodeDelegationResponse, NyxdError> {
417 self.query_mixnet_contract(MixnetQueryMsg::GetDelegationDetails {
418 node_id,
419 delegator: delegator.to_string(),
420 proxy,
421 })
422 .await
423 }
424
425 async fn get_all_network_delegations_paged(
427 &self,
428 start_after: Option<delegation::StorageKey>,
429 limit: Option<u32>,
430 ) -> Result<PagedAllDelegationsResponse, NyxdError> {
431 self.query_mixnet_contract(MixnetQueryMsg::GetAllDelegations { start_after, limit })
432 .await
433 }
434
435 async fn get_pending_operator_reward(
437 &self,
438 operator: &AccountId,
439 ) -> Result<PendingRewardResponse, NyxdError> {
440 self.query_mixnet_contract(MixnetQueryMsg::GetPendingOperatorReward {
441 address: operator.to_string(),
442 })
443 .await
444 }
445
446 async fn get_pending_mixnode_operator_reward(
447 &self,
448 node_id: NodeId,
449 ) -> Result<PendingRewardResponse, NyxdError> {
450 self.query_mixnet_contract(MixnetQueryMsg::GetPendingNodeOperatorReward { node_id })
451 .await
452 }
453
454 async fn get_pending_delegator_reward(
455 &self,
456 delegator: &AccountId,
457 node_id: NodeId,
458 proxy: Option<String>,
459 ) -> Result<PendingRewardResponse, NyxdError> {
460 self.query_mixnet_contract(MixnetQueryMsg::GetPendingDelegatorReward {
461 address: delegator.to_string(),
462 node_id,
463 proxy,
464 })
465 .await
466 }
467
468 async fn get_estimated_current_epoch_operator_reward(
470 &self,
471 node_id: NodeId,
472 estimated_performance: Performance,
473 estimated_work: Option<WorkFactor>,
474 ) -> Result<EstimatedCurrentEpochRewardResponse, NyxdError> {
475 self.query_mixnet_contract(MixnetQueryMsg::GetEstimatedCurrentEpochOperatorReward {
476 node_id,
477 estimated_performance,
478 estimated_work,
479 })
480 .await
481 }
482
483 async fn get_estimated_current_epoch_delegator_reward(
485 &self,
486 delegator: &AccountId,
487 node_id: NodeId,
488 estimated_performance: Performance,
489 estimated_work: Option<WorkFactor>,
490 ) -> Result<EstimatedCurrentEpochRewardResponse, NyxdError> {
491 self.query_mixnet_contract(MixnetQueryMsg::GetEstimatedCurrentEpochDelegatorReward {
492 address: delegator.to_string(),
493 node_id,
494 estimated_performance,
495 estimated_work,
496 })
497 .await
498 }
499
500 async fn get_pending_epoch_events_paged(
503 &self,
504 start_after: Option<EpochEventId>,
505 limit: Option<u32>,
506 ) -> Result<PendingEpochEventsResponse, NyxdError> {
507 self.query_mixnet_contract(MixnetQueryMsg::GetPendingEpochEvents { start_after, limit })
508 .await
509 }
510
511 async fn get_pending_interval_events_paged(
512 &self,
513 start_after: Option<IntervalEventId>,
514 limit: Option<u32>,
515 ) -> Result<PendingIntervalEventsResponse, NyxdError> {
516 self.query_mixnet_contract(MixnetQueryMsg::GetPendingIntervalEvents { start_after, limit })
517 .await
518 }
519
520 async fn get_pending_epoch_event(
521 &self,
522 event_id: EpochEventId,
523 ) -> Result<PendingEpochEventResponse, NyxdError> {
524 self.query_mixnet_contract(MixnetQueryMsg::GetPendingEpochEvent { event_id })
525 .await
526 }
527
528 async fn get_pending_interval_event(
529 &self,
530 event_id: IntervalEventId,
531 ) -> Result<PendingIntervalEventResponse, NyxdError> {
532 self.query_mixnet_contract(MixnetQueryMsg::GetPendingIntervalEvent { event_id })
533 .await
534 }
535
536 async fn get_number_of_pending_events(
537 &self,
538 ) -> Result<NumberOfPendingEventsResponse, NyxdError> {
539 self.query_mixnet_contract(MixnetQueryMsg::GetNumberOfPendingEvents {})
540 .await
541 }
542
543 async fn get_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
544 self.query_mixnet_contract(MixnetQueryMsg::GetSigningNonce {
545 address: address.to_string(),
546 })
547 .await
548 }
549
550 async fn get_key_rotation_state(&self) -> Result<KeyRotationState, NyxdError> {
551 self.query_mixnet_contract(MixnetQueryMsg::GetKeyRotationState {})
552 .await
553 }
554
555 async fn get_key_rotation_id(&self) -> Result<KeyRotationIdResponse, NyxdError> {
556 self.query_mixnet_contract(MixnetQueryMsg::GetKeyRotationId {})
557 .await
558 }
559}
560
561#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
564#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
565pub trait PagedMixnetQueryClient: MixnetQueryClient {
566 async fn get_all_nymnode_bonds(&self) -> Result<Vec<NymNodeBond>, NyxdError> {
567 collect_paged!(self, get_nymnode_bonds_paged, nodes)
568 }
569
570 async fn get_all_nymnodes_detailed(&self) -> Result<Vec<NymNodeDetails>, NyxdError> {
571 collect_paged!(self, get_nymnodes_detailed_paged, nodes)
572 }
573
574 async fn get_all_unbonded_nymnodes(&self) -> Result<Vec<UnbondedNymNode>, NyxdError> {
575 collect_paged!(self, get_unbonded_nymnodes_paged, nodes)
576 }
577
578 async fn get_all_unbonded_nymnodes_by_owner(
579 &self,
580 owner: &AccountId,
581 ) -> Result<Vec<UnbondedNymNode>, NyxdError> {
582 collect_paged!(self, get_unbonded_nymnodes_by_owner_paged, nodes, owner)
583 }
584
585 async fn get_all_unbonded_nymnodes_by_identity(
586 &self,
587 identity_key: IdentityKeyRef<'_>,
588 ) -> Result<Vec<UnbondedNymNode>, NyxdError> {
589 collect_paged!(
590 self,
591 get_unbonded_nymnodes_by_identity_paged,
592 nodes,
593 identity_key
594 )
595 }
596
597 async fn get_all_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, NyxdError> {
598 collect_paged!(self, get_mixnode_bonds_paged, nodes)
599 }
600
601 async fn get_all_mixnodes_detailed(&self) -> Result<Vec<MixNodeDetails>, NyxdError> {
602 collect_paged!(self, get_mixnodes_detailed_paged, nodes)
603 }
604
605 async fn get_all_unbonded_mixnodes(&self) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
606 collect_paged!(self, get_unbonded_mixnodes_paged, nodes)
607 }
608
609 async fn get_all_unbonded_mixnodes_by_owner(
610 &self,
611 owner: &AccountId,
612 ) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
613 collect_paged!(self, get_unbonded_mixnodes_by_owner_paged, nodes, owner)
614 }
615
616 async fn get_all_unbonded_mixnodes_by_identity(
617 &self,
618 identity_key: IdentityKeyRef<'_>,
619 ) -> Result<Vec<(NodeId, UnbondedMixnode)>, NyxdError> {
620 collect_paged!(
621 self,
622 get_unbonded_mixnodes_by_identity_paged,
623 nodes,
624 identity_key
625 )
626 }
627
628 async fn get_all_gateways(&self) -> Result<Vec<GatewayBond>, NyxdError> {
629 collect_paged!(self, get_gateways_paged, nodes)
630 }
631
632 async fn get_all_preassigned_gateway_ids(&self) -> Result<Vec<PreassignedId>, NyxdError> {
633 collect_paged!(self, get_preassigned_gateway_ids_paged, ids)
634 }
635
636 async fn get_all_single_mixnode_delegations(
637 &self,
638 mix_id: NodeId,
639 ) -> Result<Vec<Delegation>, NyxdError> {
640 collect_paged!(self, get_mixnode_delegations_paged, delegations, mix_id)
641 }
642
643 async fn get_all_delegator_delegations(
644 &self,
645 delegation_owner: &AccountId,
646 ) -> Result<Vec<Delegation>, NyxdError> {
647 collect_paged!(
648 self,
649 get_delegator_delegations_paged,
650 delegations,
651 delegation_owner
652 )
653 }
654
655 async fn get_all_network_delegations(&self) -> Result<Vec<Delegation>, NyxdError> {
656 collect_paged!(self, get_all_network_delegations_paged, delegations)
657 }
658
659 async fn get_all_pending_epoch_events(&self) -> Result<Vec<PendingEpochEvent>, NyxdError> {
660 collect_paged!(self, get_pending_epoch_events_paged, events)
661 }
662
663 async fn get_all_pending_interval_events(
664 &self,
665 ) -> Result<Vec<PendingIntervalEvent>, NyxdError> {
666 collect_paged!(self, get_pending_interval_events_paged, events)
667 }
668
669 async fn get_full_nym_node_version_history(
670 &self,
671 ) -> Result<Vec<HistoricalNymNodeVersionEntry>, NyxdError> {
672 collect_paged!(self, get_nym_node_version_history_paged, history)
673 }
674}
675
676#[async_trait]
677impl<T> PagedMixnetQueryClient for T where T: MixnetQueryClient {}
678
679#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
681#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
682pub trait MixnetQueryClientExt: MixnetQueryClient {
683 async fn get_rewarded_set(&self) -> Result<EpochRewardedSet, NyxdError> {
684 let error_response = |message| Err(NyxdError::extension_query_failure("mixnet", message));
685
686 let metadata = self.get_rewarded_set_metadata().await?;
689
690 let is_default = metadata.metadata == RewardedSetMetadata::default();
691 if !metadata.metadata.fully_assigned && !is_default {
692 return error_response("the rewarded set hasn't been fully assigned for this epoch");
693 }
694 let expected_epoch_id = metadata.metadata.epoch_id;
695
696 if is_default {
697 return Ok(Default::default());
698 }
699
700 let entry = self.get_role_assignment(Role::EntryGateway).await?;
703 if entry.epoch_id != expected_epoch_id {
704 return error_response("the nodes assigned for 'entry' returned unexpected epoch_id");
705 }
706
707 let exit = self.get_role_assignment(Role::ExitGateway).await?;
708 if exit.epoch_id != expected_epoch_id {
709 return error_response("the nodes assigned for 'exit' returned unexpected epoch_id");
710 }
711
712 let layer1 = self.get_role_assignment(Role::Layer1).await?;
713 if layer1.epoch_id != expected_epoch_id {
714 return error_response("the nodes assigned for 'layer1' returned unexpected epoch_id");
715 }
716
717 let layer2 = self.get_role_assignment(Role::Layer2).await?;
718 if layer2.epoch_id != expected_epoch_id {
719 return error_response("the nodes assigned for 'layer2' returned unexpected epoch_id");
720 }
721
722 let layer3 = self.get_role_assignment(Role::Layer3).await?;
723 if layer3.epoch_id != expected_epoch_id {
724 return error_response("the nodes assigned for 'layer3' returned unexpected epoch_id");
725 }
726
727 let standby = self.get_role_assignment(Role::Standby).await?;
728 if standby.epoch_id != expected_epoch_id {
729 return error_response("the nodes assigned for 'standby' returned unexpected epoch_id");
730 }
731
732 Ok(EpochRewardedSet {
733 epoch_id: expected_epoch_id,
734 assignment: RewardedSet {
735 entry_gateways: entry.nodes,
736 exit_gateways: exit.nodes,
737 layer1: layer1.nodes,
738 layer2: layer2.nodes,
739 layer3: layer3.nodes,
740 standby: standby.nodes,
741 },
742 })
743 }
744}
745
746#[async_trait]
747impl<T> MixnetQueryClientExt for T where T: MixnetQueryClient {}
748
749#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
750#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
751impl<C> MixnetQueryClient for C
752where
753 C: CosmWasmClient + NymContractsProvider + Send + Sync,
754{
755 async fn query_mixnet_contract<T>(&self, query: MixnetQueryMsg) -> Result<T, NyxdError>
756 where
757 for<'a> T: Deserialize<'a>,
758 {
759 let mixnet_contract_address = &self
760 .mixnet_contract_address()
761 .ok_or_else(|| NyxdError::unavailable_contract_address("mixnet contract"))?;
762 self.query_contract_smart(mixnet_contract_address, &query)
763 .await
764 }
765}
766
767#[cfg(test)]
768mod tests {
769 use super::*;
770 use crate::nyxd::contract_traits::tests::IgnoreValue;
771 use nym_mixnet_contract_common::QueryMsg;
772
773 #[allow(dead_code)]
775 fn all_query_variants_are_covered<C: MixnetQueryClient + Send + Sync>(
776 client: C,
777 msg: MixnetQueryMsg,
778 ) -> u32 {
779 match msg {
780 MixnetQueryMsg::Admin {} => client.admin().ignore(),
781 MixnetQueryMsg::GetContractVersion {} => client.get_mixnet_contract_version().ignore(),
782 MixnetQueryMsg::GetCW2ContractVersion {} => {
783 client.get_mixnet_contract_cw2_version().ignore()
784 }
785 MixnetQueryMsg::GetRewardingValidatorAddress {} => {
786 client.get_rewarding_validator_address().ignore()
787 }
788 MixnetQueryMsg::GetStateParams {} => client.get_mixnet_contract_state_params().ignore(),
789 MixnetQueryMsg::GetState {} => client.get_mixnet_contract_state().ignore(),
790 MixnetQueryMsg::GetRewardingParams {} => client.get_rewarding_parameters().ignore(),
791 MixnetQueryMsg::GetEpochStatus {} => client.get_current_epoch_status().ignore(),
792 MixnetQueryMsg::GetCurrentIntervalDetails {} => {
793 client.get_current_interval_details().ignore()
794 }
795 MixnetQueryMsg::GetMixNodeBonds { limit, start_after } => {
796 client.get_mixnode_bonds_paged(start_after, limit).ignore()
797 }
798 MixnetQueryMsg::GetMixNodesDetailed { limit, start_after } => client
799 .get_mixnodes_detailed_paged(start_after, limit)
800 .ignore(),
801 MixnetQueryMsg::GetUnbondedMixNodes { limit, start_after } => client
802 .get_unbonded_mixnodes_paged(start_after, limit)
803 .ignore(),
804 MixnetQueryMsg::GetUnbondedMixNodesByOwner {
805 owner,
806 limit,
807 start_after,
808 } => client
809 .get_unbonded_mixnodes_by_owner_paged(&owner.parse().unwrap(), start_after, limit)
810 .ignore(),
811 MixnetQueryMsg::GetUnbondedMixNodesByIdentityKey {
812 identity_key,
813 limit,
814 start_after,
815 } => client
816 .get_unbonded_mixnodes_by_identity_paged(&identity_key, start_after, limit)
817 .ignore(),
818 MixnetQueryMsg::GetOwnedMixnode { address } => {
819 client.get_owned_mixnode(&address.parse().unwrap()).ignore()
820 }
821 MixnetQueryMsg::GetMixnodeDetails { mix_id } => {
822 client.get_mixnode_details(mix_id).ignore()
823 }
824 MixnetQueryMsg::GetMixnodeRewardingDetails { mix_id } => {
825 client.get_mixnode_rewarding_details(mix_id).ignore()
826 }
827 MixnetQueryMsg::GetStakeSaturation { mix_id } => {
828 client.get_mixnode_stake_saturation(mix_id).ignore()
829 }
830 MixnetQueryMsg::GetUnbondedMixNodeInformation { mix_id } => {
831 client.get_unbonded_mixnode_information(mix_id).ignore()
832 }
833 MixnetQueryMsg::GetBondedMixnodeDetailsByIdentity { mix_identity } => client
834 .get_mixnode_details_by_identity(mix_identity)
835 .ignore(),
836 MixnetQueryMsg::GetGateways { start_after, limit } => {
837 client.get_gateways_paged(start_after, limit).ignore()
838 }
839 MixnetQueryMsg::GetGatewayBond { identity } => {
840 client.get_gateway_bond(identity).ignore()
841 }
842 MixnetQueryMsg::GetOwnedGateway { address } => {
843 client.get_owned_gateway(&address.parse().unwrap()).ignore()
844 }
845 MixnetQueryMsg::GetNodeDelegations {
846 node_id: mix_id,
847 start_after,
848 limit,
849 } => client
850 .get_mixnode_delegations_paged(mix_id, start_after, limit)
851 .ignore(),
852 MixnetQueryMsg::GetDelegatorDelegations {
853 delegator,
854 start_after,
855 limit,
856 } => client
857 .get_delegator_delegations_paged(&delegator.parse().unwrap(), start_after, limit)
858 .ignore(),
859 MixnetQueryMsg::GetDelegationDetails {
860 node_id: mix_id,
861 delegator,
862 proxy,
863 } => client
864 .get_delegation_details(mix_id, &delegator.parse().unwrap(), proxy)
865 .ignore(),
866 MixnetQueryMsg::GetAllDelegations { start_after, limit } => client
867 .get_all_network_delegations_paged(start_after, limit)
868 .ignore(),
869 MixnetQueryMsg::GetPendingOperatorReward { address } => client
870 .get_pending_operator_reward(&address.parse().unwrap())
871 .ignore(),
872 MixnetQueryMsg::GetPendingNodeOperatorReward { node_id: mix_id } => {
873 client.get_pending_mixnode_operator_reward(mix_id).ignore()
874 }
875 MixnetQueryMsg::GetPendingDelegatorReward {
876 address,
877 node_id: mix_id,
878 proxy,
879 } => client
880 .get_pending_delegator_reward(&address.parse().unwrap(), mix_id, proxy)
881 .ignore(),
882 MixnetQueryMsg::GetEstimatedCurrentEpochOperatorReward {
883 node_id,
884 estimated_performance,
885 estimated_work,
886 } => client
887 .get_estimated_current_epoch_operator_reward(
888 node_id,
889 estimated_performance,
890 estimated_work,
891 )
892 .ignore(),
893 MixnetQueryMsg::GetEstimatedCurrentEpochDelegatorReward {
894 address,
895 node_id,
896 estimated_performance,
897 estimated_work,
898 } => client
899 .get_estimated_current_epoch_delegator_reward(
900 &address.parse().unwrap(),
901 node_id,
902 estimated_performance,
903 estimated_work,
904 )
905 .ignore(),
906 MixnetQueryMsg::GetPendingEpochEvents { limit, start_after } => client
907 .get_pending_epoch_events_paged(start_after, limit)
908 .ignore(),
909 MixnetQueryMsg::GetPendingIntervalEvents { limit, start_after } => client
910 .get_pending_interval_events_paged(start_after, limit)
911 .ignore(),
912 MixnetQueryMsg::GetPendingEpochEvent { event_id } => {
913 client.get_pending_epoch_event(event_id).ignore()
914 }
915 MixnetQueryMsg::GetPendingIntervalEvent { event_id } => {
916 client.get_pending_interval_event(event_id).ignore()
917 }
918 MixnetQueryMsg::GetNumberOfPendingEvents {} => {
919 client.get_number_of_pending_events().ignore()
920 }
921 MixnetQueryMsg::GetSigningNonce { address } => {
922 client.get_signing_nonce(&address.parse().unwrap()).ignore()
923 }
924 MixnetQueryMsg::GetPreassignedGatewayIds { start_after, limit } => client
925 .get_preassigned_gateway_ids_paged(start_after, limit)
926 .ignore(),
927 MixnetQueryMsg::GetNymNodeBondsPaged { limit, start_after } => {
928 client.get_nymnode_bonds_paged(limit, start_after).ignore()
929 }
930 MixnetQueryMsg::GetNymNodesDetailedPaged { limit, start_after } => client
931 .get_nymnodes_detailed_paged(limit, start_after)
932 .ignore(),
933 MixnetQueryMsg::GetUnbondedNymNode { node_id } => {
934 client.get_unbonded_nymnode_information(node_id).ignore()
935 }
936 MixnetQueryMsg::GetUnbondedNymNodesPaged { limit, start_after } => client
937 .get_unbonded_nymnodes_paged(limit, start_after)
938 .ignore(),
939 MixnetQueryMsg::GetUnbondedNymNodesByOwnerPaged {
940 owner,
941 limit,
942 start_after,
943 } => client
944 .get_unbonded_nymnodes_by_owner_paged(&owner.parse().unwrap(), limit, start_after)
945 .ignore(),
946 MixnetQueryMsg::GetUnbondedNymNodesByIdentityKeyPaged {
947 identity_key,
948 limit,
949 start_after,
950 } => client
951 .get_unbonded_nymnodes_by_identity_paged(&identity_key, limit, start_after)
952 .ignore(),
953 MixnetQueryMsg::GetOwnedNymNode { address } => {
954 client.get_owned_nymnode(&address.parse().unwrap()).ignore()
955 }
956 MixnetQueryMsg::GetNymNodeDetails { node_id } => {
957 client.get_nymnode_details(node_id).ignore()
958 }
959 MixnetQueryMsg::GetNymNodeDetailsByIdentityKey { node_identity } => client
960 .get_nymnode_details_by_identity(node_identity)
961 .ignore(),
962 MixnetQueryMsg::GetNodeRewardingDetails { node_id } => {
963 client.get_nymnode_rewarding_details(node_id).ignore()
964 }
965 MixnetQueryMsg::GetNodeStakeSaturation { node_id } => {
966 client.get_node_stake_saturation(node_id).ignore()
967 }
968 MixnetQueryMsg::GetRoleAssignment { role } => client.get_role_assignment(role).ignore(),
969 MixnetQueryMsg::GetRewardedSetMetadata {} => {
970 client.get_rewarded_set_metadata().ignore()
971 }
972 QueryMsg::GetCurrentNymNodeVersion {} => client.get_current_nym_node_version().ignore(),
973 QueryMsg::GetNymNodeVersionHistory { limit, start_after } => client
974 .get_nym_node_version_history_paged(start_after, limit)
975 .ignore(),
976 QueryMsg::GetKeyRotationState {} => client.get_key_rotation_state().ignore(),
977 QueryMsg::GetKeyRotationId {} => client.get_key_rotation_id().ignore(),
978 }
979 }
980}