@@ -279,20 +279,15 @@ mod tests {
279279 }
280280}
281281
282- #[ cfg_attr( feature = "uniffi" , uniffi:: export) ]
283282impl Bolt11Payment {
284- /// Send a payment given an invoice.
285- ///
286- /// If `route_parameters` are provided they will override the default as well as the
287- /// node-wide parameters configured via [`Config::route_parameters`] on a per-field basis.
288- pub fn send (
289- & self , invoice : & Bolt11Invoice , route_parameters : Option < RouteParametersConfig > ,
283+ fn send_internal (
284+ & self , invoice : & LdkBolt11Invoice , amount_msat : Option < u64 > ,
285+ route_parameters : Option < RouteParametersConfig > , invalid_amount_log : & ' static str ,
290286 ) -> Result < PaymentId , Error > {
291287 if !* self . is_running . read ( ) . expect ( "lock" ) {
292288 return Err ( Error :: NotRunning ) ;
293289 }
294290
295- let invoice = maybe_deref ( invoice) ;
296291 let payment_hash = invoice. payment_hash ( ) ;
297292 let payment_id = PaymentId ( invoice. payment_hash ( ) . 0 ) ;
298293 if let Some ( payment) = self . payment_store . get ( & payment_id) {
@@ -308,6 +303,13 @@ impl Bolt11Payment {
308303 route_parameters. or ( self . config . route_parameters ) . unwrap_or_default ( ) ;
309304 let retry_strategy = Retry :: Timeout ( LDK_PAYMENT_RETRY_TIMEOUT ) ;
310305 let payment_secret = Some ( * invoice. payment_secret ( ) ) ;
306+ let payment_amount_msat = match amount_msat. or_else ( || invoice. amount_milli_satoshis ( ) ) {
307+ Some ( amount_msat) => amount_msat,
308+ None => {
309+ log_error ! ( self . logger, "{}" , invalid_amount_log) ;
310+ return Err ( Error :: InvalidInvoice ) ;
311+ } ,
312+ } ;
311313
312314 let optional_params = OptionalBolt11PaymentParams {
313315 retry_strategy,
@@ -317,14 +319,17 @@ impl Bolt11Payment {
317319 match self . channel_manager . pay_for_bolt11_invoice (
318320 invoice,
319321 payment_id,
320- None ,
322+ amount_msat ,
321323 optional_params,
322324 ) {
323325 Ok ( ( ) ) => {
324326 let payee_pubkey = invoice. recover_payee_pub_key ( ) ;
325- let amt_msat =
326- invoice. amount_milli_satoshis ( ) . expect ( "invoice amount should be set" ) ;
327- log_info ! ( self . logger, "Initiated sending {}msat to {}" , amt_msat, payee_pubkey) ;
327+ log_info ! (
328+ self . logger,
329+ "Initiated sending {} msat to {}" ,
330+ payment_amount_msat,
331+ payee_pubkey
332+ ) ;
328333
329334 let kind = PaymentKind :: Bolt11 {
330335 hash : payment_hash,
@@ -335,7 +340,7 @@ impl Bolt11Payment {
335340 let payment = PaymentDetails :: new (
336341 payment_id,
337342 kind,
338- invoice . amount_milli_satoshis ( ) ,
343+ Some ( payment_amount_msat ) ,
339344 None ,
340345 PaymentDirection :: Outbound ,
341346 PaymentStatus :: Pending ,
@@ -346,9 +351,7 @@ impl Bolt11Payment {
346351 Ok ( payment_id)
347352 } ,
348353 Err ( Bolt11PaymentError :: InvalidAmount ) => {
349- log_error ! ( self . logger,
350- "Failed to send payment due to the given invoice being \" zero-amount\" . Please use send_using_amount instead."
351- ) ;
354+ log_error ! ( self . logger, "{}" , invalid_amount_log) ;
352355 return Err ( Error :: InvalidInvoice ) ;
353356 } ,
354357 Err ( Bolt11PaymentError :: SendingFailed ( e) ) => {
@@ -365,7 +368,7 @@ impl Bolt11Payment {
365368 let payment = PaymentDetails :: new (
366369 payment_id,
367370 kind,
368- invoice . amount_milli_satoshis ( ) ,
371+ Some ( payment_amount_msat ) ,
369372 None ,
370373 PaymentDirection :: Outbound ,
371374 PaymentStatus :: Failed ,
@@ -378,6 +381,29 @@ impl Bolt11Payment {
378381 } ,
379382 }
380383 }
384+ }
385+
386+ #[ cfg_attr( feature = "uniffi" , uniffi:: export) ]
387+ impl Bolt11Payment {
388+ /// Send a payment given an invoice.
389+ ///
390+ /// If `route_parameters` are provided they will override the default as well as the
391+ /// node-wide parameters configured via [`Config::route_parameters`] on a per-field basis.
392+ pub fn send (
393+ & self , invoice : & Bolt11Invoice , route_parameters : Option < RouteParametersConfig > ,
394+ ) -> Result < PaymentId , Error > {
395+ if !* self . is_running . read ( ) . expect ( "lock" ) {
396+ return Err ( Error :: NotRunning ) ;
397+ }
398+
399+ let invoice = maybe_deref ( invoice) ;
400+ self . send_internal (
401+ invoice,
402+ None ,
403+ route_parameters,
404+ "Failed to send payment due to the given invoice being \" zero-amount\" . Please use send_using_amount instead." ,
405+ )
406+ }
381407
382408 /// Send a payment given an invoice and an amount in millisatoshis.
383409 ///
@@ -406,94 +432,12 @@ impl Bolt11Payment {
406432 }
407433 }
408434
409- let payment_hash = invoice. payment_hash ( ) ;
410- let payment_id = PaymentId ( invoice. payment_hash ( ) . 0 ) ;
411- if let Some ( payment) = self . payment_store . get ( & payment_id) {
412- if payment. status == PaymentStatus :: Pending
413- || payment. status == PaymentStatus :: Succeeded
414- {
415- log_error ! ( self . logger, "Payment error: an invoice must not be paid twice." ) ;
416- return Err ( Error :: DuplicatePayment ) ;
417- }
418- }
419-
420- let route_params_config =
421- route_parameters. or ( self . config . route_parameters ) . unwrap_or_default ( ) ;
422- let retry_strategy = Retry :: Timeout ( LDK_PAYMENT_RETRY_TIMEOUT ) ;
423- let payment_secret = Some ( * invoice. payment_secret ( ) ) ;
424-
425- let optional_params = OptionalBolt11PaymentParams {
426- retry_strategy,
427- route_params_config,
428- ..Default :: default ( )
429- } ;
430- match self . channel_manager . pay_for_bolt11_invoice (
435+ self . send_internal (
431436 invoice,
432- payment_id,
433437 Some ( amount_msat) ,
434- optional_params,
435- ) {
436- Ok ( ( ) ) => {
437- let payee_pubkey = invoice. recover_payee_pub_key ( ) ;
438- log_info ! (
439- self . logger,
440- "Initiated sending {} msat to {}" ,
441- amount_msat,
442- payee_pubkey
443- ) ;
444-
445- let kind = PaymentKind :: Bolt11 {
446- hash : payment_hash,
447- preimage : None ,
448- secret : payment_secret,
449- counterparty_skimmed_fee_msat : None ,
450- } ;
451-
452- let payment = PaymentDetails :: new (
453- payment_id,
454- kind,
455- Some ( amount_msat) ,
456- None ,
457- PaymentDirection :: Outbound ,
458- PaymentStatus :: Pending ,
459- ) ;
460- self . runtime . block_on ( self . payment_store . insert ( payment) ) ?;
461-
462- Ok ( payment_id)
463- } ,
464- Err ( Bolt11PaymentError :: InvalidAmount ) => {
465- log_error ! (
466- self . logger,
467- "Failed to send payment due to amount given being insufficient."
468- ) ;
469- return Err ( Error :: InvalidInvoice ) ;
470- } ,
471- Err ( Bolt11PaymentError :: SendingFailed ( e) ) => {
472- log_error ! ( self . logger, "Failed to send payment: {:?}" , e) ;
473- match e {
474- RetryableSendFailure :: DuplicatePayment => Err ( Error :: DuplicatePayment ) ,
475- _ => {
476- let kind = PaymentKind :: Bolt11 {
477- hash : payment_hash,
478- preimage : None ,
479- secret : payment_secret,
480- counterparty_skimmed_fee_msat : None ,
481- } ;
482- let payment = PaymentDetails :: new (
483- payment_id,
484- kind,
485- Some ( amount_msat) ,
486- None ,
487- PaymentDirection :: Outbound ,
488- PaymentStatus :: Failed ,
489- ) ;
490-
491- self . runtime . block_on ( self . payment_store . insert ( payment) ) ?;
492- Err ( Error :: PaymentSendingFailed )
493- } ,
494- }
495- } ,
496- }
438+ route_parameters,
439+ "Failed to send payment due to amount given being insufficient." ,
440+ )
497441 }
498442
499443 /// Allows to attempt manually claiming payments with the given preimage that have previously
0 commit comments