aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-08 23:16:37 -0700
committerAdam Soltys <[email protected]>2026-10-08 23:16:37 -0700
commit0cbfab4779545afcc621d019ec93b30e5aec99df (patch)
tree3c2999f4c27ea6a5447d5a44c2328acb4f395fc2
parent5df9bc39ac48fdf1b19b00b9b457f9ebc1ee157c (diff)
downloadcoinos-server-0cbfab4779545afcc621d019ec93b30e5aec99df.tar.gz
coinos-server-0cbfab4779545afcc621d019ec93b30e5aec99df.zip
bolt12: put the requested expiry and single-use on the offer itself
The expiry was only stored on our invoice record, so CLN kept issuing invoices for the offer after it had expired. Pass it as absolute_expiry, and accept single_use to cap an offer at one payment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--lib/invoices.ts9
1 files changed, 9 insertions, 0 deletions
diff --git a/lib/invoices.ts b/lib/invoices.ts
index c4e6a131..0028dc91 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -44,6 +44,7 @@ export const generate = async ({ invoice, user }) => {
memo,
memoPrompt,
prompt,
+ single_use,
type = PaymentType.lightning,
usePreimage,
webhook,
@@ -195,10 +196,18 @@ export const generate = async ({ invoice, user }) => {
if (bolt12) fail("Cannot provide your own bolt12 invoice");
let r;
{
+ // The offer itself has to carry the expiry: CLN keeps answering
+ // invoice requests for an offer until its absolute_expiry, so an
+ // expiry only stored on our invoice record was never enforced.
+ expiry = Number.parseInt(expiry) || undefined;
r = await ln.offer({
amount: amount ? `${amount + tip}sat` : "any",
label: `${id} ${user.username} ${new Date()}`,
description: memo || id,
+ absolute_expiry: expiry
+ ? Math.floor(Date.now() / 1000) + expiry
+ : undefined,
+ single_use: !!single_use || undefined,
});
// CLN returns the same offer_id for identical offer contents, so a