7171 crate :: onion_message:: dns_resolution:: { DNSResolverMessage , DNSSECQuery , OMNameResolver } ,
7272} ;
7373
74+ /// Defines the events that can be optionally triggered when processing offers messages.
75+ ///
76+ /// Once generated, these events are stored in the [`OffersMessageFlow`], where they can be
77+ /// manually inspected and responded to.
78+ pub enum OfferMessageFlowEvent {
79+ /// Notifies that an [`InvoiceRequest`] has been received.
80+ ///
81+ /// To respond to this message:
82+ /// - Based on the variant of [`InvoiceRequestVerifiedFromOffer`], create the appropriate invoice builder:
83+ /// - [`InvoiceRequestVerifiedFromOffer::DerivedKeys`] → use
84+ /// [`OffersMessageFlow::create_invoice_builder_from_invoice_request_with_keys`]
85+ /// - [`InvoiceRequestVerifiedFromOffer::ExplicitKeys`] → use
86+ /// [`OffersMessageFlow::create_invoice_builder_from_invoice_request_without_keys`]
87+ /// - After building the invoice, sign it and send it back using the provided reply path via
88+ /// [`OffersMessageFlow::enqueue_invoice_using_reply_paths`].
89+ ///
90+ /// If the invoice request is invalid, respond with an [`InvoiceError`] using
91+ /// [`OffersMessageFlow::enqueue_invoice_error`].
92+ InvoiceRequestReceived {
93+ /// The received, verified invoice request.
94+ invoice_request : InvoiceRequestVerifiedFromOffer ,
95+ /// The reply path to use when responding to the invoice request.
96+ reply_path : BlindedMessagePath ,
97+ } ,
98+ }
99+
74100/// A BOLT12 offers code and flow utility provider, which facilitates
75101/// BOLT12 builder generation and onion message handling.
76102///
93119 secp_ctx : Secp256k1 < secp256k1:: All > ,
94120 message_router : MR ,
95121
122+ pub ( crate ) enable_events : bool ,
123+
96124 #[ cfg( not( any( test, feature = "_test_utils" ) ) ) ]
97125 pending_offers_messages : Mutex < Vec < ( OffersMessage , MessageSendInstructions ) > > ,
98126 #[ cfg( any( test, feature = "_test_utils" ) ) ]
@@ -106,6 +134,8 @@ where
106134 #[ cfg( feature = "dnssec" ) ]
107135 pending_dns_onion_messages : Mutex < Vec < ( DNSResolverMessage , MessageSendInstructions ) > > ,
108136
137+ pending_flow_events : Mutex < Vec < OfferMessageFlowEvent > > ,
138+
109139 logger : L ,
110140}
111141
@@ -119,7 +149,7 @@ where
119149 chain_hash : ChainHash , best_block : BestBlock , our_network_pubkey : PublicKey ,
120150 current_timestamp : u32 , inbound_payment_key : inbound_payment:: ExpandedKey ,
121151 receive_auth_key : ReceiveAuthKey , secp_ctx : Secp256k1 < secp256k1:: All > , message_router : MR ,
122- logger : L ,
152+ enable_events : bool , logger : L ,
123153 ) -> Self {
124154 Self {
125155 chain_hash,
@@ -134,6 +164,8 @@ where
134164 secp_ctx,
135165 message_router,
136166
167+ enable_events,
168+
137169 pending_offers_messages : Mutex :: new ( Vec :: new ( ) ) ,
138170 pending_async_payments_messages : Mutex :: new ( Vec :: new ( ) ) ,
139171
@@ -144,6 +176,8 @@ where
144176
145177 async_receive_offer_cache : Mutex :: new ( AsyncReceiveOfferCache :: new ( ) ) ,
146178
179+ pending_flow_events : Mutex :: new ( Vec :: new ( ) ) ,
180+
147181 logger,
148182 }
149183 }
@@ -160,6 +194,18 @@ where
160194 self
161195 }
162196
197+ /// Enables [`OfferMessageFlowEvent`] for this flow.
198+ ///
199+ /// By default, events are not emitted when processing offers messages. Calling this method
200+ /// sets the internal `enable_events` flag to `true`, allowing you to receive [`OfferMessageFlowEvent`]
201+ /// such as [`OfferMessageFlowEvent::InvoiceRequestReceived`].
202+ ///
203+ /// This is useful when you want to manually inspect, handle, or respond to incoming
204+ /// offers messages rather than having them processed automatically.
205+ pub fn enable_events ( & mut self ) {
206+ self . enable_events = true ;
207+ }
208+
163209 /// Sets the [`BlindedMessagePath`]s that we will use as an async recipient to interactively build
164210 /// [`Offer`]s with a static invoice server, so the server can serve [`StaticInvoice`]s to payers
165211 /// on our behalf when we're offline.
@@ -421,6 +467,8 @@ pub enum InvreqResponseInstructions {
421467 /// [`OffersMessageFlow::enqueue_invoice_request_to_forward`].
422468 invoice_request : InvoiceRequest ,
423469 } ,
470+ /// We are recipient of this payment, and should handle the response asynchronously.
471+ AsynchronouslyHandleResponse ,
424472}
425473
426474/// Parameters for the reply path to a [`HeldHtlcAvailable`] onion message.
@@ -449,6 +497,7 @@ where
449497 L :: Target : Logger ,
450498{
451499 /// Verifies an [`InvoiceRequest`] using the provided [`OffersContext`] or the [`InvoiceRequest::metadata`].
500+ /// It also helps determine the response instructions, corresponding to the verified invoice request must be taken.
452501 ///
453502 /// - If an [`OffersContext::InvoiceRequest`] with a `nonce` is provided, verification is performed using recipient context data.
454503 /// - If no context is provided but the [`InvoiceRequest`] contains [`Offer`] metadata, verification is performed using that metadata.
@@ -461,6 +510,7 @@ where
461510 /// - The verification process (via recipient context data or metadata) fails.
462511 pub fn verify_invoice_request (
463512 & self , invoice_request : InvoiceRequest , context : Option < OffersContext > ,
513+ responder : Responder ,
464514 ) -> Result < InvreqResponseInstructions , ( ) > {
465515 let secp_ctx = & self . secp_ctx ;
466516 let expanded_key = & self . inbound_payment_key ;
@@ -494,7 +544,18 @@ where
494544 None => invoice_request. verify_using_metadata ( expanded_key, secp_ctx) ,
495545 } ?;
496546
497- Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
547+ if self . enable_events {
548+ self . pending_flow_events . lock ( ) . unwrap ( ) . push (
549+ OfferMessageFlowEvent :: InvoiceRequestReceived {
550+ invoice_request,
551+ reply_path : responder. into_blinded_path ( ) ,
552+ } ,
553+ ) ;
554+
555+ Ok ( InvreqResponseInstructions :: AsynchronouslyHandleResponse )
556+ } else {
557+ Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
558+ }
498559 }
499560
500561 /// Verifies a [`Bolt12Invoice`] using the provided [`OffersContext`] or the invoice's payer metadata,
@@ -1385,6 +1446,11 @@ where
13851446 Ok ( ( ) )
13861447 }
13871448
1449+ /// Enqueues the generated [`OfferMessageFlowEvent`] to be processed.
1450+ pub fn enqueue_flow_event ( & self , flow_event : OfferMessageFlowEvent ) {
1451+ self . pending_flow_events . lock ( ) . unwrap ( ) . push ( flow_event) ;
1452+ }
1453+
13881454 /// Gets the enqueued [`OffersMessage`] with their corresponding [`MessageSendInstructions`].
13891455 pub fn release_pending_offers_messages ( & self ) -> Vec < ( OffersMessage , MessageSendInstructions ) > {
13901456 core:: mem:: take ( & mut self . pending_offers_messages . lock ( ) . unwrap ( ) )
@@ -1397,6 +1463,11 @@ where
13971463 core:: mem:: take ( & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) )
13981464 }
13991465
1466+ /// Gets the enqueued [`OfferMessageFlowEvent`] to be processed.
1467+ pub fn release_pending_flow_events ( & self ) -> Vec < OfferMessageFlowEvent > {
1468+ core:: mem:: take ( & mut self . pending_flow_events . lock ( ) . unwrap ( ) )
1469+ }
1470+
14001471 /// Gets the enqueued [`DNSResolverMessage`] with their corresponding [`MessageSendInstructions`].
14011472 #[ cfg( feature = "dnssec" ) ]
14021473 pub fn release_pending_dns_messages (
0 commit comments