aboutsummaryrefslogtreecommitdiffstats
path: root/routes
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-02 12:54:10 -0700
committerAdam Soltys <[email protected]>2026-11-02 12:54:10 -0700
commit8fbc6ea19c9f4959799f3d72b32e2b8661596ea8 (patch)
treeea26d3daa86be2ea647e9ef86a2090099b5629fa /routes
parent9c7d26e0312b7e133801fe9a512e31908c2b29da (diff)
downloadcoinos-server-8fbc6ea19c9f4959799f3d72b32e2b8661596ea8.tar.gz
coinos-server-8fbc6ea19c9f4959799f3d72b32e2b8661596ea8.zip
payments: credit each on-chain output once and require uuid invoice ids
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6VN9xvnX1cgvV6hrUV
Diffstat (limited to 'routes')
-rw-r--r--routes/payments.ts12
1 files changed, 12 insertions, 0 deletions
diff --git a/routes/payments.ts b/routes/payments.ts
index 66fd3386..cfb34af7 100644
--- a/routes/payments.ts
+++ b/routes/payments.ts
@@ -616,6 +616,18 @@ export default {
const p = await getPayment(`${txid}:${vout}`);
+ // A pointer whose payment record is gone (account deleted, record
+ // overwritten) means this output was already credited once. Never
+ // treat it as a first sighting.
+ if (
+ !p &&
+ ((await db.exists(`payment:${txid}:${vout}`)) ||
+ (await db.exists(`credited:${txid}:${vout}`)))
+ ) {
+ warn("blocked re-credit of seen output", txid, vout, sats(amount), address);
+ continue;
+ }
+
if (!p) {
const invoice = await getInvoice(address);
if (!hot && aid !== invoice?.aid) continue;