diff options
| author | Adam Soltys <[email protected]> | 2026-09-27 14:48:24 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-27 14:48:24 -0700 |
| commit | b1e175c1faa46ed67cf0575f8d8808f1ae10892c (patch) | |
| tree | 4672affbc88789b4f5d17e5d92ffca8db49248b0 | |
| parent | 0912f443cc738af7dd7093670f00420de72a095f (diff) | |
| download | coinos-server-b1e175c1faa46ed67cf0575f8d8808f1ae10892c.tar.gz coinos-server-b1e175c1faa46ed67cf0575f8d8808f1ae10892c.zip | |
ecash: drop anonymous token storage in favour of a stateless status lookup
POST /cash stored any submitted string under a fresh id with no auth, no
validation and no expiry. Replace it with POST /ecash/status, which checks a
token the client already holds and returns its total, spent amount and mint.
GET /cash/:id/:version stays so previously shared ids keep resolving.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
| -rw-r--r-- | index.ts | 2 | ||||
| -rw-r--r-- | routes/ecash.ts | 14 |
2 files changed, 9 insertions, 7 deletions
@@ -198,7 +198,7 @@ app.post("/shopify/:id", shopify); app.get("/bolt12", fixBolt12); app.get("/cash/:id/:version", ecash.get); -app.post("/cash", ecash.save); +app.post("/ecash/status", ecash.status); app.post("/claim", auth, ecash.claim); app.post("/ecash/:id", ecash.receive); diff --git a/routes/ecash.ts b/routes/ecash.ts index d089ed15..995a8dce 100644 --- a/routes/ecash.ts +++ b/routes/ecash.ts @@ -1,19 +1,21 @@ -import { s } from "$lib/db"; import { check, get, redeem } from "$lib/ecash"; import { err } from "$lib/logging"; import { bail, fail, getInvoice, getUser } from "$lib/utils"; import { getEncodedToken } from "@cashu/cashu-ts"; -import { v4 } from "uuid"; export default { - async save(req, res) { + // Stateless status lookup for a token the client is holding. This replaced + // an unauthenticated POST that stored any submitted string under a fresh id + // forever (thousands of forged and foreign tokens accumulated); `get` below + // still serves the ids that were handed out while it existed. + async status(req, res) { const { body: { token }, } = req; try { - const id = v4(); - await s(`cash:${id}`, token); - res.send({ id }); + if (typeof token !== "string" || !token.startsWith("cashu")) + fail("Invalid token"); + res.send(await check(token)); } catch (e) { err(e.message); bail(res, e.message); |
