aboutsummaryrefslogtreecommitdiffstats
path: root/routes
diff options
context:
space:
mode:
authorDedan Kibere <[email protected]>2024-10-27 23:05:49 +0300
committerGitHub <[email protected]>2024-10-27 23:05:49 +0300
commit87059fe805d3372263d26b391f8855139f84ad34 (patch)
tree7099fbce72e7614c0c689d2f9a62e69f8b2e621a /routes
parent041db323e4c23d87663bc29519af604137f3eb42 (diff)
parentd09712ef8f8ea8218ce229b233fc0013e6c06f7a (diff)
downloadcoinos-server-87059fe805d3372263d26b391f8855139f84ad34.tar.gz
coinos-server-87059fe805d3372263d26b391f8855139f84ad34.zip
Merge branch 'coinos:master' into master
Diffstat (limited to 'routes')
-rw-r--r--routes/ecash.ts61
-rw-r--r--routes/invoices.ts6
-rw-r--r--routes/payments.ts188
-rw-r--r--routes/users.ts48
4 files changed, 157 insertions, 146 deletions
diff --git a/routes/ecash.ts b/routes/ecash.ts
index 48b03fd3..cc617138 100644
--- a/routes/ecash.ts
+++ b/routes/ecash.ts
@@ -1,20 +1,20 @@
-import { g, s, db } from "$lib/db";
-import { get, claim, mint, check } from "$lib/ecash";
+import { db, g, s } from "$lib/db";
+import { check, claim, get, mint } from "$lib/ecash";
+import { err, l } from "$lib/logging";
+import { credit, debit, types } from "$lib/payments";
+import { emit } from "$lib/sockets";
import { bail, fail } from "$lib/utils";
-import { debit, credit, types } from "$lib/payments";
import { v4 } from "uuid";
-import { l, err } from "$lib/logging";
-import { emit } from "$lib/sockets";
-let { ecash: type } = types;
+const { ecash: type } = types;
export default {
async save(req, res) {
- let {
+ const {
body: { token },
} = req;
try {
- let id = v4();
+ const id = v4();
await s(`cash:${id}`, token);
res.send({ id });
} catch (e) {
@@ -24,12 +24,12 @@ export default {
},
async get(req, res) {
- let {
+ const {
params: { id, version },
} = req;
try {
- let token = await get(id, version);
- let status = await check(token);
+ const token = await get(id, version);
+ const status = await check(token);
res.send({ token, status });
} catch (e) {
err(e.message);
@@ -38,17 +38,17 @@ export default {
},
async claim(req, res) {
- let {
+ const {
body: { token },
user,
} = req;
try {
- let amount = await claim(token);
+ const amount = await claim(token);
let memo;
- let hash = v4();
- let { currency, id: uid } = user;
- let rates = await g("rates");
+ const hash = v4();
+ const { currency, id: uid } = user;
+ const rates = await g("rates");
await s(`invoice:${hash}`, {
currency,
id: hash,
@@ -68,18 +68,17 @@ export default {
},
async mint(req, res) {
- let {
+ const {
body: { amount },
user,
} = req;
try {
- let id = v4();
- let hash = v4();
+ const id = v4();
+ const hash = v4();
- let memo, rate;
- let p = await debit({ hash, amount, user, type, memo, rate });
- let token = await mint(amount);
- p.memo = token;
+ const p = await debit({ hash, amount, user, type });
+ const token = await mint(amount);
+ p.memo = id;
await s(`payment:${p.id}`, p);
s(`cash:${id}`, token);
@@ -97,11 +96,11 @@ export default {
} = req;
try {
amount = Math.round(amount / 1000);
- let ref = preimage;
- let { lightning: type } = types;
+ const ref = preimage;
+ const { lightning: type } = types;
if (user.username !== "mint") fail("unauthorized");
- let { id: uid, currency } = user;
- let ourfee = await db.debit(
+ const { id: uid, currency } = user;
+ const ourfee = await db.debit(
`balance:${uid}`,
`credit:${type}:${uid}`,
amount || 0,
@@ -110,13 +109,13 @@ export default {
0,
);
- let rates = await g("rates");
- let rate = rates[currency];
+ const rates = await g("rates");
+ const rate = rates[currency];
if (ourfee.err) fail(ourfee.err);
- let id = v4();
- let p = {
+ const id = v4();
+ const p = {
id,
amount: -amount,
hash,
diff --git a/routes/invoices.ts b/routes/invoices.ts
index acad5ce7..c571f4de 100644
--- a/routes/invoices.ts
+++ b/routes/invoices.ts
@@ -1,11 +1,11 @@
import { g } from "$lib/db";
import { generate } from "$lib/invoices";
-import { bail, pick } from "$lib/utils";
import { err } from "$lib/logging";
+import { bail, pick } from "$lib/utils";
export default {
async get(req, res) {
- let {
+ const {
params: { id },
} = req;
let invoice = await g(`invoice:${id}`);
@@ -31,7 +31,7 @@ export default {
async create(req, res) {
let { body, user } = req;
if (body.user) user = body.user;
- let { invoice } = body;
+ const { invoice } = body;
try {
res.send(await generate({ invoice, user }));
diff --git a/routes/payments.ts b/routes/payments.ts
index 33f66e8d..4573ac4f 100644
--- a/routes/payments.ts
+++ b/routes/payments.ts
@@ -1,33 +1,33 @@
import config from "$config";
-import { emit } from "$lib/sockets";
-import { v4 } from "uuid";
+import api from "$lib/api";
+import { requirePin } from "$lib/auth";
import { db, g, s, t } from "$lib/db";
-import { l, err, warn } from "$lib/logging";
+import { err, l, warn } from "$lib/logging";
+import mqtt from "$lib/mqtt";
+import {
+ build,
+ completePayment,
+ credit,
+ debit,
+ decode,
+ sendInternal,
+ sendLightning,
+ sendOnchain,
+ types,
+} from "$lib/payments";
+import { emit } from "$lib/sockets";
import {
+ SATS,
bail,
fail,
getInvoice,
getPayment,
getUser,
sats,
- SATS,
} from "$lib/utils";
-import { requirePin } from "$lib/auth";
-import {
- completePayment,
- decode,
- debit,
- credit,
- types,
- build,
- sendInternal,
- sendLightning,
- sendOnchain,
-} from "$lib/payments";
-import { mqtt1, mqtt2 } from "$lib/mqtt";
-import got from "got";
-import api from "$lib/api";
import rpc from "@coinos/rpc";
+import got from "got";
+import { v4 } from "uuid";
import ln from "$lib/ln";
@@ -37,16 +37,16 @@ export default {
},
async create(req, res) {
- let { body, user } = req;
+ const { body, user } = req;
let { amount, hash, maxfee, fund, memo, payreq } = body;
- let balance = await g(`balance:${user.id}`);
+ const balance = await g(`balance:${user.id}`);
try {
if (await g("freeze")) fail("Problem sending payment");
if (typeof amount !== "undefined") {
amount = parseInt(amount);
- if (amount < 0 || amount > SATS || isNaN(amount))
+ if (amount < 0 || amount > SATS || Number.isNaN(amount))
fail("Invalid amount");
}
@@ -92,7 +92,7 @@ export default {
payments = (
await Promise.all(
payments.map(async (pid) => {
- let p = await g(`payment:${pid}`);
+ const p = await g(`payment:${pid}`);
if (!p) {
warn("user", id, "missing payment", pid);
await db.lRem(`${aid || id}:payments`, 0, pid);
@@ -107,9 +107,9 @@ export default {
.filter((p) => p)
.sort((a, b) => b.created - a.created);
- let count = payments.length;
+ const count = payments.length;
- let fn = (a, b) => ({
+ const fn = (a, b) => ({
...a,
[b.currency]: {
tips: (a[b.currency] ? a[b.currency].tips : 0) + (b.tip || 0),
@@ -135,8 +135,8 @@ export default {
},
});
- let incoming = payments.filter((p: any) => p.amount > 0).reduce(fn, {});
- let outgoing = payments.filter((p: any) => p.amount < 0).reduce(fn, {});
+ const incoming = payments.filter((p: any) => p.amount > 0).reduce(fn, {});
+ const outgoing = payments.filter((p: any) => p.amount < 0).reduce(fn, {});
if (limit) payments = payments.slice(offset, offset + limit);
@@ -145,10 +145,10 @@ export default {
async get(req, res) {
try {
- let {
+ const {
params: { hash },
} = req;
- let p = await getPayment(hash);
+ const p = await getPayment(hash);
if (p.type === types.internal) p.with = await g(`user:${p.ref}`);
res.send(p);
} catch (e) {
@@ -158,14 +158,14 @@ export default {
},
async parse(req, res) {
- let {
+ const {
body: { payreq },
user,
} = req;
try {
- let hour = 1000 * 60 * 60;
+ const hour = 1000 * 60 * 60;
let nodes = await g("nodes");
- let { last } = nodes || {};
+ const { last } = nodes || {};
if (!last || last > Date.now() - hour) {
({ nodes } = await ln.listnodes());
@@ -173,15 +173,15 @@ export default {
await s("nodes", nodes);
}
- let decoded = await ln.decodepay(payreq);
- let { amount_msat, payee } = decoded;
- let node = nodes.find((n) => n.nodeid === payee);
- let alias = node ? node.alias : payee.substr(0, 12);
+ const decoded = await ln.decodepay(payreq);
+ const { amount_msat, payee } = decoded;
+ const node = nodes.find((n) => n.nodeid === payee);
+ const alias = node ? node.alias : payee.substr(0, 12);
- let amount = Math.round(amount_msat / 1000);
+ const amount = Math.round(amount_msat / 1000);
let ourfee = Math.round(amount * config.fee);
- let credit = await g(`credit:lightning:${user.id}`);
- let covered = Math.min(credit, ourfee) || 0;
+ const credit = await g(`credit:lightning:${user.id}`);
+ const covered = Math.min(credit, ourfee) || 0;
ourfee -= covered;
res.send({ alias, amount, ourfee });
@@ -191,10 +191,10 @@ export default {
},
async fund(req, res) {
- let {
+ const {
params: { name },
} = req;
- let amount = await g(`fund:${name}`);
+ const amount = await g(`fund:${name}`);
if (typeof amount === "undefined" || amount === null)
return bail(res, "fund not found");
let payments = (await db.lRange(`fund:${name}:payments`, 0, -1)) || [];
@@ -209,10 +209,10 @@ export default {
},
async withdraw(req, res) {
- let {
+ const {
params: { name },
} = req;
- let maxWithdrawable = await g(`fund:${name}`);
+ const maxWithdrawable = await g(`fund:${name}`);
res.send({
tag: "withdrawRequest",
callback: `${URL}/lnurlw/${name}`,
@@ -239,8 +239,8 @@ export default {
if (!iid) {
iid = v4();
- let rates = await g("rates");
- let { currency } = user;
+ const rates = await g("rates");
+ const { currency } = user;
await s(`invoice:${iid}`, {
currency,
id: iid,
@@ -251,7 +251,7 @@ export default {
});
}
- let payment = await credit({
+ const payment = await credit({
hash: iid,
amount,
memo: id,
@@ -268,23 +268,23 @@ export default {
},
async confirm(req, res) {
- let {
+ const {
body: { txid, wallet, type },
} = req;
try {
- let node = rpc({ ...config[type], wallet });
- let { confirmations, details } = await node.getTransaction(txid);
- let hot = wallet === config[type].wallet;
+ const node = rpc({ ...config[type], wallet });
+ const { confirmations, details } = await node.getTransaction(txid);
+ const hot = wallet === config[type].wallet;
let aid;
if (!hot) aid = wallet;
- for (let { address, amount, asset, category, vout } of details) {
+ for (const { address, amount, asset, category, vout } of details) {
if (!address) continue;
if (type === types.liquid && asset !== config.liquid.btc) continue;
if (category === "send") {
- let p = await getPayment(txid);
+ const p = await getPayment(txid);
if (!p) continue;
if (confirmations) {
@@ -299,10 +299,10 @@ export default {
continue;
}
- let p = await getPayment(`${txid}:${vout}`);
+ const p = await getPayment(`${txid}:${vout}`);
if (!p) {
- let invoice = await getInvoice(address);
+ const invoice = await getInvoice(address);
if (!hot && aid !== invoice?.aid) continue;
await credit({
hash: address,
@@ -312,13 +312,13 @@ export default {
aid,
});
} else if (confirmations >= 1) {
- let id = `payment:${txid}:${vout}`;
- let p = await getPayment(`${txid}:${vout}`);
+ const id = `payment:${txid}:${vout}`;
+ const p = await getPayment(`${txid}:${vout}`);
if (!p) return db.sAdd("missed", id);
if (p.confirmed) return;
- let invoice = await getInvoice(address);
- let { id: iid } = invoice;
+ const invoice = await getInvoice(address);
+ const { id: iid } = invoice;
p.confirmed = true;
invoice.received += parseInt(invoice.pending);
@@ -334,9 +334,8 @@ export default {
.incrBy(`balance:${p.aid || p.uid}`, p.amount)
.exec();
- emit(p.uid, "payment", p);
- let user = await g(`user:${p.uid}`);
- await completePayment(p, user);
+ const user = await g(`user:${p.uid}`);
+ await completePayment(invoice, p, user);
}
}
res.send({});
@@ -348,7 +347,7 @@ export default {
},
async fee(req, res) {
- let { body, user } = req;
+ const { body, user } = req;
try {
res.send(await build({ ...body, user }));
} catch (e) {
@@ -366,12 +365,12 @@ export default {
},
async send(req, res) {
- let { body, user } = req;
+ const { body, user } = req;
try {
await requirePin({ body, user });
- let { hash: txid } = await sendOnchain({ ...body, user });
- let pid = await g(`payment:${txid}`);
- let p = await g(`payment:${pid}`);
+ const { hash: txid } = await sendOnchain({ ...body, user });
+ const pid = await g(`payment:${txid}`);
+ const p = await g(`payment:${pid}`);
res.send(p);
} catch (e) {
@@ -382,7 +381,7 @@ export default {
},
async freeze(req, res) {
- let {
+ const {
body: { secret },
} = req;
try {
@@ -396,23 +395,18 @@ export default {
},
async print(req, res) {
- let {
+ const {
body: { id },
user,
} = req;
try {
- let p = await g(`payment:${id}`);
+ const p = await g(`payment:${id}`);
if (p.uid !== user.id) fail("unauthorized");
emit(user.id, "payment", p);
- let { username } = user;
-
- mqtt1.publish(
- username,
- `pay:${p.amount}:${p.tip}:${p.rate}:${p.created}:${p.id}`,
- );
+ const { username } = user;
- mqtt2.publish(
+ mqtt.publish(
username,
`pay:${p.amount}:${p.tip}:${p.rate}:${p.created}:${p.id}`,
);
@@ -433,21 +427,21 @@ export default {
lnaddress = decodeURIComponent(lnaddress);
await requirePin({ body, user });
- let [username, domain] = lnaddress.split("@");
- let { minSendable, maxSendable, callback, metadata } = (await got(
+ const [username, domain] = lnaddress.split("@");
+ const { minSendable, maxSendable, callback, metadata } = (await got(
`https://${domain}/.well-known/lnurlp/${username}`,
).json()) as any;
- let memo = metadata["text/plain"] || "";
+ const memo = metadata["text/plain"] || "";
if (amount * 1000 < minSendable || amount * 1000 > maxSendable)
fail("amount out of range");
- let r: any = await got(`${callback}?amount=${amount * 1000}`).json();
+ const r: any = await got(`${callback}?amount=${amount * 1000}`).json();
if (r.reason) fail(r.reason);
- let { pr } = r;
+ const { pr } = r;
- let { payee } = await ln.decode(pr);
- let { id } = await ln.getinfo();
+ const { payee } = await ln.decode(pr);
+ const { id } = await ln.getinfo();
let p;
if (payee === id) {
@@ -463,7 +457,7 @@ export default {
},
async gateway(req, res) {
- let {
+ const {
body: { short_channel_id, webhook },
} = req;
@@ -472,24 +466,24 @@ export default {
},
async replace(req, res) {
- let {
+ const {
body: { id },
user,
} = req;
try {
- let p = await g(`payment:${id}`);
+ const p = await g(`payment:${id}`);
if (!p) fail("Payment not found");
if (p.uid !== user.id) fail("unauthorized");
- let { tx, type } = await decode(p.hex);
- let node = rpc(config[type]);
+ const { tx, type } = await decode(p.hex);
+ const node = rpc(config[type]);
- let fees: any = await fetch(`${api[type]}/fees/recommended`).then((r) =>
+ const fees: any = await fetch(`${api[type]}/fees/recommended`).then((r) =>
r.json(),
);
- let outputs = [];
- for (let {
+ const outputs = [];
+ for (const {
scriptPubKey: { address },
value,
} of tx.vout) {
@@ -497,21 +491,21 @@ export default {
outputs.push({ [address]: value });
}
- let raw = await node.createRawTransaction(tx.vin, outputs);
+ const raw = await node.createRawTransaction(tx.vin, outputs);
- let newTx = await node.fundRawTransaction(raw, {
+ const newTx = await node.fundRawTransaction(raw, {
fee_rate: fees.fastestFee + 50,
replaceable: true,
subtractFeeFromOutputs: [],
});
- let diff = sats(newTx.fee) - p.fee;
+ const diff = sats(newTx.fee) - p.fee;
if (diff < 0) fail("fee must increase");
if (config[type].walletpass)
await node.walletPassphrase(config[type].walletpass, 300);
p.hex = (await node.signRawTransactionWithWallet(newTx.hex)).hex;
- let r = await node.testMempoolAccept([p.hex]);
+ const r = await node.testMempoolAccept([p.hex]);
if (!r[0].allowed) fail(`transaction rejected ${p.hex}`);
warn("bump", user.username, p.hex);
@@ -523,12 +517,12 @@ export default {
},
async internal(req, res) {
- let {
+ const {
body: { username, amount },
user: sender,
} = req;
- let recipient = await getUser(username);
+ const recipient = await getUser(username);
res.send(await sendInternal({ amount, sender, recipient }));
},
};
diff --git a/routes/users.ts b/routes/users.ts
index 5f6f0747..25a6a6d2 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -256,6 +256,7 @@ export default {
"prompt",
"profile",
"pubkey",
+ "push",
"reserve",
"salt",
"seed",
@@ -340,21 +341,38 @@ export default {
}
},
- async subscribe(req, res) {
- let { body, user } = req;
- let { subscriptions } = user;
- let { subscription } = body;
- if (!subscriptions) subscriptions = [];
- if (
- !subscriptions.find(
- (s) => JSON.stringify(s) === JSON.stringify(subscription),
- )
- )
- subscriptions.push(subscription);
- user.subscriptions = subscriptions;
- l("subscribing", user.username);
- await user.save();
- res.sendStatus(201);
+ async subscriptions(req, res) {
+ try {
+ let { user } = req;
+ let subscriptions = await db.sMembers(`${user.id}:subscriptions`);
+ res.send(subscriptions);
+ } catch (e) {
+ bail(res, e.message);
+ }
+ },
+
+ async subscription(req, res) {
+ try {
+ let { subscription } = req.body;
+ let { id } = req.user;
+ await db.sAdd(`${id}:subscriptions`, JSON.stringify(subscription));
+ res.send(subscription);
+ } catch (e) {
+ console.log(e);
+ bail(res, e.message);
+ }
+ },
+
+ async deleteSubscription(req, res) {
+ try {
+ let { subscription } = req.body;
+ let { id } = req.user;
+ await db.sRem(`${id}:subscriptions`, JSON.stringify(subscription));
+ res.send(subscription);
+ } catch (e) {
+ console.log(e);
+ bail(res, e.message);
+ }
},
async password(req, res) {