@@ -86,22 +86,25 @@ use std::{
8686#[ cfg( target_arch = "wasm32" ) ]
8787use web_time:: Instant ;
8888
89- // The maximum amount of operations we try to pull
90- // from fedimint when we need to search through
91- // their internal list.
89+ /// The maximum amount of operations we try to pull
90+ /// from fedimint when we need to search through
91+ /// their internal list.
9292const FEDIMINT_OPERATIONS_LIST_MAX : usize = 100 ;
9393
94- // On chain peg in timeout
94+ /// On chain peg in timeout
9595const PEG_IN_TIMEOUT_YEAR : Duration = Duration :: from_secs ( 86400 * 365 ) ;
9696
97+ /// For key value storage
9798pub const FEDIMINTS_PREFIX_KEY : & str = "fedimints/" ;
9899
99100// Default signet/mainnet federation gateway info
101+ // TODO: Remove these hardcoded gateways and use our improved gateway selection logic
100102const SIGNET_GATEWAY : & str = "0256f5ef1d986e9abf559651b7167de28bfd954683cd0f14703be12d1421aedc55" ;
101103const MAINNET_GATEWAY : & str = "025b9f090d3daab012346701f27d1c220d6d290f6b498255cddc492c255532a09d" ;
102104const SIGNET_FEDERATION : & str = "c8d423964c7ad944d30f57359b6e5b260e211dcfdb945140e28d4df51fd572d2" ;
103105const MAINNET_FEDERATION : & str = "c36038cce5a97e3467f03336fa8e7e3410960b81d1865cda2a609f70a8f51efb" ;
104106
107+ // Translate from Fedimint's internal status to our HTLCStatus
105108impl From < LnReceiveState > for HTLCStatus {
106109 fn from ( state : LnReceiveState ) -> Self {
107110 match state {
@@ -143,40 +146,42 @@ impl From<LnPayState> for HTLCStatus {
143146 }
144147}
145148
146- // This is the FederationStorage object saved to the DB
149+ /// FederationStorage object saved to the DB
147150#[ derive( Debug , Serialize , Deserialize , Clone , Default ) ]
148151pub struct FederationStorage {
149152 pub federations : HashMap < String , FederationIndex > ,
150153 pub version : u32 ,
151154}
152155
153- // This is the FederationIdentity that refer to a specific federation
154- // Used for public facing identification.
156+ /// FederationIdentity that refers to a specific federation
157+ /// Used for public facing identification. (What the frontend needs to display a federation to the user)
158+ /// Constructed via FederationMetaConfig -> FederationMeta -> FederationIdentity
155159#[ derive( Serialize , Deserialize , Clone , Eq , PartialEq ) ]
156160pub struct FederationIdentity {
157161 pub uuid : String ,
158162 pub federation_id : FederationId ,
159163 pub invite_code : InviteCode ,
160- // https://github.com/fedimint/fedimint/tree/master/docs/meta_fields
164+ /// https://github.com/fedimint/fedimint/tree/master/docs/meta_fields
161165 pub federation_name : Option < String > ,
162166 pub federation_expiry_timestamp : Option < String > ,
163167 pub welcome_message : Option < String > ,
164- // undocumented parameters that fedi uses: https://meta.dev.fedibtc.com/meta.json
168+ /// undocumented parameters that fedi uses: https://meta.dev.fedibtc.com/meta.json
165169 pub federation_icon_url : Option < String > ,
166170 pub meta_external_url : Option < String > ,
167171 pub preview_message : Option < String > ,
168172 pub popup_end_timestamp : Option < u32 > ,
169173 pub popup_countdown_message : Option < String > ,
170174}
171175
176+ /// Fedi's federation listing format
172177#[ derive( Serialize , Deserialize , Debug ) ]
173178pub ( crate ) struct FederationMetaConfig {
174179 #[ serde( flatten) ]
175180 pub federations : std:: collections:: HashMap < String , FederationMeta > ,
176181}
177182
178- // This is the FederationUrlConfig that refer to a specific federation
179- // Normal config information that might exist from their URL.
183+ /// FederationUrlConfig that refer to a specific federation
184+ /// Normal config information that might exist from their URL.
180185#[ derive( Serialize , Deserialize , Clone , Eq , PartialEq , Debug ) ]
181186pub struct FederationMeta {
182187 // https://github.com/fedimint/fedimint/tree/master/docs/meta_fields
@@ -196,14 +201,6 @@ pub struct FederationMeta {
196201 pub popup_countdown_message : Option < String > ,
197202}
198203
199- #[ derive( Default , Debug , Clone , Eq , PartialEq , Serialize , Deserialize ) ]
200- pub struct Site {
201- pub id : Option < String > ,
202- pub url : Option < String > ,
203- pub title : Option < String > ,
204- pub image_url : Option < String > ,
205- }
206-
207204#[ derive( Debug , Serialize , Deserialize , PartialEq , Eq , Clone , Default ) ]
208205pub struct GatewayFees {
209206 pub base_msat : u32 ,
@@ -229,6 +226,7 @@ pub struct FedimintBalance {
229226 pub amount : u64 ,
230227}
231228
229+ // This is for the sake of test mocking
232230#[ cfg_attr( test, mockall:: automock) ]
233231pub trait FedimintClient {
234232 async fn claim_external_receive (
@@ -238,6 +236,8 @@ pub trait FedimintClient {
238236 ) -> Result < ( ) , MutinyError > ;
239237}
240238
239+ /// FederationClient is Mutiny's main abstraction on top of the fedimint library
240+ /// We use this object to pay invoices, get addresses, etc.
241241pub ( crate ) struct FederationClient < S : MutinyStorage > {
242242 pub ( crate ) uuid : String ,
243243 pub ( crate ) fedimint_client : ClientHandleArc ,
@@ -252,6 +252,8 @@ pub(crate) struct FederationClient<S: MutinyStorage> {
252252}
253253
254254impl < S : MutinyStorage > FederationClient < S > {
255+ /// We call this when it's the first time we're joining a federation, and also
256+ /// when we're starting up the wallet.
255257 #[ allow( clippy:: too_many_arguments) ]
256258 pub ( crate ) async fn new (
257259 uuid : String ,
@@ -285,6 +287,7 @@ impl<S: MutinyStorage> FederationClient<S> {
285287 log_trace ! ( logger, "Building fedimint client db" ) ;
286288 let secret = create_federation_secret ( xprivkey, network) ?;
287289
290+ // Handle if we've joined the federation already
288291 let fedimint_client = if is_initialized {
289292 client_builder
290293 . open ( get_default_client_secret ( & secret, & federation_id) )
@@ -315,6 +318,7 @@ impl<S: MutinyStorage> FederationClient<S> {
315318 MutinyError :: FederationConnectionFailed
316319 } ) ?
317320 } ;
321+ // TODO: does this need to be an arc?
318322 let fedimint_client = Arc :: new ( fedimint_client) ;
319323
320324 log_trace ! ( logger, "Retrieving fedimint wallet client module" ) ;
@@ -343,6 +347,9 @@ impl<S: MutinyStorage> FederationClient<S> {
343347 let client_clone = fedimint_client. clone ( ) ;
344348 let gateway_clone = gateway. clone ( ) ;
345349 let logger_clone = logger. clone ( ) ;
350+
351+ // don't want to block wallet startup with these gateway updates
352+ // so we spawn here
346353 spawn ( async move {
347354 let start = Instant :: now ( ) ;
348355 // get lock immediately to block other actions until gateway is set
@@ -396,6 +403,9 @@ impl<S: MutinyStorage> FederationClient<S> {
396403 Ok ( federation_client)
397404 }
398405
406+ /// The fedimint database has its own representation of transactions, but we need to
407+ /// track them in our own database. This checks for unprocessed transactions and
408+ /// processes them.
399409 pub ( crate ) async fn process_previous_operations ( & self ) -> Result < ( ) , MutinyError > {
400410 // look for our internal state pending transactions
401411 let mut pending_invoices: HashSet < [ u8 ; 32 ] > = HashSet :: new ( ) ;
@@ -470,6 +480,7 @@ impl<S: MutinyStorage> FederationClient<S> {
470480 Ok ( ( ) )
471481 }
472482
483+ /// Subscribe to status of actions like invoice creation, pay invoice, on-chain address creation, etc.
473484 fn subscribe_operation ( & self , entry : OperationLogEntry , operation_id : OperationId ) {
474485 subscribe_operation_ext (
475486 entry,
@@ -482,11 +493,15 @@ impl<S: MutinyStorage> FederationClient<S> {
482493 ) ;
483494 }
484495
496+ /// Get the current gateway fees
485497 pub ( crate ) async fn gateway_fee ( & self ) -> Result < GatewayFees , MutinyError > {
486498 let gateway = self . gateway . read ( ) . await ;
487499 Ok ( gateway. as_ref ( ) . map ( |x| x. fees . into ( ) ) . unwrap_or_default ( ) )
488500 }
489501
502+ /// Create a new lightning invoice
503+ /// Important limitation: if the FedimintClient hasn't updated the lightning gateways yet, this will
504+ /// create an invoice that can only be paid inside to the federation.
490505 pub ( crate ) async fn get_invoice (
491506 & self ,
492507 amount : u64 ,
@@ -560,6 +575,7 @@ impl<S: MutinyStorage> FederationClient<S> {
560575 Ok ( invoice. into ( ) )
561576 }
562577
578+ /// Get a new on-chain address
563579 pub ( crate ) async fn get_new_address (
564580 & self ,
565581 labels : Vec < String > ,
@@ -619,6 +635,8 @@ impl<S: MutinyStorage> FederationClient<S> {
619635 )
620636 }
621637
638+ /// Pay a lightning invoice
639+ /// Important limitation: same as get_invoice
622640 pub ( crate ) async fn pay_invoice (
623641 & self ,
624642 invoice : Bolt11Invoice ,
@@ -802,6 +820,7 @@ impl<S: MutinyStorage> FederationClient<S> {
802820 Err ( MutinyError :: PaymentTimeout )
803821 }
804822
823+ /// Ask the federation for the on chain fee estimate
805824 pub async fn estimate_tx_fee (
806825 & self ,
807826 destination_address : bitcoin:: Address ,
@@ -822,6 +841,7 @@ impl<S: MutinyStorage> FederationClient<S> {
822841 }
823842
824843 /// Someone received a payment on our behalf, we need to claim it
844+ /// This is used for claiming Hermes lightning address payments
825845 pub async fn claim_external_receive (
826846 & self ,
827847 secret_key : & SecretKey ,
@@ -871,6 +891,7 @@ impl<S: MutinyStorage> FederationClient<S> {
871891 Ok ( ( ) )
872892 }
873893
894+ /// Get the federation info for displaying to the user
874895 pub async fn get_mutiny_federation_identity ( & self ) -> FederationIdentity {
875896 get_federation_identity (
876897 self . uuid . clone ( ) ,
@@ -881,7 +902,7 @@ impl<S: MutinyStorage> FederationClient<S> {
881902 . await
882903 }
883904
884- // delete_fedimint_storage is not suggested at the moment due to the lack of easy restores
905+ /// WARNING delete_fedimint_storage is not suggested at the moment due to the lack of easy restores
885906 #[ allow( dead_code) ]
886907 pub async fn delete_fedimint_storage ( & self ) -> Result < ( ) , MutinyError > {
887908 self . fedimint_storage . delete_store ( ) . await
0 commit comments