@@ -68,6 +68,8 @@ use crate::offers::offer::{Offer, OfferBuilder};
68
68
use crate::offers::parse::Bolt12SemanticError;
69
69
use crate::offers::refund::{Refund, RefundBuilder};
70
70
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
71
+ #[cfg(async_payments)]
72
+ use crate::offers::static_invoice::StaticInvoice;
71
73
use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction};
72
74
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
73
75
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
@@ -4130,6 +4132,35 @@ where
4130
4132
)
4131
4133
}
4132
4134
4135
+ #[cfg(async_payments)]
4136
+ fn initiate_async_payment(
4137
+ &self, invoice: &StaticInvoice, payment_id: PaymentId
4138
+ ) -> Result<(), InvoiceError> {
4139
+ if invoice.message_paths().is_empty() { return Err(Bolt12SemanticError::MissingPaths.into()) }
4140
+
4141
+ let reply_path = self.create_blinded_path(
4142
+ MessageContext::AsyncPayments(AsyncPaymentsContext::OutboundPayment { payment_id })
4143
+ ).map_err(|_| Bolt12SemanticError::MissingPaths)?;
4144
+
4145
+ let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4146
+ let payment_release_secret = self.pending_outbound_payments.static_invoice_received(
4147
+ invoice, payment_id, &*self.entropy_source
4148
+ ).map_err(|e| InvoiceError::from_string(format!("{:?}", e)))?;
4149
+
4150
+ let mut pending_async_payments_messages = self.pending_async_payments_messages.lock().unwrap();
4151
+ const HTLC_AVAILABLE_LIMIT: usize = 10;
4152
+ for path in invoice.message_paths().into_iter().take(HTLC_AVAILABLE_LIMIT) {
4153
+ let message = new_pending_onion_message(
4154
+ AsyncPaymentsMessage::HeldHtlcAvailable(HeldHtlcAvailable { payment_release_secret }),
4155
+ Destination::BlindedPath(path.clone()),
4156
+ Some(reply_path.clone()),
4157
+ );
4158
+ pending_async_payments_messages.push(message);
4159
+ }
4160
+
4161
+ Ok(())
4162
+ }
4163
+
4133
4164
/// Signals that no further attempts for the given payment should occur. Useful if you have a
4134
4165
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
4135
4166
/// retries are exhausted.
@@ -10652,14 +10683,22 @@ where
10652
10683
}
10653
10684
},
10654
10685
#[cfg(async_payments)]
10655
- OffersMessage::StaticInvoice(_invoice) => {
10656
- match responder {
10657
- Some(responder) => {
10658
- responder.respond(OffersMessage::InvoiceError(
10659
- InvoiceError::from_string("Static invoices not yet supported".to_string())
10660
- ))
10661
- },
10686
+ OffersMessage::StaticInvoice(invoice) => {
10687
+ let responder = match responder {
10688
+ Some(responder) => responder,
10662
10689
None => return ResponseInstruction::NoResponse,
10690
+ };
10691
+ let payment_id = match context {
10692
+ OffersContext::OutboundPayment { payment_id } => payment_id,
10693
+ _ => {
10694
+ return responder.respond(OffersMessage::InvoiceError(
10695
+ InvoiceError::from_string("Unrecognized invoice".to_string())
10696
+ ))
10697
+ }
10698
+ };
10699
+ match self.initiate_async_payment(&invoice, payment_id) {
10700
+ Ok(()) => return ResponseInstruction::NoResponse,
10701
+ Err(e) => responder.respond(OffersMessage::InvoiceError(e)),
10663
10702
}
10664
10703
},
10665
10704
OffersMessage::InvoiceError(invoice_error) => {
@@ -10696,7 +10735,7 @@ where
10696
10735
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {}
10697
10736
10698
10737
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
10699
- Vec::new( )
10738
+ core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap() )
10700
10739
}
10701
10740
}
10702
10741
0 commit comments