aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-01-22 18:48:07 -0800
committerAdam Soltys <[email protected]>2026-01-22 18:48:07 -0800
commitd147e04d1b52f1359507a6f9d88e0227cf6bb250 (patch)
tree2eb562735a335831cec4737610f9638aaf50f32f
parent0edd59be4bbfc62f73b972e4992ec3c31d6baab1 (diff)
downloadcoinos-server-d147e04d1b52f1359507a6f9d88e0227cf6bb250.tar.gz
coinos-server-d147e04d1b52f1359507a6f9d88e0227cf6bb250.zip
read payments from archive
-rw-r--r--lib/db.ts37
-rw-r--r--lib/utils.ts10
-rw-r--r--routes/payments.ts23
-rw-r--r--routes/users.ts12
4 files changed, 66 insertions, 16 deletions
diff --git a/lib/db.ts b/lib/db.ts
index 56921adb..12e89757 100644
--- a/lib/db.ts
+++ b/lib/db.ts
@@ -152,6 +152,43 @@ export const sa = (k, v) => {
archive.set(k, JSON.stringify(v));
};
+// Get with fallback to archive
+export const gf = async (k) => {
+ let v = await db.get(k);
+ if (v === null) v = await archive.get(k);
+ try {
+ return JSON.parse(v);
+ } catch (e) {
+ return v;
+ }
+};
+
+// lRange with fallback to archive for missing items
+export const lRangeWithArchive = async (k, start, end) => {
+ const items = await db.lRange(k, start, end);
+ return items || [];
+};
+
+// Get payment/invoice with archive fallback - for individual lookups
+export const getWithArchive = async (prefix, id) => {
+ let v = await db.get(`${prefix}:${id}`);
+ if (v === null) v = await archive.get(`${prefix}:${id}`);
+ if (v === null) return null;
+ try {
+ const parsed = JSON.parse(v);
+ // If it's a reference to another key, follow it
+ if (typeof parsed === "string") {
+ let ref = await db.get(`${prefix}:${parsed}`);
+ if (ref === null) ref = await archive.get(`${prefix}:${parsed}`);
+ if (ref === null) return null;
+ return JSON.parse(ref);
+ }
+ return parsed;
+ } catch (e) {
+ return v;
+ }
+};
+
const retries = {};
export const t = async (k, f) => {
try {
diff --git a/lib/utils.ts b/lib/utils.ts
index 018dc92e..add09782 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -1,5 +1,5 @@
import config from "$config";
-import { g } from "$lib/db";
+import { g, gf } from "$lib/db";
import locales from "$lib/locales/index";
const { URL } = process.env;
@@ -57,15 +57,15 @@ export const getUser = async (username, fields = undefined) => {
};
export const getInvoice = async (hash) => {
- let iid = await g(`invoice:${hash}`);
+ let iid = await gf(`invoice:${hash}`);
if (iid?.id) iid = iid.id;
else if (iid?.hash) iid = iid.hash;
- return await g(`invoice:${iid}`);
+ return await gf(`invoice:${iid}`);
};
export const getPayment = async (id) => {
- let p = await g(`payment:${id}`);
- if (typeof p === "string") p = await g(`payment:${p}`);
+ let p = await gf(`payment:${id}`);
+ if (typeof p === "string") p = await gf(`payment:${p}`);
return p;
};
diff --git a/routes/payments.ts b/routes/payments.ts
index d4d83bd2..a61c4c3c 100644
--- a/routes/payments.ts
+++ b/routes/payments.ts
@@ -1,7 +1,7 @@
import config from "$config";
import api from "$lib/api";
import { requirePin } from "$lib/auth";
-import { db, g, s } from "$lib/db";
+import { archive, db, g, gf, s } from "$lib/db";
import { generate } from "$lib/invoices";
import { replay } from "$lib/lightning";
import ln from "$lib/ln";
@@ -112,15 +112,28 @@ export default {
offset = Number.parseInt(offset) || 0;
const range = !limit || received || start || end ? -1 : limit - 1;
- let payments = (await db.lRange(`${aid || id}:payments`, 0, range)) || [];
+ const listKey = `${aid || id}:payments`;
+ let payments = (await db.lRange(listKey, 0, range)) || [];
+
+ if (range === -1) {
+ const archived = (await archive.lRange(listKey, 0, -1)) || [];
+ payments = [...new Set([...payments, ...archived])];
+ } else if (limit) {
+ const needed = Math.max(0, limit + offset - payments.length);
+ if (needed > 0) {
+ const archived =
+ (await archive.lRange(listKey, 0, limit + offset - 1)) || [];
+ payments = [...new Set([...payments, ...archived])];
+ }
+ }
payments = (
await Promise.all(
payments.map(async (pid) => {
- const p = await g(`payment:${pid}`);
+ const p = await gf(`payment:${pid}`);
if (!p) {
warn("user", id, "missing payment", pid);
- await db.lRem(`${aid || id}:payments`, 0, pid);
+ await db.lRem(listKey, 0, pid);
return p;
}
if (received && p.amount < 0) return;
@@ -237,7 +250,7 @@ export default {
if (typeof amount === "undefined" || amount === null)
return bail(res, "fund not found");
let payments = (await db.lRange(`fund:${id}:payments`, 0, -1)) || [];
- payments = await Promise.all(payments.map((hash) => g(`payment:${hash}`)));
+ payments = await Promise.all(payments.map((hash) => gf(`payment:${hash}`)));
await Promise.all(
payments.map(async (p: any) => (p.user = await getUser(p.uid, fields))),
diff --git a/routes/users.ts b/routes/users.ts
index 91928503..8cb24870 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -2,7 +2,7 @@ import { createReadStream } from "node:fs";
import { appendFile, unlink, writeFile } from "node:fs/promises";
import config from "$config";
import { requirePin } from "$lib/auth";
-import { db, g, ga, s } from "$lib/db";
+import { db, g, ga, gf, s } from "$lib/db";
import { err, l, warn } from "$lib/logging";
import { mail, templates } from "$lib/mail";
import { getNostrUser, getProfile, serverPubkey2 } from "$lib/nostr";
@@ -109,7 +109,7 @@ export default {
let total = 0;
for (const pid of payments) {
- const p = await g(`payment:${pid}`);
+ const p = await gf(`payment:${pid}`);
if (!p) continue;
total += p.amount;
if (p.amount < 0)
@@ -571,7 +571,7 @@ export default {
for (const { ref } of (
await Promise.all(
- payments.reverse().map(async (id) => await g(`payment:${id}`)),
+ payments.reverse().map(async (id) => await gf(`payment:${id}`)),
)
).filter((p) => p && p.type === PaymentType.internal && p.ref)) {
if (ref === id) continue;
@@ -950,8 +950,8 @@ export default {
const payments = await Promise.all(
pids.map(async (pid) => {
- const p = await g(`payment:${pid}`);
- p.user = await g(`user:${p.uid}`);
+ const p = await gf(`payment:${pid}`);
+ if (p) p.user = await g(`user:${p.uid}`);
return p;
}),
);
@@ -976,7 +976,7 @@ export default {
const pids = await db.lRange(`${a.pubkey}:payments`, 0, -1);
let payments = await Promise.all(
- pids.map((pid) => g(`payment:${pid}`)),
+ pids.map((pid) => gf(`payment:${pid}`)),
);
payments = payments.filter((p) => p);
a.spent = payments.reduce(