fedimint_mint_client/
api.rs1use fedimint_api_client::api::{FederationApiExt, FederationResult, IModuleFederationApi};
2use fedimint_core::bitcoin::hashes::sha256;
3use fedimint_core::module::registry::ModuleRegistry;
4use fedimint_core::module::{ApiRequestErased, SerdeModuleEncodingBase64};
5use fedimint_core::task::{MaybeSend, MaybeSync};
6use fedimint_core::{OutPoint, PeerId, apply, async_trait_maybe_send};
7use fedimint_mint_common::endpoint_constants::{
8 BLIND_NONCE_USED_ENDPOINT, NOTE_SPENT_ENDPOINT, RECOVERY_BLIND_NONCE_OUTPOINTS_ENDPOINT,
9 RECOVERY_COUNT_ENDPOINT, RECOVERY_SLICE_ENDPOINT, RECOVERY_SLICE_HASH_ENDPOINT,
10};
11use fedimint_mint_common::{BlindNonce, Nonce, RecoveryItem};
12
13#[apply(async_trait_maybe_send!)]
14pub trait MintFederationApi {
15 async fn check_blind_nonce_used(&self, blind_nonce: BlindNonce) -> FederationResult<bool>;
16
17 async fn check_note_spent(&self, nonce: Nonce) -> FederationResult<bool>;
18
19 async fn fetch_recovery_count(&self) -> anyhow::Result<u64>;
21
22 async fn fetch_recovery_slice_hash(&self, start: u64, end: u64) -> sha256::Hash;
25
26 async fn fetch_recovery_slice(
28 &self,
29 peer: PeerId,
30 start: u64,
31 end: u64,
32 ) -> anyhow::Result<Vec<RecoveryItem>>;
33
34 async fn fetch_blind_nonce_outpoints(
36 &self,
37 blind_nonces: Vec<BlindNonce>,
38 ) -> anyhow::Result<Vec<OutPoint>>;
39}
40
41#[apply(async_trait_maybe_send!)]
42impl<T: ?Sized> MintFederationApi for T
43where
44 T: IModuleFederationApi + MaybeSend + MaybeSync + 'static,
45{
46 async fn check_blind_nonce_used(&self, blind_nonce: BlindNonce) -> FederationResult<bool> {
47 self.request_current_consensus(
48 BLIND_NONCE_USED_ENDPOINT.to_string(),
49 ApiRequestErased::new(blind_nonce),
50 )
51 .await
52 }
53
54 async fn check_note_spent(&self, nonce: Nonce) -> FederationResult<bool> {
55 self.request_current_consensus(
56 NOTE_SPENT_ENDPOINT.to_string(),
57 ApiRequestErased::new(nonce),
58 )
59 .await
60 }
61
62 async fn fetch_recovery_count(&self) -> anyhow::Result<u64> {
63 self.request_current_consensus::<u64>(
64 RECOVERY_COUNT_ENDPOINT.to_string(),
65 ApiRequestErased::default(),
66 )
67 .await
68 .map_err(|e| anyhow::anyhow!("{e}"))
69 }
70
71 async fn fetch_recovery_slice_hash(&self, start: u64, end: u64) -> sha256::Hash {
72 self.request_current_consensus_retry(
73 RECOVERY_SLICE_HASH_ENDPOINT.to_owned(),
74 ApiRequestErased::new((start, end)),
75 )
76 .await
77 }
78
79 async fn fetch_recovery_slice(
80 &self,
81 peer: PeerId,
82 start: u64,
83 end: u64,
84 ) -> anyhow::Result<Vec<RecoveryItem>> {
85 let result = self
86 .request_single_peer::<SerdeModuleEncodingBase64<Vec<RecoveryItem>>>(
87 RECOVERY_SLICE_ENDPOINT.to_owned(),
88 ApiRequestErased::new((start, end)),
89 peer,
90 )
91 .await?;
92
93 Ok(result.try_into_inner(&ModuleRegistry::default())?)
94 }
95
96 async fn fetch_blind_nonce_outpoints(
97 &self,
98 blind_nonces: Vec<BlindNonce>,
99 ) -> anyhow::Result<Vec<OutPoint>> {
100 self.request_current_consensus::<Vec<OutPoint>>(
101 RECOVERY_BLIND_NONCE_OUTPOINTS_ENDPOINT.to_string(),
102 ApiRequestErased::new(blind_nonces),
103 )
104 .await
105 .map_err(|e| anyhow::anyhow!("{e}"))
106 }
107}