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
426474impl < MR : Deref , L : Deref > OffersMessageFlow < MR , L >
@@ -429,6 +477,7 @@ where
429477 L :: Target : Logger ,
430478{
431479 /// Verifies an [`InvoiceRequest`] using the provided [`OffersContext`] or the [`InvoiceRequest::metadata`].
480+ /// It also helps determine the response instructions, corresponding to the verified invoice request must be taken.
432481 ///
433482 /// - If an [`OffersContext::InvoiceRequest`] with a `nonce` is provided, verification is performed using recipient context data.
434483 /// - If no context is provided but the [`InvoiceRequest`] contains [`Offer`] metadata, verification is performed using that metadata.
@@ -441,6 +490,7 @@ where
441490 /// - The verification process (via recipient context data or metadata) fails.
442491 pub fn verify_invoice_request (
443492 & self , invoice_request : InvoiceRequest , context : Option < OffersContext > ,
493+ responder : Responder ,
444494 ) -> Result < InvreqResponseInstructions , ( ) > {
445495 let secp_ctx = & self . secp_ctx ;
446496 let expanded_key = & self . inbound_payment_key ;
@@ -474,7 +524,18 @@ where
474524 None => invoice_request. verify_using_metadata ( expanded_key, secp_ctx) ,
475525 } ?;
476526
477- Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
527+ if self . enable_events {
528+ self . pending_flow_events . lock ( ) . unwrap ( ) . push (
529+ OfferMessageFlowEvent :: InvoiceRequestReceived {
530+ invoice_request,
531+ reply_path : responder. into_blinded_path ( ) ,
532+ } ,
533+ ) ;
534+
535+ Ok ( InvreqResponseInstructions :: AsynchronouslyHandleResponse )
536+ } else {
537+ Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
538+ }
478539 }
479540
480541 /// Verifies a [`Bolt12Invoice`] using the provided [`OffersContext`] or the invoice's payer metadata,
@@ -1352,6 +1413,11 @@ where
13521413 Ok ( ( ) )
13531414 }
13541415
1416+ /// Enqueues the generated [`OfferMessageFlowEvent`] to be processed.
1417+ pub fn enqueue_flow_event ( & self , flow_event : OfferMessageFlowEvent ) {
1418+ self . pending_flow_events . lock ( ) . unwrap ( ) . push ( flow_event) ;
1419+ }
1420+
13551421 /// Gets the enqueued [`OffersMessage`] with their corresponding [`MessageSendInstructions`].
13561422 pub fn release_pending_offers_messages ( & self ) -> Vec < ( OffersMessage , MessageSendInstructions ) > {
13571423 core:: mem:: take ( & mut self . pending_offers_messages . lock ( ) . unwrap ( ) )
@@ -1364,6 +1430,11 @@ where
13641430 core:: mem:: take ( & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) )
13651431 }
13661432
1433+ /// Gets the enqueued [`OfferMessageFlowEvent`] to be processed.
1434+ pub fn release_pending_flow_events ( & self ) -> Vec < OfferMessageFlowEvent > {
1435+ core:: mem:: take ( & mut self . pending_flow_events . lock ( ) . unwrap ( ) )
1436+ }
1437+
13671438 /// Gets the enqueued [`DNSResolverMessage`] with their corresponding [`MessageSendInstructions`].
13681439 #[ cfg( feature = "dnssec" ) ]
13691440 pub fn release_pending_dns_messages (
0 commit comments