diff options
| author | Adam Soltys <[email protected]> | 2026-06-18 07:37:04 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-18 08:27:11 -0700 |
| commit | 290acb73beff82762572d6eb69c6297bf7d88af7 (patch) | |
| tree | 44840ef972b886b5809287e161be7a7f7f530f0a | |
| parent | 497277ef7b48c86aa2f44b613e0a35a0c3b0c238 (diff) | |
| download | coinos-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]>
| -rw-r--r-- | lib/invoices.ts | 8 |
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}`); |
