aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-18 07:37:04 -0700
committerAdam Soltys <[email protected]>2026-06-18 08:27:11 -0700
commit290acb73beff82762572d6eb69c6297bf7d88af7 (patch)
tree44840ef972b886b5809287e161be7a7f7f530f0a /lib
parent497277ef7b48c86aa2f44b613e0a35a0c3b0c238 (diff)
downloadcoinos-server-290acb73beff82762572d6eb69c6297bf7d88af7.tar.gz
coinos-server-290acb73beff82762572d6eb69c6297bf7d88af7.zip
invoices: don't re-list an invoice id on update (dedupe :invoices)
generate() unconditionally lPush'd the invoice id to `${aid}:invoices`, but it's also called from the update() handler (tip/webhook changes, and repeated bolt12 offer creation) re-using the existing id — so each update re-appended the same id and the user's :invoices accumulated duplicate entries, rendering the same offer/invoice multiple times. Only push when the id isn't already in the list (LPOS guard). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'lib')
-rw-r--r--lib/invoices.ts8
1 files changed, 7 insertions, 1 deletions
diff --git a/lib/invoices.ts b/lib/invoices.ts
index ad0b604e..79bf6f19 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -159,7 +159,13 @@ export const generate = async ({ invoice, user }) => {
await s(`invoice:${hash}`, id);
await s(`invoice:${id}`, invoice);
- await db.lPush(`${aid}:invoices`, id);
+ // generate() is also called on UPDATE (re-using an existing invoice id, e.g.
+ // a tip/webhook change or a repeated bolt12 offer create), which must NOT
+ // re-append the id to the list. Only add it the first time — otherwise the
+ // user's :invoices accumulates duplicate entries and the same offer/invoice
+ // renders multiple times (see kaliyi's OCEAN offer, listed 2-6x).
+ if ((await db.lPos(`${aid}:invoices`, id)) === null)
+ await db.lPush(`${aid}:invoices`, id);
if (request_id) {
const request = await g(`request:${request_id}`);