7
7
// You may not use this file except in accordance with one or both of these
8
8
// licenses.
9
9
10
- //! Convenient utilities for paying Lightning invoices and sending spontaneous payments .
10
+ //! Convenient utilities for paying Lightning invoices.
11
11
12
- use crate :: Bolt11Invoice ;
12
+ use crate :: { Bolt11Invoice , Vec } ;
13
13
14
14
use bitcoin_hashes:: Hash ;
15
15
16
16
use lightning:: chain;
17
17
use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
18
18
use lightning:: sign:: { NodeSigner , SignerProvider , EntropySource } ;
19
19
use 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 } ;
21
21
use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router } ;
22
22
use lightning:: util:: logger:: Logger ;
23
23
@@ -32,22 +32,12 @@ use core::time::Duration;
32
32
/// with the same [`PaymentHash`] is never sent.
33
33
///
34
34
/// 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
38
37
) -> 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 ,
48
38
{
49
39
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 ( ) )
51
41
. map ( |( ) | payment_id)
52
42
}
53
43
@@ -61,22 +51,12 @@ where
61
51
/// [`PaymentHash`] has never been paid before.
62
52
///
63
53
/// 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
67
56
) -> 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 ,
77
57
{
78
58
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 ( ) )
80
60
}
81
61
82
62
/// Pays the given zero-value [`Bolt11Invoice`] using the given amount, retrying if needed based on
88
68
///
89
69
/// If you wish to use a different payment idempotency token, see
90
70
/// [`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
94
73
) -> 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 ,
104
74
{
105
75
let payment_id = PaymentId ( invoice. payment_hash ( ) . into_inner ( ) ) ;
106
76
pay_zero_value_invoice_with_id ( invoice, amount_msats, payment_id, retry_strategy,
@@ -119,25 +89,16 @@ where
119
89
///
120
90
/// See [`pay_zero_value_invoice`] for a variant which uses the [`PaymentHash`] for the
121
91
/// 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 > (
123
93
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
125
95
) -> 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 ,
135
96
{
136
97
if invoice. amount_milli_satoshis ( ) . is_some ( ) {
137
98
Err ( PaymentError :: Invoice ( "amount unexpected" ) )
138
99
} else {
139
100
pay_invoice_using_amount ( invoice, amount_msats, payment_id, retry_strategy,
140
- channelmanager)
101
+ channelmanager. get_cm ( ) )
141
102
}
142
103
}
143
104
@@ -163,6 +124,66 @@ fn pay_invoice_using_amount<P: Deref>(
163
124
payer. send_payment ( payment_hash, recipient_onion, payment_id, route_params, retry_strategy)
164
125
}
165
126
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
+
166
187
fn expiry_time_from_unix_epoch ( invoice : & Bolt11Invoice ) -> Duration {
167
188
invoice. signed_invoice . raw_invoice . data . timestamp . 0 + invoice. expiry_time ( )
168
189
}
@@ -176,6 +197,15 @@ pub enum PaymentError {
176
197
Sending ( RetryableSendFailure ) ,
177
198
}
178
199
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
+
179
209
/// A trait defining behavior of a [`Bolt11Invoice`] payer.
180
210
///
181
211
/// Useful for unit testing internal methods.
0 commit comments