@@ -33,12 +33,12 @@ pub use lightning::util::string::UntrustedString;
3333
3434pub use lightning_types:: payment:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
3535
36- pub use lightning_invoice:: { Bolt11Invoice , Description } ;
36+ pub use lightning_invoice:: {
37+ Bolt11Invoice as LdkBolt11Invoice , Description , SignedRawBolt11Invoice ,
38+ } ;
3739
3840pub use lightning_liquidity:: lsps1:: msgs:: ChannelInfo as ChannelOrderInfo ;
39- pub use lightning_liquidity:: lsps1:: msgs:: {
40- Bolt11PaymentInfo , OrderId , OrderParameters , PaymentState ,
41- } ;
41+ pub use lightning_liquidity:: lsps1:: msgs:: { OrderId , OrderParameters , PaymentState } ;
4242
4343pub use bitcoin:: { Address , BlockHash , FeeRate , Network , OutPoint , Txid } ;
4444
@@ -60,10 +60,11 @@ use bitcoin::hashes::Hash;
6060use bitcoin:: secp256k1:: PublicKey ;
6161use lightning:: ln:: channelmanager:: PaymentId ;
6262use lightning:: util:: ser:: Writeable ;
63- use lightning_invoice:: SignedRawBolt11Invoice ;
6463
6564use std:: convert:: TryInto ;
6665use std:: str:: FromStr ;
66+ use std:: sync:: Arc ;
67+ use std:: time:: Duration ;
6768
6869impl UniffiCustomTypeConverter for PublicKey {
6970 type Builtin = String ;
@@ -113,24 +114,6 @@ impl UniffiCustomTypeConverter for Address {
113114 }
114115}
115116
116- impl UniffiCustomTypeConverter for Bolt11Invoice {
117- type Builtin = String ;
118-
119- fn into_custom ( val : Self :: Builtin ) -> uniffi:: Result < Self > {
120- if let Ok ( signed) = val. parse :: < SignedRawBolt11Invoice > ( ) {
121- if let Ok ( invoice) = Bolt11Invoice :: from_signed ( signed) {
122- return Ok ( invoice) ;
123- }
124- }
125-
126- Err ( Error :: InvalidInvoice . into ( ) )
127- }
128-
129- fn from_custom ( obj : Self ) -> Self :: Builtin {
130- obj. to_string ( )
131- }
132- }
133-
134117impl UniffiCustomTypeConverter for Offer {
135118 type Builtin = String ;
136119
@@ -405,6 +388,100 @@ impl From<lightning_invoice::Bolt11InvoiceDescription> for Bolt11InvoiceDescript
405388 }
406389}
407390
391+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
392+ pub struct Bolt11Invoice {
393+ pub inner : LdkBolt11Invoice ,
394+ }
395+
396+ impl Bolt11Invoice {
397+ pub fn signable_hash ( & self ) -> Vec < u8 > {
398+ self . inner . signable_hash ( ) . to_vec ( )
399+ }
400+
401+ pub fn expiry_time ( & self ) -> u64 {
402+ self . inner . expiry_time ( ) . as_secs ( )
403+ }
404+
405+ pub fn min_final_cltv_expiry_delta ( & self ) -> u64 {
406+ self . inner . min_final_cltv_expiry_delta ( )
407+ }
408+
409+ pub fn amount_milli_satoshis ( & self ) -> Option < u64 > {
410+ self . inner . amount_milli_satoshis ( )
411+ }
412+
413+ pub fn is_expired ( & self ) -> bool {
414+ self . inner . is_expired ( )
415+ }
416+
417+ pub fn duration_since_epoch ( & self ) -> u64 {
418+ self . inner . duration_since_epoch ( ) . as_secs ( )
419+ }
420+
421+ pub fn would_expire ( & self , at_time : u64 ) -> bool {
422+ self . inner . would_expire ( Duration :: from_secs ( at_time) )
423+ }
424+
425+ pub fn duration_until_expiry ( & self ) -> u64 {
426+ self . inner . duration_until_expiry ( ) . as_secs ( )
427+ }
428+
429+ pub fn payment_hash ( & self ) -> PaymentHash {
430+ PaymentHash ( self . inner . payment_hash ( ) . to_byte_array ( ) )
431+ }
432+
433+ pub fn into_inner ( self ) -> lightning_invoice:: Bolt11Invoice {
434+ self . inner
435+ }
436+
437+ pub fn from_string ( invoice_str : String ) -> Result < Arc < Self > , Error > {
438+ match invoice_str. parse :: < SignedRawBolt11Invoice > ( ) {
439+ Ok ( signed) => match LdkBolt11Invoice :: from_signed ( signed) {
440+ Ok ( invoice) => Ok ( Arc :: new ( Bolt11Invoice { inner : invoice } ) ) ,
441+ Err ( _) => Err ( Error :: InvalidInvoice . into ( ) ) ,
442+ } ,
443+ Err ( _) => Err ( Error :: InvalidInvoice . into ( ) ) ,
444+ }
445+ }
446+
447+ pub fn to_string ( & self ) -> String {
448+ format ! ( "{}" , self . inner)
449+ }
450+ }
451+
452+ impl From < lightning_invoice:: Bolt11Invoice > for Bolt11Invoice {
453+ fn from ( invoice : lightning_invoice:: Bolt11Invoice ) -> Self {
454+ Bolt11Invoice { inner : invoice }
455+ }
456+ }
457+
458+ impl From < Bolt11Invoice > for lightning_invoice:: Bolt11Invoice {
459+ fn from ( wrapper : Bolt11Invoice ) -> Self {
460+ wrapper. into_inner ( )
461+ }
462+ }
463+
464+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
465+ pub struct Bolt11PaymentInfo {
466+ pub state : lightning_liquidity:: lsps1:: msgs:: PaymentState ,
467+ pub expires_at : chrono:: DateTime < chrono:: Utc > ,
468+ pub fee_total_sat : u64 ,
469+ pub order_total_sat : u64 ,
470+ pub invoice : Arc < Bolt11Invoice > ,
471+ }
472+
473+ impl From < lightning_liquidity:: lsps1:: msgs:: Bolt11PaymentInfo > for Bolt11PaymentInfo {
474+ fn from ( info : lightning_liquidity:: lsps1:: msgs:: Bolt11PaymentInfo ) -> Self {
475+ Self {
476+ state : info. state ,
477+ expires_at : info. expires_at ,
478+ fee_total_sat : info. fee_total_sat ,
479+ order_total_sat : info. order_total_sat ,
480+ invoice : Arc :: new ( info. invoice . into ( ) ) ,
481+ }
482+ }
483+ }
484+
408485impl UniffiCustomTypeConverter for OrderId {
409486 type Builtin = String ;
410487
@@ -441,4 +518,59 @@ mod tests {
441518 let reconverted_description: Bolt11InvoiceDescription = converted_description. into ( ) ;
442519 assert_eq ! ( description, reconverted_description) ;
443520 }
521+
522+ #[ test]
523+ fn test_bolt11_invoice ( ) {
524+ let invoice_string = "lnbc1pn8g249pp5f6ytj32ty90jhvw69enf30hwfgdhyymjewywcmfjevflg6s4z86qdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdfjjzh2j9f7ye5qqqqryqqqqthqqpysp5mm832athgcal3m7h35sc29j63lmgzvwc5smfjh2es65elc2ns7dq9qrsgqu2xcje2gsnjp0wn97aknyd3h58an7sjj6nhcrm40846jxphv47958c6th76whmec8ttr2wmg6sxwchvxmsc00kqrzqcga6lvsf9jtqgqy5yexa" ;
525+ let ldk_invoice = LdkBolt11Invoice :: from_str ( invoice_string) . unwrap ( ) ;
526+
527+ let wrapped_invoice = Bolt11Invoice :: from ( ldk_invoice. clone ( ) ) ;
528+
529+ assert_eq ! (
530+ ldk_invoice. payment_hash( ) . to_byte_array( ) . to_vec( ) ,
531+ wrapped_invoice. payment_hash( ) . 0 . to_vec( )
532+ ) ;
533+ assert_eq ! ( ldk_invoice. amount_milli_satoshis( ) , wrapped_invoice. amount_milli_satoshis( ) ) ;
534+ assert_eq ! ( ldk_invoice. expiry_time( ) . as_secs( ) , wrapped_invoice. expiry_time( ) ) ;
535+ assert_eq ! (
536+ ldk_invoice. min_final_cltv_expiry_delta( ) ,
537+ wrapped_invoice. min_final_cltv_expiry_delta( )
538+ ) ;
539+
540+ let future_time = Duration :: from_secs ( wrapped_invoice. duration_since_epoch ( ) + 10000 ) ;
541+ assert ! ( !ldk_invoice. would_expire( future_time) ) ;
542+ assert ! ( !wrapped_invoice. would_expire( future_time. as_secs( ) ) ) ;
543+
544+ let invoice_str = wrapped_invoice. to_string ( ) ;
545+ let parsed_invoice = Bolt11Invoice :: from_string ( invoice_str) ;
546+ assert_eq ! (
547+ wrapped_invoice. inner. payment_hash( ) . to_byte_array( ) . to_vec( ) ,
548+ parsed_invoice. unwrap( ) . inner. payment_hash( ) . to_byte_array( ) . to_vec( )
549+ ) ;
550+ }
551+
552+ #[ test]
553+ fn test_bolt11_invoice_roundtrip ( ) {
554+ let invoice_string = "lnbc1pn8g249pp5f6ytj32ty90jhvw69enf30hwfgdhyymjewywcmfjevflg6s4z86qdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdfjjzh2j9f7ye5qqqqryqqqqthqqpysp5mm832athgcal3m7h35sc29j63lmgzvwc5smfjh2es65elc2ns7dq9qrsgqu2xcje2gsnjp0wn97aknyd3h58an7sjj6nhcrm40846jxphv47958c6th76whmec8ttr2wmg6sxwchvxmsc00kqrzqcga6lvsf9jtqgqy5yexa" ;
555+ let original_invoice = LdkBolt11Invoice :: from_str ( invoice_string) . unwrap ( ) ;
556+ let wrapped_invoice = Bolt11Invoice { inner : original_invoice. clone ( ) } ;
557+ let unwrapped_invoice: LdkBolt11Invoice = wrapped_invoice. clone ( ) . into ( ) ;
558+
559+ assert_eq ! ( original_invoice. payment_hash( ) , unwrapped_invoice. payment_hash( ) ) ;
560+ assert_eq ! ( original_invoice. payment_secret( ) , unwrapped_invoice. payment_secret( ) ) ;
561+ assert_eq ! (
562+ original_invoice. amount_milli_satoshis( ) ,
563+ unwrapped_invoice. amount_milli_satoshis( )
564+ ) ;
565+ assert_eq ! ( original_invoice. timestamp( ) , unwrapped_invoice. timestamp( ) ) ;
566+ assert_eq ! ( original_invoice. expiry_time( ) , unwrapped_invoice. expiry_time( ) ) ;
567+ assert_eq ! (
568+ original_invoice. min_final_cltv_expiry_delta( ) ,
569+ unwrapped_invoice. min_final_cltv_expiry_delta( )
570+ ) ;
571+
572+ let original_hints = original_invoice. route_hints ( ) ;
573+ let unwrapped_hints = unwrapped_invoice. route_hints ( ) ;
574+ assert_eq ! ( original_hints. len( ) , unwrapped_hints. len( ) ) ;
575+ }
444576}
0 commit comments