1
- use crate :: utils:: { convert_from_fedimint_invoice, convert_to_fedimint_invoice, now, spawn} ;
1
+ use crate :: utils:: {
2
+ convert_from_fedimint_invoice, convert_to_fedimint_invoice, fetch_with_timeout, now, spawn,
3
+ } ;
2
4
use crate :: {
3
5
error:: { MutinyError , MutinyStorageError } ,
4
6
event:: PaymentInfo ,
@@ -56,6 +58,7 @@ use futures_util::{pin_mut, StreamExt};
56
58
use hex_conservative:: { DisplayHex , FromHex } ;
57
59
use lightning:: { log_debug, log_error, log_info, log_trace, log_warn, util:: logger:: Logger } ;
58
60
use lightning_invoice:: Bolt11Invoice ;
61
+ use reqwest:: Method ;
59
62
use serde:: { de:: DeserializeOwned , Deserialize , Serialize } ;
60
63
#[ cfg( not( target_arch = "wasm32" ) ) ]
61
64
use std:: time:: Instant ;
@@ -162,6 +165,39 @@ pub struct FederationIdentity {
162
165
pub social_recovery_disabled : Option < bool > ,
163
166
}
164
167
168
+ #[ derive( Serialize , Deserialize ) ]
169
+ struct FederationMetaConfig {
170
+ #[ serde( flatten) ]
171
+ pub federations : std:: collections:: HashMap < String , FederationMeta > ,
172
+ }
173
+
174
+ // This is the FederationUrlConfig that refer to a specific federation
175
+ // Normal config information that might exist from their URL.
176
+ #[ derive( Serialize , Deserialize , Clone , Eq , PartialEq ) ]
177
+ pub struct FederationMeta {
178
+ // https://github.com/fedimint/fedimint/tree/master/docs/meta_fields
179
+ pub federation_name : Option < String > ,
180
+ pub federation_expiry_timestamp : Option < String > ,
181
+ pub welcome_message : Option < String > ,
182
+ pub gateway_fees : Option < GatewayFees > ,
183
+ // undocumented parameters that fedi uses: https://meta.dev.fedibtc.com/meta.json
184
+ pub default_currency : Option < String > ,
185
+ pub federation_icon_url : Option < String > ,
186
+ pub max_balance_msats : Option < u32 > ,
187
+ pub max_invoice_msats : Option < u32 > ,
188
+ pub meta_external_url : Option < String > ,
189
+ pub onchain_deposits_disabled : Option < bool > ,
190
+ pub preview_message : Option < String > ,
191
+ pub sites : Option < Site > ,
192
+ pub public : Option < bool > ,
193
+ pub tos_url : Option < String > ,
194
+ pub popup_end_timestamp : Option < u32 > ,
195
+ pub popup_countdown_message : Option < String > ,
196
+ pub invite_codes_disabled : Option < bool > ,
197
+ pub stability_pool_disabled : Option < bool > ,
198
+ pub social_recovery_disabled : Option < bool > ,
199
+ }
200
+
165
201
#[ derive( Default , Debug , Clone , Eq , PartialEq , Serialize , Deserialize ) ]
166
202
pub struct Site {
167
203
pub id : Option < String > ,
@@ -688,6 +724,7 @@ impl<S: MutinyStorage> FederationClient<S> {
688
724
self . invite_code . clone ( ) ,
689
725
gateway_fees,
690
726
)
727
+ . await
691
728
}
692
729
693
730
// delete_fedimint_storage is not suggested at the moment due to the lack of easy restores
@@ -697,53 +734,142 @@ impl<S: MutinyStorage> FederationClient<S> {
697
734
}
698
735
}
699
736
700
- pub ( crate ) fn get_federation_identity (
737
+ pub ( crate ) async fn get_federation_identity (
701
738
uuid : String ,
702
739
fedimint_client : ClientHandleArc ,
703
740
invite_code : InviteCode ,
704
741
gateway_fees : Option < GatewayFees > ,
705
742
) -> FederationIdentity {
743
+ let federation_id = fedimint_client. federation_id ( ) ;
744
+ let meta_external_url = fedimint_client. get_meta ( "meta_external_url" ) ;
745
+ let config = if let Some ( ref url) = meta_external_url {
746
+ let http_client = reqwest:: Client :: new ( ) ;
747
+ let request = http_client. request ( Method :: GET , url) ;
748
+
749
+ match fetch_with_timeout ( & http_client, request. build ( ) . expect ( "should build req" ) ) . await {
750
+ Ok ( r) => match r. json :: < FederationMetaConfig > ( ) . await {
751
+ Ok ( c) =>
752
+ {
753
+ #[ allow( clippy:: map_clone) ]
754
+ c. federations
755
+ . get ( & federation_id. to_string ( ) )
756
+ . map ( |f| f. clone ( ) )
757
+ }
758
+ Err ( _) => None ,
759
+ } ,
760
+ Err ( _) => None ,
761
+ }
762
+ } else {
763
+ None
764
+ } ;
765
+
706
766
FederationIdentity {
707
767
uuid : uuid. clone ( ) ,
708
- federation_id : fedimint_client . federation_id ( ) ,
768
+ federation_id,
709
769
invite_code : invite_code. clone ( ) ,
710
- federation_name : fedimint_client. get_meta ( "federation_name" ) ,
711
- federation_expiry_timestamp : fedimint_client. get_meta ( "federation_expiry_timestamp" ) ,
712
- welcome_message : fedimint_client. get_meta ( "welcome_message" ) ,
713
- gateway_fees,
714
- default_currency : fedimint_client. get_meta ( "default_currency" ) ,
715
- federation_icon_url : fedimint_client. get_meta ( "federation_icon_url" ) ,
716
- max_balance_msats : fedimint_client
717
- . get_meta ( "max_balance_msats" )
718
- . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
719
- max_invoice_msats : fedimint_client
720
- . get_meta ( "max_invoice_msats" )
721
- . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
722
- meta_external_url : fedimint_client. get_meta ( "meta_external_url" ) ,
723
- onchain_deposits_disabled : fedimint_client
724
- . get_meta ( "onchain_deposits_disabled" )
725
- . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
726
- preview_message : fedimint_client. get_meta ( "preview_message" ) ,
727
- sites : fedimint_client
728
- . get_meta ( "sites" )
729
- . map ( |v| serde_json:: from_str ( & v) . unwrap_or_default ( ) ) ,
730
- public : fedimint_client
731
- . get_meta ( "public" )
732
- . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
733
- tos_url : fedimint_client. get_meta ( "tos_url" ) ,
734
- popup_end_timestamp : fedimint_client
735
- . get_meta ( "popup_end_timestamp" )
736
- . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
737
- popup_countdown_message : fedimint_client. get_meta ( "popup_countdown_message" ) ,
738
- invite_codes_disabled : fedimint_client
739
- . get_meta ( "invite_codes_disabled" )
740
- . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
741
- stability_pool_disabled : fedimint_client
742
- . get_meta ( "stability_pool_disabled" )
743
- . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
744
- social_recovery_disabled : fedimint_client
745
- . get_meta ( "social_recovery_disabled" )
746
- . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
770
+ federation_name : merge_values (
771
+ fedimint_client. get_meta ( "federation_name" ) . clone ( ) ,
772
+ config. as_ref ( ) . and_then ( |c| c. federation_name . clone ( ) ) ,
773
+ ) ,
774
+ federation_expiry_timestamp : merge_values (
775
+ fedimint_client. get_meta ( "federation_expiry_timestamp" ) ,
776
+ config
777
+ . as_ref ( )
778
+ . and_then ( |c| c. federation_expiry_timestamp . clone ( ) ) ,
779
+ ) ,
780
+ welcome_message : merge_values (
781
+ fedimint_client. get_meta ( "welcome_message" ) ,
782
+ config. as_ref ( ) . and_then ( |c| c. welcome_message . clone ( ) ) ,
783
+ ) ,
784
+ gateway_fees, // Already merged using helper function...
785
+ default_currency : merge_values (
786
+ fedimint_client. get_meta ( "default_currency" ) ,
787
+ config. as_ref ( ) . and_then ( |c| c. default_currency . clone ( ) ) ,
788
+ ) ,
789
+ federation_icon_url : merge_values (
790
+ fedimint_client. get_meta ( "federation_icon_url" ) ,
791
+ config. as_ref ( ) . and_then ( |c| c. federation_icon_url . clone ( ) ) ,
792
+ ) ,
793
+ max_balance_msats : merge_values (
794
+ fedimint_client
795
+ . get_meta ( "max_balance_msats" )
796
+ . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
797
+ config. as_ref ( ) . and_then ( |c| c. max_balance_msats ) ,
798
+ ) ,
799
+ max_invoice_msats : merge_values (
800
+ fedimint_client
801
+ . get_meta ( "max_invoice_msats" )
802
+ . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
803
+ config. as_ref ( ) . and_then ( |c| c. max_invoice_msats ) ,
804
+ ) ,
805
+ meta_external_url, // Already set...
806
+ onchain_deposits_disabled : merge_values (
807
+ fedimint_client
808
+ . get_meta ( "onchain_deposits_disabled" )
809
+ . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
810
+ config. as_ref ( ) . and_then ( |c| c. onchain_deposits_disabled ) ,
811
+ ) ,
812
+ preview_message : merge_values (
813
+ fedimint_client. get_meta ( "preview_message" ) ,
814
+ config. as_ref ( ) . and_then ( |c| c. preview_message . clone ( ) ) ,
815
+ ) ,
816
+ sites : merge_values (
817
+ fedimint_client
818
+ . get_meta ( "sites" )
819
+ . map ( |v| serde_json:: from_str ( & v) . unwrap_or_default ( ) ) ,
820
+ config. as_ref ( ) . and_then ( |c| c. sites . clone ( ) ) ,
821
+ ) ,
822
+ public : merge_values (
823
+ fedimint_client
824
+ . get_meta ( "public" )
825
+ . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
826
+ config. as_ref ( ) . and_then ( |c| c. public ) ,
827
+ ) ,
828
+ tos_url : merge_values (
829
+ fedimint_client. get_meta ( "tos_url" ) ,
830
+ config. as_ref ( ) . and_then ( |c| c. tos_url . clone ( ) ) ,
831
+ ) ,
832
+ popup_end_timestamp : merge_values (
833
+ fedimint_client
834
+ . get_meta ( "popup_end_timestamp" )
835
+ . map ( |v| v. parse ( ) . unwrap_or ( 0 ) ) ,
836
+ config. as_ref ( ) . and_then ( |c| c. popup_end_timestamp ) ,
837
+ ) ,
838
+ popup_countdown_message : merge_values (
839
+ fedimint_client
840
+ . get_meta ( "popup_countdown_message" )
841
+ . map ( |v| v. to_string ( ) ) ,
842
+ config
843
+ . as_ref ( )
844
+ . and_then ( |c| c. popup_countdown_message . clone ( ) ) ,
845
+ ) ,
846
+ invite_codes_disabled : merge_values (
847
+ fedimint_client
848
+ . get_meta ( "invite_codes_disabled" )
849
+ . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
850
+ config. as_ref ( ) . and_then ( |c| c. invite_codes_disabled ) ,
851
+ ) ,
852
+ stability_pool_disabled : merge_values (
853
+ fedimint_client
854
+ . get_meta ( "stability_pool_disabled" )
855
+ . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
856
+ config. as_ref ( ) . and_then ( |c| c. stability_pool_disabled ) ,
857
+ ) ,
858
+ social_recovery_disabled : merge_values (
859
+ fedimint_client
860
+ . get_meta ( "social_recovery_disabled" )
861
+ . map ( |v| v. parse ( ) . unwrap_or ( false ) ) ,
862
+ config. as_ref ( ) . and_then ( |c| c. social_recovery_disabled ) ,
863
+ ) ,
864
+ }
865
+ }
866
+
867
+ fn merge_values < T > ( a : Option < T > , b : Option < T > ) -> Option < T > {
868
+ match ( a, b) {
869
+ // If a has value return that; otherwise, use the one from b if available.
870
+ ( Some ( val) , _) => Some ( val) ,
871
+ ( None , Some ( val) ) => Some ( val) ,
872
+ ( None , None ) => None ,
747
873
}
748
874
}
749
875
0 commit comments