aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-18 07:43:48 -0700
committerAdam Soltys <[email protected]>2026-06-18 07:43:48 -0700
commit64691693e7ff40aae59b05a234f88025757959e3 (patch)
tree842bf72560b118f2d059be2814b113b35b6f3da3 /lib
parent0a1450ada9c20499fa86a619ee36176f717d5414 (diff)
downloadcoinos-server-staging.tar.gz
coinos-server-staging.zip
invoices: don't re-list an invoice id on update (dedupe :invoices)staging
Port of the master fix (2d2f9856) + cleanup script to staging. generate() unconditionally lPush'd the invoice id to `${aid}:invoices`, but it's also called from update() (tip/webhook changes, 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. Guard the push with LPOS so it only adds the id the first time. Also add scripts/dedup-invoices.ts to scrub already-accumulated dupes (dry-run by default, --apply to write, idempotent). 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 c5194ce3..27e25c48 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -202,7 +202,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}`);