Skip to content

Commit 918ed61

Browse files
Add API to retrieve cached async receive offers
Over the past several commits we've implemented interactively building an async receive offer with a static invoice server that will service invoice requests on our behalf as an async recipient. Here we add an API to retrieve the resulting offers so we can receive payments when we're offline.
1 parent c2e8b11 commit 918ed61

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10357,9 +10357,21 @@ where
1035710357
#[cfg(c_bindings)]
1035810358
create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder);
1035910359

10360+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
10361+
/// Will only be set if [`UserConfig::paths_to_static_invoice_server`] is set and we succeeded in
10362+
/// interactively building a [`StaticInvoice`] with the static invoice server.
10363+
#[cfg(async_payments)]
10364+
pub fn get_cached_async_receive_offers(&self) -> Vec<Offer> {
10365+
self.flow.get_cached_async_receive_offers()
10366+
}
10367+
1036010368
/// Create an offer for receiving async payments as an often-offline recipient.
1036110369
///
10362-
/// Because we may be offline when the payer attempts to request an invoice, you MUST:
10370+
/// Instead of using this method, it is preferable to set
10371+
/// [`UserConfig::paths_to_static_invoice_server`] and retrieve the automatically built offer via
10372+
/// [`Self::get_cached_async_receive_offers`].
10373+
///
10374+
/// If you want to build the [`StaticInvoice`] manually using this method instead, you MUST:
1036310375
/// 1. Provide at least 1 [`BlindedMessagePath`] terminating at an always-online node that will
1036410376
/// serve the [`StaticInvoice`] created from this offer on our behalf.
1036510377
/// 2. Use [`Self::create_static_invoice_builder`] to create a [`StaticInvoice`] from this
@@ -10375,6 +10387,10 @@ where
1037510387
/// Creates a [`StaticInvoiceBuilder`] from the corresponding [`Offer`] and [`Nonce`] that were
1037610388
/// created via [`Self::create_async_receive_offer_builder`]. If `relative_expiry` is unset, the
1037710389
/// invoice's expiry will default to [`STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY`].
10390+
///
10391+
/// Instead of using this method to manually build the invoice, it is preferable to set
10392+
/// [`UserConfig::paths_to_static_invoice_server`] and retrieve the automatically built offer via
10393+
/// [`Self::get_cached_async_receive_offers`].
1037810394
#[cfg(async_payments)]
1037910395
pub fn create_static_invoice_builder<'a>(
1038010396
&self, offer: &'a Offer, offer_nonce: Nonce, relative_expiry: Option<Duration>

lightning/src/offers/async_receive_offer_cache.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,26 @@ impl AsyncReceiveOfferCache {
9393
// invoice before giving up.
9494
const MAX_UPDATE_ATTEMPTS: u8 = 3;
9595

96+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
97+
pub fn offers(&self, duration_since_epoch: Duration) -> Vec<Offer> {
98+
const NEVER_EXPIRES: Duration = Duration::from_secs(u64::MAX);
99+
100+
self.offers
101+
.iter()
102+
.filter_map(|offer| {
103+
if offer.static_invoice_absolute_expiry < duration_since_epoch {
104+
None
105+
} else if offer.offer.absolute_expiry().unwrap_or(NEVER_EXPIRES)
106+
< duration_since_epoch
107+
{
108+
None
109+
} else {
110+
Some(offer.offer.clone())
111+
}
112+
})
113+
.collect()
114+
}
115+
96116
/// Remove expired offers from the cache.
97117
pub(super) fn prune_expired_offers(&mut self, duration_since_epoch: Duration) {
98118
// Remove expired offers from the cache.

lightning/src/offers/flow.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,14 @@ where
11411141
core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap())
11421142
}
11431143

1144+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
1145+
/// Will only be set if [`UserConfig::paths_to_static_invoice_server`] is set and we succeeded in
1146+
/// interactively building a [`StaticInvoice`] with the static invoice server.
1147+
#[cfg(async_payments)]
1148+
pub(crate) fn get_cached_async_receive_offers(&self) -> Vec<Offer> {
1149+
self.async_receive_offer_cache.lock().unwrap().offers(self.duration_since_epoch())
1150+
}
1151+
11441152
/// Sends out [`OfferPathsRequest`] and [`ServeStaticInvoice`] onion messages if we are an
11451153
/// often-offline recipient and are configured to interactively build offers and static invoices
11461154
/// with a static invoice server.

0 commit comments

Comments
 (0)