aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJohn Barratt <[email protected]>2023-02-28 13:55:59 -0800
committerJohn Barratt <[email protected]>2023-02-28 13:55:59 -0800
commite47d50a443f0a396321716a506e1df325dd4a1fb (patch)
tree1c010c5970e9cbfbf8671e6f00a97d6518446fdd /lib
parent58e996a4ac227162f171e84530fe898cb504e045 (diff)
parente4702b4d13e4d966d735c2ba4657e10d7c436a57 (diff)
downloadcoinos-server-e47d50a443f0a396321716a506e1df325dd4a1fb.tar.gz
coinos-server-e47d50a443f0a396321716a506e1df325dd4a1fb.zip
Merge branch 'master' of https://github.com/coinos/coinos-server into notifications
Diffstat (limited to 'lib')
-rw-r--r--lib/auth.js20
-rw-r--r--lib/db.js15
-rw-r--r--lib/invoices.js17
-rw-r--r--lib/nostr.js42
-rw-r--r--lib/payments.js28
-rw-r--r--lib/register.js25
-rw-r--r--lib/sockets.js2
-rw-r--r--lib/upload.js2
-rw-r--r--lib/utils.js2
-rw-r--r--lib/webhooks.js9
10 files changed, 98 insertions, 64 deletions
diff --git a/lib/auth.js b/lib/auth.js
index f3cfd1e9..0533de31 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -7,17 +7,17 @@ export const optional = {
preValidation: fastifyPassport.authenticate(
"jwt",
{ session: false },
- function (req, res, err, user, info) {
+ function(req, res, err, user, info) {
req.user = user;
}
- ),
+ )
};
export const auth = {
preValidation: fastifyPassport.authenticate("jwt", {
authInfo: false,
- session: false,
- }),
+ session: false
+ })
};
export const requirePin = async ({ body, user }) => {
@@ -29,13 +29,17 @@ export const jwtStrategy = new jwt.Strategy(
{
jwtFromRequest: jwt.ExtractJwt.fromExtractors([
jwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
- (req) => (req.cookies ? req.cookies.token : null),
+ req => (req.cookies ? req.cookies.token : null)
]),
- secretOrKey: config.jwt,
+ secretOrKey: config.jwt
},
async (payload, next) => {
- let user = await g(`user:${payload.id}`);
- if (typeof user === "string") await g(`user:${user}`);
+ let user;
+ if (payload.id) {
+ user = await g(`user:${payload.id}`);
+ if (typeof user === "string") await g(`user:${user}`);
+ }
+
next(null, user);
}
);
diff --git a/lib/db.js b/lib/db.js
index 7b7fefdb..17d88639 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -1,6 +1,7 @@
import config from "$config";
import { sleep } from "$lib/utils";
import { createClient } from "redis";
+import { warn } from "$lib/logging";
export const db = createClient({ url: config.db });
try {
@@ -15,11 +16,17 @@ export let g = async k => {
let v = await db.get(k);
try {
return JSON.parse(v);
- } catch(e) {
+ } catch (e) {
return v;
- }
-}
-export let s = (k, v) => db.set(k, JSON.stringify(v));
+ }
+};
+export let s = (k, v) => {
+ if (k === "user:null" || k === "user:undefined") {
+ warn("###### NULL USER #######");
+ console.trace();
+ }
+ db.set(k, JSON.stringify(v));
+};
let retries = {};
export let t = async (k, f) => {
diff --git a/lib/invoices.js b/lib/invoices.js
index bab48515..f64cf409 100644
--- a/lib/invoices.js
+++ b/lib/invoices.js
@@ -16,10 +16,9 @@ export let generate = async ({ invoice, user, sender, memo }) => {
tip = parseInt(tip || 0);
if (amount < 0) fail("amount out of range");
- if (tip > 5 * amount || tip < 0) fail("tip amount out of range");
if (!user) user = sender;
- let uid = await g(`user:${user.username}`);
+ let uid = await g(`user:${user.username.toLowerCase()}`);
user = await g(`user:${uid}`);
if (!user) fail("user not provided");
@@ -30,9 +29,8 @@ export let generate = async ({ invoice, user, sender, memo }) => {
let hash, text;
if (type === types.lightning) {
- let amt = amount ? `${amount + tip}sat` : "any";
let r = await ln.invoice(
- amt,
+ amount ? `${amount + tip}sat` : "any",
new Date(),
memo || "",
3600,
@@ -55,16 +53,17 @@ export let generate = async ({ invoice, user, sender, memo }) => {
}
invoice = {
- ...invoice,
amount,
- hash,
- text,
+ created: Date.now(),
currency,
+ hash,
rate,
+ received: 0,
+ request_id,
+ text,
tip,
+ type,
uid,
- received: 0,
- created: Date.now()
};
l("creating invoice", user.username, amount, tip, currency, invoice.hash);
diff --git a/lib/nostr.js b/lib/nostr.js
index 065fafb0..604d207d 100644
--- a/lib/nostr.js
+++ b/lib/nostr.js
@@ -1,16 +1,17 @@
import config from "$config";
import { Relay, RelayPool } from "nostr";
-import { broadcast } from "$lib/sockets";
+import { broadcast, emit } from "$lib/sockets";
import store from "$lib/store";
import { g, s, db } from "$lib/db";
import { nada, wait } from "$lib/utils";
+export let coinos;
export let pool;
export let fillPool = () => {
pool = RelayPool(config.relays);
pool.on("open", relay => {
- if (relay.url.includes(config.relay)) coinos = relay;
+ if (relay.url.includes(config.nostr)) coinos = relay;
relay.subscribe("live", { limit: 1 });
});
@@ -39,6 +40,13 @@ export let fillPool = () => {
// coinos.send(["EVENT", ev]);
ev.user = await getUser(pubkey);
// broadcast("event", ev);
+
+ if (ev.kind === 4) {
+ let uid = await g(`user:${ev.tags[0][1]}`);
+ if (uid) ev.recipient = await g(`user:${uid}`);
+ ev.author = ev.user;
+ emit(uid, "event", ev);
+ }
}
} else if (sub.includes("profile")) {
let { pubkey } = ev;
@@ -59,9 +67,13 @@ export let fillPool = () => {
await s(`user:${pubkey}`, JSON.stringify(user));
coinos.send(ev);
+ } else if (sub.includes("messages")) {
+ let pubkey = sub.split(":")[0];
+ await db.sAdd(`${pubkey}:messages`, ev.id);
+ await s(`ev:${ev.id}`, ev);
} else if (sub.includes("follows")) {
let pubkey = sub.split(":")[0];
- await s(`${pubkey}:follows`, JSON.stringify(ev.tags));
+ await s(`${pubkey}:follows`, ev.tags);
for (let f of ev.tags) {
let [_, followPubkey] = f;
await db.sAdd(`${followPubkey}:followers`, pubkey);
@@ -75,7 +87,7 @@ export let fillPool = () => {
} else if (sub.includes("notes")) {
let pubkey = sub.split(":")[0];
await db.sAdd(pubkey, ev.id);
- await s(`ev:${ev.id}`, JSON.stringify(ev));
+ await s(`ev:${ev.id}`, ev);
}
} catch (e) {
console.log(e);
@@ -83,7 +95,6 @@ export let fillPool = () => {
});
};
-export let coinos;
let now = () => Math.round(Date.now() / 1000);
let timeouts = {};
@@ -96,8 +107,8 @@ export let q = async (
let start = Date.now();
let seen = [];
let rejected;
- query.since = await g(`since:${sub}`);
- if (now() - query.since < since) return r();
+ // query.since = await g(`since:${sub}`);
+ // if (now() - query.since < since) return r();
let done = { [sub]: [] };
@@ -156,9 +167,14 @@ export let q = async (
let seen = [];
-let getUser = async pubkey =>
- JSON.parse(await g(`user:${pubkey}`)) || {
- username: pubkey.substr(0, 6),
- pubkey,
- anon: true
- };
+let getUser = async pubkey => {
+ let id = await g(`user:${pubkey}`);
+ let user = await g(`user:${id}`);
+ return (
+ user || {
+ username: pubkey.substr(0, 6),
+ pubkey,
+ anon: true
+ }
+ );
+};
diff --git a/lib/payments.js b/lib/payments.js
index 2c0eb0c0..aaf39210 100644
--- a/lib/payments.js
+++ b/lib/payments.js
@@ -4,7 +4,7 @@ import { emit } from "$lib/sockets";
import { v4 } from "uuid";
import { notify } from "$lib/notifications";
import { db, g, s, t } from "$lib/db";
-import { l, err } from "$lib/logging";
+import { l, err, warn } from "$lib/logging";
import { fail } from "$lib/utils";
import { callWebhook } from "$lib/webhooks";
@@ -13,7 +13,7 @@ export const types = {
bitcoin: "bitcoin",
lightning: "lightning",
pot: "pot",
- classic: "classic",
+ classic: "classic"
};
export let debit = async (
@@ -25,9 +25,11 @@ export let debit = async (
type = types.internal,
id = v4()
) => {
- let ref;
+ let ref, tip;
let invoice = await g(`invoice:${hash}`);
- if (invoice) ref = invoice.uid;
+ if (invoice) {
+ ref = invoice.uid;
+ }
let { id: uid, currency, username } = user;
@@ -44,16 +46,21 @@ export let debit = async (
let covered = Math.min(credit, ourfee) || 0;
ourfee -= covered;
- l("debiting", user.username, balance, amount, ourfee, amount + ourfee);
- if (balance < amount + ourfee) fail("Insufficient funds");
+ l("debiting", user.username, balance, amount, fee, ourfee, amount + fee + ourfee);
+ if (balance < amount + fee + ourfee) fail("Insufficient funds");
await db
.multi()
.decrBy(`credit:${type}:${uid}`, covered)
- .decrBy(`balance:${uid}`, amount + ourfee)
+ .decrBy(`balance:${uid}`, amount + fee + ourfee)
.exec();
});
});
+ if (invoice?.tip) {
+ tip = invoice.tip;
+ amount -= tip;
+ }
+
let p = {
id,
amount: -amount,
@@ -66,7 +73,8 @@ export let debit = async (
currency,
type,
ref,
- created: Date.now(),
+ tip,
+ created: Date.now()
};
await s(`payment:${id}`, p);
@@ -81,7 +89,7 @@ export let debit = async (
export let credit = async (hash, amount, memo, ref, type = types.internal) => {
amount = parseInt(amount);
let invoice = await g(`invoice:${hash}`);
- if (!invoice) return;
+ if (!invoice) return warn("failed to credit", hash, ", invoice not found");
if (!memo) ({ memo } = invoice);
let user = await g(`user:${invoice.uid}`);
@@ -98,7 +106,7 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => {
ref,
type,
confirmed: true,
- created: Date.now(),
+ created: Date.now()
};
let { tip } = invoice;
diff --git a/lib/register.js b/lib/register.js
index c55d2f9d..22c36b4c 100644
--- a/lib/register.js
+++ b/lib/register.js
@@ -2,7 +2,7 @@ import countries from "$lib/countries";
import config from "$config";
import { authenticator } from "otplib";
import bcrypt from "bcrypt";
-import { l } from "$lib/logging";
+import { l, warn } from "$lib/logging";
import { v4 } from "uuid";
import { s, g } from "$lib/db";
import { got } from "got";
@@ -17,7 +17,7 @@ export default async (user, ip, requireChallenge) => {
let id = v4();
user.id = id;
- let exists = await g(`user:${username}`);
+ let exists = await g(`user:${username.toLowerCase()}`);
if (exists) throw new Error(`Username ${username} taken`);
if (password) {
@@ -25,19 +25,20 @@ export default async (user, ip, requireChallenge) => {
}
user.currency = "USD";
- if (config.ipxapi) {
- let countryCode = "US";
-
+ if (config.ipregistry) {
try {
- let r = await got(`https://ipxapi.com/api/ip?ip=${ip}`, {
- headers: { authorization: `Bearer ${config.ipxapi}` }
- }).json();
- if (r.success) ({ countryCode } = r);
+ let {
+ location: {
+ country: { code }
+ }
+ } = await got(
+ `https://api.ipregistry.co/${ip}?key=${config.ipregistry}&fields=location.country.code`
+ ).json();
+
+ user.currency = countries[code];
} catch (e) {
- console.log(e);
+ warn("unable to detect country from IP", username);
}
-
- user.currency = countries[countryCode];
}
user.currencies = [...new Set([user.currency, "CAD", "USD"])];
diff --git a/lib/sockets.js b/lib/sockets.js
index 11d8ea9e..458c77a9 100644
--- a/lib/sockets.js
+++ b/lib/sockets.js
@@ -130,6 +130,8 @@ export async function socketServer(app) {
}
});
+ ws.on("error", console.log);
+
ws.on("close", function(code, reason) {
try {
const uid = users[id];
diff --git a/lib/upload.js b/lib/upload.js
index 954e8d4d..50c26cbf 100644
--- a/lib/upload.js
+++ b/lib/upload.js
@@ -12,7 +12,7 @@ export default async (req, res) => {
params: { type },
user
} = req;
- console.log("TYPE", type);
+
if (!["banner", "profile"].includes(type)) throw new Error("invalid upload");
let data = await req.file();
diff --git a/lib/utils.js b/lib/utils.js
index 8c3852e8..45353e8e 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -22,6 +22,8 @@ export const fail = msg => {
throw new Error(msg);
};
+export const bail = (res, msg) => res.code(500).send(msg);
+
export const SATS = 100000000;
export const sats = n => Math.round(n * SATS);
export const btc = n => parseFloat((n / SATS).toFixed(8));
diff --git a/lib/webhooks.js b/lib/webhooks.js
index c071eccb..1158fe9d 100644
--- a/lib/webhooks.js
+++ b/lib/webhooks.js
@@ -9,23 +9,18 @@ export const callWebhook = async (invoice, payment) => {
let { address, received, text, webhook } = invoice;
if (webhook) {
- let { amount, confirmed, hash, memo, account } = payment;
- let { asset } = account;
- let secret = config.webhooks[webhook];
+ let { amount, confirmed, hash, memo } = payment;
l("calling webhook", webhook, amount, hash, address, text);
let res = await got(webhook, {
- headers: { "x-webhook": secret },
json: {
address,
amount,
- asset,
confirmed,
hash,
memo,
received,
- text,
- webhook
+ text
}
}).res();
return res;