@@ -69,6 +69,8 @@ use crate::offers::offer::{Offer, OfferBuilder};
69
69
use crate::offers::parse::Bolt12SemanticError;
70
70
use crate::offers::refund::{Refund, RefundBuilder};
71
71
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
72
+ #[cfg(async_payments)]
73
+ use crate::offers::static_invoice::StaticInvoice;
72
74
use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction};
73
75
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
74
76
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
@@ -4251,6 +4253,37 @@ where
4251
4253
)
4252
4254
}
4253
4255
4256
+ #[cfg(async_payments)]
4257
+ fn initiate_async_payment(
4258
+ &self, invoice: &StaticInvoice, payment_id: PaymentId
4259
+ ) -> Result<(), Bolt12PaymentError> {
4260
+ let reply_paths = self.create_blinded_paths(
4261
+ MessageContext::AsyncPayments(AsyncPaymentsContext::OutboundPayment { payment_id })
4262
+ ).map_err(|_| Bolt12PaymentError::BlindedPathNotFound)?;
4263
+
4264
+ let payment_release_secret = self.pending_outbound_payments.static_invoice_received(
4265
+ invoice, payment_id, &*self.entropy_source
4266
+ )?;
4267
+ let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4268
+
4269
+ let mut pending_async_payments_messages = self.pending_async_payments_messages.lock().unwrap();
4270
+ const HTLC_AVAILABLE_LIMIT: usize = 10;
4271
+ reply_paths
4272
+ .iter()
4273
+ .flat_map(|reply_path| invoice.message_paths().iter().map(move |invoice_path| (invoice_path, reply_path)))
4274
+ .take(HTLC_AVAILABLE_LIMIT)
4275
+ .for_each(|(invoice_path, reply_path)| {
4276
+ let message = new_pending_onion_message(
4277
+ AsyncPaymentsMessage::HeldHtlcAvailable(HeldHtlcAvailable { payment_release_secret }),
4278
+ Destination::BlindedPath(invoice_path.clone()),
4279
+ Some(reply_path.clone()),
4280
+ );
4281
+ pending_async_payments_messages.push(message);
4282
+ });
4283
+
4284
+ Ok(())
4285
+ }
4286
+
4254
4287
/// Signals that no further attempts for the given payment should occur. Useful if you have a
4255
4288
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
4256
4289
/// retries are exhausted.
@@ -10878,15 +10911,15 @@ where
10878
10911
}
10879
10912
},
10880
10913
#[cfg(async_payments)]
10881
- OffersMessage::StaticInvoice(_invoice) => {
10882
- match responder {
10883
- Some(responder) => {
10884
- responder.respond(OffersMessage::InvoiceError(
10885
- InvoiceError::from_string("Static invoices not yet supported".to_string())
10886
- ))
10887
- },
10888
- None => return ResponseInstruction::NoResponse,
10914
+ OffersMessage::StaticInvoice(invoice) => {
10915
+ let payment_id = match context {
10916
+ OffersContext::OutboundPayment { payment_id, nonce: _ } => payment_id,
10917
+ _ => return ResponseInstruction::NoResponse
10918
+ };
10919
+ if let Err(e) = self.initiate_async_payment(&invoice, payment_id) {
10920
+ log_trace!(self.logger, "Failed to initiate async payment to static invoice: {:?}", e);
10889
10921
}
10922
+ ResponseInstruction::NoResponse
10890
10923
},
10891
10924
OffersMessage::InvoiceError(invoice_error) => {
10892
10925
abandon_if_payment(context);
@@ -10922,7 +10955,7 @@ where
10922
10955
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {}
10923
10956
10924
10957
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
10925
- Vec::new( )
10958
+ core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap() )
10926
10959
}
10927
10960
}
10928
10961
0 commit comments