@@ -11,12 +11,15 @@ use crate::payment::store::{
1111use crate :: types:: ChannelManager ;
1212
1313use lightning:: ln:: channelmanager:: { PaymentId , Retry } ;
14+ use lightning:: offers:: invoice:: Bolt12Invoice ;
1415use lightning:: offers:: offer:: { Amount , Offer } ;
1516use lightning:: offers:: parse:: Bolt12SemanticError ;
17+ use lightning:: offers:: refund:: Refund ;
1618
1719use rand:: RngCore ;
1820
1921use std:: sync:: { Arc , RwLock } ;
22+ use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
2023
2124/// A payment handler allowing to create and pay [BOLT 12] offers and refunds.
2225///
@@ -264,4 +267,62 @@ impl Bolt12Payment {
264267
265268 Ok ( offer)
266269 }
270+
271+ /// Requests a refund payment for the given [`Refund`].
272+ ///
273+ /// The returned [`Bolt12Invoice`] is for informational purposes only (i.e., isn't needed to
274+ /// retrieve the refund).
275+ pub fn request_refund ( & self , refund : & Refund ) -> Result < Bolt12Invoice , Error > {
276+ self . channel_manager . request_refund_payment ( refund) . map_err ( |e| {
277+ log_error ! ( self . logger, "Failed to request refund payment: {:?}" , e) ;
278+ Error :: InvalidRefund
279+ } )
280+ }
281+
282+ /// Returns a [`Refund`] that can be used to offer a refund payment of the amount given.
283+ pub fn offer_refund ( & self , amount_msat : u64 , expiry_secs : u32 ) -> Result < Refund , Error > {
284+ let mut random_bytes = [ 0u8 ; 32 ] ;
285+ rand:: thread_rng ( ) . fill_bytes ( & mut random_bytes) ;
286+ let payment_id = PaymentId ( random_bytes) ;
287+
288+ let expiration = ( SystemTime :: now ( ) + Duration :: from_secs ( expiry_secs as u64 ) )
289+ . duration_since ( UNIX_EPOCH )
290+ . unwrap ( ) ;
291+ let retry_strategy = Retry :: Timeout ( LDK_PAYMENT_RETRY_TIMEOUT ) ;
292+ let max_total_routing_fee_msat = None ;
293+
294+ let refund_builder = self
295+ . channel_manager
296+ . create_refund_builder (
297+ amount_msat,
298+ expiration,
299+ payment_id,
300+ retry_strategy,
301+ max_total_routing_fee_msat,
302+ )
303+ . map_err ( |e| {
304+ log_error ! ( self . logger, "Failed to create refund builder: {:?}" , e) ;
305+ Error :: RefundCreationFailed
306+ } ) ?;
307+ let refund = refund_builder. build ( ) . map_err ( |e| {
308+ log_error ! ( self . logger, "Failed to create refund: {:?}" , e) ;
309+ Error :: RefundCreationFailed
310+ } ) ?;
311+
312+ log_info ! ( self . logger, "Offering refund of {}msat" , amount_msat) ;
313+
314+ let kind = PaymentKind :: Bolt12Refund { hash : None , preimage : None , secret : None } ;
315+
316+ let payment = PaymentDetails {
317+ id : payment_id,
318+ kind,
319+ amount_msat : Some ( amount_msat) ,
320+ direction : PaymentDirection :: Outbound ,
321+ status : PaymentStatus :: Pending ,
322+ } ;
323+
324+ self . payment_store . insert ( payment) ?;
325+
326+ Ok ( refund)
327+ }
267328}
0 commit comments