From 316039601e5170d6f753cf09eac92a94176b4756 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 21 Dec 2022 21:50:06 -0800 Subject: store nostr keys --- lib/whitelist.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/whitelist.js') diff --git a/lib/whitelist.js b/lib/whitelist.js index 93e601c7..5a9c0ba3 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -5,6 +5,7 @@ export default [ "address", "admin", "banner", + "cipher", "currencies", "currency", "email", @@ -14,7 +15,9 @@ export default [ "index", "keys", "payments", + "pubkey", "profile", + "salt", "seed", "symbol", "theme", -- cgit v1.2.3 From 2d2c991645f3b0ac7fb3ad88afdad0bb67c28b74 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 27 Dec 2022 22:51:33 -0800 Subject: follower endpoints --- lib/nostr.js | 59 +++++++++++++++++++++---- lib/utils.js | 21 +++++++++ lib/whitelist.js | 2 + routes/events.js | 32 +++++++++----- routes/users.js | 132 +++++++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 206 insertions(+), 40 deletions(-) (limited to 'lib/whitelist.js') diff --git a/lib/nostr.js b/lib/nostr.js index 477d2b12..257bca9e 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -5,6 +5,7 @@ import store from "$lib/store"; import redis from "$lib/redis"; const { relays } = await got("https://nostr.watch/relays.json").json(); + export const pool = RelayPool(relays); pool.on("open", relay => { @@ -12,11 +13,18 @@ pool.on("open", relay => { relay.subscribe("live", { limit: 1 }); }); -let coinos; +export let coinos; let seen = []; let timeout; pool.on("event", async (relay, sub, ev) => { try { + let parsed; + try { + parsed = JSON.parse(ev.content); + } catch (e) { + parsed = ev.content; + } + if (sub === "live") { let { pubkey } = ev; @@ -28,26 +36,59 @@ pool.on("event", async (relay, sub, ev) => { seen.length > 1000 && seen.shift(); if (coinos && ev.kind < 5) { - let parsed; - try { - parsed = JSON.parse(ev.content); - } catch (e) { - parsed = ev.content; - } - coinos.send(["EVENT", ev]); - ev.user = JSON.parse(await redis.get(`user:${pubkey}`)) || { + let newuser = { username: pubkey.substr(0, 6), pubkey, anon: true }; + ev.user = JSON.parse(await redis.get(`user:${pubkey}`)) || newuser; + + if (!ev.user.initialized) { + relay.subscribe("zero", { + limit: 1, + kinds: [0], + authors: [pubkey] + }); + } + if (ev.kind === 1) { broadcast("event", ev); } } + } else if (sub === "zero") { + let { pubkey } = ev; + let newuser = { + username: pubkey.substr(0, 6), + pubkey, + anon: true + }; + + let user = JSON.parse(await redis.get(`user:${pubkey}`)) || newuser; + if (parsed.name && user.username === pubkey.substr(0, 6)) + user.username = parsed.name; + + delete parsed.name; + + user = { + ...user, + ...parsed, + initialized: true + }; + + await redis.set(`user:${pubkey}`, JSON.stringify(user)); + } else if (sub.includes("follows")) { + let pubkey = sub.split(":")[0]; + await redis.set(`${pubkey}:follows`, JSON.stringify(ev.tags)); + for (let f of ev.tags) { + await redis.sAdd(`${f[1]}:followers`, pubkey); + } + store.fetching[pubkey] = false; } else { + if (!relay.url.includes("coinos")) return; + let pubkey = sub; clearTimeout(store.timeouts[pubkey]); diff --git a/lib/utils.js b/lib/utils.js index 46267dbd..2854fefc 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,3 +1,4 @@ +import store from "$lib/store"; import config from "$config"; import db from "$db"; import sequelize from "@sequelize/core"; @@ -37,6 +38,26 @@ export const getUser = async (username, transaction) => { user.haspin = !!user.pin; + let { pubkey } = user; + + if (pubkey) { + store.fetching[pubkey] = true; + store.timeouts[pubkey] = setTimeout( + () => (store.fetching[pubkey] = false), + 500 + ); + + coinos.subscribe(`${pubkey}:follows`, { + limit: 1, + kinds: [3], + authors: [pubkey] + }); + + await wait(() => !store.fetching[pubkey], 100, 10); + user.follows = JSON.parse(await redis.get(`${pubkey}:follows`)); + user.followers = await redis.sMembers(`${pubkey}:followers`); + } + return user; }; diff --git a/lib/whitelist.js b/lib/whitelist.js index 5a9c0ba3..e78bc8e5 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -10,6 +10,8 @@ export default [ "currency", "email", "fiat", + "follows", + "followers", "haspin", "id", "index", diff --git a/routes/events.js b/routes/events.js index 07062140..4dcc44f0 100644 --- a/routes/events.js +++ b/routes/events.js @@ -5,33 +5,41 @@ import { pool } from "$lib/nostr"; import store from "$lib/store"; import { wait } from "$lib/utils"; -app.get("/:pubkey/events", async (req, res) => { +app.get("/nostr/:pubkey", async (req, res) => { try { let { pubkey } = req.params; + store.fetching[pubkey] = true; store.timeouts[pubkey] = setTimeout( () => (store.fetching[pubkey] = false), 500 ); - let user = await db.User.findOne({ - where: { pubkey } - }); + let user = JSON.parse(await redis.get(`user:${pubkey}`)); - if (!user) user = { username: pubkey.substr(0,6), pubkey, anon: true } - await redis.set(`user:${pubkey}`, JSON.stringify(user)); + if (!user) { + user = await db.User.findOne({ + where: { pubkey } + }); + } + + if (!user) user = { username: pubkey.substr(0, 6), pubkey, anon: true }; + + let { since } = user; pool.subscribe(pubkey, { - limit: 500, + since, kinds: [1], authors: [pubkey] }); - let events = []; - await wait(() => !store.fetching[pubkey], 10, 10); - for (let id of await redis.sMembers(pubkey)) { - events.push(JSON.parse(await redis.get(`ev:${id}`))); - } + user.since = Math.round(Date.now() / 1000); + await redis.set(`user:${pubkey}`, JSON.stringify(user)); + + await wait(() => !store.fetching[pubkey], 100, 100); + let events = ( + await redis.mGet((await redis.sMembers(pubkey)).map(k => "ev:" + k)) + ).map(JSON.parse); res.send(events); } catch (e) { diff --git a/routes/users.js b/routes/users.js index 70186145..4c6305b5 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,8 +1,9 @@ import app from "$app"; +import redis from "$lib/redis"; import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; -import { getUser } from "$lib/utils"; +import { getUser, wait } from "$lib/utils"; import axios from "axios"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; @@ -21,6 +22,7 @@ import lq from "$lib/liquid"; import { emit } from "$lib/sockets"; import register from "$lib/register"; import { requirePin } from "$lib/utils"; +import { coinos } from "$lib/nostr"; const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); @@ -44,35 +46,84 @@ app.get("/me", auth, async (req, res) => { } ] }); + + let { pubkey } = user; + + if (pubkey) { + store.fetching[pubkey] = true; + store.timeouts[pubkey] = setTimeout( + () => (store.fetching[pubkey] = false), + 500 + ); + + coinos.subscribe(`${pubkey}:follows`, { + limit: 1, + kinds: [3], + authors: [pubkey] + }); + + await wait(() => !store.fetching[pubkey], 100, 10); + user.follows = JSON.parse(await redis.get(`${pubkey}:follows`)); + user.followers = await redis.sMembers(`${pubkey}:followers`); + } + user.accounts = await req.user.getAccounts(); user.payments = payments; user.haspin = !!user.pin; + res.send(pick(user, ...whitelist)); } catch (e) { + console.log("problem fetching user", e); res.code(500).send(e.message); } }); app.get("/users/:username", async (req, res) => { - const { username } = req.params; - - let user = await db.User.findOne({ - attributes: [ - "username", - "banner", - "profile", - "address", - "currency", - "pubkey" - ], - where: Sequelize.where( - Sequelize.fn("lower", Sequelize.col("username")), - username.toLowerCase() - ) - }); + try { + const { username } = req.params; - if (user) res.send(user); - else res.code(500).send("User not found"); + let user = await db.User.findOne({ + attributes: [ + "username", + "banner", + "profile", + "address", + "currency", + "pubkey" + ], + where: Sequelize.where( + Sequelize.fn("lower", Sequelize.col("username")), + username.toLowerCase() + ) + }); + + if (!user) return res.code(500).send("User not found"); + + user = user.get({ plain: true }); + let { pubkey } = user; + + if (pubkey) { + store.fetching[pubkey] = true; + store.timeouts[pubkey] = setTimeout( + () => (store.fetching[pubkey] = false), + 500 + ); + + coinos.subscribe(`${pubkey}:follows`, { + limit: 1, + kinds: [3], + authors: [pubkey] + }); + + await wait(() => !store.fetching[pubkey], 100, 10); + user.follows = JSON.parse(await redis.get(`${pubkey}:follows`)); + user.followers = await redis.sMembers(`${pubkey}:followers`); + } + + res.send(user); + } catch (e) { + res.code(500).send(e.message); + } }); app.post("/register", async (req, res) => { @@ -603,3 +654,46 @@ app.get("/contacts", auth, async function(req, res) { res.code(500).send(e.message); } }); + +app.post("/checkPassword", auth, async function(req, res) { + let { user } = req; + let result = await bcrypt.compare(req.body.password, user.password); + if (!result) return res.code(500).send("Invalid password"); + res.send(result); +}); + +app.get("/:pubkey/follows", async (req, res) => { + try { + let { pubkey } = req.params; + let follows = JSON.parse(await redis.get(`${pubkey}:follows`)) || []; + + if (follows.length) { + follows = await db.User.findAll({ + where: { pubkey: follows.map(t => t[1]) } + }); + + res.send(follows); + } + } catch (e) { + console.log(e); + res.code(500).send(e.message); + } +}); + +app.get("/:pubkey/followers", async (req, res) => { + try { + let { pubkey } = req.params; + let followers = await redis.sMembers(`${pubkey}:followers`); + + if (followers.length) { + followers = await db.User.findAll({ + where: { pubkey: followers } + }); + + res.send(followers); + } + } catch (e) { + console.log(e); + res.code(500).send(e.message); + } +}); -- cgit v1.2.3 From 8266d3adad8d093212b208ff93e6bee41f3370e3 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Jan 2023 13:59:03 -0800 Subject: locktime field, uuid for token --- db/models/users.js | 3 +++ lib/nostr.js | 61 +++++++++++++++++++++++++++++++++++------------------- lib/passport.js | 14 +++++++++---- lib/whitelist.js | 1 + routes/users.js | 31 +++++++++++---------------- 5 files changed, 66 insertions(+), 44 deletions(-) (limited to 'lib/whitelist.js') diff --git a/db/models/users.js b/db/models/users.js index cc63ac57..23dab0bf 100644 --- a/db/models/users.js +++ b/db/models/users.js @@ -247,6 +247,9 @@ const attributes = { }, phone: { type: DataTypes.STRING(255) + }, + locktime: { + type: DataTypes.INTEGER(11) } }; diff --git a/lib/nostr.js b/lib/nostr.js index 99265f7d..4730883f 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -5,22 +5,16 @@ import { broadcast } from "$lib/sockets"; import store from "$lib/store"; import redis from "$lib/redis"; import proxy from "@fastify/http-proxy"; +import { wait } from "$lib/utils"; app.register(proxy, { upstream: config.nostr, prefix: "/nostr", rewritePrefix: "", - disableRequestLogging: true, + disableRequestLogging: true }); -const relays = [ - config.relay, - "wss://relay.damus.io", - "wss://nostr-pub.wellorder.net", - "wss://nostr.rocks", -]; - -export const pool = RelayPool(relays); +export const pool = RelayPool(config.relays); pool.on("open", relay => { if (relay.url.includes(config.relay)) coinos = relay; @@ -31,38 +25,63 @@ export let coinos; let now = () => Math.round(Date.now() / 1000); let timeouts = {}; -export let q = async (sub, query, timeout = 8000) => +export let q = async (sub, query, timeout = 20000) => new Promise(async (r, j) => { + let start = Date.now(); + let seen = []; let rejected; - if (!coinos) return j(new Error("relay not initialized")); query.since = await redis.get(`since:${sub}`); if (now() - query.since < 3600) return r(); + let done = { [sub]: [] }; - coinos.on("eose", s => { - return !rejected && s === sub && r(timeouts[sub].clear()); - }); + let check = s => { + let elapsed = Date.now() - start; + if (rejected) return true; + if (done[s].length === pool.relays.length || elapsed > 200) { + r(); + if (timeouts[s]) timeouts[s].clear(); + return true; + } + }; timeouts[sub] = { async clear() { clearTimeout(this.timer); delete timeouts[sub]; - coinos.unsubscribe(sub); + pool.unsubscribe(sub); await redis.set(`since:${sub}`, now()); }, - extend(t = timeout) { + extend(ev) { + if (ev) { + if (seen.includes(ev.id)) return; + seen.push(ev.id); + seen.length > 1000 && seen.shift(); + } + clearTimeout(this.timer); this.timer = setTimeout(() => { j(new Error(`query timed out: ${sub} ${Date.now()}`)); - coinos.unsubscribe(sub); + pool.unsubscribe(sub); rejected = true; - }, t); + }, timeout); }, timer: undefined }; - timeouts[sub].extend(timeout); - coinos.subscribe(sub, query); + timeouts[sub].extend(); + pool.subscribe(sub, query); + + pool.on("eose", (relay, s) => { + if (done[s]) done[s].push(relay.url); + check(s); + }); + + try { + await wait(() => check(sub)); + } catch (e) { + console.log(e); + } }); let seen = []; @@ -75,7 +94,7 @@ let getUser = async pubkey => }; pool.on("event", async (relay, sub, ev) => { - if (timeouts[sub]) timeouts[sub].extend(); + if (timeouts[sub]) timeouts[sub].extend(ev); try { let content; try { diff --git a/lib/passport.js b/lib/passport.js index ac2949a5..1244aab5 100644 --- a/lib/passport.js +++ b/lib/passport.js @@ -35,13 +35,19 @@ fastifyPassport.use( }, async (payload, next) => { try { - let { username } = payload; + let { username, uuid } = payload; + let where = {}; + + if (username) + where.username = { [Op.or]: [username, username.replace(/ /g, "")] }; + + if (uuid) where.uuid = uuid; + let user = await db.User.findOne({ - where: { - username: { [Op.or]: [username, username.replace(/ /g, "")] } - }, + where, include: { model: db.Account, as: "account" } }); + if (user.locked) throw new Error("account is locked"); next(null, user); } catch (e) { diff --git a/lib/whitelist.js b/lib/whitelist.js index e78bc8e5..4e4dc14e 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -16,6 +16,7 @@ export default [ "id", "index", "keys", + "locktime", "payments", "pubkey", "profile", diff --git a/routes/users.js b/routes/users.js index c935a137..764d1f03 100644 --- a/routes/users.js +++ b/routes/users.js @@ -4,13 +4,10 @@ import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; import { getUser, uniq, wait } from "$lib/utils"; -import axios from "axios"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { authenticator } from "otplib"; import Sequelize from "@sequelize/core"; -import bitcoin from "bitcoinjs-lib"; -import liquid from "liquidjs-lib"; import { fromBase58, fromPrivateKey } from "bip32"; import { Mutex } from "async-mutex"; import bip32 from "bip32"; @@ -191,7 +188,7 @@ app.post("/user", auth, async (req, res) => { let { confirm, password, pin, newpin, username } = req.body; if (user.pin && !(pin === user.pin)) throw new Error("Pin required"); - if (typeof newpin !== 'undefined') user.pin = newpin; + if (typeof newpin !== "undefined") user.pin = newpin; if (!user.pin) user.pin = null; let exists; @@ -210,26 +207,22 @@ app.post("/user", auth, async (req, res) => { if (user.username !== username) l("changing username", user.username, username); user.username = username; - - token = jwt.sign({ username }, config.jwt); - res.cookie("token", token, { - expires: new Date(Date.now() + 432000000) - }); } let attributes = [ - "unit", + "address", "cipher", + "currencies", + "currency", + "email", + "fiat", + "locktime", "pubkey", "salt", - "currency", - "currencies", + "seed", "tokens", "twofa", - "seed", - "fiat", - "email", - "address" + "unit" ]; for (let a of attributes) { @@ -356,8 +349,8 @@ let login = async (req, res) => { try { const url = `${callback}&sig=${sig}&key=${key}`; - const response = await axios.get(url); - res.send(response.data); + const response = await got(url).json(); + res.send(response); } catch (e) { err("problem calling lnurl login", e.message); res.code(500).send(e.message); @@ -393,7 +386,7 @@ let login = async (req, res) => { req.headers["x-forwarded-for"] || req.connection.remoteAddress ); - let payload = { username: user.username }; + let payload = { uuid: user.uuid }; let token = jwt.sign(payload, config.jwt); res.cookie("token", token, { expires: new Date(Date.now() + 432000000) }); user.accounts = await user.getAccounts(); -- cgit v1.2.3 From e3266ddecd825b8716df7dc418246441d4dcb0f7 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Jan 2023 17:31:22 -0800 Subject: background nostr fetching --- db/models/users.js | 6 ++++++ lib/nostr.js | 21 +++++++++++-------- lib/sockets.js | 7 +++++-- lib/utils.js | 7 ++++++- lib/whitelist.js | 4 +++- routes/events.js | 5 +++-- routes/users.js | 59 ++++++++++++++++++++++++++++++++++++++++-------------- 7 files changed, 80 insertions(+), 29 deletions(-) (limited to 'lib/whitelist.js') diff --git a/db/models/users.js b/db/models/users.js index 72680fd8..fce79537 100644 --- a/db/models/users.js +++ b/db/models/users.js @@ -250,6 +250,12 @@ const attributes = { }, locktime: { type: DataTypes.INTEGER(11) + }, + prompt: { + type: DataTypes.BOOLEAN + }, + display: { + type: DataTypes.STRING(255) } }; diff --git a/lib/nostr.js b/lib/nostr.js index 4730883f..4ee5cb13 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -25,20 +25,24 @@ export let coinos; let now = () => Math.round(Date.now() / 1000); let timeouts = {}; -export let q = async (sub, query, timeout = 20000) => +export let q = async (sub, query, timeout = 20000, since = 3600, eager = 200) => new Promise(async (r, j) => { let start = Date.now(); let seen = []; let rejected; query.since = await redis.get(`since:${sub}`); - if (now() - query.since < 3600) return r(); + if (now() - query.since < since) return r(); let done = { [sub]: [] }; let check = s => { let elapsed = Date.now() - start; if (rejected) return true; - if (done[s].length === pool.relays.length || elapsed > 200) { + if ( + done[s] && + (done[s].length === pool.relays.length || + (done[s].length && elapsed > eager)) + ) { r(); if (timeouts[s]) timeouts[s].clear(); return true; @@ -78,7 +82,7 @@ export let q = async (sub, query, timeout = 20000) => }); try { - await wait(() => check(sub)); + await wait(() => check(sub), 100, 200); } catch (e) { console.log(e); } @@ -137,6 +141,7 @@ pool.on("event", async (relay, sub, ev) => { await redis.set(`user:${pubkey}`, JSON.stringify(user)); await redis.set(`user:${user.username}`, JSON.stringify(user)); + coinos.send(ev); } else if (sub.includes("follows")) { let pubkey = sub.split(":")[0]; await redis.set(`${pubkey}:follows`, JSON.stringify(ev.tags)); @@ -144,14 +149,14 @@ pool.on("event", async (relay, sub, ev) => { let [_, followPubkey] = f; await redis.sAdd(`${followPubkey}:followers`, pubkey); } + coinos.send(ev); } else if (sub.includes("followers")) { let followed = sub.split(":")[0]; let { pubkey } = ev; await redis.sAdd(`${followed}:followers`, pubkey); - } else { - if (!relay.url.includes("coinos")) return; - - let pubkey = sub; + coinos.send(ev); + } else if (sub.includes("notes")) { + let pubkey = sub.split(":")[0]; ev.user = await getUser(pubkey); if (!ev.user.updated) { diff --git a/lib/sockets.js b/lib/sockets.js index 3bd0c2c2..82cf3f51 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -85,6 +85,7 @@ app.register(async function(app) { break; case "login": + let user; let token = data; if (lastSeen[token] > subtractSeconds(5)) return; lastSeen[token] = new Date(); @@ -92,7 +93,9 @@ app.register(async function(app) { try { if (!token || token === "null" || !jwt.decode(token)) return ws.close(code, `bad token ${token}`); - const { username, uuid } = jwt.decode(token); + let { username, uuid } = jwt.decode(token); + if (uuid) user = await getUser(uuid); + username = user.username; if (!(username || uuid)) throw new Error("Invalid JWT token"); if (!store.sockets[username]) store.sockets[username] = {}; @@ -110,7 +113,7 @@ app.register(async function(app) { store.sockets[username][id] = ws; names[id] = username; - let user = await getUser(username); + if (!user) user = await getUser(username); let { haspin } = user; diff --git a/lib/utils.js b/lib/utils.js index 748b2a74..95ee5fb1 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -11,6 +11,8 @@ import ln from "$lib/ln"; const { Op } = sequelize; +export const nada = () => {}; + export const sleep = n => new Promise(r => setTimeout(r, n)); export const wait = async (f, s = 300, n = 50) => { let i = 0; @@ -33,7 +35,10 @@ export const getUser = async (username, transaction) => { } ], where: { - username: { [Op.or]: [username, username.replace(/ /g, "")] } + [Op.or]: { + username: { [Op.or]: [username, username.replace(/ /g, "")] }, + uuid: { [Op.or]: [username, username.replace(/ /g, "")] } + } } }; diff --git a/lib/whitelist.js b/lib/whitelist.js index 4e4dc14e..96db6cdc 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -8,6 +8,7 @@ export default [ "cipher", "currencies", "currency", + "display", "email", "fiat", "follows", @@ -18,8 +19,9 @@ export default [ "keys", "locktime", "payments", - "pubkey", "profile", + "prompt", + "pubkey", "salt", "seed", "symbol", diff --git a/routes/events.js b/routes/events.js index 1734af24..bbdd8891 100644 --- a/routes/events.js +++ b/routes/events.js @@ -26,14 +26,15 @@ app.get("/nostr/:pubkey", async (req, res) => { followers: [] }; - await q(pubkey, { + q(`${pubkey}:notes`, { kinds: [1], authors: [pubkey] - }); + }).catch(console.log); await redis.set(`user:${pubkey}`, JSON.stringify(user)); let ids = await redis.sMembers(pubkey); + console.log("IDS", ids); let events = ids.length ? (await redis.mGet(ids.map(k => "ev:" + k))).map(JSON.parse) diff --git a/routes/users.js b/routes/users.js index d2cb1540..d209c3d9 100644 --- a/routes/users.js +++ b/routes/users.js @@ -3,7 +3,7 @@ import redis from "$lib/redis"; import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; -import { getUser, uniq, wait } from "$lib/utils"; +import { getUser, nada, uniq, wait } from "$lib/utils"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { authenticator } from "otplib"; @@ -74,7 +74,9 @@ app.get("/users/:username", async (req, res) => { "profile", "address", "currency", - "pubkey" + "pubkey", + "display", + "prompt" ], where: { [Sequelize.Op.or]: [ @@ -214,9 +216,11 @@ app.post("/user", auth, async (req, res) => { "cipher", "currencies", "currency", + "display", "email", "fiat", "locktime", + "prompt", "pubkey", "salt", "seed", @@ -654,11 +658,17 @@ app.get("/:pubkey/follows", async (req, res) => { let { tagsonly } = req.query; let sub = `${pubkey}:follows`; - await q(sub, { - limit: 1, - kinds: [3], - authors: [pubkey] - }); + q( + sub, + { + limit: 1, + kinds: [3], + authors: [pubkey] + }, + 60000, + 3600, + 60000 + ).catch(nada); let tags = JSON.parse(await redis.get(`${pubkey}:follows`)) || []; if (tagsonly) return res.send(tags); @@ -667,14 +677,22 @@ app.get("/:pubkey/follows", async (req, res) => { for (let f of tags) { let [_, pubkey] = f; - await q(`${pubkey}:profile:f1`, { + q(`${pubkey}:profile:f1`, { limit: 1, kinds: [0], authors: [pubkey] - }); + }).catch(nada); let user = JSON.parse(await redis.get(`user:${pubkey}`)); - if (user) follows.push(user); + + if (!user) + user = { + username: pubkey.substr(0, 6), + pubkey, + anon: true + }; + + follows.push(user); } follows = uniq(follows, e => e.pubkey); @@ -691,20 +709,31 @@ app.get("/:pubkey/followers", async (req, res) => { try { let { pubkey } = req.params; - let pubkeys = await got( - `${config.nostr}/followers?pubkey=${pubkey}` - ).json(); + let pubkeys = [ + ...new Set([ + ...(await got(`${config.nostr}/followers?pubkey=${pubkey}`).json()), + ...(await redis.sMembers(`${pubkey}:followers`)) + ]) + ]; let followers = []; + q( + `${pubkey}:followers`, + { kinds: [3], "#p": [pubkey] }, + 60000, + 3600, + 60000 + ).catch(nada); + for (let pubkey of pubkeys) { let user = JSON.parse(await redis.get(`user:${pubkey}`)); if (!user || !user.updated) { - await q(`${pubkey}:profile:f2`, { + q(`${pubkey}:profile:f2`, { limit: 1, kinds: [0], authors: [pubkey] - }); + }).catch(nada); user = JSON.parse(await redis.get(`user:${pubkey}`)); } -- cgit v1.2.3 From b6b806d142590a121c79c811b7fbb1f5ac6cdaa6 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Jan 2023 21:20:44 -0800 Subject: whitelist uuid --- lib/whitelist.js | 1 + routes/users.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/whitelist.js') diff --git a/lib/whitelist.js b/lib/whitelist.js index 96db6cdc..47e9ed4e 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -27,6 +27,7 @@ export default [ "symbol", "theme", "twofa", + "uuid", "unit", "username", "verified" diff --git a/routes/users.js b/routes/users.js index d209c3d9..329210c8 100644 --- a/routes/users.js +++ b/routes/users.js @@ -76,7 +76,8 @@ app.get("/users/:username", async (req, res) => { "currency", "pubkey", "display", - "prompt" + "prompt", + "uuid" ], where: { [Sequelize.Op.or]: [ -- cgit v1.2.3 From c3565838644123e77881ff4f8536792f074047b9 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 11 Jan 2023 22:09:48 -0800 Subject: migrating to redis --- docker-compose.yml | 2 + index.js | 6 +- lib/binance.js | 3 - lib/countries.js | 249 +++++ lib/ln.js | 2 +- lib/nostr.js | 1 - lib/passport.js | 7 +- lib/rates.js | 34 +- lib/redis.js | 6 +- lib/register.js | 33 +- lib/sockets.js | 12 +- lib/utils.js | 6 +- lib/webhooks.js | 13 +- lib/whitelist.js | 4 +- package.json | 3 +- pnpm-lock.yaml | 1958 +----------------------------------- routes/invoices.js | 188 +--- routes/lightning/channel.js | 29 - routes/lightning/channelRequest.js | 24 - routes/lightning/index.js | 2 - routes/requests.js | 130 +-- routes/users.js | 68 +- 22 files changed, 413 insertions(+), 2367 deletions(-) create mode 100644 lib/countries.js delete mode 100644 routes/lightning/channel.js delete mode 100644 routes/lightning/channelRequest.js (limited to 'lib/whitelist.js') diff --git a/docker-compose.yml b/docker-compose.yml index 72c3cec1..95516fe0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,8 @@ services: environment: NODE_OPTIONS: "--es-module-specifier-resolution=node --experimental-modules --loader ./loader.js" NODE_ENV: development + ports: + - '3119:3119' volumes: - ./:/app - ./logs:/logs diff --git a/index.js b/index.js index bec89372..580435e0 100644 --- a/index.js +++ b/index.js @@ -18,7 +18,7 @@ import "./routes/requests"; let host = process.env.HOST || "0.0.0.0"; let port = process.env.PORT || 3119; -app.listen({ host, port }, (e, address) => { - e && err(e) && process.exit(1); - l(`CoinOS Server listening on ${address}`); + +app.listen({ host, port }, (e, h) => { + if (e) return err("Failed to start:", e.message); }); diff --git a/lib/binance.js b/lib/binance.js index 9f7f149f..e583d312 100644 --- a/lib/binance.js +++ b/lib/binance.js @@ -18,10 +18,7 @@ export default () => { store.rates[symbol] = msg.c * store.fx[symbol]; }); - // app.set("ask", msg.a); - // app.set("bid", msg.b); store.last = msg.c; - // console.log("last", msg.c, store.fx["CAD"], msg.c * store.fx["CAD"]); } catch (e) { err("binance message error", e.message); } diff --git a/lib/countries.js b/lib/countries.js new file mode 100644 index 00000000..4d5a48dc --- /dev/null +++ b/lib/countries.js @@ -0,0 +1,249 @@ +export default { + AF: "AFG", + AL: "ALB", + DZ: "DZA", + AD: "AND", + AO: "AGO", + AI: "AIA", + AQ: "ATA", + AR: "ARG", + AM: "ARM", + AW: "ABW", + AU: "AUS", + AT: "AUT", + AZ: "AZE", + BS: "BHS", + BH: "BHR", + BD: "BGD", + BB: "BRB", + BY: "BLR", + BE: "BEL", + BZ: "BLZ", + BJ: "BEN", + BM: "BMU", + BT: "BTN", + BO: "BOL", + BW: "BWA", + BV: "NOK", + BR: "BRA", + IO: "USD", + VG: "USD", + BN: "BRN", + BG: "BGR", + BF: "XOF", + BI: "BDI", + KH: "KHM", + CM: "CMR", + CA: "CAN", + IC: "EUR", + CV: "CVE", + KY: "KYD", + CF: "XAF", + TD: "TCD", + CL: "CHL", + CN: "CHN", + CX: "AUD", + CC: "AUD", + CO: "COL", + KM: "COM", + CG: "XAF", + CD: "CDF", + CK: "NZD", + CR: "CRC", + CI: "XOF", + HR: "HRV", + CU: "CUB", + CW: "ANG", + CY: "CYP", + CZ: "CZK", + DK: "DNK", + DJ: "DJI", + DM: "DMA", + DO: "DOP", + TL: "IDS", + EC: "ECU", + EG: "EGY", + SV: "SVC", + GQ: "XAF", + ER: "ERI", + EE: "EST", + ET: "ETH", + FK: "FKP", + FO: "DKK", + FJ: "FJI", + FI: "FIN", + FR: "FRA", + GF: "EUR", + PF: "XPF", + TF: "EUR", + GA: "GAB", + GM: "GMB", + GE: "GEO", + DE: "DEU", + GH: "GHA", + GI: "GIB", + GR: "GRC", + GL: "GRL", + GD: "GRD", + GP: "GLP", + GU: "GUM", + GT: "GTM", + GG: "GGY", + GN: "GIN", + GW: "XOF", + GY: "GUY", + HT: "HTI", + HM: "AUD", + HN: "HND", + HK: "HKD", + HU: "HUN", + IS: "ISL", + IN: "IND", + ID: "IDN", + IR: "IRN", + IQ: "IRQ", + IE: "IRL", + Of: "Man", + IL: "ISR", + IT: "ITA", + JM: "JAM", + JP: "JPN", + JE: "JEY", + JO: "JOR", + KZ: "KAZ", + KE: "KEN", + KI: "KIR", + XK: "XKX", + KW: "KWT", + KG: "KGZ", + LA: "LAO", + LV: "LVA", + LB: "LBN", + LS: "LSO", + LR: "LBR", + LY: "LBY", + LI: "LIE", + LT: "LTU", + LU: "LUX", + MO: "MAC", + MK: "MKD", + MG: "MDG", + MW: "MWI", + MY: "MYS", + MV: "MDV", + ML: "MLI", + MT: "MLT", + MH: "USD", + MQ: "MTQ", + MR: "MRT", + MU: "MUS", + YT: "MYT", + MX: "MEX", + FM: "FSM", + MD: "MDA", + MC: "MCO", + MN: "MNG", + ME: "MNE", + MS: "MSR", + MA: "MAR", + MZ: "MOZ", + MM: "MMR", + NA: "NAM", + NR: "NRU", + NP: "NPL", + NL: "NLD", + AN: "ANG", + NC: "XPF", + NZ: "NZD", + NI: "NIC", + NE: "NER", + NG: "NGA", + NU: "NIU", + NF: "AUD", + KP: "KPW", + MP: "USD", + NO: "NOR", + OM: "OMN", + PK: "PAK", + PW: "PLW", + PS: "PSE", + PA: "PAN", + PG: "PGK", + PY: "PRY", + PE: "PER", + PH: "PHL", + PN: "PCN", + PL: "POL", + PT: "PRT", + PR: "USD", + QA: "QAT", + RE: "REU", + RO: "ROU", + RU: "RUS", + RW: "RWA", + BL: "EUR", + SH: "GPB", + KN: "XCD", + LC: "XCD", + MF: "EUR", + PM: "EUR", + VC: "XCD", + WS: "WSM", + SM: "EUR", + ST: "STN", + SA: "SAR", + SN: "SEN", + RS: "SRB", + CS: "RSD", + SC: "SYC", + SL: "SLL", + SG: "SGP", + SX: "ANG", + SK: "SVK", + SI: "SVN", + SB: "SBD", + SO: "SOM", + ZA: "ZAR", + GS: "GBP", + KR: "KRW", + SS: "SSP", + ES: "ESP", + LK: "LKR", + SD: "SDN", + SR: "SUR", + SJ: "NOK", + SZ: "SWZ", + SE: "SWE", + CH: "CHE", + SY: "SYR", + TW: "TWN", + TJ: "TJK", + TZ: "TZA", + TH: "THA", + TG: "TGO", + TK: "TKL", + TO: "TON", + TT: "TTD", + TA: "SHP", + TN: "TUN", + TR: "TUR", + TM: "TKM", + TC: "USD", + TV: "TUV", + UM: "USD", + VI: "USD", + UG: "UGA", + UA: "UKR", + AE: "AED", + GB: "GBP", + US: "USD", + UY: "URY", + UZ: "UZB", + VU: "VUT", + VA: "VAT", + VE: "VEN", + VN: "VNM", + YE: "YEM", + ZM: "ZMB", + ZW: "ZWE" +}; diff --git a/lib/ln.js b/lib/ln.js index 13bbd004..c4445b26 100644 --- a/lib/ln.js +++ b/lib/ln.js @@ -2,6 +2,6 @@ import config from "$config"; let ln; let { LightningClient } = (await import("clightning-client")).default; -ln = new LightningClient(config.lna.dir); +ln = new LightningClient(config.lightning); export default ln; diff --git a/lib/nostr.js b/lib/nostr.js index bc75cc96..ad089bb5 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -4,7 +4,6 @@ import { Relay, RelayPool } from "nostr"; import { broadcast } from "$lib/sockets"; import store from "$lib/store"; import redis from "$lib/redis"; -import proxy from "@fastify/http-proxy"; import { nada, wait } from "$lib/utils"; export let pool; diff --git a/lib/passport.js b/lib/passport.js index 6638fe73..b559b2f9 100644 --- a/lib/passport.js +++ b/lib/passport.js @@ -6,9 +6,10 @@ import config from "$config"; import fs from "fs"; import path from "path"; import { err } from "$lib/logging"; +import { g } from "$lib/redis"; app.register(fastifySecureSession, { - key: config.jwt + key: Buffer.from(config.jwt, "hex") }); app.register(fastifyPassport.initialize()); @@ -34,10 +35,10 @@ fastifyPassport.use( async (payload, next) => { try { let { uuid } = payload; - let user = await redis.get(`user:${uuid}`); + let user = await g(`user:${uuid}`); next(null, user); } catch (e) { - console.log("payload", payload) + console.log("payload", payload); if (!e.message.includes("locked")) { console.log(e); err("problem logging in", e); diff --git a/lib/rates.js b/lib/rates.js index 8970ca64..8064a117 100644 --- a/lib/rates.js +++ b/lib/rates.js @@ -1,23 +1,23 @@ import app from "$app"; -import axios from "axios"; +import got from "got"; import config from "$config"; import fs from "fs"; -// import binance from "./binance"; +import binance from "./binance"; import { broadcast } from "./sockets"; import store from "./store"; import { err, warn } from "$lib/logging"; -// let b = binance(); -// setInterval(() => { -// b.terminate(); -// b = binance(); -// }, 360000); +let b = binance(); +setInterval(() => { + b.terminate(); + b = binance(); +}, 360000); let fetchRates = async () => { let date, fx; try { - ({ date, fx } = JSON.parse(fs.readFileSync("fx"))); + ({ date, fx } = JSON.parse(fs.readFileSync("data/fx"))); } catch (e) { warn("Failed to read fx file"); } @@ -28,26 +28,22 @@ let fetchRates = async () => { if (date !== today) { try { - let { - data: { rates: fx } - } = await axios.get( + let { rates: fx } = await got( `https://api.exchangerate.host/latest?base=USD&v={(new Date()).toISOString().split('T')[0]}` - ); - fs.writeFileSync("fx", JSON.stringify({ date, fx })); + ).json(); + fs.writeFileSync("data/fx", JSON.stringify({ date, fx })); } catch (e) { try { - let { - data: { rates: fx } - } = await axios.get( + let { rates: fx } = await got( `http://data.fixer.io/api/latest?access_key=${config.fixer}` - ); + ).json(); let USD = fx["USD"]; Object.keys(fx).map(k => { fx[k] = parseFloat((fx[k] / fx["USD"]).toFixed(6)); }); - fs.writeFileSync("fx", JSON.stringify({ date, fx })); + fs.writeFileSync("data/fx", JSON.stringify({ date, fx })); } catch (e) { err("error fetching rates", e.message); } @@ -58,7 +54,7 @@ let fetchRates = async () => { setTimeout(fetchRates, 7200000); }; -// fetchRates(); +fetchRates(); app.get("/rate", async (req, res, next) => { res.send(store.last); diff --git a/lib/redis.js b/lib/redis.js index 3aed1bd0..6aec2af7 100644 --- a/lib/redis.js +++ b/lib/redis.js @@ -1,7 +1,7 @@ import { createClient } from "redis"; const redis = createClient({ - url: "redis://redis" + url: "redis://rd" }); redis.on("error", err => console.log("redis error", err)); @@ -9,3 +9,7 @@ redis.on("error", err => console.log("redis error", err)); await redis.connect(); export default redis; + +export let g = async k => JSON.parse(await redis.get(k)); +export let s = (k, v) => redis.set(k, JSON.stringify(v)); +export let rd = redis; diff --git a/lib/register.js b/lib/register.js index fd6f27ae..9f18c15e 100644 --- a/lib/register.js +++ b/lib/register.js @@ -4,10 +4,12 @@ import { authenticator } from "otplib"; import bcrypt from "bcrypt"; import { l } from "$lib/logging"; import { v4 } from "uuid"; -import redis from "$lib/redis"; +import { s, g } from "$lib/redis"; +import { got } from "got"; export default async (user, ip, requireChallenge) => { let { password, username } = user; + l("registering", username); if (!username) throw new Error("Username required"); @@ -15,26 +17,35 @@ export default async (user, ip, requireChallenge) => { let uuid = v4(); user.uuid = uuid; - let exists = await redis.get(`user:${username}`); + let exists = await g(`user:${username}`); if (exists) throw new Error(`Username ${username} taken`); if (password) { user.password = await bcrypt.hash(password, 1); } + console.log("BOO"); + if (!config.ipxapi || ip.startsWith("127") || ip.startsWith("192")) { user.currency = "CAD"; } else { - let { countryCode } = await got(`https://ipxapi.com/api/ip?ip=${ip}`, { - headers: { authorization: `Bearer ${config.ipxapi}` } - }).json(); + let countryCode = "US"; + try { + let r = await got(`https://ipxapi.com/api/ip?ip=${ip}`, { + headers: { authorization: `Bearer ${config.ipxapi}` } + }).json(); + if (r.success) ({ countryCode } = r); + } catch (e) { + console.log(e); + } - user.currency = countries[countryCode] || "USD"; + user.currency = countries[countryCode]; } user.currencies = [...new Set([user.currency, "CAD", "USD"])]; user.fiat = false; user.otpsecret = authenticator.generateSecret(); + user.balance = 0; let d = ip.split("."); ip = ((+d[0] * 256 + +d[1]) * 256 + +d[2]) * 256 + +d[3]; @@ -42,8 +53,14 @@ export default async (user, ip, requireChallenge) => { user.ip = ip; } - await redis.set(`user:${user.uuid}`, user); - await redis.set(`user:${user.username}`, user); + console.log("user uuid", user.uuid, user.username); + + try { + await s(`user:${user.uuid}`, user); + await s(`user:${user.username}`, user); + } catch (e) { + console.log("HUH", e); + } l("new user", user.username); return user; }; diff --git a/lib/sockets.js b/lib/sockets.js index ecf15dd7..0f343937 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -91,8 +91,10 @@ app.register(async function(app) { try { if (!token || token === "null" || !jwt.decode(token)) return ws.close(code, `bad token ${token}`); + let { uuid } = jwt.decode(token); if (!uuid) throw new Error("Invalid JWT token"); + console.log("UUID", uuid) let user = await getUser(uuid); if (!user) throw new Error("User not found"); @@ -109,15 +111,6 @@ app.register(async function(app) { store.sockets[uuid][id] = ws; names[id] = uuid; - let { haspin } = user; - - let keys = await user.getKeys(); - user = user.get({ plain: true }); - user.accounts = accounts; - user.keys = keys; - user.payments = payments; - user.haspin = haspin; - ws.user = user; ws.send( JSON.stringify({ type: "login", data: pick(user, ...whitelist) }) @@ -126,6 +119,7 @@ app.register(async function(app) { JSON.stringify({ type: "version", data: config.clientVersion }) ); } catch (e) { + console.log(e) err("caught socket error", e.message); if (e.message.includes("not found")) ws.send(JSON.stringify({ type: "logout" })); diff --git a/lib/utils.js b/lib/utils.js index 1513138b..559f8531 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,5 @@ import store from "$lib/store"; -import redis from "$lib/redis"; +import { g } from "$lib/redis"; import config from "$config"; import ln from "$lib/ln"; @@ -19,7 +19,9 @@ export const requirePin = async ({ body, user }) => { }; export const getUser = async (uuid) => { - let user = await redis.get(`user:${uuid}`); + let user = g(`user:${uuid}`); + if (!user) throw new Error("user not found"); + user.haspin = !!user.pin; return user; diff --git a/lib/webhooks.js b/lib/webhooks.js index 4741932a..c071eccb 100644 --- a/lib/webhooks.js +++ b/lib/webhooks.js @@ -1,5 +1,5 @@ import config from "$config"; -import wretch from "./wretch"; +import got from "got"; import { l } from "$lib/logging"; export const callWebhook = async (invoice, payment) => { @@ -14,10 +14,9 @@ export const callWebhook = async (invoice, payment) => { let secret = config.webhooks[webhook]; l("calling webhook", webhook, amount, hash, address, text); - let res = await wretch() - .headers({ "x-webhook": secret }) - .url(webhook) - .post({ + let res = await got(webhook, { + headers: { "x-webhook": secret }, + json: { address, amount, asset, @@ -27,8 +26,8 @@ export const callWebhook = async (invoice, payment) => { received, text, webhook - }) - .res(); + } + }).res(); return res; } } catch (e) { diff --git a/lib/whitelist.js b/lib/whitelist.js index 47e9ed4e..523e9d37 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -1,7 +1,5 @@ export default [ - "account", - "account_id", - "accounts", + "balance", "address", "admin", "banner", diff --git a/package.json b/package.json index 631f61e9..408df40e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "scripts": { - "start": "node index.js", + "start": "bun index.js", "dev": "nodemon index.js" }, "dependencies": { @@ -30,6 +30,7 @@ "postmark": "^3.0.11", "pump": "^3.0.0", "query-string": "^6.13.1", + "readable-stream-clone": "^0.0.7", "redis": "^4.3.1", "sharp": "^0.31.1", "uuid": "8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3bbe6727..5c9f09dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,49 +1,19 @@ lockfileVersion: 5.4 specifiers: - '@fastify/http-proxy': ^8.4.0 '@fastify/multipart': ^7.1.2 '@fastify/passport': ^2.2.0 '@fastify/secure-session': ^5.2.0 '@fastify/static': ^6.5.0 '@fastify/websocket': ^7.0.1 - '@sequelize/core': 7.0.0-alpha.10 - async-mutex: ^0.2.4 - axios: ^0.21.1 bcrypt: ^5.0.0 - bech32: ^2.0.0 - bip32: ^2.0.5 - bip39: ^3.0.2 - bitcoinjs-lib: '6' - body-parser: ^1.19.0 - bolt11: ^1.3.2 - buffer-reverse: ^1.0.1 clightning-client: ^0.1.2 - coinselect: ^3.1.12 - compression: ^1.7.4 - cookie-parser: ^1.4.4 - cors: ^2.8.5 date-fns: ^2.21.3 - ecpair: ^2.0.1 - express: 4.17.1 - express-async-handler: ^1.1.4 - express-pino-logger: ^6.0.0 - express-session: ^1.16.2 fastify: ^4.5.3 file-type: ^18.0.0 got: ^12.5.3 - http-proxy-middleware: ^0.20.0 - imap: ^0.8.19 jsonwebtoken: ^8.5.1 - knex: ^2.3.0 - liquidjs-lib: 6.0.2-liquid.8 lnurl: ^0.24.2 - long: ^4.0.0 - mailgun-js: ^0.22.0 - mariadb: ^2.4.0 - mysql: ^2.18.1 - mysql2: ^2.2.5 - node-fetch: ^2.6.1 nodemon: ^2.0.7 nostr: ^0.2.7 otplib: ^12.0.1 @@ -58,58 +28,24 @@ specifiers: readable-stream-clone: ^0.0.7 redis: ^4.3.1 sharp: ^0.31.1 - sqlite3: ^5.0.11 - tiny-secp256k1: ^2.1.2 uuid: '8' web-push: ^3.4.4 - wretch: ^1.7.4 ws: ^7.4.6 - zeromq: 6.0.0-beta.6 dependencies: - '@fastify/http-proxy': 8.4.0 '@fastify/multipart': 7.2.0 '@fastify/passport': 2.2.0 '@fastify/secure-session': 5.2.0 '@fastify/static': 6.5.0 '@fastify/websocket': 7.1.0 - '@sequelize/core': 7.0.0-alpha.10_qwzqhxtweawy7vupwb2a75td54 - async-mutex: 0.2.6 - axios: 0.21.4 bcrypt: 5.1.0 - bech32: 2.0.0 - bip32: 2.0.6 - bip39: 3.0.4 - bitcoinjs-lib: 6.0.2 - body-parser: 1.20.1 - bolt11: 1.4.0 - buffer-reverse: 1.0.1 clightning-client: 0.1.4 - coinselect: 3.1.13 - compression: 1.7.4 - cookie-parser: 1.4.6 - cors: 2.8.5 date-fns: 2.29.3 - ecpair: 2.1.0 - express: 4.17.1 - express-async-handler: 1.2.0 - express-pino-logger: 6.0.0 - express-session: 1.17.3 fastify: 4.8.1 file-type: 18.0.0 got: 12.5.3 - http-proxy-middleware: 0.20.0 - imap: 0.8.19 jsonwebtoken: 8.5.1 - knex: 2.3.0_miwdxfk6g3dfg4gj6dnwby2onu - liquidjs-lib: 6.0.2-liquid.8 lnurl: 0.24.2 - long: 4.0.0 - mailgun-js: 0.22.0 - mariadb: 2.5.6 - mysql: 2.18.1 - mysql2: 2.3.3 - node-fetch: 2.6.7 nodemon: 2.0.20 nostr: 0.2.7 otplib: 12.0.1 @@ -123,13 +59,9 @@ dependencies: readable-stream-clone: 0.0.7 redis: 4.3.1 sharp: 0.31.1 - sqlite3: 5.1.2 - tiny-secp256k1: 2.2.1 uuid: 8.3.2 web-push: 3.5.0 - wretch: 1.7.10 ws: 7.5.9 - zeromq: 6.0.0-beta.6 devDependencies: prettier: 1.19.1 @@ -190,16 +122,6 @@ packages: fastify-plugin: 4.3.0 dev: false - /@fastify/http-proxy/8.4.0: - resolution: {integrity: sha512-H8nwsmawFtKKRE6uhh1BtF1gQi/l147SmLsDGxB0HdYTHzjXz6uSQO3lEVmY7unKMzbArRjdoJQkEGpScszdSw==} - dependencies: - '@fastify/reply-from': 8.3.1 - ws: 8.9.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@fastify/multipart/7.2.0: resolution: {integrity: sha512-LwfwbCLy30Be1pa5q7F8xCTygxJdEWkfkQhD4OWZ13+vMH4tP/6Bu3OkSTlFatxLAmbEl2UpHLf7CU7w7csRIw==} dependencies: @@ -220,18 +142,6 @@ packages: fastify-plugin: 4.3.0 dev: false - /@fastify/reply-from/8.3.1: - resolution: {integrity: sha512-fRByAvTMXuBuYIimcinukOB3YdmqtYPeoybXIBNY0aPVgetHkmCVffBo/M4pEOib9Pes8wuoYL4VawI65aHl4w==} - dependencies: - '@fastify/error': 3.0.0 - end-of-stream: 1.4.4 - fast-querystring: 1.0.0 - fastify-plugin: 4.3.0 - pump: 3.0.0 - tiny-lru: 10.0.1 - undici: 5.14.0 - dev: false - /@fastify/secure-session/5.2.0: resolution: {integrity: sha512-oRWKdHwWUzp4rsJ3GnR8w8doE+7vllWMtohBVp77bENkhm4/OvofaO6PJLJuQvKF7XJAKiGip29dX1RsllKT7g==} hasBin: true @@ -265,11 +175,6 @@ packages: - utf-8-validate dev: false - /@gar/promisify/1.1.3: - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - dev: false - optional: true - /@mapbox/node-pre-gyp/1.0.10: resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==} hasBin: true @@ -288,23 +193,6 @@ packages: - supports-color dev: false - /@npmcli/fs/1.1.1: - resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.3.8 - dev: false - optional: true - - /@npmcli/move-file/1.1.2: - resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} - engines: {node: '>=10'} - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - dev: false - optional: true - /@otplib/core/12.0.1: resolution: {integrity: sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==} dev: false @@ -387,61 +275,6 @@ packages: '@redis/client': 1.3.0 dev: false - /@sequelize/core/7.0.0-alpha.10_qwzqhxtweawy7vupwb2a75td54: - resolution: {integrity: sha512-uikpWaCiIaijsgoa9cH+3jCQl8r+FaQPhoE8AOJYvPwxOx52E1JZnRPMXNnlpbFy3Xu0qekrc5LBJq7IR8UB0Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - ibm_db: '*' - mariadb: '*' - mysql2: '*' - odbc: '*' - pg: '*' - pg-hstore: '*' - snowflake-sdk: '*' - sqlite3: '*' - tedious: '*' - peerDependenciesMeta: - ibm_db: - optional: true - mariadb: - optional: true - mysql2: - optional: true - odbc: - optional: true - pg: - optional: true - pg-hstore: - optional: true - snowflake-sdk: - optional: true - sqlite3: - optional: true - tedious: - optional: true - dependencies: - '@types/debug': 4.1.7 - debug: 4.3.4 - dottie: 2.0.2 - inflection: 1.13.4 - lodash: 4.17.21 - mariadb: 2.5.6 - moment: 2.29.4 - moment-timezone: 0.5.37 - mysql2: 2.3.3 - pg-connection-string: 2.5.0 - retry-as-promised: 5.0.0 - semver: 7.3.8 - sequelize-pool: 7.1.0 - sqlite3: 5.1.2 - toposort-class: 1.0.1 - uuid: 8.3.2 - validator: 13.7.0 - wkx: 0.5.0 - transitivePeerDependencies: - - supports-color - dev: false - /@sindresorhus/is/5.3.0: resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==} engines: {node: '>=14.16'} @@ -458,76 +291,20 @@ packages: resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} dev: false - /@tootallnate/once/1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: false - optional: true - /@types/bn.js/4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: '@types/node': 18.8.5 dev: false - /@types/debug/4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} - dependencies: - '@types/ms': 0.7.31 - dev: false - - /@types/geojson/7946.0.10: - resolution: {integrity: sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==} - dev: false - /@types/http-cache-semantics/4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: false - /@types/ms/0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: false - - /@types/node/10.12.18: - resolution: {integrity: sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==} - dev: false - - /@types/node/11.11.6: - resolution: {integrity: sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==} - dev: false - - /@types/node/13.13.52: - resolution: {integrity: sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ==} - dev: false - - /@types/node/17.0.45: - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - dev: false - /@types/node/18.8.5: resolution: {integrity: sha512-Bq7G3AErwe5A/Zki5fdD3O6+0zDChhg671NfPjtIcbtzDNZTv4NPKMRFr7gtYPG7y+B8uTiNK4Ngd9T0FTar6Q==} dev: false - /@types/randombytes/2.0.0: - resolution: {integrity: sha512-bz8PhAVlwN72vqefzxa14DKNT8jK/mV66CSjwdVQM/k3Th3EPKfUtdMniwZgMedQTFuywAsfjnZsg+pEnltaMA==} - dependencies: - '@types/node': 18.8.5 - dev: false - - /@types/wif/2.0.2: - resolution: {integrity: sha512-IiIuBeJzlh4LWJ7kVTrX0nwB60OG0vvGTaWC/SgSbVFw7uYUTF6gEuvDZ1goWkeirekJDD58Y8g7NljQh2fNkA==} - dependencies: - '@types/node': 18.8.5 - dev: false - - /@vulpemventures/secp256k1-zkp/2.1.0: - resolution: {integrity: sha512-86EGAkPqEwy5KKeC8Ow8+fMhSiFtorvIQQ9yhTwwHqT0UdUVOW/Fu2ZDoooQK5KAQbyISBB+vf0jK3eYH+Dlqw==} - engines: {node: '>=12.0.0'} - dependencies: - '@types/node': 13.13.52 - long: 4.0.0 - dev: false - /abbrev/1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} dev: false @@ -551,20 +328,6 @@ packages: negotiator: 0.6.3 dev: false - /agent-base/4.2.1: - resolution: {integrity: sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==} - engines: {node: '>= 4.0.0'} - dependencies: - es6-promisify: 5.0.0 - dev: false - - /agent-base/4.3.0: - resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==} - engines: {node: '>= 4.0.0'} - dependencies: - es6-promisify: 5.0.0 - dev: false - /agent-base/6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -574,27 +337,6 @@ packages: - supports-color dev: false - /agentkeepalive/4.2.1: - resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==} - engines: {node: '>= 8.0.0'} - dependencies: - debug: 4.3.4 - depd: 1.1.2 - humanize-ms: 1.2.1 - transitivePeerDependencies: - - supports-color - dev: false - optional: true - - /aggregate-error/3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: false - optional: true - /ajv-formats/2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependenciesMeta: @@ -649,15 +391,6 @@ packages: readable-stream: 3.6.0 dev: false - /are-we-there-yet/3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.0 - dev: false - optional: true - /args/5.0.3: resolution: {integrity: sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==} engines: {node: '>= 6.0.0'} @@ -681,25 +414,6 @@ packages: safer-buffer: 2.1.2 dev: false - /ast-types/0.14.2: - resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} - engines: {node: '>=4'} - dependencies: - tslib: 2.4.0 - dev: false - - /async-mutex/0.2.6: - resolution: {integrity: sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==} - dependencies: - tslib: 2.4.0 - dev: false - - /async/2.6.4: - resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} - dependencies: - lodash: 4.17.21 - dev: false - /async/3.2.3: resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} dev: false @@ -708,10 +422,6 @@ packages: resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} dev: false - /asynckit/0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false - /atomic-sleep/1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -727,14 +437,6 @@ packages: - supports-color dev: false - /axios/0.21.4: - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.2 - transitivePeerDependencies: - - debug - dev: false - /axios/0.25.0: resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: @@ -777,10 +479,6 @@ packages: resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==} dev: false - /bignumber.js/9.0.0: - resolution: {integrity: sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==} - dev: false - /bignumber.js/9.0.2: resolution: {integrity: sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==} dev: false @@ -790,54 +488,11 @@ packages: engines: {node: '>=8'} dev: false - /bindings/1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - dev: false - - /bip174-liquid/1.0.3: - resolution: {integrity: sha512-e69sC0Cq2tBJuhG2+wieXv40DN13YBR/wbIjZp4Mqwpar5vQm8Ldqijdd6N33XG7LtfvQi/zKm5fSzdPY/9mgw==} - engines: {node: '>=8.0.0'} - dev: false - /bip174/2.1.0: resolution: {integrity: sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==} engines: {node: '>=8.0.0'} dev: false - /bip32/2.0.6: - resolution: {integrity: sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==} - engines: {node: '>=6.0.0'} - dependencies: - '@types/node': 10.12.18 - bs58check: 2.1.2 - create-hash: 1.2.0 - create-hmac: 1.1.7 - tiny-secp256k1: 1.1.6 - typeforce: 1.18.0 - wif: 2.0.6 - dev: false - - /bip39/3.0.4: - resolution: {integrity: sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==} - dependencies: - '@types/node': 11.11.6 - create-hash: 1.2.0 - pbkdf2: 3.1.2 - randombytes: 2.1.0 - dev: false - - /bip66/1.1.5: - resolution: {integrity: sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /bitcoin-ops/1.4.1: - resolution: {integrity: sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==} - dev: false - /bitcoinjs-lib/6.0.2: resolution: {integrity: sha512-I994pGt9cL5s5OA6mkv1e8IuYcsKN2ORXnWbkqAXLNGvEnOHBhKBSvCjFl7YC2uVoJnfr/iwq7JMrq575SYO5w==} engines: {node: '>=8.0.0'} @@ -860,35 +515,10 @@ packages: readable-stream: 3.6.0 dev: false - /blech32/1.1.2: - resolution: {integrity: sha512-C5qxzoF9KyX88X8Zz18cZ6BOeL0n5/Eg/cDot1frntkArRMwg1djNim5wA6QFWwu0lJ1LN8iiRMN4Lp2kZzdfA==} - engines: {node: '>=10'} - dependencies: - long: 4.0.0 - dev: false - /bn.js/4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} dev: false - /body-parser/1.19.0: - resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.0 - content-type: 1.0.4 - debug: 2.6.9 - depd: 1.1.2 - http-errors: 1.7.2 - iconv-lite: 0.4.24 - on-finished: 2.3.0 - qs: 6.7.0 - raw-body: 2.4.0 - type-is: 1.6.18 - transitivePeerDependencies: - - supports-color - dev: false - /body-parser/1.20.0: resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -909,26 +539,6 @@ packages: - supports-color dev: false - /body-parser/1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.4 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - /bolt11/1.3.4: resolution: {integrity: sha512-x4lHDv0oid13lGlZU7cl/5gx9nRwjB2vgK/uB3c50802Wh+9WjWQMwzD2PCETHylUijx2iBAqUQYbx3ZgwF06Q==} dependencies: @@ -942,19 +552,6 @@ packages: secp256k1: 4.0.3 dev: false - /bolt11/1.4.0: - resolution: {integrity: sha512-TeGIOpFNrvNA1XGvwBr+lYmzKfoJeyMRt7nsGmIci+5gbmSz7s46jwKLNYXH3IoxV7fjmYUEUu2NM19n9w0msg==} - dependencies: - '@types/bn.js': 4.11.6 - bech32: 1.1.4 - bitcoinjs-lib: 6.0.2 - bn.js: 4.12.0 - create-hash: 1.2.0 - lodash: 4.17.21 - safe-buffer: 5.2.1 - secp256k1: 4.0.3 - dev: false - /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -997,10 +594,6 @@ packages: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false - /buffer-reverse/1.0.1: - resolution: {integrity: sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==} - dev: false - /buffer/5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -1015,55 +608,11 @@ packages: ieee754: 1.2.1 dev: false - /busboy/1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /bytes/3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: false - - /bytes/3.1.0: - resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} - engines: {node: '>= 0.8'} - dev: false - /bytes/3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} dev: false - /cacache/15.3.0: - resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} - engines: {node: '>= 10'} - dependencies: - '@npmcli/fs': 1.1.1 - '@npmcli/move-file': 1.1.2 - chownr: 2.0.0 - fs-minipass: 2.1.0 - glob: 7.2.3 - infer-owner: 1.0.4 - lru-cache: 6.0.0 - minipass: 3.3.4 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - mkdirp: 1.0.4 - p-map: 4.0.0 - promise-inflight: 1.0.1 - rimraf: 3.0.2 - ssri: 8.0.1 - tar: 6.1.11 - unique-filename: 1.1.1 - transitivePeerDependencies: - - bluebird - dev: false - optional: true - /cacheable-lookup/7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} engines: {node: '>=14.16'} @@ -1134,12 +683,6 @@ packages: safe-buffer: 5.2.1 dev: false - /clean-stack/2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: false - optional: true - /clightning-client/0.1.4: resolution: {integrity: sha512-M5UclkZcKvh15CmZOpbM0p6Dyua3ixRlgp7EP5IhL9jYWW8AL7qpROWLQFqSW2ANy48W1vGlw9igSyWV2A/iqw==} dependencies: @@ -1154,15 +697,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /co/4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: false - - /coinselect/3.1.13: - resolution: {integrity: sha512-iJOrKH/7N9gX0jRkxgOHuGjvzvoxUMSeylDhH1sHn+CjLjdin5R0Hz2WEBu/jrZV5OrHcm+6DMzxwu9zb5mSZg==} - dev: false - /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1208,45 +742,11 @@ packages: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} dev: false - /combined-stream/1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: false - /commander/9.3.0: resolution: {integrity: sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==} engines: {node: ^12.20.0 || >=14} dev: false - /commander/9.4.1: - resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} - engines: {node: ^12.20.0 || >=14} - dev: false - - /compressible/2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - - /compression/1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /concat-map/0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: false @@ -1255,13 +755,6 @@ packages: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: false - /content-disposition/0.5.3: - resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.1.2 - dev: false - /content-disposition/0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -1274,50 +767,15 @@ packages: engines: {node: '>= 0.6'} dev: false - /cookie-parser/1.4.6: - resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==} - engines: {node: '>= 0.8.0'} - dependencies: - cookie: 0.4.1 - cookie-signature: 1.0.6 - dev: false - /cookie-signature/1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: false - /cookie/0.4.0: - resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: false - /cookie/0.4.1: - resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} - engines: {node: '>= 0.6'} - dev: false - - /cookie/0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - dev: false - - /cookie/0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: false - - /core-util-is/1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: false - - /cors/2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - dev: false - /create-hash/1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} dependencies: @@ -1328,21 +786,6 @@ packages: sha.js: 2.4.11 dev: false - /create-hmac/1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - dependencies: - cipher-base: 1.0.4 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: false - - /data-uri-to-buffer/1.2.0: - resolution: {integrity: sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==} - dev: false - /date-fns/2.29.3: resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} engines: {node: '>=0.11'} @@ -1363,28 +806,6 @@ packages: ms: 2.0.0 dev: false - /debug/3.1.0: - resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - - /debug/3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: false - /debug/3.2.7_supports-color@5.5.0: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1426,51 +847,20 @@ packages: engines: {node: '>=4.0.0'} dev: false - /deep-is/0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: false - /defer-to-connect/2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} dev: false - /degenerator/1.0.4: - resolution: {integrity: sha512-EMAC+riLSC64jKfOs1jp8J7M4ZXstUUwTdwFBEv6HOzL/Ae+eAzMKEK0nJnpof2fnw9IOjmE6u6qXFejVyk8AA==} - dependencies: - ast-types: 0.14.2 - escodegen: 1.14.3 - esprima: 3.1.3 - dev: false - - /delayed-stream/1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: false - /delegates/1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} dev: false - /denque/2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - dev: false - - /depd/1.1.2: - resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} - engines: {node: '>= 0.6'} - dev: false - /depd/2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} dev: false - /destroy/1.0.4: - resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} - dev: false - /destroy/1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -1481,10 +871,6 @@ packages: engines: {node: '>=8'} dev: false - /dottie/2.0.2: - resolution: {integrity: sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==} - dev: false - /duplexify/4.1.2: resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==} dependencies: @@ -1500,15 +886,6 @@ packages: safe-buffer: 5.2.1 dev: false - /ecpair/2.1.0: - resolution: {integrity: sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==} - engines: {node: '>=8.0.0'} - dependencies: - randombytes: 2.1.0 - typeforce: 1.18.0 - wif: 2.0.6 - dev: false - /ee-first/1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false @@ -1534,52 +911,18 @@ packages: engines: {node: '>= 0.8'} dev: false - /encoding/0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - dev: false - optional: true - /end-of-stream/1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: once: 1.4.0 dev: false - /env-paths/2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: false - optional: true - - /err-code/2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: false - optional: true - /error/7.2.1: resolution: {integrity: sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==} dependencies: string-template: 0.2.1 dev: false - /es6-promise/4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - dev: false - - /es6-promisify/5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - dependencies: - es6-promise: 4.2.8 - dev: false - - /escalade/3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: false - /escape-html/1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} dev: false @@ -1589,46 +932,6 @@ packages: engines: {node: '>=0.8.0'} dev: false - /escodegen/1.14.3: - resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} - engines: {node: '>=4.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 4.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - dev: false - - /esm/3.2.25: - resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} - engines: {node: '>=6'} - dev: false - - /esprima/3.1.3: - resolution: {integrity: sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /esprima/4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /estraverse/4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: false - - /esutils/2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: false - /etag/1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -1639,10 +942,6 @@ packages: engines: {node: '>=6'} dev: false - /eventemitter3/4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: false - /events/3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -1653,10 +952,6 @@ packages: engines: {node: '>=6'} dev: false - /express-async-handler/1.2.0: - resolution: {integrity: sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==} - dev: false - /express-handlebars/6.0.3: resolution: {integrity: sha512-cG6/CeriAhAYKC9+VivXtj41+HNDB6xnigwzcXv/m9BBtijR2Yg5I5VWsK6nPc1+E06FIS23nGfr2COUv8sG3A==} engines: {node: '>=v12.22.9'} @@ -1666,66 +961,6 @@ packages: handlebars: 4.7.7 dev: false - /express-pino-logger/6.0.0: - resolution: {integrity: sha512-YjBnalqgsNylRnWEpQGf8YzBP54stpoqX/o+SnpGr04OB7dRIQlsC1qvutFOyRjhLhXIWCe43pYJcjp9zM1Ccg==} - dependencies: - pino-http: 5.8.0 - dev: false - - /express-session/1.17.3: - resolution: {integrity: sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==} - engines: {node: '>= 0.8.0'} - dependencies: - cookie: 0.4.2 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - on-headers: 1.0.2 - parseurl: 1.3.3 - safe-buffer: 5.2.1 - uid-safe: 2.1.5 - transitivePeerDependencies: - - supports-color - dev: false - - /express/4.17.1: - resolution: {integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.19.0 - content-disposition: 0.5.3 - content-type: 1.0.4 - cookie: 0.4.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 1.1.2 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.1.2 - fresh: 0.5.2 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.3.0 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.7.0 - range-parser: 1.2.1 - safe-buffer: 5.1.2 - send: 0.17.1 - serve-static: 1.14.1 - setprototypeof: 1.1.1 - statuses: 1.5.0 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /express/4.18.1: resolution: {integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==} engines: {node: '>= 0.10.0'} @@ -1765,10 +1000,6 @@ packages: - supports-color dev: false - /extend/3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false - /fast-decode-uri-component/1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} dev: false @@ -1788,10 +1019,6 @@ packages: rfdc: 1.3.0 dev: false - /fast-levenshtein/2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: false - /fast-querystring/1.0.0: resolution: {integrity: sha512-3LQi62IhQoDlmt4ULCYmh17vRO2EtS7hTSsG4WwoKWgV7GLMKBOecEh+aiavASnLx8I2y89OD33AGLo0ccRhzA==} dependencies: @@ -1811,12 +1038,6 @@ packages: resolution: {integrity: sha512-qKRta6N7BWEFVlyonVY/V+BMLgFqktCUV0QjT259ekAIlbVrMaFnFLxJ4s/JPl4tou56S1BzPufI60bLe29fHA==} dev: false - /fast-url-parser/1.1.3: - resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} - dependencies: - punycode: 1.4.1 - dev: false - /fastify-plugin/3.0.1: resolution: {integrity: sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==} dev: false @@ -1861,10 +1082,6 @@ packages: token-types: 5.0.1 dev: false - /file-uri-to-path/1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: false - /fill-range/7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1877,21 +1094,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /finalhandler/1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - /finalhandler/1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} @@ -1916,10 +1118,6 @@ packages: safe-regex2: 2.0.0 dev: false - /flatstr/1.0.12: - resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==} - dev: false - /follow-redirects/1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -1935,15 +1133,6 @@ packages: engines: {node: '>= 14.17'} dev: false - /form-data/2.5.1: - resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} - engines: {node: '>= 0.12'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - /forwarded/0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -1977,14 +1166,6 @@ packages: dev: false optional: true - /ftp/0.3.10: - resolution: {integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==} - engines: {node: '>=0.8.0'} - dependencies: - readable-stream: 1.1.14 - xregexp: 2.0.0 - dev: false - /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: false @@ -2004,27 +1185,6 @@ packages: wide-align: 1.1.5 dev: false - /gauge/4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false - optional: true - - /generate-function/2.3.1: - resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} - dependencies: - is-property: 1.0.2 - dev: false - /generic-pool/3.8.2: resolution: {integrity: sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==} engines: {node: '>= 4'} @@ -2038,33 +1198,11 @@ packages: has-symbols: 1.0.3 dev: false - /get-package-type/0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: false - /get-stream/6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} dev: false - /get-uri/2.0.4: - resolution: {integrity: sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==} - dependencies: - data-uri-to-buffer: 1.2.0 - debug: 2.6.9 - extend: 3.0.2 - file-uri-to-path: 1.0.0 - ftp: 0.3.10 - readable-stream: 2.3.7 - transitivePeerDependencies: - - supports-color - dev: false - - /getopts/2.3.0: - resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==} - dev: false - /github-from-package/0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} dev: false @@ -2186,28 +1324,6 @@ packages: resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} dev: false - /http-errors/1.7.2: - resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.1 - statuses: 1.5.0 - toidentifier: 1.0.0 - dev: false - - /http-errors/1.7.3: - resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.4 - setprototypeof: 1.1.1 - statuses: 1.5.0 - toidentifier: 1.0.0 - dev: false - /http-errors/2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -2219,51 +1335,6 @@ packages: toidentifier: 1.0.1 dev: false - /http-proxy-agent/2.1.0: - resolution: {integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==} - engines: {node: '>= 4.5.0'} - dependencies: - agent-base: 4.3.0 - debug: 3.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /http-proxy-agent/4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - optional: true - - /http-proxy-middleware/0.20.0: - resolution: {integrity: sha512-dNJAk71nEJhPiAczQH9hGvE/MT9kEs+zn2Dh+Hi94PGZe1GluQirC7mw5rdREUtWx6qGS1Gu0bZd4qEAg+REgw==} - engines: {node: '>=8.0.0'} - dependencies: - http-proxy: 1.18.1 - is-glob: 4.0.3 - lodash: 4.17.21 - micromatch: 4.0.5 - transitivePeerDependencies: - - debug - dev: false - - /http-proxy/1.18.1: - resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} - engines: {node: '>=8.0.0'} - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.2 - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - dev: false - /http2-wrapper/2.2.0: resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==} engines: {node: '>=10.19.0'} @@ -2279,16 +1350,6 @@ packages: urlsafe-base64: 1.0.0 dev: false - /https-proxy-agent/3.0.1: - resolution: {integrity: sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==} - engines: {node: '>= 4.5.0'} - dependencies: - agent-base: 4.3.0 - debug: 3.2.7 - transitivePeerDependencies: - - supports-color - dev: false - /https-proxy-agent/5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -2299,13 +1360,6 @@ packages: - supports-color dev: false - /humanize-ms/1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - dependencies: - ms: 2.1.3 - dev: false - optional: true - /iconv-lite/0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -2313,13 +1367,6 @@ packages: safer-buffer: 2.1.2 dev: false - /iconv-lite/0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - /ieee754/1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: false @@ -2328,76 +1375,19 @@ packages: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} dev: false - /imap/0.8.19: - resolution: {integrity: sha512-z5DxEA1uRnZG73UcPA4ES5NSCGnPuuouUx43OPX7KZx1yzq3N8/vx2mtXEShT5inxB3pRgnfG1hijfu7XN2YMw==} - engines: {node: '>=0.8.0'} - dependencies: - readable-stream: 1.1.14 - utf7: 1.0.2 - dev: false - - /imurmurhash/0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: false - optional: true - - /indent-string/4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: false - optional: true - - /infer-owner/1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - dev: false - optional: true - - /inflection/1.12.0: - resolution: {integrity: sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==} - engines: {'0': node >= 0.4.0} - dev: false - - /inflection/1.13.4: - resolution: {integrity: sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==} - engines: {'0': node >= 0.4.0} - dev: false - - /inflection/1.3.8: - resolution: {integrity: sha512-xRvG6XhAkbneGO5BXP0uKyGkzmZ2bBbrFkx4ZVNx2TmsECbiq/pJapbbx/NECh+E85IfZwW5+IeVNJfkQgavag==} - engines: {'0': node >= 0.4.0} - dev: false - /inflight/1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 - wrappy: 1.0.2 - dev: false - - /inherits/2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: false - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false - - /ini/1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: false - - /interpret/2.2.0: - resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} - engines: {node: '>= 0.10'} + wrappy: 1.0.2 dev: false - /ip/1.1.5: - resolution: {integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==} + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false - /ip/1.1.8: - resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: false /ip/2.0.0: @@ -2420,12 +1410,6 @@ packages: binary-extensions: 2.2.0 dev: false - /is-core-module/2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} - dependencies: - has: 1.0.3 - dev: false - /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2443,38 +1427,11 @@ packages: is-extglob: 2.1.1 dev: false - /is-lambda/1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - dev: false - optional: true - /is-number/7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} dev: false - /is-property/1.0.2: - resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} - dev: false - - /is-stream/1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} - engines: {node: '>=0.10.0'} - dev: false - - /isarray/0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - dev: false - - /isarray/1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: false - - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false - optional: true - /joycon/3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -2540,68 +1497,11 @@ packages: json-buffer: 3.0.1 dev: false - /knex/2.3.0_miwdxfk6g3dfg4gj6dnwby2onu: - resolution: {integrity: sha512-WMizPaq9wRMkfnwKXKXgBZeZFOSHGdtoSz5SaLAVNs3WRDfawt9O89T4XyH52PETxjV8/kRk0Yf+8WBEP/zbYw==} - engines: {node: '>=12'} - hasBin: true - peerDependencies: - better-sqlite3: '*' - mysql: '*' - mysql2: '*' - pg: '*' - pg-native: '*' - sqlite3: '*' - tedious: '*' - peerDependenciesMeta: - better-sqlite3: - optional: true - mysql: - optional: true - mysql2: - optional: true - pg: - optional: true - pg-native: - optional: true - sqlite3: - optional: true - tedious: - optional: true - dependencies: - colorette: 2.0.19 - commander: 9.4.1 - debug: 4.3.4 - escalade: 3.1.1 - esm: 3.2.25 - get-package-type: 0.1.0 - getopts: 2.3.0 - interpret: 2.2.0 - lodash: 4.17.21 - mysql: 2.18.1 - mysql2: 2.3.3 - pg-connection-string: 2.5.0 - rechoir: 0.8.0 - resolve-from: 5.0.0 - sqlite3: 5.1.2 - tarn: 3.0.2 - tildify: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: false - /leven/2.1.0: resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==} engines: {node: '>=0.10.0'} dev: false - /levn/0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: false - /light-my-request/5.6.1: resolution: {integrity: sha512-sbJnC1UBRivi9L1kICr3CESb82pNiPNB3TvtdIrZZqW0Qh8uDXvoywMmWKZlihDcmw952CMICCzM+54LDf+E+g==} dependencies: @@ -2622,29 +1522,6 @@ packages: - supports-color dev: false - /liquidjs-lib/6.0.2-liquid.8: - resolution: {integrity: sha512-KCtO/lXfKyZUJeZ1Mok3FQ5/viNLmKEEhGEC3iySnBakIII2rd1ijn3np16/3LzBiQhQ+tFm4Q1NYEG3YhWBTg==} - engines: {node: '>=8.0.0'} - dependencies: - '@types/randombytes': 2.0.0 - '@types/wif': 2.0.2 - '@vulpemventures/secp256k1-zkp': 2.1.0 - axios: 0.21.4 - bech32: 2.0.0 - bip174-liquid: 1.0.3 - bip66: 1.1.5 - bitcoin-ops: 1.4.1 - blech32: 1.1.2 - bs58check: 2.1.2 - create-hash: 1.2.0 - ecpair: 2.1.0 - typeforce: 1.18.0 - varuint-bitcoin: 1.1.2 - wif: 2.0.6 - transitivePeerDependencies: - - debug - dev: false - /lnurl-offline/1.1.1: resolution: {integrity: sha512-iyryv7hLS/MdDzNg6wzVgRZyA8rwjyZpn61KXHlLwr9YoDc8Vf+YXvH273fNUD+5WQC6rh+pxZN0lrNvvUnVQQ==} dev: false @@ -2699,32 +1576,11 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false - /long/4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - dev: false - - /long/5.2.0: - resolution: {integrity: sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==} - dev: false - /lowercase-keys/3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false - /lru-cache/4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - dev: false - - /lru-cache/5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: false - /lru-cache/6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -2732,24 +1588,6 @@ packages: yallist: 4.0.0 dev: false - /mailgun-js/0.22.0: - resolution: {integrity: sha512-a2alg5nuTZA9Psa1pSEIEsbxr1Zrmqx4VkgGCQ30xVh0kIH7Bu57AYILo+0v8QLSdXtCyLaS+KVmdCrQo0uWFA==} - engines: {node: '>=6.0.0'} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - dependencies: - async: 2.6.4 - debug: 4.3.4 - form-data: 2.5.1 - inflection: 1.12.0 - is-stream: 1.1.0 - path-proxy: 1.0.0 - promisify-call: 2.0.4 - proxy-agent: 3.1.1 - tsscmp: 1.0.6 - transitivePeerDependencies: - - supports-color - dev: false - /make-dir/3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -2757,45 +1595,6 @@ packages: semver: 6.3.0 dev: false - /make-fetch-happen/9.1.0: - resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} - engines: {node: '>= 10'} - dependencies: - agentkeepalive: 4.2.1 - cacache: 15.3.0 - http-cache-semantics: 4.1.0 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - is-lambda: 1.0.1 - lru-cache: 6.0.0 - minipass: 3.3.4 - minipass-collect: 1.0.2 - minipass-fetch: 1.4.1 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.3 - promise-retry: 2.0.1 - socks-proxy-agent: 6.2.1 - ssri: 8.0.1 - transitivePeerDependencies: - - bluebird - - supports-color - dev: false - optional: true - - /mariadb/2.5.6: - resolution: {integrity: sha512-zBx7loYY5GzLl8Y6AKxGXfY9DUYIIdGrmEORPOK9FEu0pg5ZLBKCGJuucHwKADxTBxKY7eM4rxndqxRcnMZKIw==} - engines: {node: '>= 10.13'} - dependencies: - '@types/geojson': 7946.0.10 - '@types/node': 17.0.45 - denque: 2.1.0 - iconv-lite: 0.6.3 - long: 5.2.0 - moment-timezone: 0.5.37 - please-upgrade-node: 3.2.0 - dev: false - /md5.js/1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} dependencies: @@ -2818,14 +1617,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: false - /mime-db/1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2879,50 +1670,6 @@ packages: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} dev: false - /minipass-collect/1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.4 - dev: false - optional: true - - /minipass-fetch/1.4.1: - resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.4 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - dev: false - optional: true - - /minipass-flush/1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.4 - dev: false - optional: true - - /minipass-pipeline/1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.4 - dev: false - optional: true - - /minipass-sized/1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - dependencies: - minipass: 3.3.4 - dev: false - optional: true - /minipass/3.3.4: resolution: {integrity: sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==} engines: {node: '>=8'} @@ -2948,16 +1695,6 @@ packages: hasBin: true dev: false - /moment-timezone/0.5.37: - resolution: {integrity: sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==} - dependencies: - moment: 2.29.4 - dev: false - - /moment/2.29.4: - resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} - dev: false - /mri/1.1.4: resolution: {integrity: sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==} engines: {node: '>=4'} @@ -2967,10 +1704,6 @@ packages: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false - /ms/2.1.1: - resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} - dev: false - /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false @@ -2979,41 +1712,6 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false - /mysql/2.18.1: - resolution: {integrity: sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==} - engines: {node: '>= 0.6'} - dependencies: - bignumber.js: 9.0.0 - readable-stream: 2.3.7 - safe-buffer: 5.1.2 - sqlstring: 2.3.1 - dev: false - - /mysql2/2.3.3: - resolution: {integrity: sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==} - engines: {node: '>= 8.0'} - dependencies: - denque: 2.1.0 - generate-function: 2.3.1 - iconv-lite: 0.6.3 - long: 4.0.0 - lru-cache: 6.0.0 - named-placeholders: 1.1.2 - seq-queue: 0.0.5 - sqlstring: 2.3.3 - dev: false - - /named-placeholders/1.1.2: - resolution: {integrity: sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==} - engines: {node: '>=6.0.0'} - dependencies: - lru-cache: 4.1.5 - dev: false - - /nan/2.17.0: - resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} - dev: false - /napi-build-utils/1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: false @@ -3027,11 +1725,6 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: false - /netmask/1.0.6: - resolution: {integrity: sha512-3DWDqAtIiPSkBXZyYEjwebfK56nrlQfRGt642fu8RPaL+ePu750+HCMHxjJCG3iEHq/0aeMvX6KIzlv7nuhfrA==} - engines: {node: '>= 0.4.0'} - dev: false - /noble-secp256k1/1.2.14: resolution: {integrity: sha512-GSCXyoZBUaaPwVWdYncMEmzlSUjF9J/YeEHpklYJCyg8wPuJP3NzDx0BkiwArzINkdX2HJHvUJhL6vVWPOQQcg==} deprecated: Switch to namespaced @noble/secp256k1 for security and feature updates @@ -3048,10 +1741,6 @@ packages: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} dev: false - /node-addon-api/4.3.0: - resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} - dev: false - /node-addon-api/5.0.0: resolution: {integrity: sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==} dev: false @@ -3073,28 +1762,6 @@ packages: hasBin: true dev: false - /node-gyp/8.4.1: - resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} - engines: {node: '>= 10.12.0'} - hasBin: true - requiresBuild: true - dependencies: - env-paths: 2.2.1 - glob: 7.2.3 - graceful-fs: 4.2.10 - make-fetch-happen: 9.1.0 - nopt: 5.0.0 - npmlog: 6.0.2 - rimraf: 3.0.2 - semver: 7.3.8 - tar: 6.1.11 - which: 2.0.2 - transitivePeerDependencies: - - bluebird - - supports-color - dev: false - optional: true - /nodemon/2.0.20: resolution: {integrity: sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==} engines: {node: '>=8.10.0'} @@ -3156,17 +1823,6 @@ packages: set-blocking: 2.0.0 dev: false - /npmlog/6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - are-we-there-yet: 3.0.1 - console-control-strings: 1.1.0 - gauge: 4.0.4 - set-blocking: 2.0.0 - dev: false - optional: true - /object-assign/4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -3184,13 +1840,6 @@ packages: resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==} dev: false - /on-finished/2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - /on-finished/2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -3198,29 +1847,12 @@ packages: ee-first: 1.1.1 dev: false - /on-headers/1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: false - /once/1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 dev: false - /optionator/0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - dev: false - /otplib/12.0.1: resolution: {integrity: sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==} dependencies: @@ -3241,39 +1873,6 @@ packages: yocto-queue: 0.1.0 dev: false - /p-map/4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: false - optional: true - - /pac-proxy-agent/3.0.1: - resolution: {integrity: sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==} - dependencies: - agent-base: 4.3.0 - debug: 4.3.4 - get-uri: 2.0.4 - http-proxy-agent: 2.1.0 - https-proxy-agent: 3.0.1 - pac-resolver: 3.0.0 - raw-body: 2.5.1 - socks-proxy-agent: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /pac-resolver/3.0.0: - resolution: {integrity: sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==} - dependencies: - co: 4.6.0 - degenerator: 1.0.4 - ip: 1.1.8 - netmask: 1.0.6 - thunkify: 2.1.2 - dev: false - /parseurl/1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -3303,40 +1902,15 @@ packages: engines: {node: '>=0.10.0'} dev: false - /path-parse/1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: false - - /path-proxy/1.0.0: - resolution: {integrity: sha512-p9IuY9FRY1nU59RDW+tnLL6qMxmBnY03WGYxzy1FcqE5OMO5ggz7ahmOBH0JBS+9f95Yc7V5TZ+kHpTeFWaLQA==} - dependencies: - inflection: 1.3.8 - dev: false - /path-to-regexp/0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} dev: false - /pbkdf2/3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: false - /peek-readable/5.0.0: resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} engines: {node: '>=14.16'} dev: false - /pg-connection-string/2.5.0: - resolution: {integrity: sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==} - dev: false - /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -3356,14 +1930,6 @@ packages: split2: 4.1.0 dev: false - /pino-http/5.8.0: - resolution: {integrity: sha512-YwXiyRb9y0WCD1P9PcxuJuh3Dc5qmXde/paJE86UGYRdiFOi828hR9iUGmk5gaw6NBT9gLtKANOHFimvh19U5w==} - dependencies: - fast-url-parser: 1.1.3 - pino: 6.14.0 - pino-std-serializers: 4.0.0 - dev: false - /pino-pretty/7.6.1: resolution: {integrity: sha512-H7N6ZYkiyrfwBGW9CSjx0uyO9Q2Lyt73881+OTYk8v3TiTdgN92QHrWlEq/LeWw5XtDP64jeSk3mnc6T+xX9/w==} hasBin: true @@ -3383,31 +1949,10 @@ packages: strip-json-comments: 3.1.1 dev: false - /pino-std-serializers/3.2.0: - resolution: {integrity: sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==} - dev: false - - /pino-std-serializers/4.0.0: - resolution: {integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==} - dev: false - /pino-std-serializers/6.0.0: resolution: {integrity: sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==} dev: false - /pino/6.14.0: - resolution: {integrity: sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==} - hasBin: true - dependencies: - fast-redact: 3.1.2 - fast-safe-stringify: 2.1.1 - flatstr: 1.0.12 - pino-std-serializers: 3.2.0 - process-warning: 1.0.0 - quick-format-unescaped: 4.0.4 - sonic-boom: 1.4.1 - dev: false - /pino/8.6.1: resolution: {integrity: sha512-fi+V2K98eMZjQ/uEHHSiMALNrz7HaFdKNYuyA3ZUrbH0f1e8sPFDmeRGzg7ZH2q4QDxGnJPOswmqlEaTAZeDPA==} hasBin: true @@ -3425,12 +1970,6 @@ packages: thread-stream: 2.2.0 dev: false - /please-upgrade-node/3.2.0: - resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} - dependencies: - semver-compare: 1.0.0 - dev: false - /postmark/3.0.14: resolution: {integrity: sha512-Bkt6msv+I4Z3Y/jwt2owTNVmahOOyJlS1aQLiWsFAz5fzeJPfEqIUMSPPQTk7lYyJvYnLXQuzhFNG7M8yxqPhA==} dependencies: @@ -3458,58 +1997,19 @@ packages: tunnel-agent: 0.6.0 dev: false - /prelude-ls/1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: false - /prettier/1.19.1: resolution: {integrity: sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /process-nextick-args/2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: false - - /process-warning/1.0.0: - resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} - dev: false - - /process-warning/2.0.0: - resolution: {integrity: sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==} - dev: false - - /process/0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: false - - /promise-inflight/1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dev: false - optional: true + engines: {node: '>=4'} + hasBin: true + dev: true - /promise-retry/2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - dependencies: - err-code: 2.0.3 - retry: 0.12.0 + /process-warning/2.0.0: + resolution: {integrity: sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==} dev: false - optional: true - /promisify-call/2.0.4: - resolution: {integrity: sha512-ZX68J1+1Pe0I8NC0P6Ji3fDDcJceVfpoygfDLgdb1fp5vW9IRlwSpDaxe1T5HgwchyHV2DsL/pWzWikUiWEbLQ==} - engines: {node: '>=4.0'} - dependencies: - with-callback: 1.0.2 + /process/0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} dev: false /proxy-addr/2.0.7: @@ -3520,30 +2020,6 @@ packages: ipaddr.js: 1.9.1 dev: false - /proxy-agent/3.1.1: - resolution: {integrity: sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==} - engines: {node: '>=6'} - dependencies: - agent-base: 4.3.0 - debug: 4.3.4 - http-proxy-agent: 2.1.0 - https-proxy-agent: 3.0.1 - lru-cache: 5.1.1 - pac-proxy-agent: 3.0.1 - proxy-from-env: 1.1.0 - socks-proxy-agent: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /proxy-from-env/1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: false - - /pseudomap/1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: false - /pstree.remy/1.1.8: resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} dev: false @@ -3555,10 +2031,6 @@ packages: once: 1.4.0 dev: false - /punycode/1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - dev: false - /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -3571,18 +2043,6 @@ packages: side-channel: 1.0.4 dev: false - /qs/6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: false - - /qs/6.7.0: - resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} - engines: {node: '>=0.6'} - dev: false - /query-string/6.14.1: resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} engines: {node: '>=6'} @@ -3602,32 +2062,11 @@ packages: engines: {node: '>=10'} dev: false - /random-bytes/1.0.0: - resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} - engines: {node: '>= 0.8'} - dev: false - - /randombytes/2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: false - /range-parser/1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} dev: false - /raw-body/2.4.0: - resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.0 - http-errors: 1.7.2 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - /raw-body/2.5.1: resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} engines: {node: '>= 0.8'} @@ -3652,27 +2091,6 @@ packages: resolution: {integrity: sha512-mdkQtdg5elliOR64xcHVMkghSHQGjpsdCFAs6fSe28wTaVypR0GywmK5ndKpOSQzzuNpSrzC12Rv9UEkDLX73A==} dev: false - /readable-stream/1.1.14: - resolution: {integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: false - - /readable-stream/2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: false - /readable-stream/3.6.0: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} engines: {node: '>= 6'} @@ -3711,13 +2129,6 @@ packages: engines: {node: '>= 12.13.0'} dev: false - /rechoir/0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - dependencies: - resolve: 1.22.1 - dev: false - /redis/4.3.1: resolution: {integrity: sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==} dependencies: @@ -3734,28 +2145,10 @@ packages: engines: {node: '>=0.10.0'} dev: false - /requires-port/1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: false - /resolve-alpn/1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: false - /resolve-from/5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: false - - /resolve/1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: false - /responselike/3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} @@ -3768,16 +2161,6 @@ packages: engines: {node: '>=4'} dev: false - /retry-as-promised/5.0.0: - resolution: {integrity: sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==} - dev: false - - /retry/0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: false - optional: true - /reusify/1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -3801,10 +2184,6 @@ packages: inherits: 2.0.4 dev: false - /safe-buffer/5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: false - /safe-buffer/5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: false @@ -3838,15 +2217,6 @@ packages: resolution: {integrity: sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==} dev: false - /semver-compare/1.0.0: - resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} - dev: false - - /semver/5.3.0: - resolution: {integrity: sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==} - hasBin: true - dev: false - /semver/5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true @@ -3870,27 +2240,6 @@ packages: lru-cache: 6.0.0 dev: false - /send/0.17.1: - resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 1.1.2 - destroy: 1.0.4 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 1.7.3 - mime: 1.6.0 - ms: 2.1.1 - on-finished: 2.3.0 - range-parser: 1.2.1 - statuses: 1.5.0 - transitivePeerDependencies: - - supports-color - dev: false - /send/0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} @@ -3912,27 +2261,6 @@ packages: - supports-color dev: false - /seq-queue/0.0.5: - resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} - dev: false - - /sequelize-pool/7.1.0: - resolution: {integrity: sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==} - engines: {node: '>= 10.0.0'} - dev: false - - /serve-static/1.14.1: - resolution: {integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.17.1 - transitivePeerDependencies: - - supports-color - dev: false - /serve-static/1.15.0: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} @@ -3953,10 +2281,6 @@ packages: resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==} dev: false - /setprototypeof/1.1.1: - resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} - dev: false - /setprototypeof/1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: false @@ -4026,14 +2350,6 @@ packages: engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} dev: false - /socks-proxy-agent/4.0.2: - resolution: {integrity: sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==} - engines: {node: '>= 6'} - dependencies: - agent-base: 4.2.1 - socks: 2.3.3 - dev: false - /socks-proxy-agent/6.2.0: resolution: {integrity: sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==} engines: {node: '>= 10'} @@ -4045,26 +2361,6 @@ packages: - supports-color dev: false - /socks-proxy-agent/6.2.1: - resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} - engines: {node: '>= 10'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - dev: false - optional: true - - /socks/2.3.3: - resolution: {integrity: sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dependencies: - ip: 1.1.5 - smart-buffer: 4.2.0 - dev: false - /socks/2.7.1: resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} @@ -4080,13 +2376,6 @@ packages: node-gyp-build: 4.5.0 dev: false - /sonic-boom/1.4.1: - resolution: {integrity: sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==} - dependencies: - atomic-sleep: 1.0.0 - flatstr: 1.0.12 - dev: false - /sonic-boom/2.8.0: resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} dependencies: @@ -4114,47 +2403,6 @@ packages: engines: {node: '>= 10.x'} dev: false - /sqlite3/5.1.2: - resolution: {integrity: sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg==} - requiresBuild: true - peerDependenciesMeta: - node-gyp: - optional: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.10 - node-addon-api: 4.3.0 - tar: 6.1.11 - optionalDependencies: - node-gyp: 8.4.1 - transitivePeerDependencies: - - bluebird - - encoding - - supports-color - dev: false - - /sqlstring/2.3.1: - resolution: {integrity: sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==} - engines: {node: '>= 0.6'} - dev: false - - /sqlstring/2.3.3: - resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} - engines: {node: '>= 0.6'} - dev: false - - /ssri/8.0.1: - resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.4 - dev: false - optional: true - - /statuses/1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - dev: false - /statuses/2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -4169,11 +2417,6 @@ packages: engines: {node: '>=4.0.0'} dev: false - /streamsearch/1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - /strict-uri-encode/2.0.0: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} engines: {node: '>=4'} @@ -4192,16 +2435,6 @@ packages: strip-ansi: 6.0.1 dev: false - /string_decoder/0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} - dev: false - - /string_decoder/1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: false - /string_decoder/1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: @@ -4240,11 +2473,6 @@ packages: has-flag: 3.0.0 dev: false - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: false - /tar-fs/2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} dependencies: @@ -4277,11 +2505,6 @@ packages: yallist: 4.0.0 dev: false - /tarn/3.0.2: - resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} - engines: {node: '>=8.0.0'} - dev: false - /text-decoding/1.0.0: resolution: {integrity: sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==} dev: false @@ -4297,44 +2520,11 @@ packages: real-require: 0.2.0 dev: false - /thunkify/2.1.2: - resolution: {integrity: sha512-w9foI80XcGImrhMQ19pxunaEC5Rp2uzxZZg4XBAFRfiLOplk3F0l7wo+bO16vC2/nlQfR/mXZxcduo0MF2GWLg==} - dev: false - - /tildify/2.0.0: - resolution: {integrity: sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==} - engines: {node: '>=8'} - dev: false - - /tiny-lru/10.0.1: - resolution: {integrity: sha512-Vst+6kEsWvb17Zpz14sRJV/f8bUWKhqm6Dc+v08iShmIJ/WxqWytHzCTd6m88pS33rE2zpX34TRmOpAJPloNCA==} - engines: {node: '>=6'} - dev: false - /tiny-lru/9.0.3: resolution: {integrity: sha512-/i9GruRjXsnDgehxvy6iZ4AFNVxngEFbwzirhdulomMNPGPVV3ECMZOWSw0w4sRMZ9Al9m4jy08GPvRxRUGYlw==} engines: {node: '>=6'} dev: false - /tiny-secp256k1/1.1.6: - resolution: {integrity: sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==} - engines: {node: '>=6.0.0'} - requiresBuild: true - dependencies: - bindings: 1.5.0 - bn.js: 4.12.0 - create-hmac: 1.1.7 - elliptic: 6.5.4 - nan: 2.17.0 - dev: false - - /tiny-secp256k1/2.2.1: - resolution: {integrity: sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==} - engines: {node: '>=14.0.0'} - dependencies: - uint8array-tools: 0.0.7 - dev: false - /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4342,11 +2532,6 @@ packages: is-number: 7.0.0 dev: false - /toidentifier/1.0.0: - resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} - engines: {node: '>=0.6'} - dev: false - /toidentifier/1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -4360,10 +2545,6 @@ packages: ieee754: 1.2.1 dev: false - /toposort-class/1.0.1: - resolution: {integrity: sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==} - dev: false - /touch/3.1.0: resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} hasBin: true @@ -4375,28 +2556,12 @@ packages: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: false - /tslib/2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: false - - /tsscmp/1.0.6: - resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} - engines: {node: '>=0.6.x'} - dev: false - /tunnel-agent/0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} dependencies: safe-buffer: 5.2.1 dev: false - /type-check/0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: false - /type-is/1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -4417,18 +2582,6 @@ packages: dev: false optional: true - /uid-safe/2.1.5: - resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} - engines: {node: '>= 0.8'} - dependencies: - random-bytes: 1.0.0 - dev: false - - /uint8array-tools/0.0.7: - resolution: {integrity: sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==} - engines: {node: '>=14.0.0'} - dev: false - /undefsafe/2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} dev: false @@ -4437,27 +2590,6 @@ packages: resolution: {integrity: sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==} dev: false - /undici/5.14.0: - resolution: {integrity: sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==} - engines: {node: '>=12.18'} - dependencies: - busboy: 1.6.0 - dev: false - - /unique-filename/1.1.1: - resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} - dependencies: - unique-slug: 2.0.2 - dev: false - optional: true - - /unique-slug/2.0.2: - resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} - dependencies: - imurmurhash: 0.1.4 - dev: false - optional: true - /unpipe/1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -4473,12 +2605,6 @@ packages: resolution: {integrity: sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA==} dev: false - /utf7/1.0.2: - resolution: {integrity: sha512-qQrPtYLLLl12NF4DrM9CvfkxkYI97xOb5dsnGZHE3teFr0tWiEZ9UdgMPczv24vl708cYMpe6mGXGHrotIp3Bw==} - dependencies: - semver: 5.3.0 - dev: false - /util-deprecate/1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false @@ -4493,11 +2619,6 @@ packages: hasBin: true dev: false - /validator/13.7.0: - resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} - engines: {node: '>= 0.10'} - dev: false - /varuint-bitcoin/1.1.2: resolution: {integrity: sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==} dependencies: @@ -4535,15 +2656,6 @@ packages: webidl-conversions: 3.0.1 dev: false - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: false - optional: true - /wide-align/1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: @@ -4556,22 +2668,6 @@ packages: bs58check: 2.1.2 dev: false - /with-callback/1.0.2: - resolution: {integrity: sha512-zaUhn7OWgikdqWlPYpZ4rTX/6IAV0czMVyd+C6QLVrif2tATF28CYUnHBmHs2a5EaZo7bB1+plBUPHto+HW8uA==} - engines: {node: '>=4'} - dev: false - - /wkx/0.5.0: - resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==} - dependencies: - '@types/node': 18.8.5 - dev: false - - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: false - /wordwrap/1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: false @@ -4580,10 +2676,6 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: false - /wretch/1.7.10: - resolution: {integrity: sha512-UgF2o63bZRsz3LoOxaxzAUdFdlIJzVYbCHHhQ+LNMSBD1FeFJn8ADaekopJclHUm6sN8Lhu0DQFGQloliS0Twg==} - dev: false - /ws/7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} engines: {node: '>=8.3.0'} @@ -4610,18 +2702,6 @@ packages: optional: true dev: false - /xregexp/2.0.0: - resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==} - dev: false - - /yallist/2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: false - - /yallist/3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: false - /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: false @@ -4630,11 +2710,3 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: false - - /zeromq/6.0.0-beta.6: - resolution: {integrity: sha512-wLf6M7pBHijl+BRltUL2VoDpgbQcOZetiX8UzycHL8CcYFxYnRrpoG5fi3UX3+Umavz1lk4/dGaQez8qiDgr/Q==} - engines: {node: '>= 10.2'} - requiresBuild: true - dependencies: - node-gyp-build: 4.5.0 - dev: false diff --git a/routes/invoices.js b/routes/invoices.js index f3c95a21..ddd840ec 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -4,64 +4,25 @@ import { optionalAuth } from "$lib/passport"; import { err, l } from "$lib/logging"; import { SATS, derivePayRequest } from "$lib/utils"; import { emit } from "$lib/sockets"; +import { v4 } from "uuid"; +import { rd, g, s } from "$lib/redis"; -app.get("/invoice", async (req, res, next) => { - try { - const invoice = await db.Invoice.findOne({ - where: { - uuid: req.query.uuid - }, - include: [ - { - model: db.User, - as: "user", - attributes: ["username", "currency", "profile", "uuid"] - }, - { - model: db.Request, - as: "request" - } - ] - }); - - res.send(invoice); - } catch (e) { - err("invoice not found", e); - res.code(500).send("Invoice not found"); - } -}); - -app.get("/invoice/:text", async (req, res, next) => { - try { - let { text } = req.params; - let where = - text.split("-").length > 4 - ? { uuid: text } - : text.startsWith("ln") - ? { text } - : { - [Op.or]: [{ unconfidential: text }, { address: text }] - }; - - const invoice = await db.Invoice.findOne({ - where, - include: { - model: db.User, - as: "user", - attributes: ["username", "currency", "profile", "uuid"] - } - }); - - res.send(invoice); - } catch (e) { - err("invoice not found", e); - res.code(500).send("Invoice not found"); - } +app.get("/invoice", async ({ query: { id } }, res) => { + let invoice = await g(`invoice:${id}`); + invoice.user = await g(`user:${invoice.user_id}`); + res.send(invoice); }); -app.post("/invoice", optionalAuth, async (req, res, next) => { - try { - let { type = "bech32", liquidAddress, id, invoice, user, tx } = req.body; +app.post( + "/invoice", + optionalAuth, + async ( + { + body: { type = "bech32", liquidAddress, id, invoice, user, tx }, + user: me + }, + res + ) => { let { blindkey, currency, @@ -71,49 +32,24 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { network, request_id } = invoice; - let address, unconfidential, text; + let text; if (amount < 0) throw new Error("amount out of range"); if (tip > 5 * amount || tip < 0) throw new Error("tip amount out of range"); + tip = tip || 0; - if (!user) ({ user } = req); - else { - user = await db.User.findOne({ - where: { - username: user.username - }, - include: { - model: db.Account, - as: "account" - } - }); - } + if (!user) user = me; if (!user) throw new Error("user not provided"); + + user = await g(`user:${user.id}`); + if (!currency) currency = user.currency; if (!rate) rate = store.rates[currency]; if (amount < 0) throw new Error("invalid amount"); - if (user.account.pubkey) { - let { address, confidentialAddress } = await deriveAddress( - user.account, - type - ); - if (confidentialAddress) { - address = confidentialAddress; - unconfidential = address; - } else { - address = address; - } - } else if (network !== "lightning") { - address = await { bitcoin: bc, liquid: lq }[network].getNewAddress(); - if (network === "liquid") - ({ unconfidential } = await lq.getAddressInfo(address)); - } - invoice = { ...invoice, - account_id: user.account.id, - address, + id: v4(), amount, currency, rate, @@ -122,83 +58,29 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { user_id: user.id }; - if (network === "lightning") { - invoice.text = await derivePayRequest(invoice); - } else { - invoice.text = bip21(invoice, user.account); - } - - if (liquidAddress) { - if (network === "lightning") { - l("conversion request for", liquidAddress, invoice.text); - store.convert[invoice.text] = { address: liquidAddress, tx }; - } else if (network === "liquid") { - l("conversion request for", liquidAddress, invoice.unconfidential); - store.convert[invoice.unconfidential] = { address: liquidAddress, tx }; - } else { - l("conversion request for", liquidAddress, invoice.address); - store.convert[invoice.address] = { address: liquidAddress, tx }; - } - } + invoice.text = await derivePayRequest(invoice); l( "creating invoice", user.username, - invoice.network, - invoice.amount, - invoice.tip, - invoice.currency, - invoice.text && `${invoice.text.substr(0, 8)}..${invoice.text.substr(-6)}` + network, + amount, + tip, + currency, + `${text.substr(0, 8)}..${text.substr(-6)}` ); - if (!invoice.tip) invoice.tip = 0; - - invoice = await db.Invoice.create(invoice); - store.addresses[invoice.address] = user.username; - if (invoice.unconfidential) { - store.addresses[invoice.unconfidential] = user.username; - if (blindkey) await lq.importBlindingKey(invoice.address, blindkey); - } + await rd.lPush(`${id}:invoices`, invoice.id); if (request_id) { - let request = await db.Request.findOne({ - where: { id: request_id }, - - include: { - model: db.User, - as: "requester", - attributes: ["username"] - } - }); + let request = await g(`request:${request_id}`); + let { invoice_id: prev } = request; + request.invoice_id = invoice.id; + await s(`request:${request_id}`, request); - if (request) { - let existing = request.invoice_id; - request.invoice_id = invoice.id; - await request.save(); - - if (!existing) - emit(request.requester.username, "invoice", { - amount: invoice.amount, - currency: invoice.currency, - rate: invoice.rate, - request_id, - uuid: invoice.uuid, - user: { username: user.username, profile: user.profile } - }); - } + if (!prev) emit(request.requester.username, "invoice", invoice); } res.send(invoice); - } catch (e) { - err(e.message, e.stack); - res.code(500).send(`Problem during invoice creation: ${e.message}`); - } -}); - -app.post( - "/:username/:network/invoice", - optionalAuth, - async (req, res, next) => { - let { network, username } = req.params; } ); diff --git a/routes/lightning/channel.js b/routes/lightning/channel.js deleted file mode 100644 index d5d5b7b2..00000000 --- a/routes/lightning/channel.js +++ /dev/null @@ -1,29 +0,0 @@ -import axios from "axios"; -import ln from "$lib/ln"; - -export default async (req, res) => { - const { params } = req.body; - const [public_key, socket] = params.uri.split("@"); - - l("connecting to peer", req.user.username, public_key, socket); - let result; - - const { callback, k1 } = params; - let remoteid; - try { - remoteid = (await ln.getinfo()).id; - } catch (e) { - err("problem getting lightning node info", e.message); - return res.code(500).send(e.message); - } - - let url = `${callback}?k1=${k1}&remoteid=${remoteid}&private=0`; - - try { - let response = await axios.get(url); - res.send(response.data); - } catch (e) { - err("problem sending channel request", e.message); - return res.code(500).send({ status: "ERROR", reason: e.message }); - } -}; diff --git a/routes/lightning/channelRequest.js b/routes/lightning/channelRequest.js deleted file mode 100644 index 74e4cbba..00000000 --- a/routes/lightning/channelRequest.js +++ /dev/null @@ -1,24 +0,0 @@ -import { lnurlServer } from "$routes/lnurl"; -import { err } from "$lib/logging"; - -export const channelRequest = async (req, res) => { - let { localAmt, pushAmt } = req.body; - - pushAmt = 0; - - try { - if (localAmt < 20000) - throw new Error("amount must be greater than 20000 SAT"); - if (localAmt > 1000000) throw new Error("amount must be <= 1000000"); - - const result = await lnurlServer.generateNewUrl("channelRequest", { - localAmt, - pushAmt - }); - - res.send(result); - } catch (e) { - err("problem generating channel request", e.message); - res.code(500).send(e.message); - } -}; diff --git a/routes/lightning/index.js b/routes/lightning/index.js index b4611ef5..ddc10bfe 100644 --- a/routes/lightning/index.js +++ b/routes/lightning/index.js @@ -1,11 +1,9 @@ -import channel from "./channel"; import invoice from "./invoice"; import query from "./query"; import send from "./send"; import parse from "./parse"; export default { - channel, invoice, query, send, diff --git a/routes/requests.js b/routes/requests.js index 0b3832e8..bea8f7fd 100644 --- a/routes/requests.js +++ b/routes/requests.js @@ -1,92 +1,23 @@ import app from "$app"; import { auth } from "$lib/passport"; import { emit } from "$lib/sockets"; +import { g, rd } from "$lib/redis"; -app.get("/request/:id", auth, async (req, res) => { +app.get("/request/:id", auth, async ({ params: { id } }, res) => { try { - let request = await db.Request.findOne({ - where: { id: req.params.id }, - include: [ - { - attributes: ["username", "profile"], - model: db.User, - as: "recipient" - }, - { - attributes: ["username", "profile"], - model: db.User, - as: "requester" - }, - { - model: db.Invoice, - as: "invoice" - } - ] - }); - - res.send({ request }); + res.send({ request: await g(id) }); } catch (e) { console.log(e); res.code(500).send(e.message); } }); -app.get("/requests", auth, async (req, res) => { +app.get("/requests", auth, async ({ user: { uuid } }, res) => { try { const day = new Date(new Date().setDate(new Date().getDate() - 1)); - let invoices = ( - await db.Request.findAll({ - where: { - [Op.or]: { - recipient_id: req.user.id, - requester_id: req.user.id - }, - createdAt: { [Op.gt]: day } - }, - order: [["createdAt", "DESC"]], - include: [ - { - model: db.Invoice, - as: "invoice", - where: { received: { [Op.lt]: col("invoice.amount") } }, - include: { - model: db.User, - as: "user", - attributes: ["username", "profile"] - } - }, - { - model: db.User, - as: "requester", - attributes: ["username", "profile"] - } - ] - }) - ) - .map( - r => - r.invoice && { - request_id: r.id, - requester: r.requester.get({ plain: true }), - ...r.invoice.get({ plain: true }) - } - ) - .filter(r => r); - - let requests = await db.Request.findAll({ - where: { - recipient_id: req.user.id, - createdAt: { [Op.gt]: day }, - invoice_id: { [Op.eq]: null } - }, - order: [["createdAt", "DESC"]], - include: { - attributes: ["username", "profile"], - model: db.User, - as: "requester" - } - }); + let invoices = await rd.lRange(`${uuid}:invoices`, 0, -1); + let requests = await rd.lRange(`${uuid}:requests`, 0, -1); res.send({ invoices, requests }); } catch (e) { @@ -95,41 +26,32 @@ app.get("/requests", auth, async (req, res) => { } }); -app.post("/requests", auth, async (req, res) => { - try { - let { recipient: username, ...params } = req.body; - let { id: recipient_id } = await db.User.findOne({ where: { username } }); +app.post( + "/requests", + auth, + async ( + { body: { recipient, ...params }, user: { username, profile } }, + res + ) => { + let { id: recipient_id } = await g(`user:${recipient}`); - let request = await db.Request.create({ recipient_id, ...params }); - request = request.get({ plain: true }); + let request = { recipient_id, ...params }; request.requester = { - username: req.user.username, - profile: req.user.profile + username, + profile }; - emit(username, "request", request); + + emit(recipient, "request", request); res.send(request); - } catch (e) { - console.log(e); - res.code(500).send(e.message); } -}); - -app.post("/requests/delete", auth, async (req, res) => { - try { - let r = await db.Request.findOne({ - where: { - id: req.body.request_id, - [Op.or]: { requester_id: req.user.id, recipient_id: req.user.id } - } - }); - - if (!r) throw new Error("request not found"); - await r.destroy(); +); +app.post( + "/requests/delete", + auth, + async ({ body: { request_id }, user: { id } }, res) => { + await rd.lrem(`user:${id}:requests`, request_id); res.send(); - } catch (e) { - console.log(e); - res.code(500).send(e.message); } -}); +); diff --git a/routes/users.js b/routes/users.js index 4a01cc1e..8f0b9106 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,5 +1,5 @@ import app from "$app"; -import redis from "$lib/redis"; +import { g, s } from "$lib/redis"; import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; @@ -13,30 +13,25 @@ import { emit } from "$lib/sockets"; import register from "$lib/register"; import { requirePin } from "$lib/utils"; import got from "got"; -import { bech32 } from "bech32"; - -const { encode, decode, fromWords, toWords } = bech32; const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); app.get("/me", auth, async (req, res) => { try { - let user = req.user.get({ plain: true }); - user.haspin = !!user.pin; - res.send(pick(user, ...whitelist)); + res.send(pick(req.user, ...whitelist)); } catch (e) { console.log("problem fetching user", e); res.code(500).send(e.message); } }); -app.get("/users/:key", async (req, res) => { +app.get("/users/:key", async ({ params: { key } }, res) => { try { if (key.startsWith("npub")) { key = Buffer.from(fromWords(decode(key).words)).toString("hex"); } - user = JSON.parse(await redis.get(`user:${key}`)); + let user = await g(`user:${key}`); if (!user && key.length === 64) { user = { @@ -46,6 +41,7 @@ app.get("/users/:key", async (req, res) => { }; } + console.log(user) if (!user) return res.code(500).send("User not found"); let whitelist = [ @@ -69,7 +65,7 @@ app.get("/users/:key", async (req, res) => { app.post("/register", async (req, res) => { try { - const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; + const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress; let { cipher, pubkey, password, username, salt } = req.body.user; let user = { @@ -129,14 +125,6 @@ app.post("/2fa", auth, async (req, res) => { res.send({}); }); -app.get("/exists", async (req, res) => { - let exists = await db.User.findOne({ - where: { username: req.query.username } - }); - - res.send(!!exists); -}); - app.post("/user", auth, async (req, res) => { try { let { user } = req; @@ -303,6 +291,7 @@ app.post("/accounts", auth, async (req, res) => { let login = async (req, res) => { try { const { params, sig, key, password, username, token: twofa } = req.body; + l("logging in", username); if (sig) { const { callback } = params; @@ -340,18 +329,17 @@ let login = async (req, res) => { l( "login", username, - req.headers["x-forwarded-for"] || req.connection.remoteAddress + req.headers["x-forwarded-for"] || req.socket.remoteAddress ); let payload = { username, uuid: user.uuid }; let token = jwt.sign(payload, config.jwt); res.cookie("token", token, { expires: new Date(Date.now() + 432000000) }); - user.accounts = await user.getAccounts(); - user.keys = await user.getKeys(); user = pick(user, ...whitelist); res.send({ user, token }); } catch (e) { - err("login error", e.message, req.connection.remoteAddress); + console.log(e); + err("login error", e.message, req.socket.remoteAddress); res.code(401).send({}); } }; @@ -424,35 +412,13 @@ app.post("/otpsecret", auth, async function(req, res) { } }); -app.get("/contacts", auth, async function(req, res) { - try { - let contacts = await db.Payment.findAll({ - where: { - user_id: req.user.id, - with_id: { [Sequelize.Op.ne]: null } - }, - include: { - attributes: ["username", "profile", "uuid"], - model: db.User, - as: "with" - }, - attributes: [ - [Sequelize.fn("max", Sequelize.col("payments_model.createdAt")), "last"] - ], - group: ["with_id"], - order: [[{ model: db.User, as: "with" }, "username", "ASC"]] - }); - - res.send( - contacts.map(c => { - c = c.get({ plain: true }); - return { ...c.with, last: c.last }; - }) - ); - } catch (e) { - console.log(e); - res.code(500).send(e.message); - } +app.get("/contacts", auth, async function({ user: { uuid } }, res) { + let payments = await g(`${uuid}:payments`) || []; + res.send( + Promise.all( + [...new Set(payments.map(p => p.with_id))].map(id => g(`user:${id}`)) + ) + ); }); app.post("/checkPassword", auth, async function(req, res) { -- cgit v1.2.3 From 8a114c50efaac41767042766f05390aa906da157 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 13 Jan 2023 20:27:18 -0800 Subject: migrating to redis --- docker-compose.yml | 13 +++- index.js | 30 ++++---- lib/nostr.js | 1 - lib/passport.js | 5 +- lib/register.js | 15 +--- lib/sockets.js | 26 +++---- lib/utils.js | 21 +----- lib/whitelist.js | 1 - package.json | 2 +- routes/invoices.js | 49 +++++------- routes/lightning/receive.js | 179 ++++++++++++++++---------------------------- routes/users.js | 26 ++++--- 12 files changed, 144 insertions(+), 224 deletions(-) (limited to 'lib/whitelist.js') diff --git a/docker-compose.yml b/docker-compose.yml index 95516fe0..83214b92 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,6 @@ services: - rd - bc - cl - build: . command: "pnpm dev" environment: NODE_OPTIONS: "--es-module-specifier-resolution=node --experimental-modules --loader ./loader.js" @@ -32,8 +31,16 @@ services: volumes: - ./data/lightning:/root/.lightning restart: always + clb: + image: elementsproject/lightningd:latest + container_name: clb + environment: + LIGHTNINGD_NETWORK: regtest + volumes: + - ./data/lightningb:/root/.lightning + restart: always rd: - image: redis + image: eqalpha/keydb container_name: rd volumes: - ./data/redis:/data @@ -45,6 +52,6 @@ services: user: 100:100 volumes: - "./data/nostr/data:/usr/src/app/db" - - "./data/nostr/data.toml:/usr/src/app/config.toml" + - "./data/nostr/config.toml:/usr/src/app/config.toml" ports: - '8080:8080' diff --git a/index.js b/index.js index 580435e0..640f7389 100644 --- a/index.js +++ b/index.js @@ -1,20 +1,20 @@ -import app from "./app"; -import { l, err } from "./lib/logging"; +import app from "./app.js"; +import { l, err } from "$lib/logging"; -import "./lib/redis"; -import "./lib/sockets"; -import "./lib/passport"; -import "./lib/upload"; -import "./lib/rates"; -import "./lib/notifications"; -import "./lib/mail"; -import "./lib/nostr"; +import "$lib/redis"; +import "$lib/sockets"; +import "$lib/passport"; +import "$lib/upload"; +import "$lib/rates"; +import "$lib/notifications"; +import "$lib/mail"; +import "$lib/nostr"; -import "./routes/locations"; -import "./routes/invoices"; -import "./routes/payments"; -import "./routes/users"; -import "./routes/requests"; +import "$routes/locations"; +import "$routes/invoices"; +import "$routes/payments"; +import "$routes/users"; +import "$routes/requests"; let host = process.env.HOST || "0.0.0.0"; let port = process.env.PORT || 3119; diff --git a/lib/nostr.js b/lib/nostr.js index ad089bb5..08ed8b61 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -142,7 +142,6 @@ pool.on("event", async (relay, sub, ev) => { }; await redis.set(`user:${pubkey}`, JSON.stringify(user)); - await redis.set(`user:${user.username}`, JSON.stringify(user)); coinos.send(ev); } else if (sub.includes("follows")) { let pubkey = sub.split(":")[0]; diff --git a/lib/passport.js b/lib/passport.js index b559b2f9..25dc0103 100644 --- a/lib/passport.js +++ b/lib/passport.js @@ -34,8 +34,9 @@ fastifyPassport.use( }, async (payload, next) => { try { - let { uuid } = payload; - let user = await g(`user:${uuid}`); + let { id } = payload; + let user = await g(`user:${id}`); + user.haspin = !!user.pin; next(null, user); } catch (e) { console.log("payload", payload); diff --git a/lib/register.js b/lib/register.js index 9f18c15e..8ac5355f 100644 --- a/lib/register.js +++ b/lib/register.js @@ -14,8 +14,8 @@ export default async (user, ip, requireChallenge) => { if (!username) throw new Error("Username required"); username = username.replace(/ /g, ""); - let uuid = v4(); - user.uuid = uuid; + let id = v4(); + user.id = id; let exists = await g(`user:${username}`); if (exists) throw new Error(`Username ${username} taken`); @@ -24,8 +24,6 @@ export default async (user, ip, requireChallenge) => { user.password = await bcrypt.hash(password, 1); } - console.log("BOO"); - if (!config.ipxapi || ip.startsWith("127") || ip.startsWith("192")) { user.currency = "CAD"; } else { @@ -53,14 +51,9 @@ export default async (user, ip, requireChallenge) => { user.ip = ip; } - console.log("user uuid", user.uuid, user.username); + await s(`user:${id}`, user); + await s(`user:${user.username}`, id); - try { - await s(`user:${user.uuid}`, user); - await s(`user:${user.username}`, user); - } catch (e) { - console.log("HUH", e); - } l("new user", user.username); return user; }; diff --git a/lib/sockets.js b/lib/sockets.js index 0f343937..c94c29a0 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -8,7 +8,7 @@ import { differenceInSeconds, subSeconds } from "date-fns"; import fastifyWs from "@fastify/websocket"; import whitelist from "./whitelist"; import { l, err, warn } from "$lib/logging"; -import { getUser } from "$lib/utils"; +import { g } from "$lib/redis"; const code = 1000; @@ -92,24 +92,24 @@ app.register(async function(app) { if (!token || token === "null" || !jwt.decode(token)) return ws.close(code, `bad token ${token}`); - let { uuid } = jwt.decode(token); - if (!uuid) throw new Error("Invalid JWT token"); - console.log("UUID", uuid) - let user = await getUser(uuid); + let { id: user_id } = jwt.decode(token); + if (!user_id) throw new Error("Invalid JWT token"); + let user = await g(`user:${user_id}`); if (!user) throw new Error("User not found"); + user.haspin = !!user.pin; - if (!store.sockets[uuid]) store.sockets[uuid] = {}; - const existing = Object.keys(store.sockets[uuid]); + if (!store.sockets[user_id]) store.sockets[user_id] = {}; + const existing = Object.keys(store.sockets[user_id]); if (existing.length > 4) { - const p = existing.find(sid => sid !== id); - store.sockets[uuid][p].send(JSON.stringify({ type: "logout" })); + const p = existing.find(sid => sid !== user_id); + store.sockets[user_id][p].send(JSON.stringify({ type: "logout" })); setTimeout(() => { - if (store.sockets[uuid][p]) - store.sockets[uuid][p].close(code, "too many sockets"); + if (store.sockets[user_id][p]) + store.sockets[user_id][p].close(code, "too many sockets"); }, 5000); } - store.sockets[uuid][id] = ws; - names[id] = uuid; + store.sockets[user_id][id] = ws; + names[id] = user_id; ws.user = user; ws.send( diff --git a/lib/utils.js b/lib/utils.js index 559f8531..b556c46a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,7 +1,6 @@ import store from "$lib/store"; import { g } from "$lib/redis"; import config from "$config"; -import ln from "$lib/ln"; export const nada = () => {}; @@ -18,15 +17,6 @@ export const requirePin = async ({ body, user }) => { throw new Error("Invalid pin"); }; -export const getUser = async (uuid) => { - let user = g(`user:${uuid}`); - if (!user) throw new Error("user not found"); - - user.haspin = !!user.pin; - - return user; -}; - export const prod = process.env.NODE_ENV === "production"; export const fail = msg => { throw new Error(msg); @@ -35,14 +25,5 @@ export const fail = msg => { export const SATS = 100000000; export const toSats = n => Math.round(n * SATS); -export const derivePayRequest = async ({ amount, memo, tip }) => { - if (!tip) tip = 0; - let value = amount + tip; - - if (!memo) memo = "coinos"; - return ( - await ln.invoice(value ? `${value}sat` : "any", new Date(), memo, 360) - ).bolt11; -}; - export const uniq = (a, k) => [...new Map(a.map(x => [k(x), x])).values()]; +export const pick = (O, K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); diff --git a/lib/whitelist.js b/lib/whitelist.js index 523e9d37..49cc9af3 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -25,7 +25,6 @@ export default [ "symbol", "theme", "twofa", - "uuid", "unit", "username", "verified" diff --git a/package.json b/package.json index 408df40e..2c1b7258 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "scripts": { - "start": "bun index.js", + "start": "node index.js", "dev": "nodemon index.js" }, "dependencies": { diff --git a/routes/invoices.js b/routes/invoices.js index ddd840ec..f7ab78cf 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -1,76 +1,67 @@ import app from "$app"; import store from "$lib/store"; import { optionalAuth } from "$lib/passport"; -import { err, l } from "$lib/logging"; -import { SATS, derivePayRequest } from "$lib/utils"; +import { l } from "$lib/logging"; import { emit } from "$lib/sockets"; -import { v4 } from "uuid"; import { rd, g, s } from "$lib/redis"; +import ln from "$lib/ln"; app.get("/invoice", async ({ query: { id } }, res) => { let invoice = await g(`invoice:${id}`); invoice.user = await g(`user:${invoice.user_id}`); + console.log("INV", invoice) res.send(invoice); }); app.post( "/invoice", optionalAuth, - async ( - { - body: { type = "bech32", liquidAddress, id, invoice, user, tx }, - user: me - }, - res - ) => { - let { - blindkey, - currency, - tip, - amount, - rate, - network, - request_id - } = invoice; - let text; + async ({ body: { invoice, user }, user: me }, res) => { + let { currency, tip, amount, rate, request_id } = invoice; if (amount < 0) throw new Error("amount out of range"); if (tip > 5 * amount || tip < 0) throw new Error("tip amount out of range"); tip = tip || 0; if (!user) user = me; - if (!user) throw new Error("user not provided"); + let user_id = await g(`user:${user.username}`); + user = await g(`user:${user_id}`); - user = await g(`user:${user.id}`); + if (!user) throw new Error("user not provided"); if (!currency) currency = user.currency; if (!rate) rate = store.rates[currency]; if (amount < 0) throw new Error("invalid amount"); + let { payment_hash: id, bolt11: text } = await ln.invoice( + amount ? `${amount + tip}sat` : "any", + new Date(), + "", + 3600 + ); + invoice = { ...invoice, - id: v4(), + id, amount, currency, rate, tip, - unconfidential, - user_id: user.id + user_id, + text }; - invoice.text = await derivePayRequest(invoice); - l( "creating invoice", user.username, - network, amount, tip, currency, `${text.substr(0, 8)}..${text.substr(-6)}` ); - await rd.lPush(`${id}:invoices`, invoice.id); + await s(`invoice:${id}`, invoice); + await rd.lPush(`${user.id}:invoices`, id); if (request_id) { let request = await g(`request:${request_id}`); diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index a778271b..a37dc716 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -6,132 +6,79 @@ import { callWebhook } from "$lib/webhooks"; import { computeConversionFee } from "./conversionFee"; import ln from "$lib/ln"; import { l, err, warn } from "$lib/logging"; +import { g, s, rd } from "$lib/redis"; + +let handle = async () => { + let { + payment_hash, + bolt11: request, + pay_index, + status, + msatoshi_received, + payment_preimage: secret + } = await ln.waitanyinvoice(await g("pay_index")); + + await s("pay_index", pay_index); + + let received = Math.round(msatoshi_received / 1000); -const handlePayment = async msg => { try { - l("incoming lightning payment", msg.received); + l("incoming lightning payment", received); - if (!msg.secret) return; + if (!secret) return; let account, total, user; - const invoice = await db.Invoice.findOne({ - where: { - text: msg.request - } - }); - - if (!invoice) - return warn("received lightning with no invoice", msg.request); - - await db.transaction(async transaction => { - const { text: hash, currency, memo, rate, tip, user_id } = invoice; - const amount = parseInt(msg.received) - tip; - if (amount < 0) throw new Error("amount out of range"); - - account = await db.Account.findOne({ - where: { - user_id, - asset: config.liquid.btcasset, - pubkey: null - }, - include: { - model: db.User, - as: "user" - }, - lock: transaction.LOCK.UPDATE, - transaction - }); - - ({ user } = account); - - let preimage = msg.secret; - - let payment = await db.Payment.create( - { - account_id: account.id, - user_id, - hash, - memo, - amount, - currency, - preimage, - rate, - received: true, - confirmed: true, - network: "lightning", - tip, - invoice_id: invoice.id - }, - { transaction } - ); - - total = amount + tip; - - invoice.status = "paid"; - await invoice.save({ transaction }); - - await invoice.increment({ received: total }, { transaction }); - await account.increment({ balance: total }, { transaction }); - // get the # of fee credits you would need to pay off this amount of bitcoin - await account.increment( - { lightning_credits: computeConversionFee(total) }, - { transaction } - ); - await account.reload({ transaction }); - await invoice.reload({ transaction }); - await payment.save({ transaction }); - store.payments.push(msg.request); - - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); - payment.invoice = invoice.get({ plain: true }); - - callWebhook(invoice, payment); - - emit(user.username, "payment", payment); - emit(user.username, "account", payment.account); - notify(user, `Received ${total} SAT`); - - l( - "lightning payment received", - user.username, - payment.amount, - payment.tip - ); - }); + let invoice = await g(`invoice:${payment_hash}`); + if (!invoice) return warn("received lightning with no invoice", request); + + let { text: hash, currency, memo, rate, tip, user_id } = invoice; + let amount = parseInt(received) - tip; + if (amount < 0) throw new Error("amount out of range"); + + let payment = { + user_id, + hash, + memo, + amount, + currency, + secret, + rate, + tip, + invoice_id: invoice.id + }; + + total = amount + tip; + + invoice.status = "paid"; + invoice.received += total; + await s(`invoice:${payment_hash}`, invoice); + + let t = async () => { + await rd.watch(`user:${user_id}`); + user = await g(`user:${user_id}`); + user.balance += total; + let m = await rd.multi(); + await s(`user:${user.id}`, user); + if (!(await m.exec())) t(); + }; + await t(); + + payment.invoice = invoice; + callWebhook(invoice, payment); + + emit(user.username, "payment", payment); + notify(user, `Received ${total} SAT`); + + l("lightning payment received", user.username, payment.amount, payment.tip); } catch (e) { console.log(e); err("problem receiving lightning payment", e.message); } }; -const poll = async ln => { - try { - const wait = async i => { - const { - bolt11: request, - pay_index, - status, - msatoshi_received, - payment_preimage: secret - } = await ln.waitanyinvoice(i); - - let settled = status === "paid"; - let received = parseInt(msatoshi_received / 1000); - - await handlePayment({ - request, - received, - secret - }); - await wait(pay_index); - }; - - const { invoices } = await ln.listinvoices(); - await wait(Math.max(...invoices.map(i => i.pay_index).filter(n => n))); - } catch (e) { - err("problem waiting for c-lightning invoice", e.message); - } +let listen = async () => { + await handle(); + listen(); }; -poll(ln); +listen(); diff --git a/routes/users.js b/routes/users.js index 8f0b9106..97ff9dd4 100644 --- a/routes/users.js +++ b/routes/users.js @@ -3,7 +3,7 @@ import { g, s } from "$lib/redis"; import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; -import { getUser, nada, uniq, wait } from "$lib/utils"; +import { nada, pick, uniq, wait } from "$lib/utils"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { authenticator } from "otplib"; @@ -14,11 +14,9 @@ import register from "$lib/register"; import { requirePin } from "$lib/utils"; import got from "got"; -const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); - app.get("/me", auth, async (req, res) => { try { - res.send(pick(req.user, ...whitelist)); + res.send(pick(req.user, whitelist)); } catch (e) { console.log("problem fetching user", e); res.code(500).send(e.message); @@ -32,6 +30,9 @@ app.get("/users/:key", async ({ params: { key } }, res) => { } let user = await g(`user:${key}`); + if (typeof user === "string") { + user = await g(`user:${user}`); + } if (!user && key.length === 64) { user = { @@ -41,7 +42,6 @@ app.get("/users/:key", async ({ params: { key } }, res) => { }; } - console.log(user) if (!user) return res.code(500).send("User not found"); let whitelist = [ @@ -53,10 +53,10 @@ app.get("/users/:key", async ({ params: { key } }, res) => { "pubkey", "display", "prompt", - "uuid" + "id" ]; - res.send(pick(user, ...whitelist)); + res.send(pick(user, whitelist)); } catch (e) { console.log(e); res.code(500).send(e.message); @@ -78,7 +78,7 @@ app.post("/register", async (req, res) => { user = await register(user, ip, false); l("registered new user", username); - res.send(pick(user, ...whitelist)); + res.send(pick(user, whitelist)); } catch (e) { res.code(500).send(e.message); } @@ -308,7 +308,8 @@ let login = async (req, res) => { return; } - let user = await getUser(username); + let id = await g(`user:${username}`); + let user = await g(`user:${id}`); if ( !user || @@ -332,10 +333,11 @@ let login = async (req, res) => { req.headers["x-forwarded-for"] || req.socket.remoteAddress ); - let payload = { username, uuid: user.uuid }; + let payload = { username, id: user.id }; let token = jwt.sign(payload, config.jwt); res.cookie("token", token, { expires: new Date(Date.now() + 432000000) }); - user = pick(user, ...whitelist); + user = pick(user, whitelist); + console.log("SENDING", user, token) res.send({ user, token }); } catch (e) { console.log(e); @@ -413,7 +415,7 @@ app.post("/otpsecret", auth, async function(req, res) { }); app.get("/contacts", auth, async function({ user: { uuid } }, res) { - let payments = await g(`${uuid}:payments`) || []; + let payments = (await g(`${uuid}:payments`)) || []; res.send( Promise.all( [...new Set(payments.map(p => p.with_id))].map(id => g(`user:${id}`)) -- cgit v1.2.3 From d62cc3b3db7d96ec48b71bb4adff99d134f934d7 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 17 Jan 2023 23:19:56 -0800 Subject: revert redlock --- lib/db.js | 39 +++++++++++++++++++--- lib/lightning.js | 62 ++--------------------------------- lib/nostr.js | 6 ++-- lib/sendInternal.js | 93 ----------------------------------------------------- lib/whitelist.js | 2 -- package.json | 2 -- pnpm-lock.yaml | 65 ------------------------------------- routes/invoices.js | 2 +- routes/nostr.js | 4 +-- routes/payments.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++---- routes/requests.js | 4 +-- routes/send.js | 15 --------- routes/users.js | 1 + 13 files changed, 129 insertions(+), 255 deletions(-) delete mode 100644 lib/sendInternal.js delete mode 100644 routes/send.js (limited to 'lib/whitelist.js') diff --git a/lib/db.js b/lib/db.js index fb99a756..1122038c 100644 --- a/lib/db.js +++ b/lib/db.js @@ -1,9 +1,40 @@ -import { Redis } from "ioredis"; -import Redlock from "redlock"; +import { sleep } from "$lib/utils"; +import { createClient } from "redis"; -export const db = new Redis("redis://db", { enableAutoPipelining: true }); +export const db = createClient({ url: "redis://db" }); +await db.connect(); export default db; export let g = async k => JSON.parse(await db.get(k)); export let s = (k, v) => db.set(k, JSON.stringify(v)); -export let t = (f) => new Redlock([db]).using([db], 5000, f); + +let retries = {}; +export let t = async (k, f) => { + let result; + try { + result = await db.executeIsolated(async db => { + await db.watch(k); + let v = await db.get(k); + await db + .multi() + .set(k, await f(v)) + .exec(); + }); + } catch (err) { + if (!err.message.includes("watch")) throw err; + + let r = retries[k] || 0; + retries[k] = r + 1; + + if (r < 10) { + await sleep(100); + await t(k, f); + } else { + delete retries[k]; + throw new Error("unable to obtain lock"); + } + } + + delete retries[k]; + return result; +}; diff --git a/lib/lightning.js b/lib/lightning.js index 57667be2..86dfdb2b 100644 --- a/lib/lightning.js +++ b/lib/lightning.js @@ -5,7 +5,6 @@ import { callWebhook } from "$lib/webhooks"; import ln from "$lib/ln"; import { l, err, warn } from "$lib/logging"; import { g, s, t, db } from "$lib/db"; -import Redlock from "redlock"; export async function listenForLightning() { let { @@ -18,6 +17,7 @@ export async function listenForLightning() { } = await ln.waitanyinvoice(await g("pay_index")); await s("pay_index", pay_index); + setTimeout(listenForLightning); let received = Math.round(msatoshi_received / 1000); @@ -52,65 +52,11 @@ export async function listenForLightning() { invoice.status = "paid"; invoice.received += received; - const redlock = new Redlock([db]); - await s(`invoice:${hash}`, invoice); - console.log("BAL", await g(`balance:${uid}`)); - setTimeout(async () => { - let lock = await redlock.acquire(["b"], 5000); - try { - let bal = await g(`balance:${uid}`); - console.log("b bal", bal); - await new Promise(r => setTimeout(r, 50)); - - await s(`balance:${uid}`, bal + 100); - console.log("set b bal", bal + 100); - } finally { - await lock.release(); - } - // try { - // console.log("tweaking balance"); - // await s(`balance:${uid}`, 0); - // await new Promise(r => setTimeout(r, 5)); - // console.log("mwahaha", await g(`balance:${uid}`)); - // await new Promise(r => setTimeout(r, 600)); - // console.log("hmm", await g(`balance:${uid}`)); - // } catch (e) { - // console.log(e); - // } - }, 50); - - await new Promise(r => setTimeout(r, 5)); - - let lock = await redlock.acquire(["a"], 5000); - try { - let bal = await g(`balance:${uid}`); - console.log("a bal", bal, received); - await new Promise(r => setTimeout(r, 500)); - - await s(`balance:${uid}`, bal + received); - console.log("set a bal", bal + received); - } finally { - await lock.release(); - } - - // await t(async signal => { - // console.log("acquiring lock"); - // let bal = await g(`balance:${uid}`); - // console.log("bal", bal); - // await new Promise(r => setTimeout(r, 500)); - // - // if (signal.aborted) throw signal.error; - // - // await s(`balance:${uid}`, bal + received); - // console.log("set bal", bal + received); - // }); - console.log("done", await g(`balance:${uid}`)); - + await db.incrBy(`balance:${uid}`, received); payment.invoice = invoice; - await s(`payment:${hash}`, payment); - await db.lpush(`${uid}:payments`, hash); + await db.lPush(`${uid}:payments`, hash); callWebhook(invoice, payment); @@ -122,6 +68,4 @@ export async function listenForLightning() { console.log(e); err("problem receiving lightning payment", e.message); } - - setTimeout(listenForLightning); } diff --git a/lib/nostr.js b/lib/nostr.js index c8accf85..23ea937b 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -63,17 +63,17 @@ export let fillPool = () => { await s(`${pubkey}:follows`, JSON.stringify(ev.tags)); for (let f of ev.tags) { let [_, followPubkey] = f; - await db.sadd(`${followPubkey}:followers`, pubkey); + await db.sAdd(`${followPubkey}:followers`, pubkey); } coinos.send(ev); } else if (sub.includes("followers")) { let followed = sub.split(":")[0]; let { pubkey } = ev; - await db.sadd(`${followed}:followers`, pubkey); + await db.sAdd(`${followed}:followers`, pubkey); coinos.send(ev); } else if (sub.includes("notes")) { let pubkey = sub.split(":")[0]; - await db.sadd(pubkey, ev.id); + await db.sAdd(pubkey, ev.id); await s(`ev:${ev.id}`, JSON.stringify(ev)); } } catch (e) { diff --git a/lib/sendInternal.js b/lib/sendInternal.js deleted file mode 100644 index 6054f753..00000000 --- a/lib/sendInternal.js +++ /dev/null @@ -1,93 +0,0 @@ -import config from "$config"; -import { emit } from "$lib/sockets"; -import store from "$lib/store"; -import { callWebhook } from "$lib/webhooks"; -import { v4 } from "uuid"; -import { notify } from "$lib/notifications"; -import { l, err } from "$lib/logging"; -import { fail } from "$lib/utils"; -import ln from "$lib/ln"; -import { g, s, db } from "$lib/db"; - -const { HOSTNAME: hostname } = process.env; - -export default async ({ amount, hash, memo, tip }, user) => { - amount = parseInt(amount); - - if (!amount || amount < 0) fail("Amount must be greater than zero"); - - let fee = 0; - let invoice = await g(`invoice:${hash}`); - - let t = async () => { - await db.watch(`user:${user.id}`); - user = await g(`user:${user.id}`); - if (user.balance < amount) fail("Insufficient funds"); - user.balance -= amount; - let m = await db.multi(); - await s(`user:${user.id}`, user); - - let p1 = { - hash, - amount: -amount, - memo, - uid: user.id, - rate: store.rates[user.currency], - currency: user.currency, - type: "internal", - created: Date.now() - }; - - await s(`payment:${hash}`, p1); - await db.lpush(`${user.id}:payments`, hash); - - l("sent internal", user.username, -p1.amount); - emit(user.id, "payment", p1); - - let { uid } = invoice; - if (uid !== user.id) { - let recipient = await g(`user:${uid}`); - - let u = async () => { - await db.watch(`user:${uid}`); - recipient = await g(`user:${uid}`); - recipient.balance += amount; - let m = await db.multi(); - await s(`user:${uid}`, recipient); - if (!(await m.exec())) u(); - }; - await u(); - - let p2 = { - hash, - amount, - uid: recipient.id, - rate: store.rates[recipient.currency], - currency: recipient.currency, - memo, - type: "internal", - with_id: user.id, - created: Date.now() - }; - - let { tip } = invoice; - if (tip) { - p2.tip = tip; - p2.amount -= tip; - } - - invoice.received += amount; - await s(`invoice:${hash}`, invoice); - await s(`payment:${id}`, p2); - await db.lpush(`${recipient.id}:payments`, id); - - l("received internal", recipient.username, amount); - emit(recipient.username, "payment", p2); - notify(recipient, `Received ${amount} sats`); - callWebhook(invoice, p2); - } - - if (!(await m.exec())) t(); - }; - await t(); -}; diff --git a/lib/whitelist.js b/lib/whitelist.js index 49cc9af3..77243855 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -22,10 +22,8 @@ export default [ "pubkey", "salt", "seed", - "symbol", "theme", "twofa", - "unit", "username", "verified" ]; diff --git a/package.json b/package.json index 6f1c45f9..2c1b7258 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "fastify": "^4.5.3", "file-type": "^18.0.0", "got": "^12.5.3", - "ioredis": "^5.2.5", "jsonwebtoken": "^8.5.1", "lnurl": "^0.24.2", "nodemon": "^2.0.7", @@ -33,7 +32,6 @@ "query-string": "^6.13.1", "readable-stream-clone": "^0.0.7", "redis": "^4.3.1", - "redlock": "5.0.0-beta.2", "sharp": "^0.31.1", "uuid": "8", "web-push": "^3.4.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c22c13f..5c9f09dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,7 +12,6 @@ specifiers: fastify: ^4.5.3 file-type: ^18.0.0 got: ^12.5.3 - ioredis: ^5.2.5 jsonwebtoken: ^8.5.1 lnurl: ^0.24.2 nodemon: ^2.0.7 @@ -28,7 +27,6 @@ specifiers: query-string: ^6.13.1 readable-stream-clone: ^0.0.7 redis: ^4.3.1 - redlock: 5.0.0-beta.2 sharp: ^0.31.1 uuid: '8' web-push: ^3.4.4 @@ -46,7 +44,6 @@ dependencies: fastify: 4.8.1 file-type: 18.0.0 got: 12.5.3 - ioredis: 5.2.5 jsonwebtoken: 8.5.1 lnurl: 0.24.2 nodemon: 2.0.20 @@ -61,7 +58,6 @@ dependencies: query-string: 6.14.1 readable-stream-clone: 0.0.7 redis: 4.3.1 - redlock: 5.0.0-beta.2 sharp: 0.31.1 uuid: 8.3.2 web-push: 3.5.0 @@ -179,10 +175,6 @@ packages: - utf-8-validate dev: false - /@ioredis/commands/1.2.0: - resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - dev: false - /@mapbox/node-pre-gyp/1.0.10: resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==} hasBin: true @@ -864,11 +856,6 @@ packages: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} dev: false - /denque/2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - dev: false - /depd/2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -1403,23 +1390,6 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: false - /ioredis/5.2.5: - resolution: {integrity: sha512-7HKo/ClM2DGLRXdFq8ruS3Uuadensz4A76wPOU0adqlOqd1qkhoLPDaBhmVhUhNGpB+J65/bhLmNB8DDY99HJQ==} - engines: {node: '>=12.22.0'} - dependencies: - '@ioredis/commands': 1.2.0 - cluster-key-slot: 1.1.0 - debug: 4.3.4 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - /ip/2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} dev: false @@ -1574,18 +1544,10 @@ packages: - supports-color dev: false - /lodash.defaults/4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - dev: false - /lodash.includes/4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} dev: false - /lodash.isarguments/3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - dev: false - /lodash.isboolean/3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} dev: false @@ -1775,10 +1737,6 @@ packages: semver: 7.3.8 dev: false - /node-abort-controller/3.0.1: - resolution: {integrity: sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==} - dev: false - /node-addon-api/2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} dev: false @@ -2171,18 +2129,6 @@ packages: engines: {node: '>= 12.13.0'} dev: false - /redis-errors/1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - dev: false - - /redis-parser/3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} - dependencies: - redis-errors: 1.2.0 - dev: false - /redis/4.3.1: resolution: {integrity: sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==} dependencies: @@ -2194,13 +2140,6 @@ packages: '@redis/time-series': 1.0.3_@redis+client@1.3.0 dev: false - /redlock/5.0.0-beta.2: - resolution: {integrity: sha512-2RDWXg5jgRptDrB1w9O/JgSZC0j7y4SlaXnor93H/UJm/QyDiFgBKNtrh0TI6oCXqYSaSoXxFh6Sd3VtYfhRXw==} - engines: {node: '>=12'} - dependencies: - node-abort-controller: 3.0.1 - dev: false - /require-from-string/2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -2464,10 +2403,6 @@ packages: engines: {node: '>= 10.x'} dev: false - /standard-as-callback/2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - dev: false - /statuses/2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} diff --git a/routes/invoices.js b/routes/invoices.js index 3e43c57c..acd9457e 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -58,7 +58,7 @@ export default { ); await s(`invoice:${hash}`, invoice); - await db.lpush(`${uid}:invoices`, hash); + await db.lPush(`${uid}:invoices`, hash); if (request_id) { let request = await g(`request:${request_id}`); diff --git a/routes/nostr.js b/routes/nostr.js index bac04810..2900e949 100644 --- a/routes/nostr.js +++ b/routes/nostr.js @@ -41,7 +41,7 @@ export default { await s(`user:${pubkey}`, user); - let ids = await db.smembers(pubkey); + let ids = await db.sMembers(pubkey); let events = ids.length ? (await db.mget(ids.map(k => "ev:" + k))).map(JSON.parse) @@ -101,7 +101,7 @@ export default { async followers({ params: { pubkey } }, res) { try { let pubkeys = [ - ...new Set([...(await db.smembers(`${pubkey}:followers`))]) + ...new Set([...(await db.sMembers(`${pubkey}:followers`))]) ]; let followers = []; diff --git a/routes/payments.js b/routes/payments.js index 22de79c3..27c8c5de 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -1,16 +1,91 @@ +import config from "$config"; +import store from "$lib/store"; import { emit } from "$lib/sockets"; -import { db, g, s } from "$lib/db"; +import { v4 } from "uuid"; +import { notify } from "$lib/notifications"; +import { db, g, s, t } from "$lib/db"; import { l, err, warn } from "$lib/logging"; import { fail } from "$lib/utils"; import ln from "$lib/ln"; -import sendInternal from "$lib/sendInternal"; import { requirePin } from "$lib/auth"; +import { callWebhook } from "$lib/webhooks"; + +const { HOSTNAME: hostname } = process.env; export default { - async send(req, res) { - await requirePin(req); - let payment = await sendInternal(req.body, req.user); - res.send(payment); + async send({ body, user }, res) { + let { amount, hash, memo, tip } = body; + await requirePin({ body, user }); + if (!hash) fail("invoice hash required"); + + let { id: uid } = user; + amount = parseInt(amount); + + if (!amount || amount < 0) fail("Amount must be greater than zero"); + + await t(`balance:${uid}`, async (balance) => { + await new Promise(r => setTimeout(r, 100)); + if (balance < amount) fail("Insufficient funds"); + return balance - amount; + }); + + let fee = 0; + let invoice = await g(`invoice:${hash}`); + user = await g(`user:${uid}`); + + await s(`user:${uid}`, user); + + let p1 = { + hash, + amount: -amount, + memo, + uid, + rate: store.rates[user.currency], + currency: user.currency, + type: "internal", + created: Date.now() + }; + + await s(`payment:${hash}`, p1); + await db.lPush(`${uid}:payments`, hash); + + l("sent internal", user.username, -p1.amount); + emit(user.id, "payment", p1); + + ({ uid } = invoice); + if (uid !== user.id) { + let recipient = await g(`user:${uid}`); + + let p2 = { + hash, + amount, + uid: recipient.id, + rate: store.rates[recipient.currency], + currency: recipient.currency, + memo, + type: "internal", + with_id: user.id, + created: Date.now() + }; + + let { tip } = invoice; + if (tip) { + p2.tip = tip; + p2.amount -= tip; + } + + invoice.received += amount; + await s(`invoice:${hash}`, invoice); + await s(`payment:${hash}`, p2); + await db.lPush(`${recipient.id}:payments`, hash); + + l("received internal", recipient.username, amount); + emit(recipient.username, "payment", p2); + notify(recipient, `Received ${amount} sats`); + callWebhook(invoice, p2); + } + + res.send(p1); }, async list({ user: { id }, query: { start, end, limit, offset } }, res) { @@ -21,7 +96,7 @@ export default { // if (start) where.createdAt[Op.gte] = new Date(parseInt(start)); // if (end) where.createdAt[Op.lte] = new Date(parseInt(end)); - let payments = (await db.lrange(`${id}:payments`, 0, -1)) || []; + let payments = (await db.lRange(`${id}:payments`, 0, -1)) || []; payments = await Promise.all(payments.map(hash => g(`payment:${hash}`))); payments = payments.filter(p => p); res.send({ payments, total: payments.length }); diff --git a/routes/requests.js b/routes/requests.js index 8db373dd..79af1fb6 100644 --- a/routes/requests.js +++ b/routes/requests.js @@ -15,8 +15,8 @@ export default { try { const day = new Date(new Date().setDate(new Date().getDate() - 1)); - let invoices = await db.lrange(`${id}:invoices`, 0, -1); - let requests = await db.lrange(`${id}:requests`, 0, -1); + let invoices = await db.lRange(`${id}:invoices`, 0, -1); + let requests = await db.lRange(`${id}:requests`, 0, -1); res.send({ invoices, requests }); } catch (e) { diff --git a/routes/send.js b/routes/send.js deleted file mode 100644 index 4b954616..00000000 --- a/routes/send.js +++ /dev/null @@ -1,15 +0,0 @@ -import { err } from "$lib/logging"; -import sendInternal from "$lib/sendInternal"; -import { requirePin } from "$lib/auth"; - -export default async (req, res, next) => { - try { - await requirePin(req); - let payment = await sendInternal(req.body, req.user); - res.send(payment); - } catch (e) { - console.log(e); - err("problem sending internal payment", e.message); - return res.code(500).send(e.message); - } -}; diff --git a/routes/users.js b/routes/users.js index 49aeebd7..57a423b8 100644 --- a/routes/users.js +++ b/routes/users.js @@ -19,6 +19,7 @@ export default { async me({ user }, res) { try { user.balance = await g(`balance:${user.id}`); + console.log("USER BAL", user.id, user.balance) res.send(pick(user, whitelist)); } catch (e) { console.log("problem fetching user", e); -- cgit v1.2.3 From f0543b6d94081f43a265bb9f754a654df9c4268a Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 26 Jan 2023 11:26:05 -0800 Subject: sample notify script --- lib/db.js | 12 ++---------- lib/payments.js | 31 ++++++++++++++++++++++++------- lib/upload.js | 20 +++++++++----------- lib/whitelist.js | 1 + routes/payments.js | 12 ++++++++---- sampledata/bitcoin/bitcoin.conf | 1 + sampledata/bitcoin/transaction.sh | 2 ++ 7 files changed, 47 insertions(+), 32 deletions(-) create mode 100755 sampledata/bitcoin/transaction.sh (limited to 'lib/whitelist.js') diff --git a/lib/db.js b/lib/db.js index acc4bff1..516db236 100644 --- a/lib/db.js +++ b/lib/db.js @@ -11,16 +11,9 @@ export let s = (k, v) => db.set(k, JSON.stringify(v)); let retries = {}; export let t = async (k, f) => { - let result; try { - result = await db.executeIsolated(async db => { - await db.watch(k); - let v = await db.get(k); - await db - .multi() - .set(k, await f(v)) - .exec(); - }); + await db.watch(k); + await f(await db.get(k), db); } catch (err) { if (!err.message.includes("watch")) throw err; @@ -37,5 +30,4 @@ export let t = async (k, f) => { } delete retries[k]; - return result; }; diff --git a/lib/payments.js b/lib/payments.js index 386d84d8..d0593447 100644 --- a/lib/payments.js +++ b/lib/payments.js @@ -34,16 +34,30 @@ export let debit = async ( if (!amount || amount < 0) fail("Amount must be greater than zero"); - await t(`balance:${uid}`, async balance => { - await new Promise(r => setTimeout(r, 100)); - if (balance < amount) fail("Insufficient funds"); - return balance - amount; + let ourfee = Math.round(amount * config.fee); + await t(`balance:${uid}`, async (balance, db) => { + await t(`credit:${type}:${uid}`, async (credit, db) => { + let covered = Math.min(credit, ourfee) || 0; + ourfee -= covered; + + if (balance < amount + ourfee) fail("Insufficient funds"); + await db + .multi() + .decrBy(`credit:${type}:${uid}`, covered) + .exec(); + }); + + await db + .multi() + .decrBy(`balance:${uid}`, amount + (ourfee - credit)) + .exec(); }); let p = { id, amount: -amount, fee, + ourfee, memo, uid, confirmed: true, @@ -103,9 +117,12 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => { p.id = hash; } - await db - .multi() - .set(`invoice:${hash}`, JSON.stringify(invoice)) + let m = await db.multi(); + + if ([types.bitcoin, types.lightning].includes(type)) + m.incrBy(`credit:${type}:${uid}`, Math.round(amount * config.fee)); + + m.set(`invoice:${hash}`, JSON.stringify(invoice)) .set(`payment:${p.id}`, JSON.stringify(p)) .lPush(`${uid}:payments`, p.id) .incrBy(`${balance}:${uid}`, amount) diff --git a/lib/upload.js b/lib/upload.js index fbf9ce20..5f5aebed 100644 --- a/lib/upload.js +++ b/lib/upload.js @@ -5,12 +5,16 @@ import fs from "fs"; import path from "path"; import sharp from "sharp"; import { pipeline } from "stream"; -import { g, s } from "$lib/db"; +import { g, s, db } from "$lib/db"; -export default async ({ params: { type }, file, user }, res) => { +export default async (req, res) => { + let { + params: { type }, + user + } = req; if (!["banner", "profile"].includes(type)) throw new Error("invalid upload"); - let data = await file(); + let data = await req.file(); let s1 = new Clone(data.file); let s2 = new Clone(data.file); @@ -30,14 +34,8 @@ export default async ({ params: { type }, file, user }, res) => { await new Promise(r => pipeline(s2, t, fs.createWriteStream(path), r)); - let r = async () => { - await db.watch(`user:${user.id}`); - user = await g(`user:${user.id}`); - user[type] = true; - let m = await db.multi(); - await s(`user:${user.id}`, user); - }; - await r(); + user[type] = true; + await s(`user:${user.id}`, user); res.send(name); }; diff --git a/lib/whitelist.js b/lib/whitelist.js index 77243855..850dffc0 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -14,6 +14,7 @@ export default [ "haspin", "id", "index", + "linked", "keys", "locktime", "payments", diff --git a/routes/payments.js b/routes/payments.js index a060d90a..ca32e969 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -111,9 +111,12 @@ export default { async take({ body: { name, amount }, user }, res) { amount = parseInt(amount); - await t(`pot:${name}`, async balance => { + await t(`pot:${name}`, async (balance, db) => { if (balance < amount) fail("Insufficient funds"); - return balance - amount; + await db + .multi() + .decrBy(`pot:${name}`, amount) + .exec(); }); let hash = v4(); @@ -211,10 +214,11 @@ export default { total = total - change + fee; let amount = total - fee; + if (change && !amount) fail("Cannot send to unregistered coinos address"); + await debit(txid, amount, fee, null, user, types.bitcoin, txid); await bc.sendRawTransaction(hex); res.send({ txid }); - }, - + } }; diff --git a/sampledata/bitcoin/bitcoin.conf b/sampledata/bitcoin/bitcoin.conf index 5da37e5a..3aa44186 100644 --- a/sampledata/bitcoin/bitcoin.conf +++ b/sampledata/bitcoin/bitcoin.conf @@ -16,6 +16,7 @@ rpcwallet=coinos wallet=coinos wallet=external +walletnotify=/home/bitcoin/.bitcoin/transaction.sh %s %w zmqpubrawblock=tcp://0.0.0.0:18506 zmqpubrawtx=tcp://0.0.0.0:18507 diff --git a/sampledata/bitcoin/transaction.sh b/sampledata/bitcoin/transaction.sh new file mode 100755 index 00000000..e44789d1 --- /dev/null +++ b/sampledata/bitcoin/transaction.sh @@ -0,0 +1,2 @@ +#!/bin/sh +wget -O- --post-data='{"txid": "'$1'", "wallet": "'$2'"}' --header='Content-Type:application/json' 'http://app:3119/bitcoin' -- cgit v1.2.3