77// You may not use this file except in accordance with one or both of these
88// licenses.
99
10- //! Convenient utilities for paying Lightning invoices and sending spontaneous payments .
10+ //! Convenient utilities for paying Lightning invoices.
1111
12- use crate :: Bolt11Invoice ;
12+ use crate :: { Bolt11Invoice , Vec } ;
1313
1414use bitcoin_hashes:: Hash ;
1515
1616use lightning:: chain;
1717use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
1818use lightning:: sign:: { NodeSigner , SignerProvider , EntropySource } ;
1919use lightning:: ln:: PaymentHash ;
20- use lightning:: ln:: channelmanager:: { ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields } ;
20+ use lightning:: ln:: channelmanager:: { AChannelManager , ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields , ProbeSendFailure } ;
2121use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router } ;
2222use lightning:: util:: logger:: Logger ;
2323
@@ -32,22 +32,12 @@ use core::time::Duration;
3232/// with the same [`PaymentHash`] is never sent.
3333///
3434/// If you wish to use a different payment idempotency token, see [`pay_invoice_with_id`].
35- pub fn pay_invoice < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
36- invoice : & Bolt11Invoice , retry_strategy : Retry ,
37- channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L >
35+ pub fn pay_invoice < C : AChannelManager > (
36+ invoice : & Bolt11Invoice , retry_strategy : Retry , channelmanager : & C
3837) -> Result < PaymentId , PaymentError >
39- where
40- M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
41- T :: Target : BroadcasterInterface ,
42- ES :: Target : EntropySource ,
43- NS :: Target : NodeSigner ,
44- SP :: Target : SignerProvider ,
45- F :: Target : FeeEstimator ,
46- R :: Target : Router ,
47- L :: Target : Logger ,
4838{
4939 let payment_id = PaymentId ( invoice. payment_hash ( ) . into_inner ( ) ) ;
50- pay_invoice_with_id ( invoice, payment_id, retry_strategy, channelmanager)
40+ pay_invoice_with_id ( invoice, payment_id, retry_strategy, channelmanager. get_cm ( ) )
5141 . map ( |( ) | payment_id)
5242}
5343
@@ -61,22 +51,12 @@ where
6151/// [`PaymentHash`] has never been paid before.
6252///
6353/// See [`pay_invoice`] for a variant which uses the [`PaymentHash`] for the idempotency token.
64- pub fn pay_invoice_with_id < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
65- invoice : & Bolt11Invoice , payment_id : PaymentId , retry_strategy : Retry ,
66- channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L >
54+ pub fn pay_invoice_with_id < C : AChannelManager > (
55+ invoice : & Bolt11Invoice , payment_id : PaymentId , retry_strategy : Retry , channelmanager : & C
6756) -> Result < ( ) , PaymentError >
68- where
69- M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
70- T :: Target : BroadcasterInterface ,
71- ES :: Target : EntropySource ,
72- NS :: Target : NodeSigner ,
73- SP :: Target : SignerProvider ,
74- F :: Target : FeeEstimator ,
75- R :: Target : Router ,
76- L :: Target : Logger ,
7757{
7858 let amt_msat = invoice. amount_milli_satoshis ( ) . ok_or ( PaymentError :: Invoice ( "amount missing" ) ) ?;
79- pay_invoice_using_amount ( invoice, amt_msat, payment_id, retry_strategy, channelmanager)
59+ pay_invoice_using_amount ( invoice, amt_msat, payment_id, retry_strategy, channelmanager. get_cm ( ) )
8060}
8161
8262/// Pays the given zero-value [`Bolt11Invoice`] using the given amount, retrying if needed based on
8868///
8969/// If you wish to use a different payment idempotency token, see
9070/// [`pay_zero_value_invoice_with_id`].
91- pub fn pay_zero_value_invoice < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
92- invoice : & Bolt11Invoice , amount_msats : u64 , retry_strategy : Retry ,
93- channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L >
71+ pub fn pay_zero_value_invoice < C : AChannelManager > (
72+ invoice : & Bolt11Invoice , amount_msats : u64 , retry_strategy : Retry , channelmanager : & C
9473) -> Result < PaymentId , PaymentError >
95- where
96- M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
97- T :: Target : BroadcasterInterface ,
98- ES :: Target : EntropySource ,
99- NS :: Target : NodeSigner ,
100- SP :: Target : SignerProvider ,
101- F :: Target : FeeEstimator ,
102- R :: Target : Router ,
103- L :: Target : Logger ,
10474{
10575 let payment_id = PaymentId ( invoice. payment_hash ( ) . into_inner ( ) ) ;
10676 pay_zero_value_invoice_with_id ( invoice, amount_msats, payment_id, retry_strategy,
@@ -119,25 +89,16 @@ where
11989///
12090/// See [`pay_zero_value_invoice`] for a variant which uses the [`PaymentHash`] for the
12191/// idempotency token.
122- pub fn pay_zero_value_invoice_with_id < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
92+ pub fn pay_zero_value_invoice_with_id < C : AChannelManager > (
12393 invoice : & Bolt11Invoice , amount_msats : u64 , payment_id : PaymentId , retry_strategy : Retry ,
124- channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L >
94+ channelmanager : & C
12595) -> Result < ( ) , PaymentError >
126- where
127- M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
128- T :: Target : BroadcasterInterface ,
129- ES :: Target : EntropySource ,
130- NS :: Target : NodeSigner ,
131- SP :: Target : SignerProvider ,
132- F :: Target : FeeEstimator ,
133- R :: Target : Router ,
134- L :: Target : Logger ,
13596{
13697 if invoice. amount_milli_satoshis ( ) . is_some ( ) {
13798 Err ( PaymentError :: Invoice ( "amount unexpected" ) )
13899 } else {
139100 pay_invoice_using_amount ( invoice, amount_msats, payment_id, retry_strategy,
140- channelmanager)
101+ channelmanager. get_cm ( ) )
141102 }
142103}
143104
@@ -163,6 +124,66 @@ fn pay_invoice_using_amount<P: Deref>(
163124 payer. send_payment ( payment_hash, recipient_onion, payment_id, route_params, retry_strategy)
164125}
165126
127+ /// Sends payment probes over all paths of a route that would be used to pay the given invoice.
128+ ///
129+ /// See [`ChannelManager::send_preflight_probes`] for more information.
130+ pub fn preflight_probe_invoice < C : AChannelManager > (
131+ invoice : & Bolt11Invoice , channelmanager : & C , liquidity_limit_multiplier : Option < u64 > ,
132+ ) -> Result < Vec < ( PaymentHash , PaymentId ) > , ProbingError >
133+ {
134+ let amount_msat = if let Some ( invoice_amount_msat) = invoice. amount_milli_satoshis ( ) {
135+ invoice_amount_msat
136+ } else {
137+ return Err ( ProbingError :: Invoice ( "Failed to send probe as no amount was given in the invoice." ) ) ;
138+ } ;
139+
140+ let mut payment_params = PaymentParameters :: from_node_id (
141+ invoice. recover_payee_pub_key ( ) ,
142+ invoice. min_final_cltv_expiry_delta ( ) as u32 ,
143+ )
144+ . with_expiry_time ( expiry_time_from_unix_epoch ( invoice) . as_secs ( ) )
145+ . with_route_hints ( invoice. route_hints ( ) )
146+ . unwrap ( ) ;
147+
148+ if let Some ( features) = invoice. features ( ) {
149+ payment_params = payment_params. with_bolt11_features ( features. clone ( ) ) . unwrap ( ) ;
150+ }
151+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
152+
153+ channelmanager. get_cm ( ) . send_preflight_probes ( route_params, liquidity_limit_multiplier)
154+ . map_err ( ProbingError :: Sending )
155+ }
156+
157+ /// Sends payment probes over all paths of a route that would be used to pay the given zero-value
158+ /// invoice using the given amount.
159+ ///
160+ /// See [`ChannelManager::send_preflight_probes`] for more information.
161+ pub fn preflight_probe_zero_value_invoice < C : AChannelManager > (
162+ invoice : & Bolt11Invoice , amount_msat : u64 , channelmanager : & C ,
163+ liquidity_limit_multiplier : Option < u64 > ,
164+ ) -> Result < Vec < ( PaymentHash , PaymentId ) > , ProbingError >
165+ {
166+ if invoice. amount_milli_satoshis ( ) . is_some ( ) {
167+ return Err ( ProbingError :: Invoice ( "amount unexpected" ) ) ;
168+ }
169+
170+ let mut payment_params = PaymentParameters :: from_node_id (
171+ invoice. recover_payee_pub_key ( ) ,
172+ invoice. min_final_cltv_expiry_delta ( ) as u32 ,
173+ )
174+ . with_expiry_time ( expiry_time_from_unix_epoch ( invoice) . as_secs ( ) )
175+ . with_route_hints ( invoice. route_hints ( ) )
176+ . unwrap ( ) ;
177+
178+ if let Some ( features) = invoice. features ( ) {
179+ payment_params = payment_params. with_bolt11_features ( features. clone ( ) ) . unwrap ( ) ;
180+ }
181+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
182+
183+ channelmanager. get_cm ( ) . send_preflight_probes ( route_params, liquidity_limit_multiplier)
184+ . map_err ( ProbingError :: Sending )
185+ }
186+
166187fn expiry_time_from_unix_epoch ( invoice : & Bolt11Invoice ) -> Duration {
167188 invoice. signed_invoice . raw_invoice . data . timestamp . 0 + invoice. expiry_time ( )
168189}
@@ -176,6 +197,15 @@ pub enum PaymentError {
176197 Sending ( RetryableSendFailure ) ,
177198}
178199
200+ /// An error that may occur when sending a payment probe.
201+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
202+ pub enum ProbingError {
203+ /// An error resulting from the provided [`Bolt11Invoice`].
204+ Invoice ( & ' static str ) ,
205+ /// An error occurring when sending a payment probe.
206+ Sending ( ProbeSendFailure ) ,
207+ }
208+
179209/// A trait defining behavior of a [`Bolt11Invoice`] payer.
180210///
181211/// Useful for unit testing internal methods.
0 commit comments