@@ -66,7 +66,9 @@ use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
66
66
use crate::offers::offer::{Offer, OfferBuilder};
67
67
use crate::offers::parse::Bolt12SemanticError;
68
68
use crate::offers::refund::{Refund, RefundBuilder};
69
- use crate::onion_message::async_payments::AsyncPaymentsMessage;
69
+ #[cfg(async_payments)]
70
+ use crate::offers::static_invoice::StaticInvoice;
71
+ use crate::onion_message::async_payments::{AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
70
72
use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction};
71
73
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
72
74
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
@@ -4045,6 +4047,34 @@ where
4045
4047
)
4046
4048
}
4047
4049
4050
+ #[cfg(async_payments)]
4051
+ fn initiate_async_payment(
4052
+ &self, invoice: &StaticInvoice, payment_id: PaymentId
4053
+ ) -> Result<(), InvoiceError> {
4054
+ if invoice.message_paths().is_empty() { return Err(Bolt12SemanticError::MissingPaths.into()) }
4055
+
4056
+ let reply_path = self.create_blinded_path(Some(payment_id))
4057
+ .map_err(|_| Bolt12SemanticError::MissingPaths)?;
4058
+
4059
+ let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4060
+ let payment_release_secret = self.pending_outbound_payments.static_invoice_received(
4061
+ invoice, payment_id, &*self.entropy_source
4062
+ ).map_err(|e| InvoiceError::from_string(format!("{:?}", e)))?;
4063
+
4064
+ let mut pending_async_payments_messages = self.pending_async_payments_messages.lock().unwrap();
4065
+ const HTLC_AVAILABLE_LIMIT: usize = 10;
4066
+ for path in invoice.message_paths().into_iter().take(HTLC_AVAILABLE_LIMIT) {
4067
+ let message = new_pending_onion_message(
4068
+ AsyncPaymentsMessage::HeldHtlcAvailable(HeldHtlcAvailable { payment_release_secret }),
4069
+ Destination::BlindedPath(path.clone()),
4070
+ Some(reply_path.clone()),
4071
+ );
4072
+ pending_async_payments_messages.push(message);
4073
+ }
4074
+
4075
+ Ok(())
4076
+ }
4077
+
4048
4078
/// Signals that no further attempts for the given payment should occur. Useful if you have a
4049
4079
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
4050
4080
/// retries are exhausted.
@@ -10388,14 +10418,22 @@ where
10388
10418
}
10389
10419
},
10390
10420
#[cfg(async_payments)]
10391
- OffersMessage::StaticInvoice(_invoice) => {
10392
- match responder {
10393
- Some(responder) => {
10394
- responder.respond(OffersMessage::InvoiceError(
10395
- InvoiceError::from_string("Static invoices not yet supported".to_string())
10396
- ))
10397
- },
10421
+ OffersMessage::StaticInvoice(invoice) => {
10422
+ let responder = match responder {
10423
+ Some(responder) => responder,
10398
10424
None => return ResponseInstruction::NoResponse,
10425
+ };
10426
+ let payment_id = match _payment_id {
10427
+ Some(id) => id,
10428
+ None => {
10429
+ return responder.respond(OffersMessage::InvoiceError(
10430
+ InvoiceError::from_string("Unrecognized invoice".to_string())
10431
+ ))
10432
+ }
10433
+ };
10434
+ match self.initiate_async_payment(&invoice, payment_id) {
10435
+ Ok(()) => return ResponseInstruction::NoResponse,
10436
+ Err(e) => responder.respond(OffersMessage::InvoiceError(e)),
10399
10437
}
10400
10438
},
10401
10439
OffersMessage::InvoiceError(invoice_error) => {
@@ -10410,6 +10448,31 @@ where
10410
10448
}
10411
10449
}
10412
10450
10451
+ impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
10452
+ AsyncPaymentsMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, L>
10453
+ where
10454
+ M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
10455
+ T::Target: BroadcasterInterface,
10456
+ ES::Target: EntropySource,
10457
+ NS::Target: NodeSigner,
10458
+ SP::Target: SignerProvider,
10459
+ F::Target: FeeEstimator,
10460
+ R::Target: Router,
10461
+ L::Target: Logger,
10462
+ {
10463
+ fn held_htlc_available(
10464
+ &self, _message: HeldHtlcAvailable, _responder: Option<Responder>
10465
+ ) -> ResponseInstruction<ReleaseHeldHtlc> {
10466
+ ResponseInstruction::NoResponse
10467
+ }
10468
+
10469
+ fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _payment_id: Option<PaymentId>) {}
10470
+
10471
+ fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
10472
+ core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap())
10473
+ }
10474
+ }
10475
+
10413
10476
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
10414
10477
NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, L>
10415
10478
where
0 commit comments