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.
@@ -416,6 +462,8 @@ pub enum InvreqResponseInstructions {
416462 /// [`OffersMessageFlow::enqueue_invoice_request_to_forward`].
417463 invoice_request : InvoiceRequest ,
418464 } ,
465+ /// We are recipient of this payment, and should handle the response asynchronously.
466+ AsynchronouslyHandleResponse ,
419467}
420468
421469/// Parameters for the reply path to a [`HeldHtlcAvailable`] onion message.
@@ -444,6 +492,7 @@ where
444492 L :: Target : Logger ,
445493{
446494 /// Verifies an [`InvoiceRequest`] using the provided [`OffersContext`] or the [`InvoiceRequest::metadata`].
495+ /// It also helps determine the response instructions, corresponding to the verified invoice request must be taken.
447496 ///
448497 /// - If an [`OffersContext::InvoiceRequest`] with a `nonce` is provided, verification is performed using recipient context data.
449498 /// - If no context is provided but the [`InvoiceRequest`] contains [`Offer`] metadata, verification is performed using that metadata.
@@ -456,6 +505,7 @@ where
456505 /// - The verification process (via recipient context data or metadata) fails.
457506 pub fn verify_invoice_request (
458507 & self , invoice_request : InvoiceRequest , context : Option < OffersContext > ,
508+ responder : Responder ,
459509 ) -> Result < InvreqResponseInstructions , ( ) > {
460510 let secp_ctx = & self . secp_ctx ;
461511 let expanded_key = & self . inbound_payment_key ;
@@ -489,7 +539,18 @@ where
489539 None => invoice_request. verify_using_metadata ( expanded_key, secp_ctx) ,
490540 } ?;
491541
492- Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
542+ if self . enable_events {
543+ self . pending_flow_events . lock ( ) . unwrap ( ) . push (
544+ OfferMessageFlowEvent :: InvoiceRequestReceived {
545+ invoice_request,
546+ reply_path : responder. into_blinded_path ( ) ,
547+ } ,
548+ ) ;
549+
550+ Ok ( InvreqResponseInstructions :: AsynchronouslyHandleResponse )
551+ } else {
552+ Ok ( InvreqResponseInstructions :: SendInvoice ( invoice_request) )
553+ }
493554 }
494555
495556 /// Verifies a [`Bolt12Invoice`] using the provided [`OffersContext`] or the invoice's payer metadata,
@@ -1374,6 +1435,11 @@ where
13741435 Ok ( ( ) )
13751436 }
13761437
1438+ /// Enqueues the generated [`OfferMessageFlowEvent`] to be processed.
1439+ pub fn enqueue_flow_event ( & self , flow_event : OfferMessageFlowEvent ) {
1440+ self . pending_flow_events . lock ( ) . unwrap ( ) . push ( flow_event) ;
1441+ }
1442+
13771443 /// Gets the enqueued [`OffersMessage`] with their corresponding [`MessageSendInstructions`].
13781444 pub fn release_pending_offers_messages ( & self ) -> Vec < ( OffersMessage , MessageSendInstructions ) > {
13791445 core:: mem:: take ( & mut self . pending_offers_messages . lock ( ) . unwrap ( ) )
@@ -1386,6 +1452,11 @@ where
13861452 core:: mem:: take ( & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) )
13871453 }
13881454
1455+ /// Gets the enqueued [`OfferMessageFlowEvent`] to be processed.
1456+ pub fn release_pending_flow_events ( & self ) -> Vec < OfferMessageFlowEvent > {
1457+ core:: mem:: take ( & mut self . pending_flow_events . lock ( ) . unwrap ( ) )
1458+ }
1459+
13891460 /// Gets the enqueued [`DNSResolverMessage`] with their corresponding [`MessageSendInstructions`].
13901461 #[ cfg( feature = "dnssec" ) ]
13911462 pub fn release_pending_dns_messages (
0 commit comments