diff options
Diffstat (limited to 'routes/ecash.ts')
| -rw-r--r-- | routes/ecash.ts | 143 |
1 files changed, 20 insertions, 123 deletions
diff --git a/routes/ecash.ts b/routes/ecash.ts index 4a1806a3..d089ed15 100644 --- a/routes/ecash.ts +++ b/routes/ecash.ts @@ -1,31 +1,10 @@ -import { db, g, s } from "$lib/db"; -import { check, claim, get, mint } from "$lib/ecash"; -import { err, l } from "$lib/logging"; -import { credit, debit } from "$lib/payments"; -import { emit } from "$lib/sockets"; -import { bail, fail, getInvoice } from "$lib/utils"; +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"; -import { PaymentType } from "$lib/types"; -const { ecash: type } = PaymentType; - -Error.stackTraceLimit = 100; // Set this to the desired limit - -const sendCash = async ({ amount, user }) => { - const id = v4(); - const hash = v4(); - - const p = await debit({ hash, amount, user, type }); - const token = await mint(parseInt(amount)); - p.memo = id; - const { id: pid } = p; - await s(`payment:${pid}`, p); - s(`cash:${id}`, token); - - return { id, token, pid }; -}; - export default { async save(req, res) { const { @@ -47,6 +26,7 @@ export default { } = req; try { const token = await get(id); + if (!token) fail("Ecash not found"); const status = await check(token); res.send({ token, status }); } catch (e) { @@ -61,114 +41,31 @@ export default { user, } = req; try { - const amount = await claim(token); - - let memo; - const hash = v4(); - const { currency, id: uid } = user; - const rates = await g("rates"); - await s(`invoice:${hash}`, { - currency, - id: hash, - hash, - rate: rates[currency], - uid, - received: 0, - }); - - await credit({ hash, amount, memo, ref: user.id, type }); - - res.send({ ok: true }); + const amount = await redeem({ token, user }); + res.send({ ok: true, amount }); } catch (e) { err(e.message); bail(res, e.message); } }, - async mint(req, res) { - const { body, user } = req; - const amount = parseInt(body.amount); - fail("disabled"); - res.send(await sendCash({ amount, user })); - }, - - async melt(req, res) { - let { - body: { amount, bolt11: hash, preimage }, - user, - } = req; - try { - const ref = preimage; - const { lightning: type } = PaymentType; - if (user.username !== "mint") fail("unauthorized"); - - amount = Math.round(amount / 1000); - // A negative (or NaN) amount here is a direct ledger-inflation primitive: - // db.debit subtracts it, so -N ADDS N to the balance, and the stored - // record gets amount: -(-N). The caller gate above limits this to the - // mint service account, but that account is not a trust boundary we want - // the ledger's integrity resting on — mirror the check debit() makes in - // lib/payments.ts before any balance write. - if (!Number.isFinite(amount) || amount <= 0) - fail("Amount must be greater than zero"); - const { id: uid, currency } = user; - const ourfee = await db.debit( - `balance:${uid}`, - `credit:${type}:${uid}`, - "Insufficient funds", - amount || 0, - 0, - 0, - 0, - 0 - ); - - const rates = await g("rates"); - const rate = rates[currency]; - - if (ourfee.err) fail(ourfee.err); - - const id = v4(); - const p = { - id, - amount: -amount, - hash, - ourfee, - uid, - confirmed: true, - rate, - currency, - type, - ref, - created: Date.now(), - }; - - await s(`payment:${hash}`, id); - await s(`payment:${id}`, p); - await db.lPush(`${uid}:payments`, id); - - l(user.username, "sent", type, amount); - emit(user.id, "payment", p); - - res.send(p); - } catch (e) { - bail(res, e.message); - } - }, - + // NUT-18 payment-request transport: a wallet POSTs proofs for one of our + // ecash-type invoices, which are melted into a Lightning invoice for the + // invoice's owner under the same id. async receive(req, res) { try { const { id, proofs, mint, memo } = req.body; - const { uid: ref } = await getInvoice(id); - - const amount = await claim( - getEncodedToken({ - mint, - proofs, - }), - ); + const invoice = await getInvoice(id); + if (!invoice) fail("Invoice not found"); + const user = await getUser(invoice.uid); + if (!user) fail("User not found"); - await credit({ hash: id, amount, memo, ref, type }); + await redeem({ + token: getEncodedToken({ mint, proofs }), + user, + invoice, + memo, + }); res.send({ id }); } catch (e) { |
