@@ -22,6 +22,8 @@ use lightning::offers::invoice::Bolt12Invoice;
22
22
use lightning:: offers:: offer:: { Amount , Offer , Quantity } ;
23
23
use lightning:: offers:: parse:: Bolt12SemanticError ;
24
24
use lightning:: offers:: refund:: Refund ;
25
+ use lightning:: onion_message:: dns_resolution:: HumanReadableName ;
26
+ use lightning:: onion_message:: messenger:: Destination ;
25
27
use lightning:: util:: string:: UntrustedString ;
26
28
27
29
use rand:: RngCore ;
@@ -256,6 +258,72 @@ impl Bolt12Payment {
256
258
}
257
259
}
258
260
261
+ /// Send a payment to an offer resolved from a human-readable name [BIP 353].
262
+ ///
263
+ /// Paying to human-readable names makes it more intuitive to make payments for offers
264
+ /// as users can simply send payments to HRNs such as `user@example.com`.
265
+ ///
266
+ /// This can be used to pay so-called "zero-amount" offers, i.e., an offer that leaves the
267
+ /// amount paid to be determined by the user.
268
+ ///
269
+ /// `dns_resolvers` should be a list of node Destinations that are configured for dns resolution (as outlined in bLIP 32).
270
+ /// These nodes can be found by running a search through the `NetworkGraph` to find nodes that announce the
271
+ /// `dns_resolver` feature flag.
272
+ pub fn send_to_human_readable_name (
273
+ & self , name : & str , amount_msat : u64 , dns_resolvers : Vec < Destination > ,
274
+ ) -> Result < PaymentId , Error > {
275
+ let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
276
+ if rt_lock. is_none ( ) {
277
+ return Err ( Error :: NotRunning ) ;
278
+ }
279
+
280
+ let hrn = HumanReadableName :: from_encoded ( & name) . map_err ( |_| Error :: HrnParsingFailed ) ?;
281
+
282
+ let mut random_bytes = [ 0u8 ; 32 ] ;
283
+ rand:: thread_rng ( ) . fill_bytes ( & mut random_bytes) ;
284
+ let payment_id = PaymentId ( random_bytes) ;
285
+ let retry_strategy = Retry :: Timeout ( LDK_PAYMENT_RETRY_TIMEOUT ) ;
286
+ let max_total_routing_fee_msat = None ;
287
+
288
+ match self . channel_manager . pay_for_offer_from_human_readable_name (
289
+ hrn. clone ( ) ,
290
+ amount_msat,
291
+ payment_id,
292
+ retry_strategy,
293
+ max_total_routing_fee_msat,
294
+ dns_resolvers,
295
+ ) {
296
+ Ok ( ( ) ) => {
297
+ log_info ! ( self . logger, "Initiated sending {} msats to {}" , amount_msat, name) ;
298
+ let kind = PaymentKind :: HrnBolt12Offer { hrn } ;
299
+ let payment = PaymentDetails :: new (
300
+ payment_id,
301
+ kind,
302
+ Some ( amount_msat) ,
303
+ None ,
304
+ PaymentDirection :: Outbound ,
305
+ PaymentStatus :: Pending ,
306
+ ) ;
307
+ self . payment_store . insert ( payment) ?;
308
+ Ok ( payment_id)
309
+ } ,
310
+ Err ( ( ) ) => {
311
+ log_error ! ( self . logger, "Failed to send payment to {}" , name) ;
312
+ let kind = PaymentKind :: HrnBolt12Offer { hrn } ;
313
+ let payment = PaymentDetails :: new (
314
+ payment_id,
315
+ kind,
316
+ Some ( amount_msat) ,
317
+ None ,
318
+ PaymentDirection :: Outbound ,
319
+ PaymentStatus :: Pending ,
320
+ ) ;
321
+ self . payment_store . insert ( payment) ?;
322
+ Err ( Error :: PaymentSendingFailed )
323
+ } ,
324
+ }
325
+ }
326
+
259
327
/// Returns a payable offer that can be used to request and receive a payment of the amount
260
328
/// given.
261
329
pub fn receive (
0 commit comments