@@ -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.
@@ -10348,14 +10378,22 @@ where
10348
10378
}
10349
10379
},
10350
10380
#[cfg(async_payments)]
10351
- OffersMessage::StaticInvoice(_invoice) => {
10352
- match responder {
10353
- Some(responder) => {
10354
- responder.respond(OffersMessage::InvoiceError(
10355
- InvoiceError::from_string("Static invoices not yet supported".to_string())
10356
- ))
10357
- },
10381
+ OffersMessage::StaticInvoice(invoice) => {
10382
+ let responder = match responder {
10383
+ Some(responder) => responder,
10358
10384
None => return ResponseInstruction::NoResponse,
10385
+ };
10386
+ let payment_id = match _payment_id {
10387
+ Some(id) => id,
10388
+ None => {
10389
+ return responder.respond(OffersMessage::InvoiceError(
10390
+ InvoiceError::from_string("Unrecognized invoice".to_string())
10391
+ ))
10392
+ }
10393
+ };
10394
+ match self.initiate_async_payment(&invoice, payment_id) {
10395
+ Ok(()) => return ResponseInstruction::NoResponse,
10396
+ Err(e) => responder.respond(OffersMessage::InvoiceError(e)),
10359
10397
}
10360
10398
},
10361
10399
OffersMessage::InvoiceError(invoice_error) => {
@@ -10370,6 +10408,31 @@ where
10370
10408
}
10371
10409
}
10372
10410
10411
+ impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
10412
+ AsyncPaymentsMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, L>
10413
+ where
10414
+ M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
10415
+ T::Target: BroadcasterInterface,
10416
+ ES::Target: EntropySource,
10417
+ NS::Target: NodeSigner,
10418
+ SP::Target: SignerProvider,
10419
+ F::Target: FeeEstimator,
10420
+ R::Target: Router,
10421
+ L::Target: Logger,
10422
+ {
10423
+ fn held_htlc_available(
10424
+ &self, _message: HeldHtlcAvailable, _responder: Option<Responder>
10425
+ ) -> ResponseInstruction<ReleaseHeldHtlc> {
10426
+ ResponseInstruction::NoResponse
10427
+ }
10428
+
10429
+ fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _payment_id: Option<PaymentId>) {}
10430
+
10431
+ fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
10432
+ core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap())
10433
+ }
10434
+ }
10435
+
10373
10436
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
10374
10437
NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, L>
10375
10438
where
0 commit comments