fedimint_mint_client/
api.rs1use fedimint_api_client::api::{
2 FederationApiExt, FederationResult, IModuleFederationApi, ServerResult,
3};
4use fedimint_core::bitcoin::hashes::sha256;
5use fedimint_core::module::registry::ModuleRegistry;
6use fedimint_core::module::{ApiRequestErased, SerdeModuleEncodingBase64};
7use fedimint_core::task::{MaybeSend, MaybeSync};
8use fedimint_core::{OutPoint, PeerId, apply, async_trait_maybe_send};
9use fedimint_mint_common::endpoint_constants::{
10 BLIND_NONCE_USED_ENDPOINT, NOTE_SPENT_ENDPOINT, RECOVERY_BLIND_NONCE_OUTPOINTS_ENDPOINT,
11 RECOVERY_COUNT_ENDPOINT, RECOVERY_SLICE_ENDPOINT, RECOVERY_SLICE_HASH_ENDPOINT,
12};
13use fedimint_mint_common::{BlindNonce, Nonce, RecoveryItem};
14
15use crate::error::FetchRecoverySliceError;
16
17#[apply(async_trait_maybe_send!)]
18pub trait MintFederationApi {
19 async fn check_blind_nonce_used(&self, blind_nonce: BlindNonce) -> FederationResult<bool>;
20
21 async fn check_note_spent(&self, nonce: Nonce) -> FederationResult<bool>;
22
23 async fn check_blind_nonce_used_single_peer(
29 &self,
30 peer: PeerId,
31 blind_nonce: BlindNonce,
32 ) -> ServerResult<bool>;
33
34 async fn check_note_spent_single_peer(&self, peer: PeerId, nonce: Nonce) -> ServerResult<bool>;
40
41 async fn fetch_recovery_count(&self) -> FederationResult<u64>;
43
44 async fn fetch_recovery_slice_hash(&self, start: u64, end: u64) -> sha256::Hash;
47
48 async fn fetch_recovery_slice(
50 &self,
51 peer: PeerId,
52 start: u64,
53 end: u64,
54 ) -> Result<Vec<RecoveryItem>, FetchRecoverySliceError>;
55
56 async fn fetch_blind_nonce_outpoints(
58 &self,
59 blind_nonces: Vec<BlindNonce>,
60 ) -> FederationResult<Vec<OutPoint>>;
61}
62
63#[apply(async_trait_maybe_send!)]
64impl<T: ?Sized> MintFederationApi for T
65where
66 T: IModuleFederationApi + MaybeSend + MaybeSync + 'static,
67{
68 async fn check_blind_nonce_used(&self, blind_nonce: BlindNonce) -> FederationResult<bool> {
69 self.request_current_consensus(
70 BLIND_NONCE_USED_ENDPOINT.to_string(),
71 ApiRequestErased::new(blind_nonce),
72 )
73 .await
74 }
75
76 async fn check_note_spent(&self, nonce: Nonce) -> FederationResult<bool> {
77 self.request_current_consensus(
78 NOTE_SPENT_ENDPOINT.to_string(),
79 ApiRequestErased::new(nonce),
80 )
81 .await
82 }
83
84 async fn check_blind_nonce_used_single_peer(
85 &self,
86 peer: PeerId,
87 blind_nonce: BlindNonce,
88 ) -> ServerResult<bool> {
89 self.request_single_peer::<bool>(
90 BLIND_NONCE_USED_ENDPOINT.to_string(),
91 ApiRequestErased::new(blind_nonce),
92 peer,
93 )
94 .await
95 }
96
97 async fn check_note_spent_single_peer(&self, peer: PeerId, nonce: Nonce) -> ServerResult<bool> {
98 self.request_single_peer::<bool>(
99 NOTE_SPENT_ENDPOINT.to_string(),
100 ApiRequestErased::new(nonce),
101 peer,
102 )
103 .await
104 }
105
106 async fn fetch_recovery_count(&self) -> FederationResult<u64> {
107 self.request_current_consensus::<u64>(
108 RECOVERY_COUNT_ENDPOINT.to_string(),
109 ApiRequestErased::default(),
110 )
111 .await
112 }
113
114 async fn fetch_recovery_slice_hash(&self, start: u64, end: u64) -> sha256::Hash {
115 self.request_current_consensus_retry(
116 RECOVERY_SLICE_HASH_ENDPOINT.to_owned(),
117 ApiRequestErased::new((start, end)),
118 )
119 .await
120 }
121
122 async fn fetch_recovery_slice(
123 &self,
124 peer: PeerId,
125 start: u64,
126 end: u64,
127 ) -> Result<Vec<RecoveryItem>, FetchRecoverySliceError> {
128 let result = self
129 .request_single_peer::<SerdeModuleEncodingBase64<Vec<RecoveryItem>>>(
130 RECOVERY_SLICE_ENDPOINT.to_owned(),
131 ApiRequestErased::new((start, end)),
132 peer,
133 )
134 .await?;
135
136 Ok(result.try_into_inner(&ModuleRegistry::default())?)
137 }
138
139 async fn fetch_blind_nonce_outpoints(
140 &self,
141 blind_nonces: Vec<BlindNonce>,
142 ) -> FederationResult<Vec<OutPoint>> {
143 self.request_current_consensus::<Vec<OutPoint>>(
144 RECOVERY_BLIND_NONCE_OUTPOINTS_ENDPOINT.to_string(),
145 ApiRequestErased::new(blind_nonces),
146 )
147 .await
148 }
149}