@@ -26,8 +26,7 @@ use bitcoin_payment_instructions::amount::Amount as BPIAmount;
2626use bitcoin_payment_instructions:: hrn_resolution:: DummyHrnResolver ;
2727use bitcoin_payment_instructions:: { PaymentInstructions , PaymentMethod } ;
2828use lightning:: ln:: channelmanager:: PaymentId ;
29- use lightning:: offers:: offer:: Offer ;
30- use lightning:: onion_message:: dns_resolution:: HumanReadableName ;
29+ use lightning:: offers:: offer:: Offer as LdkOffer ;
3130use lightning:: routing:: router:: RouteParametersConfig ;
3231use lightning_invoice:: { Bolt11Invoice , Bolt11InvoiceDescription , Description } ;
3332
@@ -41,6 +40,16 @@ use crate::Config;
4140
4241type Uri < ' a > = bip21:: Uri < ' a , NetworkChecked , Extras > ;
4342
43+ #[ cfg( not( feature = "uniffi" ) ) ]
44+ type HumanReadableName = lightning:: onion_message:: dns_resolution:: HumanReadableName ;
45+ #[ cfg( feature = "uniffi" ) ]
46+ type HumanReadableName = crate :: ffi:: HumanReadableName ;
47+
48+ #[ cfg( not( feature = "uniffi" ) ) ]
49+ type Offer = LdkOffer ;
50+ #[ cfg( feature = "uniffi" ) ]
51+ type Offer = Arc < crate :: ffi:: Offer > ;
52+
4453#[ derive( Debug , Clone ) ]
4554struct Extras {
4655 bolt11_invoice : Option < Bolt11Invoice > ,
@@ -67,6 +76,8 @@ pub struct UnifiedPayment {
6776 config : Arc < Config > ,
6877 logger : Arc < Logger > ,
6978 hrn_resolver : Arc < HRNResolver > ,
79+ #[ cfg( hrn_tests) ]
80+ test_offer : std:: sync:: Mutex < Option < Offer > > ,
7081}
7182
7283impl UnifiedPayment {
@@ -75,7 +86,16 @@ impl UnifiedPayment {
7586 bolt12_payment : Arc < Bolt12Payment > , config : Arc < Config > , logger : Arc < Logger > ,
7687 hrn_resolver : Arc < HRNResolver > ,
7788 ) -> Self {
78- Self { onchain_payment, bolt11_invoice, bolt12_payment, config, logger, hrn_resolver }
89+ Self {
90+ onchain_payment,
91+ bolt11_invoice,
92+ bolt12_payment,
93+ config,
94+ logger,
95+ hrn_resolver,
96+ #[ cfg( hrn_tests) ]
97+ test_offer : std:: sync:: Mutex :: new ( None ) ,
98+ }
7999 }
80100}
81101
@@ -116,7 +136,7 @@ impl UnifiedPayment {
116136
117137 let bolt12_offer =
118138 match self . bolt12_payment . receive_inner ( amount_msats, description, None , None ) {
119- Ok ( offer) => Some ( offer) ,
139+ Ok ( offer) => Some ( maybe_wrap ( offer) ) ,
120140 Err ( e) => {
121141 log_error ! ( self . logger, "Failed to create offer: {}" , e) ;
122142 None
@@ -167,15 +187,26 @@ impl UnifiedPayment {
167187 route_parameters : Option < RouteParametersConfig > ,
168188 ) -> Result < UnifiedPaymentResult , Error > {
169189 let resolver;
190+ let target_network;
170191
171192 if let Ok ( _) = HumanReadableName :: from_encoded ( uri_str) {
172193 resolver = Arc :: clone ( & self . hrn_resolver ) ;
194+
195+ #[ cfg( hrn_tests) ]
196+ {
197+ target_network = bitcoin:: Network :: Bitcoin ;
198+ }
199+ #[ cfg( not( hrn_tests) ) ]
200+ {
201+ target_network = self . config . network ;
202+ }
173203 } else {
174204 resolver = Arc :: new ( HRNResolver :: Dummy ( DummyHrnResolver ) ) ;
205+ target_network = self . config . network ;
175206 }
176207
177208 let parse_fut =
178- PaymentInstructions :: parse ( uri_str, self . config . network , resolver. as_ref ( ) , false ) ;
209+ PaymentInstructions :: parse ( uri_str, target_network , resolver. as_ref ( ) , false ) ;
179210
180211 let instructions =
181212 tokio:: time:: timeout ( Duration :: from_secs ( HRN_RESOLUTION_TIMEOUT_SECS ) , parse_fut)
@@ -238,8 +269,18 @@ impl UnifiedPayment {
238269
239270 for method in sorted_payment_methods {
240271 match method {
241- PaymentMethod :: LightningBolt12 ( offer) => {
242- let offer = maybe_wrap ( offer. clone ( ) ) ;
272+ PaymentMethod :: LightningBolt12 ( _offer) => {
273+ #[ cfg( not( hrn_tests) ) ]
274+ let offer = maybe_wrap ( _offer. clone ( ) ) ;
275+
276+ #[ cfg( hrn_tests) ]
277+ let offer = {
278+ let guard = self . test_offer . lock ( ) . unwrap ( ) ;
279+ guard. clone ( ) . expect (
280+ "hrn_tests is active but no test_offer was set via set_test_offer" ,
281+ )
282+ } ;
283+
243284 let payment_result = if let Ok ( hrn) = HumanReadableName :: from_encoded ( uri_str) {
244285 let hrn = maybe_wrap ( hrn. clone ( ) ) ;
245286 self . bolt12_payment . send_using_amount_inner ( & offer, amount_msat. unwrap_or ( 0 ) , None , None , route_parameters, Some ( hrn) )
@@ -292,6 +333,15 @@ impl UnifiedPayment {
292333 log_error ! ( self . logger, "Payable methods not found in URI" ) ;
293334 Err ( Error :: PaymentSendingFailed )
294335 }
336+
337+ /// Sets a test offer to be used in the `send` method when the `hrn_tests` config flag is enabled.
338+ /// This is necessary to test sending Bolt12 payments via the unified payment handler in HRN tests,
339+ /// as we cannot rely on the offer being present in the parsed URI.
340+ #[ cfg( hrn_tests) ]
341+ pub fn set_test_offer ( & self , offer : Offer ) {
342+ let mut guard = self . test_offer . lock ( ) . unwrap ( ) ;
343+ * guard = Some ( offer) ;
344+ }
295345}
296346
297347/// Represents the result of a payment made using a [BIP 21] URI or a [BIP 353] Human-Readable Name.
@@ -399,9 +449,10 @@ impl<'a> bip21::de::DeserializationState<'a> for DeserializationState {
399449 "lno" => {
400450 let bolt12_value =
401451 String :: try_from ( value) . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
402- let offer =
403- bolt12_value. parse :: < Offer > ( ) . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
404- self . bolt12_offer = Some ( offer) ;
452+ let offer = bolt12_value
453+ . parse :: < LdkOffer > ( )
454+ . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
455+ self . bolt12_offer = Some ( maybe_wrap ( offer) ) ;
405456 Ok ( bip21:: de:: ParamKind :: Known )
406457 } ,
407458 _ => Ok ( bip21:: de:: ParamKind :: Unknown ) ,
@@ -424,7 +475,7 @@ mod tests {
424475 use bitcoin:: address:: NetworkUnchecked ;
425476 use bitcoin:: { Address , Network } ;
426477
427- use super :: { Amount , Bolt11Invoice , Extras , Offer } ;
478+ use super :: { maybe_wrap , Amount , Bolt11Invoice , Extras , LdkOffer } ;
428479
429480 #[ test]
430481 fn parse_uri ( ) {
@@ -478,7 +529,7 @@ mod tests {
478529 }
479530
480531 if let Some ( offer) = parsed_uri_with_offer. extras . bolt12_offer {
481- assert_eq ! ( offer, Offer :: from_str( expected_bolt12_offer_2) . unwrap( ) ) ;
532+ assert_eq ! ( offer, maybe_wrap ( LdkOffer :: from_str( expected_bolt12_offer_2) . unwrap( ) ) ) ;
482533 } else {
483534 panic ! ( "No offer found." ) ;
484535 }
0 commit comments