From 193457c5bd6c7c892c3be50674579dabd07fd2f2 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 23 Aug 2024 23:39:05 -0700 Subject: use redis to store rates --- index.js | 4 ++-- lib/ecash.js | 31 ++++++++++++++++++++++++------- lib/invoices.js | 3 ++- lib/payments.js | 31 ++++++++++++------------------- lib/rates.js | 23 ++++++++++++----------- routes/ecash.js | 12 ++++++++---- routes/payments.js | 10 +++++----- routes/rates.js | 6 +++--- 8 files changed, 68 insertions(+), 52 deletions(-) diff --git a/index.js b/index.js index 6b47fce8..5d1a4ebd 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ import { fillPool } from "$lib/nostr"; import { listenForLightning } from "$lib/lightning"; import { getLocations } from "$lib/locations"; import { catchUp } from "$lib/payments"; -import { getRates } from "$lib/rates"; +import { getFx } from "$lib/rates"; import { sendHeartbeat } from "$lib/sockets"; import { err } from "$lib/logging"; @@ -26,7 +26,7 @@ import shopify from "$routes/shopify"; try { fillPool(); getLocations(); - getRates(); + getFx(); catchUp(); } catch (e) { console.log(e); diff --git a/lib/ecash.js b/lib/ecash.js index df7759bf..8741cff1 100644 --- a/lib/ecash.js +++ b/lib/ecash.js @@ -7,8 +7,11 @@ import { MintQuoteState, } from "@cashu/cashu-ts"; import { g, s } from "$lib/db"; +import ln from "$lib/ln"; +import { fail } from "$lib/utils"; -let wallet = new CashuWallet(new CashuMint(config.mintUrl)); +let m = new CashuMint(config.mintUrl); +let w = new CashuWallet(m); let enc = (proofs) => getEncodedToken({ @@ -17,9 +20,21 @@ let enc = (proofs) => let dec = (token) => getDecodedToken(token).token[0]; +let ext = async (mint) => { + let issuer = new CashuMint(mint); + let { pubkey: issuerPk } = await issuer.getInfo(); + let { pubkey: ourPk } = await m.getInfo(); + console.log(issuerPk, ourPk); + return issuerPk !== ourPk; +}; + export async function claim(token) { let { proofs: current } = dec(await g(`cash`)); - let rcvd = await wallet.receive(token); + let { mint } = dec(token); + + if (await ext(mint)) fail("Unable to receive from other mints"); + + let rcvd = await w.receive(token); await s(`cash`, enc([...current, ...rcvd])); return rcvd.reduce((a, b) => a + b.amount, 0); @@ -27,18 +42,20 @@ export async function claim(token) { export async function mint(amount) { let { proofs } = dec(await g(`cash`)); - let { send, returnChange } = await wallet.send(amount, proofs); - let rcvd = await wallet.receive(enc(send)); + let { send, returnChange } = await w.send(amount, proofs); + let rcvd = await w.receive(enc(send)); await s(`cash`, enc(returnChange)); return enc(rcvd); } export async function check(token) { - let { proofs } = dec(token); + let { mint, proofs } = dec(token); let total = proofs.reduce((a, b) => a + b.amount, 0); - let r = await wallet.checkProofsSpent(proofs); + let external = await ext(mint); + + let r = await w.checkProofsSpent(proofs); let spent = r.reduce((a, b) => a + b.amount, 0); - return { total, spent }; + return { total, spent, mint, external }; } diff --git a/lib/invoices.js b/lib/invoices.js index 557d0de6..2f1225e7 100644 --- a/lib/invoices.js +++ b/lib/invoices.js @@ -37,8 +37,9 @@ export let generate = async ({ invoice, user, sender }) => { else if (sender) user = await getUser(sender.username); if (!user) fail("user not provided"); + let rates = await g('rates'); if (!currency) currency = user.currency; - if (!rate) rate = store.rates[currency]; + if (!rate) rate = rates[currency]; if (fiat) amount = Math.round((SATS * fiat) / rate); if (amount < 0) fail("invalid amount"); if (tip < 0) fail("invalid tip"); diff --git a/lib/payments.js b/lib/payments.js index 264a2417..92e17839 100644 --- a/lib/payments.js +++ b/lib/payments.js @@ -1,6 +1,5 @@ import locales from "$lib/locales/index"; import config from "$config"; -import store from "$lib/store"; import { emit } from "$lib/sockets"; import { v4 } from "uuid"; import { notify } from "$lib/notifications"; @@ -49,13 +48,16 @@ export let debit = async ({ type = types.internal, rate, }) => { + amount = parseInt(amount); if (type !== types.internal && (await g("freeze"))) fail("Problem sending payment"); // if (!user.unlimited && amount > 1000000) // fail(`⚡️${amount} exceeds max withdrawal of ⚡️1,000,000`); let ref; let { id: uid, currency, username } = user; - if (!rate) rate = store.rates[currency]; + + let rates = await g('rates'); + if (!rate) rate = rates[currency]; let invoice = await getInvoice(hash); let iid; @@ -67,9 +69,9 @@ export let debit = async ({ ref = invoice.uid; let equivalentRate = - invoice.rate * (store.rates[currency] / store.rates[invoice.currency]); + invoice.rate * (rates[currency] / rates[invoice.currency]); - if (Math.abs(invoice.rate / store.rates[invoice.currency] - 1) < 0.01) { + if (Math.abs(invoice.rate / rates[invoice.currency] - 1) < 0.01) { rate = equivalentRate; } else { warn("rate slipped", hash, invoice.rate, equivalentRate); @@ -120,7 +122,7 @@ export let debit = async ({ await db.lPush(`${uid}:payments`, id); l(user.username, "sent", type, amount); - emit(user.id, "payment", p); + //emit(user.id, "payment", p); return p; }; @@ -145,15 +147,16 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => { let user = await g(`user:${inv.uid}`); let { id: uid, currency, username } = user; - let rate = store.rates[currency]; + let rates = await g('rates'); + let rate = rates[currency]; if (!rate) await sleep(1000); - rate = store.rates[currency]; + rate = rates[currency]; let equivalentRate = - inv.rate * (store.rates[currency] / store.rates[inv.currency]); + inv.rate * (rates[currency] / rates[inv.currency]); - if (Math.abs(inv.rate / store.rates[inv.currency] - 1) < 0.01) { + if (Math.abs(inv.rate / rates[inv.currency] - 1) < 0.01) { rate = equivalentRate; } else { // warn("rate slipped", hash, invoice.rate, equivalentRate); @@ -208,16 +211,6 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => { callWebhook(inv, p); l(username, "received", type, amount); - // let items = ""; - // for (let i of inv.items) { - // items += `${i.quantity} ${i.name} ${f( - // i.price * i.quantity, - // inv.currency, - // )}\n`; - // } - // - // console.log(items); - let items; if (inv.items && inv.items.length) { formatReceipt(inv.items, inv.currency); diff --git a/lib/rates.js b/lib/rates.js index 1172d202..fe942453 100644 --- a/lib/rates.js +++ b/lib/rates.js @@ -17,12 +17,16 @@ let connect = async () => { ws.onmessage = async function (event) { try { let msg = JSON.parse(event.data); + let rates = await g("rates"); + let fx = await g("fx"); + if (fx) ({ fx } = fx); - Object.keys(store.fx).map((symbol) => { - store.rates[symbol] = msg.c * store.fx[symbol]; + Object.keys(fx).map((symbol) => { + rates[symbol] = msg.c * fx[symbol]; }); - store.last = msg.c; + s("rate", msg.c); + s("rates", rates); last = Date.now(); } catch (e) { console.log(e); @@ -37,13 +41,12 @@ let connect = async () => { return ws; }; -export let getRates = async () => { +export let getFx = async () => { connect(); let date = 0, - fx = {}; - let rates = await g("rates"); - if (rates) ({ date, fx } = rates); + fx = await g("fx"); + if (fx) ({ date, fx } = fx); if (Date.now() - date > 24 * 60 * 60 * 1000) { date = Date.now(); @@ -58,13 +61,11 @@ export let getRates = async () => { fx[k] = fx[k] / USD; }); - await s("rates", { date, fx }); + await s("fx", { date, fx }); } catch (e) { err("error fetching rates", e.message); } } - store.fx = fx; - - setTimeout(getRates, 30000); + setTimeout(getFx, 30000); }; diff --git a/routes/ecash.js b/routes/ecash.js index d7a9fe7b..8c2684b1 100644 --- a/routes/ecash.js +++ b/routes/ecash.js @@ -16,7 +16,7 @@ export default { await s(`cash:${id}`, token); res.send({ id }); } catch (e) { - console.log(e) + err(e.message); bail(res, e.message); } }, @@ -27,6 +27,7 @@ export default { let status = await check(token); res.send({ token, status }); } catch (e) { + err(e.message); bail(res, e.message); } }, @@ -38,11 +39,12 @@ export default { let memo; let hash = v4(); let { currency, id: uid } = user; + let rates = await g("rates"); await s(`invoice:${hash}`, { currency, id: hash, hash, - rate: store.rates[currency], + rate: rates[currency], uid, received: 0, }); @@ -51,7 +53,7 @@ export default { res.send({ ok: true }); } catch (e) { - console.log(e); + err(e.message); bail(res, e.message); } }, @@ -69,6 +71,7 @@ export default { res.send({ id }); } catch (e) { + err(e.message); bail(res, e.message); } }, @@ -89,7 +92,8 @@ export default { 0, ); - let rate = store.rates[currency]; + let rates = await g("rates"); + let rate = rates[currency]; if (ourfee.err) fail(ourfee.err); diff --git a/routes/payments.js b/routes/payments.js index 0a40317c..df479d19 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -1,5 +1,4 @@ import config from "$config"; -import store from "$lib/store"; import { emit } from "$lib/sockets"; import { v4 } from "uuid"; import { db, g, s, t } from "$lib/db"; @@ -139,11 +138,11 @@ export default { async parse({ body: { payreq }, user }, res) { try { let hour = 1000 * 60 * 60; - let { last } = store.nodes; - let { nodes } = store; + let nodes = await g("nodes"); + let { last } = nodes; if (!last || last > Date.now() - hour) ({ nodes } = await ln.listnodes()); - store.nodes = nodes; + await s("nodes", nodes); let twoWeeksAgo = new Date(new Date().setDate(new Date().getDate() - 14)); let decoded = await ln.decodepay(payreq); @@ -202,12 +201,13 @@ export default { if (!iid) { iid = v4(); + let rates = await g("rates"); let { currency } = user; await s(`invoice:${iid}`, { currency, id: iid, hash: iid, - rate: store.rates[currency], + rate: rates[currency], uid: user.id, received: 0, }); diff --git a/routes/rates.js b/routes/rates.js index 08b604bb..828e5b2c 100644 --- a/routes/rates.js +++ b/routes/rates.js @@ -1,11 +1,11 @@ -import store from "$lib/store"; +import { g } from "$lib/db"; export default { async last(req, res) { - res.send(store.last); + res.send(await g('rate')); }, async index(req, res) { - res.send(store.rates); + res.send(await g('rates')); }, }; -- cgit v1.2.3