Skip to content

Commit 5455d55

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 e1761f3 commit 5455d55

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

lightning/src/ln/channelmanager.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -10308,9 +10308,21 @@ where
1030810308
#[cfg(c_bindings)]
1030910309
create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder);
1031010310

10311+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
10312+
/// Will only be set if [`UserConfig::paths_to_static_invoice_server`] is set and we succeeded in
10313+
/// interactively building a [`StaticInvoice`] with the static invoice server.
10314+
#[cfg(async_payments)]
10315+
pub fn get_cached_async_receive_offers(&self) -> Vec<Offer> {
10316+
self.flow.get_cached_async_receive_offers()
10317+
}
10318+
1031110319
/// Create an offer for receiving async payments as an often-offline recipient.
1031210320
///
10313-
/// Because we may be offline when the payer attempts to request an invoice, you MUST:
10321+
/// Instead of using this method, it is preferable to set
10322+
/// [`UserConfig::paths_to_static_invoice_server`] and retrieve the automatically built offer via
10323+
/// [`Self::get_cached_async_receive_offers`].
10324+
///
10325+
/// If you want to build the [`StaticInvoice`] manually using this method instead, you MUST:
1031410326
/// 1. Provide at least 1 [`BlindedMessagePath`] terminating at an always-online node that will
1031510327
/// serve the [`StaticInvoice`] created from this offer on our behalf.
1031610328
/// 2. Use [`Self::create_static_invoice_builder`] to create a [`StaticInvoice`] from this
@@ -10338,6 +10350,10 @@ where
1033810350
/// Creates a [`StaticInvoiceBuilder`] from the corresponding [`Offer`] and [`Nonce`] that were
1033910351
/// created via [`Self::create_async_receive_offer_builder`]. If `relative_expiry` is unset, the
1034010352
/// invoice's expiry will default to [`STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY`].
10353+
///
10354+
/// Instead of using this method to manually build the invoice, it is preferable to set
10355+
/// [`UserConfig::paths_to_static_invoice_server`] and retrieve the automatically built offer via
10356+
/// [`Self::get_cached_async_receive_offers`].
1034110357
#[cfg(async_payments)]
1034210358
pub fn create_static_invoice_builder<'a>(
1034310359
&'a self, offer: &'a Offer, offer_nonce: Nonce, relative_expiry: Option<Duration>

lightning/src/offers/async_receive_offer_cache.rs

+20
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,26 @@ impl AsyncReceiveOfferCache {
9292
// invoice before giving up.
9393
const MAX_UPDATE_ATTEMPTS: u8 = 3;
9494

95+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
96+
pub fn offers(&self, duration_since_epoch: Duration) -> Vec<Offer> {
97+
const NEVER_EXPIRES: Duration = Duration::from_secs(u64::MAX);
98+
99+
self.offers
100+
.iter()
101+
.filter_map(|offer| {
102+
if offer.static_invoice_absolute_expiry < duration_since_epoch {
103+
None
104+
} else if offer.offer.absolute_expiry().unwrap_or(NEVER_EXPIRES)
105+
< duration_since_epoch
106+
{
107+
None
108+
} else {
109+
Some(offer.offer.clone())
110+
}
111+
})
112+
.collect()
113+
}
114+
95115
// Checks whether we should request new offer paths from the always-online static invoice server.
96116
// Will also remove any expired offers.
97117
pub(super) fn should_request_offer_paths(&mut self, duration_since_epoch: Duration) -> bool {

lightning/src/offers/flow.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,14 @@ where
10801080
core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap())
10811081
}
10821082

1083+
/// Retrieve our cached [`Offer`]s for receiving async payments as an often-offline recipient.
1084+
/// Will only be set if [`UserConfig::paths_to_static_invoice_server`] is set and we succeeded in
1085+
/// interactively building a [`StaticInvoice`] with the static invoice server.
1086+
#[cfg(async_payments)]
1087+
pub(crate) fn get_cached_async_receive_offers(&self) -> Vec<Offer> {
1088+
self.async_receive_offer_cache.lock().unwrap().offers(self.duration_since_epoch())
1089+
}
1090+
10831091
/// Sends out [`OfferPathsRequest`] and [`ServeStaticInvoice`] onion messages if we are an
10841092
/// often-offline recipient and are configured to interactively build offers and static invoices
10851093
/// with a static invoice server.

0 commit comments

Comments
 (0)