diff options
| author | Adam Soltys <[email protected]> | 2022-09-02 22:12:24 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2022-09-02 22:12:24 -0700 |
| commit | 13352f9b30eed52d2e7d0970d3cbd76f401d6de0 (patch) | |
| tree | e745685b2d7373ad391431323b0bdf5ff373b55a | |
| parent | d1cc66d1a02b75f90fbf0c05910777c76228259a (diff) | |
| download | coinos-server-13352f9b30eed52d2e7d0970d3cbd76f401d6de0.tar.gz coinos-server-13352f9b30eed52d2e7d0970d3cbd76f401d6de0.zip | |
es6 migration
| -rw-r--r-- | index.js | 86 | ||||
| -rw-r--r-- | lib/account.js | 2 | ||||
| -rw-r--r-- | lib/binance.js | 17 | ||||
| -rw-r--r-- | lib/mail.js | 2 | ||||
| -rw-r--r-- | lib/passport.js | 2 | ||||
| -rw-r--r-- | lib/rates.js | 5 | ||||
| -rw-r--r-- | lib/send.js | 6 | ||||
| -rw-r--r-- | lib/sockets.js | 47 | ||||
| -rw-r--r-- | lib/store.js | 34 | ||||
| -rw-r--r-- | lib/sync.js | 15 | ||||
| -rw-r--r-- | lib/wretch.js | 3 | ||||
| -rw-r--r-- | routes/admin.js | 2 | ||||
| -rw-r--r-- | routes/assets.js | 45 | ||||
| -rw-r--r-- | routes/bitcoin/broadcast.js | 4 | ||||
| -rw-r--r-- | routes/bitcoin/receive.js | 8 | ||||
| -rw-r--r-- | routes/bitcoin/send.js | 11 | ||||
| -rw-r--r-- | routes/info.js | 1 | ||||
| -rw-r--r-- | routes/invoices.js | 9 | ||||
| -rw-r--r-- | routes/lightning/receive.js | 6 | ||||
| -rw-r--r-- | routes/liquid/broadcast.js | 4 | ||||
| -rw-r--r-- | routes/liquid/receive.js | 15 | ||||
| -rw-r--r-- | routes/liquid/send.js | 9 | ||||
| -rw-r--r-- | routes/lnurl.js | 10 | ||||
| -rw-r--r-- | routes/payments.js | 6 | ||||
| -rw-r--r-- | routes/referrals.js | 6 | ||||
| -rw-r--r-- | routes/send.js | 20 | ||||
| -rw-r--r-- | routes/swaps.js | 23 | ||||
| -rw-r--r-- | routes/users.js | 1189 |
28 files changed, 736 insertions, 851 deletions
@@ -1,67 +1,32 @@ import app from "./app.js"; -import axios from "axios"; -import bodyParser from "body-parser"; -import compression from "compression"; -import cookieParser from "cookie-parser"; -import cors from "cors"; -import express from "express"; -import { Op } from "@sequelize/core"; import persist from "./lib/persist.js"; import config from "./config/index.js"; -import { networks } from "./lib/store.js"; +import store from "./lib/store.js"; +import { l } from "./lib/logging.js"; -// app = express(); -// app.enable("trust proxy"); -// app.use(bodyParser.urlencoded({ extended: true }); -// app.use(bodyParser.json()); +import "./lib/sockets.js"; +// import "./lib/webhooks.js"; +// import "./lib/passport.js"; +// import "./lib/register.js"; +// import "./lib/upload.js"; +// import "./lib/send.js"; +// import "./lib/sync.js"; +// import "./routes/assets.js"; +// import "./routes/info.js"; +// import "./routes/users.js"; +// if (config.bitcoin) store.networks.push("bitcoin"); +// if (config.liquid) store.networks.push("liquid"); +// if (config.lna) store.networks.push("lightning"); // -// app.use((err, req, res, next) => { -// const details = { -// path: req.path, -// body: req.body, -// msg: err.message, -// stack: err.stack -// }; +// import "./lib/rates.js"; +// import "./lib/notifications.js"; // -// if (req.user) details.username = req.user.username; +// if (config.imap) import("./lib/mail.js"); +// if (config.lnurl) import("./routes/lnurl.js"); +// if (config.mailgun) import("./routes/funding.js"); // -// err("JSON Error: ", JSON.stringify(details)); -// res.status(500); -// res.set({ -// "Cache-Control": "no-cache" -// }); -// res.send(err.message); -// return res.end(); -// }); -// app.use(cookieParser()); -// app.use(cors({ credentials: true, origin: "*" }); -// app.use(compression()); - -import "./lib/logging.js"; -import "./lib/utils.js"; -import "./lib/sockets.js"; -import "./lib/webhooks.js"; -import "./lib/passport.js"; -import "./lib/register.js"; -import "./lib/upload.js"; -import "./lib/send.js"; -import "./lib/sync.js"; -import "./routes/assets.js"; -import "./routes/info.js"; -import "./routes/users.js"; -if (config.bitcoin) networks.push("bitcoin"); -if (config.liquid) networks.push("liquid"); -if (config.lna) networks.push("lightning"); - -import "./lib/rates.js"; -import "./lib/notifications.js"; - -if (config.imap) import("./lib/mail.js"); -if (config.lnurl) import("./routes/lnurl.js"); -if (config.mailgun) import ("./routes/funding.js"); - -import "./routes/invoices.js"; -import "./routes/payments.js"; +// import "./routes/invoices.js"; +// import "./routes/payments.js"; // import "./routes/swaps.js"; // Scope based Route Handling @@ -107,13 +72,16 @@ app.post("/email", async (req, res) => { } }); -app.listen(process.env.PORT || 3119, "0.0.0.0", function(err, address) { +app.listen({ port: process.env.PORT || 3119, host: "0.0.0.0" }, function( + err, + address +) { if (err) { console.log(err); app.log.error(err); process.exit(1); } - app.log.info(`CoinOS Server listening on ${address}`); + l(`CoinOS Server listening on ${address}`); }); process.on("SIGINT", process.exit); diff --git a/lib/account.js b/lib/account.js index c4cda1a4..a1f20dc7 100644 --- a/lib/account.js +++ b/lib/account.js @@ -22,7 +22,7 @@ export default async (asset, user, transaction) => { let ticker = asset.substr(0, 3).toUpperCase(); let precision = 8; - const assets = app.get("assets"); + const assets = assets; if (assets[asset]) { ({ domain, ticker, precision, name } = assets[asset]); diff --git a/lib/binance.js b/lib/binance.js index 3e25e277..1dc1facd 100644 --- a/lib/binance.js +++ b/lib/binance.js @@ -1,7 +1,7 @@ import app from "../app.js"; import WebSocket from "ws"; import { err } from "./logging.js"; -import { rates } from "./store.js"; +import store from "./store.js"; export default () => { const binance = new WebSocket( @@ -12,18 +12,15 @@ export default () => { try { let msg = JSON.parse(event.data); - let fx = app.get("fx"); - if (!fx) return; - let rates = {}; + if (!store.fx) return; - Object.keys(fx).map(symbol => { - rates[symbol] = msg.c * fx[symbol]; + Object.keys(store.fx).map(symbol => { + store.rates[symbol] = msg.c * store.fx[symbol]; }); - app.set("ask", msg.a); - app.set("bid", msg.b); - app.set("last", msg.c); - app.set("rates", rates); + // app.set("ask", msg.a); + // app.set("bid", msg.b); + last = msg.c; } catch (e) { err("binance message error", e.message); } diff --git a/lib/mail.js b/lib/mail.js index d1b67c37..d826b845 100644 --- a/lib/mail.js +++ b/lib/mail.js @@ -86,7 +86,7 @@ imap.once("ready", function() { let { user } = account; - let rate = rates["CAD"] * 1.02; + let rate = store.rates["CAD"] * 1.02; let amount = Math.round((cad / rate) * 100000000); await account.increment({ balance: amount }, { transaction }); diff --git a/lib/passport.js b/lib/passport.js index 5f987014..36057ade 100644 --- a/lib/passport.js +++ b/lib/passport.js @@ -9,7 +9,7 @@ import fs from "fs"; import path from "path"; app.register(fastifySecureSession, { - key: fs.readFileSync(config.jwt) + key: config.jwt }); app.register(fastifyPassport.initialize()); diff --git a/lib/rates.js b/lib/rates.js index 5f0c3c42..5e24cff0 100644 --- a/lib/rates.js +++ b/lib/rates.js @@ -3,6 +3,7 @@ import axios from "axios"; import fs from "fs"; import binanceFactory from "./binance.js"; import { broadcast } from "./sockets.js"; +import store from "./store.js"; const binance = binanceFactory(); @@ -45,7 +46,7 @@ let fetchRates; } } - app.set("fx", fx); + store.fx = fx; setTimeout(fetchRates, 7200000); })(); @@ -55,7 +56,7 @@ app.get("/rates", async (req, res, next) => { }); setInterval(() => { - broadcast("rate", app.get("last")); + broadcast("rate", store.last); }, 1000); setInterval(() => { diff --git a/lib/send.js b/lib/send.js index 15855d55..dbc39325 100644 --- a/lib/send.js +++ b/lib/send.js @@ -1,4 +1,4 @@ -import { rates } from "./store.js"; +import store from "./store.js"; import bolt11 from 'bolt11'; import { Op } from '@sequelize/core'; import { computeConversionFee, conversionFeeReceiver } from '../routes/lightning/conversionFee.js'; @@ -175,7 +175,7 @@ export const send = async (amount, memo, hash, user) => { memo: "Lightning conversion fee", account_id: receiverAccount.id, user_id: receiverAccount.user_id, - rate: rates[receiverAccount.user.currency], + rate: store.rates[receiverAccount.user.currency], currency: receiverAccount.user.currency, confirmed: true, received: true, @@ -194,7 +194,7 @@ export const send = async (amount, memo, hash, user) => { hash, memo, preimage, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, network: "lightning", diff --git a/lib/sockets.js b/lib/sockets.js index 6ea369c0..de6986b1 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -1,7 +1,7 @@ -import { sockets } from "./store.js"; +import store from "./store.js"; import app from "../app.js"; import jwt from "jsonwebtoken"; -import { v4 as uuidv4 } from "uuid"; +import { v4 } from "uuid"; import WebSocket from "ws"; import { differenceInSeconds, subSeconds } from "date-fns"; import fastifyWs from "@fastify/websocket"; @@ -35,18 +35,18 @@ export const emit = (username, type, data) => { } } - if (!sockets[username]) return; - for (id in sockets[username]) { - const ws = sockets[username][id]; + if (!store.sockets[username]) return; + for (id in store.sockets[username]) { + const ws = store.sockets[username][id]; ws.send(JSON.stringify({ type, data })); } }; export const broadcast = (type, data) => { const sent = []; - for (const username in sockets) { - for (const id in sockets[username]) { - const ws = sockets[username][id]; + for (const username in store.sockets) { + for (const id in store.sockets[username]) { + const ws = store.sockets[username][id]; ws.send(JSON.stringify({ type, data })); sent.push(ws.id); } @@ -60,7 +60,7 @@ export const broadcast = (type, data) => { app.register(fastifyWs); app.register(async function(app) { app.get("/ws", { websocket: true }, ({ socket: ws }, req) => { - const id = uuidv4(); + const id = v4(); ws.id = id; ws.beats = 0; ws.send(JSON.stringify({ type: "connected", data: id })); @@ -92,17 +92,17 @@ app.register(async function(app) { const username = jwt.decode(token).username; if (!username) throw new Error("Invalid JWT token"); - if (!sockets[username]) sockets[username] = {}; - const existing = Object.keys(sockets[username]); + if (!store.sockets[username]) store.sockets[username] = {}; + const existing = Object.keys(store.sockets[username]); if (existing.length > 4) { const p = existing.find(sid => sid !== id); - sockets[username][p].send(JSON.stringify({ type: "logout" })); + store.sockets[username][p].send(JSON.stringify({ type: "logout" })); setTimeout(() => { - if (sockets[username][p]) - sockets[username][p].close(code, "too many sockets"); + if (store.sockets[username][p]) + store.sockets[username][p].close(code, "too many sockets"); }, 5000); } - sockets[username][id] = ws; + store.sockets[username][id] = ws; names[id] = username; let user = await getUser(username); @@ -187,8 +187,8 @@ app.register(async function(app) { // if (reason) console.log("closing socket", reason); try { const username = names[id]; - if (sockets[username] && sockets[username][id]) { - delete sockets[username][id]; + if (store.sockets[username] && store.sockets[username][id]) { + delete store.sockets[username][id]; } if (all[id]) delete all[id]; @@ -199,19 +199,12 @@ app.register(async function(app) { }); }); -app.listen({ port: 3000 }, err => { - if (err) { - fastify.log.error(err); - process.exit(1); - } -}); - const names = {}; setInterval(() => { - for (const username in sockets) { - for (const id in sockets[username]) { - let ws = sockets[username][id]; + for (const username in store.sockets) { + for (const id in store.sockets[username]) { + let ws = store.sockets[username][id]; ws.beats++; if (ws.beats > 10) ws.close(code, `${username} ${id} lost heartbeat`); } diff --git a/lib/store.js b/lib/store.js index f32ad101..5667474a 100644 --- a/lib/store.js +++ b/lib/store.js @@ -1,15 +1,23 @@ import persist from "./persist.js"; -export const addresses = {}; -export const challenge = {}; -export const change = []; -export const exceptions = []; -export const issuances = {}; -export const logins = {}; -export const seen = []; -export const sessions = {}; -export const sockets = {}; -export const unaccounted = []; -export const networks = []; -export const convert = persist("data/conversions.json"); -export const fx; +export default { + addresses: {}, + challenge: {}, + change: [], + exceptions: [], + issuances: {}, + logins: {}, + seen: [], + sessions: {}, + sockets: {}, + unaccounted: [], + networks: [], + convert: persist("data/conversions.json"), + rates: {}, + fx: {}, + assets: {}, + bcAddressIndex: 0, + lqAddressIndex: 0, + last: {}, + payments: [] +}; diff --git a/lib/sync.js b/lib/sync.js index 6fcf8a10..f1d28421 100644 --- a/lib/sync.js +++ b/lib/sync.js @@ -4,11 +4,12 @@ import { differenceInDays } from "date-fns"; import fs from "fs"; import read from "../lib/read.js"; import { Op } from "@sequelize/core"; -import { addresses, exceptions } from "./store.js"; +import store from "./store.js"; +import { err } from "./logging.js"; const init = async () => { try { - read(fs.createReadStream("exceptions"), data => exceptions.push(data)); + read(fs.createReadStream("exceptions"), data => store.exceptions.push(data)); } catch (e) { warn("couldn't read exceptions file", e.message); } @@ -29,14 +30,14 @@ const init = async () => { } }) ).map(({ address, user, unconfidential }) => { - if (address && user) addresses[address] = user.username; - if (unconfidential && user) addresses[unconfidential] = user.username; + if (address && user) store.addresses[address] = user.username; + if (unconfidential && user) store.addresses[unconfidential] = user.username; }); } catch (e) { console.log(e); } - payments = ( + store.payments = ( await db.Payment.findAll({ attributes: ["hash"] }) @@ -206,7 +207,7 @@ const sync = async () => { transactions.map(tx => { if ( !payments.find(p => p.hash === tx.txid) && - !exceptions.includes(tx.txid) && + !store.exceptions.includes(tx.txid) && !unaccounted.find(a => a.txid === tx.txid) && new Date(tx.blocktime * 1000) >= twoWeeksAgo ) { @@ -276,7 +277,7 @@ const sync = async () => { try { await db.transaction(async transaction => { l("found pending transaction", user.username, amount, hash); - payments.push(hash); + store.payments.push(hash); let p = await db.Payment.create( { account_id, diff --git a/lib/wretch.js b/lib/wretch.js index e4427760..67e28b88 100644 --- a/lib/wretch.js +++ b/lib/wretch.js @@ -1,3 +1,4 @@ import wretch from "wretch"; import fetch from 'node-fetch'; -export default wretch().polyfills({ fetch }); +wretch().polyfills({ fetch }); +export default wretch; diff --git a/routes/admin.js b/routes/admin.js index bf8a112a..f63c64b3 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -5,8 +5,6 @@ import * as parseInput from '../scripts/apiParse.js'; import Sequelize from '@sequelize/core'; const Op = Sequelize.Op; -import { v4 as uuidv4 } from 'uuid'; - /** * @api {get} /users Retrieve user list * @apiName getUsers diff --git a/routes/assets.js b/routes/assets.js index 451f8b6a..320c2f3b 100644 --- a/routes/assets.js +++ b/routes/assets.js @@ -1,4 +1,4 @@ -import { rates } from "../lib/store.js"; +import store from "../lib/store.js"; import app from "../app.js"; import { auth } from "../lib/passport.js"; import axios from 'axios'; @@ -8,10 +8,11 @@ import fs from 'fs'; let fetchAssets; (fetchAssets = async () => { try { - const { data: assets } = await axios.get( + const { data } = await axios.get( "https://assets.blockstream.info/" ); - app.set("assets", assets); + + store.assets = data; } catch (e) { var liquid_assets = require("./../assets.json"); if (liquid_assets) { @@ -29,30 +30,28 @@ let fetchAssets; app.get( "/assets", async (req, res) => { - if (app.get("assets")) { - const assets = app.get("assets"); - + if (store.assets) { const accounts = await db.Account.findAll({ // group: ["asset"] }); - Object.keys(assets).map(a => { - assets[a].registered = true; - if (!assets[a].asset) assets[a].asset = assets[a].asset_id; + Object.keys(store.assets).map(a => { + store.assets[a].registered = true; + if (!store.assets[a].asset) store.assets[a].asset = store.assets[a].asset_id; if ( - (assets[a].ticker === "BTC" && - assets[a].asset !== config.liquid.btcasset) || - (assets[a].ticker === "EUR" && - assets[a].asset !== config.liquid.eurasset) || - (assets[a].ticker === "CAD" && - assets[a].asset !== config.liquid.cadasset) || - (assets[a].ticker === "USDt" && - assets[a].asset !== config.liquid.usdtasset) + (store.assets[a].ticker === "BTC" && + store.assets[a].asset !== config.liquid.btcasset) || + (store.assets[a].ticker === "EUR" && + store.assets[a].asset !== config.liquid.eurasset) || + (store.assets[a].ticker === "CAD" && + store.assets[a].asset !== config.liquid.cadasset) || + (store.assets[a].ticker === "USDt" && + store.assets[a].asset !== config.liquid.usdtasset) ) - delete assets[a]; + delete store.assets[a]; }); accounts.map(({ asset, name, domain, ticker, precision }) => { - if (!assets[asset]) - assets[asset] = { + if (!store.assets[asset]) + store.assets[asset] = { asset, name, domain, @@ -61,7 +60,7 @@ app.get( }; }); - res.send(assets); + res.send(store.assets); } else { console.log("error getting blockstream assets"); res.status(500).send("Problem fetching blockstream asset registry data"); @@ -378,7 +377,7 @@ app.post( let ticker = asset.substr(0, 3).toUpperCase(); let precision = 8; - const assets = app.get("assets"); + const assets = assets; if (assets[asset]) { ({ domain, ticker, precision, name } = assets[asset]); @@ -409,7 +408,7 @@ app.post( amount: -amount, account_id: account.id, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, hash: `Loaded Faucet - ${a2.ticker}`, diff --git a/routes/bitcoin/broadcast.js b/routes/bitcoin/broadcast.js index 4eb16d3d..185db283 100644 --- a/routes/bitcoin/broadcast.js +++ b/routes/bitcoin/broadcast.js @@ -1,4 +1,4 @@ -import { rates } from "../../lib/store.js"; +import store from "../../lib/store.js"; export default async (req, res) => { try { const { user } = req; @@ -21,7 +21,7 @@ export default async (req, res) => { tip: 0, account_id: account.id, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, received: false, diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index 1d12bd9b..c5baa76e 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -1,8 +1,8 @@ import { rates } from "../../lib/store.js"; -import { notify } from "../lib/notifications.js"; -import { callWebhook } from "../lib/webhooks.js"; +import { notify } from "../../lib/notifications.js"; +import { callWebhook } from "../../lib/webhooks.js"; import reverse from 'buffer-reverse'; -import zmq from 'zeromq/v5-compat'; +import zmq from 'zeromq/v5-compat.js'; import { Op } from '@sequelize/core'; import { fromBase58 } from 'bip32'; import bitcoin from 'bitcoinjs-lib'; @@ -78,7 +78,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { const currency = invoice ? invoice.currency : user.currency; const rate = invoice ? invoice.rate - : rates[user.currency]; + : store.rates[user.currency]; const tip = invoice ? invoice.tip : 0; const memo = invoice ? invoice.memo : ""; diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index 6b991519..5cecde32 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -1,5 +1,4 @@ -import { rates } from "../../lib/store.js"; -import { addresses } from "../../lib/store.js"; +import store from "../../lib/store.js"; import config from "../../config/index.js"; const btc = config.liquid.btcasset; import { @@ -17,7 +16,7 @@ export default async (req, res) => { const isChange = async ({ address }) => (await bc.getAddressInfo(address)).ismine && - !Object.keys(addresses).includes(address); + !Object.keys(store.addresses).includes(address); tx = await bc.decodeRawTransaction(hex); @@ -123,7 +122,7 @@ export default async (req, res) => { memo: "Bitcoin conversion fee", account_id: receiverAccount.id, user_id: receiverAccount.user_id, - rate: rates[receiverAccount.user.currency], + rate: store.rates[receiverAccount.user.currency], currency: receiverAccount.user.currency, confirmed: true, received: true, @@ -141,7 +140,7 @@ export default async (req, res) => { memo, account_id: account.id, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, address, confirmed: true, @@ -165,7 +164,7 @@ export default async (req, res) => { emit(user.username, "payment", payment); res.send(payment); - payments.push(params.hash); + store.payments.push(params.hash); l("sent bitcoin", user.username, total); }); } catch (e) { diff --git a/routes/info.js b/routes/info.js index 2da1807c..970cbb2a 100644 --- a/routes/info.js +++ b/routes/info.js @@ -15,7 +15,6 @@ app.get("/info", async (req, res, next) => { const { clientVersion } = config; const info = { - fx: app.get("fx"), nodes: networks, clientVersion, }; diff --git a/routes/invoices.js b/routes/invoices.js index d4a003be..814363b0 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -1,5 +1,4 @@ -import { rates } from "../lib/store.js"; -import { addresses } from "../lib/store.js"; +import store from "../lib/store.js"; import app from "../app.js"; import { optionalAuth } from "../lib/passport.js"; import { Op } from "@sequelize/core"; @@ -52,7 +51,7 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { } if (!user) throw new Error("user not provided"); if (!invoice.currency) invoice.currency = user.currency; - if (!invoice.rate) invoice.rate = rates[invoice.currency]; + if (!invoice.rate) invoice.rate = store.rates[invoice.currency]; if (invoice.tip > invoice.amount || invoice.tip > 1000000) throw new Error("tip is too large"); if (invoice.tip < 0 || invoice.amount < 0) @@ -87,9 +86,9 @@ app.post("/invoice", optionalAuth, async (req, res, next) => { invoice = exists ? await exists.update(invoice) : await db.Invoice.create(invoice); - addresses[invoice.address] = user.username; + store.addresses[invoice.address] = user.username; if (invoice.unconfidential) { - addresses[invoice.unconfidential] = user.username; + store.addresses[invoice.unconfidential] = user.username; if (blindkey) await lq.importBlindingKey(invoice.address, blindkey); } diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index e35d91ec..f013efd7 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -1,7 +1,9 @@ +import config from "../../config/index.js"; import { notify } from "../../lib/notifications.js"; import { callWebhook } from "../../lib/webhooks.js"; import { computeConversionFee } from './conversionFee.js'; import { sendLiquid } from "../liquid/send.js"; +import ln from "../../lib/ln.js"; const handlePayment = async (msg) => { l("incoming lightning payment", msg.value, msg.payment_request, msg.settled); @@ -147,8 +149,8 @@ if (config.lna.clightning) { wait(Math.max(...invoices.map((i) => i.pay_index).filter((n) => n))); }; - poll(lna); + poll(ln); } else { - const invoices = lna.subscribeInvoices({}); + const invoices = ln.subscribeInvoices({}); invoices.on("data", handlePayment); } diff --git a/routes/liquid/broadcast.js b/routes/liquid/broadcast.js index 1a44cd2b..5deb846f 100644 --- a/routes/liquid/broadcast.js +++ b/routes/liquid/broadcast.js @@ -1,4 +1,4 @@ -import { rates } from "../../lib/store.js"; +import store from "../../lib/store.js"; export default async (req, res) => { try { const { user } = req; @@ -22,7 +22,7 @@ export default async (req, res) => { tip: 0, account_id: account.id, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, received: false, diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 380fe4f4..5f61bc73 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -1,14 +1,13 @@ -import { rates } from "../../lib/store.js"; -import { addresses } from "../../lib/store.js"; +import store from "../../lib/store.js"; import { sendLiquid } from "./send.js"; import { notify } from "../../lib/notifications.js"; import { callWebhook } from "../../lib/webhooks.js"; import reverse from 'buffer-reverse'; -import zmq from 'zeromq/v5-compat'; +import zmq from 'zeromq/v5-compat.js'; import { Op } from '@sequelize/core'; import { fromBase58 } from 'bip32'; import bitcoin from 'bitcoinjs-lib'; -// import { Block, networks, Transaction } from 'liquidjs-lib'; +import { Block, networks, Transaction } from 'liquidjs-lib'; const network = networks[ @@ -51,7 +50,7 @@ const getAccount = async (params, transaction) => { params.seed = nc.seed; } - const assets = app.get("assets"); + const assets = assets; if (assets[asset]) { ({ domain, ticker, precision, name } = assets[asset]); @@ -117,11 +116,11 @@ zmqRawTx.on("message", async (topic, message, sequence) => { const address = o.scriptPubKey.addresses[0]; if ( - Object.keys(addresses).includes(address) && + Object.keys(store.addresses).includes(address) && !change.includes(address) ) { await db.transaction(async transaction => { - let user = await getUser(addresses[address], transaction); + let user = await getUser(store.addresses[address], transaction); let invoice = await db.Invoice.findOne({ where: { @@ -172,7 +171,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { const currency = invoice ? invoice.currency : user.currency; const rate = invoice ? invoice.rate - : rates[user.currency]; + : store.rates[user.currency]; const tip = invoice ? invoice.tip : 0; const memo = invoice ? invoice.memo : ""; diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 674b93f2..5b4db184 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -1,5 +1,4 @@ -import { rates } from "../../lib/store.js"; -import { addresses } from "../../lib/store.js"; +import store from "../../lib/store.js"; import config from "../../config/index.js"; const btc = config.liquid.btcasset; const lcad = config.liquid.cadasset; @@ -25,7 +24,7 @@ export const sendLiquid = async ({ asset, amount, user, address, memo, tx, limit const isChange = async address => (await lq.getAddressInfo(address)).ismine && - !Object.keys(addresses).includes(address); + !Object.keys(store.addresses).includes(address); let totals = {}; let change = {}; @@ -184,7 +183,7 @@ export const sendLiquid = async ({ asset, amount, user, address, memo, tx, limit memo: "Liquid conversion fee", account_id: receiverAccount.id, user_id: receiverAccount.user_id, - rate: rates[receiverAccount.user.currency], + rate: store.rates[receiverAccount.user.currency], currency: receiverAccount.user.currency, confirmed: true, received: true, @@ -202,7 +201,7 @@ export const sendLiquid = async ({ asset, amount, user, address, memo, tx, limit fee, memo, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, address, confirmed: true, diff --git a/routes/lnurl.js b/routes/lnurl.js index 82420734..3e5b0fd8 100644 --- a/routes/lnurl.js +++ b/routes/lnurl.js @@ -1,4 +1,4 @@ -import { rates } from "../lib/store.js"; +import store from "../lib/store.js"; import app from "../app.js"; import config from "../config/index.js"; import axios from "axios"; @@ -87,7 +87,7 @@ app.post("/withdraw", auth, async (req, res, next) => { await db.Invoice.create({ user_id: user.id, text: pr, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, amount: value, tip: 0, @@ -271,7 +271,7 @@ lnurlServer.on("payRequest:action:processed", async function(event) { let i = await db.Invoice.create({ user_id: recipient.id, text: invoice, - rate: rates[recipient.currency], + rate: store.rates[recipient.currency], currency: recipient.currency, amount: payreq.satoshis, tip: 0, @@ -422,7 +422,7 @@ lnurlServer.bindToHook( memo: "Bitcoin conversion fee", account_id: receiverAccount.id, user_id: receiverAccount.user_id, - rate: rates[receiverAccount.user.currency], + rate: store.rates[receiverAccount.user.currency], currency: receiverAccount.user.currency, confirmed: true, received: true, @@ -439,7 +439,7 @@ lnurlServer.bindToHook( account_id: account.id, user_id: user.id, hash: pr, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, network: "lightning", diff --git a/routes/payments.js b/routes/payments.js index f947350b..f6e28f18 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -1,3 +1,4 @@ +import store from "../lib/store.js"; import bc from "../lib/bitcoin.js"; import app from "../app.js"; import config from "../config/index.js"; @@ -6,6 +7,7 @@ import fs from "fs"; import { join } from "path"; import { Op } from "@sequelize/core"; import send from "./send.js"; +import { warn } from "../lib/logging.js"; import btcRoutes from "./bitcoin/index.js"; import lnRoutes from "./lightning/index.js"; @@ -71,7 +73,7 @@ if (config.bitcoin) { const address = await bc.getNewAddress(); const { hdkeypath } = await bc.getAddressInfo(address); const parts = hdkeypath.split("/"); - app.set("bcAddressIndex", parts[parts.length - 1].replace("'", "")); + store.bcAddressIndex = parts[parts.length - 1].replace("'", ""); } catch (e) { console.error(e); } @@ -91,7 +93,7 @@ if (config.liquid) { const address = await lq.getNewAddress(); const { hdkeypath } = await lq.getAddressInfo(address); const parts = hdkeypath.split("/"); - app.set("lqAddressIndex", parts[parts.length - 1].slice(0, -1)); + store.lqAddressIndex = parts[parts.length - 1].slice(0, -1); } catch (e) { warn("Problem getting liquid address index", e.message); } diff --git a/routes/referrals.js b/routes/referrals.js index 5711532f..87cef102 100644 --- a/routes/referrals.js +++ b/routes/referrals.js @@ -1,7 +1,7 @@ import express from 'express'; var router = express.Router(); -import { v4 as uuidv4 } from 'uuid'; +import { v4 } from 'uuid'; router.get('/', function(req, res, next) { res.send('list of referrals...'); @@ -44,7 +44,7 @@ router.post( auth, async (req, res) => { const {sponsor_id, expiry} = req.body - var token = uuidv4() + var token = v4() var ref = await knex.table('referrals') .insert({ @@ -84,7 +84,7 @@ router.get( auth, async (req, res) => { const {sponsor_id, expiry} = req.query - var token = uuidv4() + var token = v4() var ref = await knex.table('referrals') .insert({ diff --git a/routes/send.js b/routes/send.js index b0f8accb..778d3534 100644 --- a/routes/send.js +++ b/routes/send.js @@ -1,7 +1,7 @@ -import { rates } from "../lib/store.js"; +import store from "../lib/store.js"; import { callWebhook } from "../lib/webhooks.js"; import axios from "axios"; -import { v4 as uuidv4 } from "uuid"; +import { v4 } from "uuid"; import { notify } from "../lib/notifications.js"; import { sendLiquid } from "./liquid/send.js"; @@ -61,10 +61,10 @@ export default async (req, res, next) => { account_id: account.id, memo, user_id: user.id, - rate: rates[user.currency], + rate: store.rates[user.currency], currency: user.currency, confirmed: true, - hash: `#${uuidv4().substr(0, 6)} ${ + hash: `#${v4().substr(0, 6)} ${ username ? `Payment to ${username}` : "Internal Transfer" }`, network: "COINOS" @@ -72,7 +72,7 @@ export default async (req, res, next) => { if (!username) { l("creating redeemable payment"); - params.redeemcode = uuidv4(); + params.redeemcode = v4(); params.hash = `${req.get("origin")}/redeem/${params.redeemcode}`; } @@ -132,10 +132,8 @@ export default async (req, res, next) => { let ticker = asset.substr(0, 3).toUpperCase(); let precision = 8; - const assets = app.get("assets"); - - if (assets[asset]) { - ({ domain, ticker, precision, name } = assets[asset]); + if (store.assets[asset]) { + ({ domain, ticker, precision, name } = store.assets[asset]); } else { const existing = await db.Account.findOne({ where: { @@ -166,10 +164,10 @@ export default async (req, res, next) => { amount, account_id: a2.id, user_id: recipient.id, - rate: rates[recipient.currency] * spread, + rate: store.rates[recipient.currency] * spread, currency: recipient.currency, confirmed: true, - hash: `#${uuidv4().substr(0, 6)} Payment from ${user.username}`, + hash: `#${v4().substr(0, 6)} Payment from ${user.username}`, memo, network: "COINOS", received: true diff --git a/routes/swaps.js b/routes/swaps.js index f1bdcbc8..89cc2188 100644 --- a/routes/swaps.js +++ b/routes/swaps.js @@ -4,7 +4,6 @@ import crypto from 'crypto'; import fs from 'fs'; import getAccount from '../lib/account.js'; import { Op, col } from '@sequelize/core'; -import { v4 as uuidv4 } from 'uuid'; import { rates } from "../lib/store.js"; const shallow = a => { @@ -65,7 +64,7 @@ const swap = async (user, { a1, a2, v1, v2 }) => { account_id: a1acc.id, user_id: user.id, currency: user.currency, - rate: rates[user.currency], + rate: store.rates[user.currency], confirmed: true, received: false, network: "COINOS" @@ -134,7 +133,7 @@ const swap = async (user, { a1, a2, v1, v2 }) => { account_id: a1acc.id, user_id: user.id, currency: user.currency, - rate: rates[user.currency], + rate: store.rates[user.currency], confirmed: true, received: true, network: "COINOS" @@ -159,7 +158,7 @@ const swap = async (user, { a1, a2, v1, v2 }) => { account_id: btc.id, user_id: order.user_id, currency: order.user.currency, - rate: rates[order.user.currency], + rate: store.rates[order.user.currency], confirmed: true, received: true, network: "COINOS" @@ -198,7 +197,7 @@ const swap = async (user, { a1, a2, v1, v2 }) => { account_id: a2acc.id, user_id: user.id, currency: user.currency, - rate: rates[user.currency], + rate: store.rates[user.currency], confirmed: true, received: true, network: "COINOS" @@ -219,7 +218,7 @@ const swap = async (user, { a1, a2, v1, v2 }) => { account_id: order.a2_id, user_id: order.user_id, currency: order.user.currency, - rate: rates[order.user.currency], + rate: store.rates[order.user.currency], confirmed: true, received: true, network: "COINOS" @@ -292,7 +291,7 @@ const cancel = async (user, id) => { account_id: account.id, user_id: user.id, currency: user.currency, - rate: rates[user.currency], + rate: store.rates[user.currency], confirmed: true, received: true, network: "COINOS" @@ -313,7 +312,7 @@ const cancel = async (user, id) => { account_id: btc.id, user_id: user.id, currency: user.currency, - rate: rates[user.currency], + rate: store.rates[user.currency], confirmed: true, received: true, network: "COINOS" @@ -445,8 +444,8 @@ if (config.maker) { v2: Math.round( amount * SATS * - (((app.get("ask") * rates[currency]) / - rates["USD"]) * + (((app.get("ask") * store.rates[currency]) / + store.rates["USD"]) * askMultiplier) ) }; @@ -528,8 +527,8 @@ if (config.maker) { v1: Math.round( amount * SATS * - ((app.get("bid") * rates[currency]) / - rates["USD"]) * + ((app.get("bid") * store.rates[currency]) / + store.rates["USD"]) * bidMultiplier ), v2: amount * SATS diff --git a/routes/users.js b/routes/users.js index d9ab92d5..2222741f 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,20 +1,21 @@ +import app from "../app.js"; +import { auth, optionalAuth } from "../lib/passport.js"; import { getUser } from "../lib/utils.js"; -import axios from 'axios'; -import bcrypt from 'bcrypt'; -import jwt from 'jsonwebtoken'; -import { authenticator } from 'otplib'; -import getAccount from '../lib/account.js'; -import Sequelize from '@sequelize/core'; -import bitcoin from 'bitcoinjs-lib'; +import axios from "axios"; +import bcrypt from "bcrypt"; +import jwt from "jsonwebtoken"; +import { authenticator } from "otplib"; +import getAccount from "../lib/account.js"; +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'; +import { fromBase58, fromPrivateKey } from "bip32"; +import { Mutex } from "async-mutex"; +import bip32 from "bip32"; import whitelist from "../lib/whitelist.js"; const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); -/* const twofa = (req, res, next) => { let { user, @@ -27,293 +28,255 @@ const twofa = (req, res, next) => { ) { return res.status(401).send("2fa required"); } else next(); -} +}; -app.get( - "/me", - auth, - async (req, res) => { - let user = req.user.get({ plain: true }); - let payments = await req.user.getPayments({ - where: { - account_id: user.account_id +app.get("/me", auth, async (req, res) => { + let user = req.user.get({ plain: true }); + let payments = await req.user.getPayments({ + where: { + account_id: user.account_id + }, + order: [["id", "DESC"]], + limit: 12, + include: [ + { + model: db.Account, + as: "account" }, - order: [["id", "DESC"]], - limit: 12, - include: [ - { - model: db.Account, - as: "account" - }, - { - model: db.Payment, - as: "fee_payment" - } - ] - }); - user.accounts = await req.user.getAccounts(); - user.payments = payments; - res.send(user); - }) + { + model: db.Payment, + as: "fee_payment" + } + ] + }); + user.accounts = await req.user.getAccounts(); + user.payments = payments; + res.send(user); +}); -app.get( - "/users/:username", - async (req, res) => { - const { username } = req.params; +app.get("/users/:username", async (req, res) => { + const { username } = req.params; - const user = await db.User.findOne({ - attributes: ["username"], - where: Sequelize.where( - Sequelize.fn("lower", Sequelize.col("username")), - username.toLowerCase() - ) - }); + const user = await db.User.findOne({ + attributes: ["username"], + where: Sequelize.where( + Sequelize.fn("lower", Sequelize.col("username")), + username.toLowerCase() + ) + }); - if (user) res.send(user); - else res.status(500).send("User not found"); - }) + if (user) res.send(user); + else res.status(500).send("User not found"); +}); -app.post( - "/register", - async (req, res) => { - try { - const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; - const user = await register(req.body.user, ip, false); - res.send(pick(user, ...whitelist)); - } catch (e) { - res.status(500).send(e.message); - } - }) +app.post("/register", async (req, res) => { + try { + const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; + const user = await register(req.body.user, ip, false); + res.send(pick(user, ...whitelist)); + } catch (e) { + res.status(500).send(e.message); + } +}); -app.post( - "/disable2fa", - auth, - twofa, - async (req, res) => { - let { user } = req; - user.twofa = false; - await user.save(); - emit(user.username, "user", user); - emit(user.username, "otpsecret", user.otpsecret); - l("disabled 2fa", user.username); - res.send({}); - }) +app.post("/disable2fa", auth, twofa, async (req, res) => { + let { user } = req; + user.twofa = false; + await user.save(); + emit(user.username, "user", user); + emit(user.username, "otpsecret", user.otpsecret); + l("disabled 2fa", user.username); + res.send({}); +}); -app.get( - "/otpsecret", - auth, - twofa, - async (req, res) => { - let { user } = req; - emit(user.username, "otpsecret", user.otpsecret); - res.end(); - }) +app.get("/otpsecret", auth, twofa, async (req, res) => { + let { user } = req; + emit(user.username, "otpsecret", user.otpsecret); + res.end(); +}); -app.post( - "/2fa", - auth, - async (req, res) => { - let { user } = req; - try { - const isValid = authenticator.check(req.body.token, req.user.otpsecret); - if (isValid) { - user.twofa = true; - user.save(); - emit(user.username, "user", req.user); - } else { - return res.status(500).send("Invalid token"); - } - } catch (e) { - err("error setting up 2fa", e); +app.post("/2fa", auth, async (req, res) => { + let { user } = req; + try { + const isValid = authenticator.check(req.body.token, req.user.otpsecret); + if (isValid) { + user.twofa = true; + user.save(); + emit(user.username, "user", req.user); + } else { + return res.status(500).send("Invalid token"); } + } catch (e) { + err("error setting up 2fa", e); + } - l("enabled 2fa", user.username); - res.send({}); - }) - -app.get( - "/exists", - async (req, res) => { - let exists = await db.User.findOne({ - where: { username: req.query.username } - }); + l("enabled 2fa", user.username); + res.send({}); +}); - res.send(!!exists); - }) +app.get("/exists", async (req, res) => { + let exists = await db.User.findOne({ + where: { username: req.query.username } + }); -app.post( - "/user", - auth, - async (req, res) => { - try { - let { user } = req; - let { - address, - confirm, - currencies, - currency, - email, - fiat, - password, - pin, - seed, - tokens, - twofa, - unit, - username - } = req.body; + res.send(!!exists); +}); - let exists = await db.User.findOne({ - where: { username } - }); +app.post("/user", auth, async (req, res) => { + try { + let { user } = req; + let { + address, + confirm, + currencies, + currency, + email, + fiat, + password, + pin, + seed, + tokens, + twofa, + unit, + username + } = req.body; - let token; - if (user.username !== username && exists) { - err("username taken", username, user.username, exists.username); - return res.status(500).send("Username taken"); - } else { - sockets[username] = sockets[user.username]; - if (user.username !== username) - l("changing username", user.username, username); - user.username = username; + let exists = await db.User.findOne({ + where: { username } + }); - token = jwt.sign({ username }, config.jwt); - res.cookie("token", token, { - expires: new Date(Date.now() + 432000000) - }); - } + let token; + if (user.username !== username && exists) { + err("username taken", username, user.username, exists.username); + return res.status(500).send("Username taken"); + } else { + sockets[username] = sockets[user.username]; + if (user.username !== username) + l("changing username", user.username, username); + user.username = username; - if (unit) user.unit = unit; - user.currency = currency; - user.currencies = currencies; + token = jwt.sign({ username }, config.jwt); + res.cookie("token", token, { + expires: new Date(Date.now() + 432000000) + }); + } - user.tokens = tokens; - user.twofa = twofa; - user.pin = pin; - user.seed = seed; - user.fiat = fiat; - user.email = email; - user.address = address; + if (unit) user.unit = unit; + user.currency = currency; + user.currencies = currencies; - if (password && password === confirm) { - user.password = await bcrypt.hash(password, 1); - } + user.tokens = tokens; + user.twofa = twofa; + user.pin = pin; + user.seed = seed; + user.fiat = fiat; + user.email = email; + user.address = address; - await user.save(); - emit(user.username, "user", user); - res.send({ user, token }); - } catch (e) { - err("error updating user", e.message); + if (password && password === confirm) { + user.password = await bcrypt.hash(password, 1); } - }) -app.post( - "/keys", - auth, - async (req, res) => { - const { key: hex } = req.body; - const key = await db.Key.create({ - user_id: req.user.id, - hex - }); - emit(req.user.username, "key", key); - res.send(key); - }) + await user.save(); + emit(user.username, "user", user); + res.send({ user, token }); + } catch (e) { + err("error updating user", e.message); + } +}); -app.post( - "/keys/delete", - auth, - async (req, res) => { - const { hex } = req.body; - ( - await db.Key.findOne({ - where: { - user_id: req.user.id, - hex - } - }) - ).destroy(); - }) +app.post("/keys", auth, async (req, res) => { + const { key: hex } = req.body; + const key = await db.Key.create({ + user_id: req.user.id, + hex + }); + emit(req.user.username, "key", key); + res.send(key); +}); -app.post( - "/updateSeeds", - auth, - async (req, res) => { - let { user } = req; - let { seeds } = req.body; - let keys = Object.keys(seeds); +app.post("/keys/delete", auth, async (req, res) => { + const { hex } = req.body; + ( + await db.Key.findOne({ + where: { + user_id: req.user.id, + hex + } + }) + ).destroy(); +}); - for (let i = 0; i < keys.length; i++) { - let id = keys[i]; - let seed = seeds[id]; - await db.Account.update( - { seed }, - { - where: { id, user_id: user.id } - } - ); +app.post("/updateSeeds", auth, async (req, res) => { + let { user } = req; + let { seeds } = req.body; + let keys = Object.keys(seeds); - const account = await db.Account.findOne({ - where: { id } - }); + for (let i = 0; i < keys.length; i++) { + let id = keys[i]; + let seed = seeds[id]; + await db.Account.update( + { seed }, + { + where: { id, user_id: user.id } + } + ); - emit(user.username, "account", account); - } + const account = await db.Account.findOne({ + where: { id } + }); - res.end(); - }) + emit(user.username, "account", account); + } -app.post( - "/accounts/delete", - auth, - async (req, res) => { - const { id } = req.body; - const account = await db.Account.findOne({ where: { id } }); - if (account) await account.destroy(); - res.end(); - }) + res.end(); +}); -app.post( - "/accounts", - auth, - async (req, res) => { - const { - name, - seed, - pubkey, - ticker, - precision, - path, - privkey, - network - } = req.body; - const { user } = req; +app.post("/accounts/delete", auth, async (req, res) => { + const { id } = req.body; + const account = await db.Account.findOne({ where: { id } }); + if (account) await account.destroy(); + res.end(); +}); - let account = await db.Account.create({ - user_id: user.id, - asset: config.liquid.btcasset, - balance: 0, - pending: 0, - name, - ticker, - precision, - pubkey, - privkey, - seed, - path, - network - }); +app.post("/accounts", auth, async (req, res) => { + const { + name, + seed, + pubkey, + ticker, + precision, + path, + privkey, + network + } = req.body; + const { user } = req; - emit(user.username, "account", account); + let account = await db.Account.create({ + user_id: user.id, + asset: config.liquid.btcasset, + balance: 0, + pending: 0, + name, + ticker, + precision, + pubkey, + privkey, + seed, + path, + network + }); - if (pubkey) user.index++; - user.account_id = account.id; - await user.save(); - user.account = account; - emit(user.username, "user", user); + emit(user.username, "account", account); + + if (pubkey) user.index++; + user.account_id = account.id; + await user.save(); + user.account = account; + emit(user.username, "user", user); - res.send(account); - }) + res.send(account); +}); let login = async (req, res) => { try { @@ -372,453 +335,413 @@ let login = async (req, res) => { err("login error", e.message, req.connection.remoteAddress); res.status(401).end(); } +}; app.post("/login", login); app.post("/taboggan", login); app.post("/doggin", login); -app.post( - "/logout", - optionalAuth, - async (req, res) => { - let { subscription } = req.body; - if (!subscription) return res.end(); +app.post("/logout", optionalAuth, async (req, res) => { + let { subscription } = req.body; + if (!subscription) return res.end(); - const { username } = req.user; + const { username } = req.user; - if (username) { - l("logging out", username); - let i = req.user.subscriptions.findIndex( - s => JSON.stringify(s) === subscription - ); - if (i > -1) { - req.user.subscriptions.splice(i, 1); - } - await req.user.save(); - Object.keys(logins).map( - k => logins[k]["username"] === username && delete logins[k] - ); + if (username) { + l("logging out", username); + let i = req.user.subscriptions.findIndex( + s => JSON.stringify(s) === subscription + ); + if (i > -1) { + req.user.subscriptions.splice(i, 1); } + await req.user.save(); + Object.keys(logins).map( + k => logins[k]["username"] === username && delete logins[k] + ); + } - res.end(); - }) + res.end(); +}); -app.get( - "/address", - async (req, res) => { - let { network, type } = req.query; - let address, confidentialAddress; +app.get("/address", async (req, res) => { + let { network, type } = req.query; + let address, confidentialAddress; - let paymentType = { - bech32: "p2wpkh", - "p2sh-segwit": "p2sh", - legacy: "p2pkh" - }[type]; - if (!paymentType) paymentType = "p2wpkh"; + let paymentType = { + bech32: "p2wpkh", + "p2sh-segwit": "p2sh", + legacy: "p2pkh" + }[type]; + if (!paymentType) paymentType = "p2wpkh"; - let hd, i, p, n; - const mutex = new Mutex(); - const release = await mutex.acquire(); - try { - if (network === "bitcoin") { - if (!config.bitcoin) - return res.status(500).send("Bitcoin not configured"); + let hd, i, p, n; + const mutex = new Mutex(); + const release = await mutex.acquire(); + try { + if (network === "bitcoin") { + if (!config.bitcoin) + return res.status(500).send("Bitcoin not configured"); - address = await bc.getNewAddress("", type); - app.set("bcAddressIndex", i + 1); - return res.send({ address }); + address = await bc.getNewAddress("", type); + bcAddressIndex = i + 1; + return res.send({ address }); - p = bitcoin.payments; - n = prod ? bitcoin.networks["bitcoin"] : bitcoin.networks["regtest"]; + p = bitcoin.payments; + n = prod ? bitcoin.networks["bitcoin"] : bitcoin.networks["regtest"]; - i = parseInt(app.get("bcAddressIndex")); - hd = fromBase58(config.bitcoin.masterkey, n).derivePath( - `m/0'/0'/${i}'` - ); + i = parseInt(app.get("bcAddressIndex")); + hd = fromBase58(config.bitcoin.masterkey, n).derivePath(`m/0'/0'/${i}'`); - // async request to node to bump its internal index but don't use result - bc.getNewAddress().catch(console.error); - res.send({ address, confidentialAddress }); + // async request to node to bump its internal index but don't use result + bc.getNewAddress().catch(console.error); + res.send({ address, confidentialAddress }); - app.set("bcAddressIndex", i + 1); - } else if (network === "liquid") { - p = liquid.payments; - n = - liquid.networks[ - config.liquid.network === "mainnet" - ? "liquid" - : config.liquid.network - ]; - paymentType = "p2sh"; + bcAddressIndex = i + 1; + } else if (network === "liquid") { + p = liquid.payments; + n = + liquid.networks[ + config.liquid.network === "mainnet" ? "liquid" : config.liquid.network + ]; + paymentType = "p2sh"; - // async request to node to bump its internal index but don't use result - lq.getNewAddress().catch(e => - warn("Problem bumping liquid address index", e.message) - ); + // async request to node to bump its internal index but don't use result + lq.getNewAddress().catch(e => + warn("Problem bumping liquid address index", e.message) + ); - i = parseInt(app.get("lqAddressIndex")); + i = parseInt(app.get("lqAddressIndex")); - if (!i) { - const { hdkeypath } = await lq.getAddressInfo( - await lq.getNewAddress() - ); - const parts = hdkeypath.split("/"); - i = parseInt(parts[parts.length - 1].slice(0, -1)); - } + if (!i) { + const { hdkeypath } = await lq.getAddressInfo(await lq.getNewAddress()); + const parts = hdkeypath.split("/"); + i = parseInt(parts[parts.length - 1].slice(0, -1)); + } - l("liquid address index", i); - if (!i) throw new Error("Problem generating address"); + l("liquid address index", i); + if (!i) throw new Error("Problem generating address"); - hd = fromBase58(config.liquid.masterkey, n).derivePath(`m/0'/0'/${i}'`); - app.set("lqAddressIndex", i + 1); - } else { - throw new Error("Unsupported network"); - } - } finally { - release(); + hd = fromBase58(config.liquid.masterkey, n).derivePath(`m/0'/0'/${i}'`); + lqAddressIndex = i + 1; + } else { + throw new Error("Unsupported network"); } + } finally { + release(); + } - if (paymentType !== "p2sh") { - ({ address } = p[paymentType]({ + if (paymentType !== "p2sh") { + ({ address } = p[paymentType]({ + pubkey: hd.publicKey, + network: n + })); + } else { + if (network === "liquid") { + const p2wpkh = p.p2wpkh({ pubkey: hd.publicKey, network: n - })); - } else { - if (network === "liquid") { - const p2wpkh = p.p2wpkh({ - pubkey: hd.publicKey, - network: n - }); + }); - const blindkey = fromPrivateKey( - Buffer.from(config.liquid.blindkey, "hex"), - hd.chainCode, - n - ); + const blindkey = fromPrivateKey( + Buffer.from(config.liquid.blindkey, "hex"), + hd.chainCode, + n + ); - ({ address, confidentialAddress } = p[paymentType]({ - redeem: p2wpkh, - network: n, - blindkey: blindkey.publicKey - })); + ({ address, confidentialAddress } = p[paymentType]({ + redeem: p2wpkh, + network: n, + blindkey: blindkey.publicKey + })); - lq.importBlindingKey( - confidentialAddress, - blindkey.privateKey.toString("hex") - ); - } else { - ({ address } = p[paymentType]({ - redeem: p.p2wpkh({ - pubkey: hd.publicKey, - network: n - }), + lq.importBlindingKey( + confidentialAddress, + blindkey.privateKey.toString("hex") + ); + } else { + ({ address } = p[paymentType]({ + redeem: p.p2wpkh({ + pubkey: hd.publicKey, network: n - })); - } + }), + network: n + })); } + } - res.send({ address, confidentialAddress }); - }) - -app.post( - "/account", - auth, - async (req, res) => { - const { user } = req; - const { - id, - name, - ticker, - precision, - domain, - seed, - pubkey, - privkey, - path, - hide, - index - } = req.body; + res.send({ address, confidentialAddress }); +}); - try { - await db.transaction(async transaction => { - let account = await db.Account.findOne({ - where: { id, user_id: user.id }, - lock: transaction.LOCK.UPDATE, - transaction - }); +app.post("/account", auth, async (req, res) => { + const { user } = req; + const { + id, + name, + ticker, + precision, + domain, + seed, + pubkey, + privkey, + path, + hide, + index + } = req.body; - let params = { - name, - ticker, - precision, - domain, - seed, - pubkey, - path, - hide, - index, - privkey - }; + try { + await db.transaction(async transaction => { + let account = await db.Account.findOne({ + where: { id, user_id: user.id }, + lock: transaction.LOCK.UPDATE, + transaction + }); - if (!account || (account.pubkey && !pubkey)) delete params.pubkey; + let params = { + name, + ticker, + precision, + domain, + seed, + pubkey, + path, + hide, + index, + privkey + }; - await db.Account.update(params, { - where: { id, user_id: user.id }, - transaction - }); + if (!account || (account.pubkey && !pubkey)) delete params.pubkey; - await account.reload({ transaction }); - emit(user.username, "account", account); - res.end(); + await db.Account.update(params, { + where: { id, user_id: user.id }, + transaction }); - } catch (e) { - err("problem updating account", e.message); - return res.status(500).send("There was a problem updating the account"); - } - }) -app.post( - "/shiftAccount", - auth, - async (req, res) => { - let { user } = req; - let { id } = req.body; + await account.reload({ transaction }); + emit(user.username, "account", account); + res.end(); + }); + } catch (e) { + err("problem updating account", e.message); + return res.status(500).send("There was a problem updating the account"); + } +}); - try { - const account = await db.Account.findOne({ - where: { id } - }); +app.post("/shiftAccount", auth, async (req, res) => { + let { user } = req; + let { id } = req.body; - if (account.user_id !== user.id) - return res.status(500).send("Failed to open wallet"); + try { + const account = await db.Account.findOne({ + where: { id } + }); - user.account_id = account.id; - await user.save(); - let payments = await db.Payment.findAll({ - where: { - account_id: id - }, - order: [["id", "DESC"]], - limit: 12, - include: { - model: db.Account, - as: "account" - } - }); + if (account.user_id !== user.id) + return res.status(500).send("Failed to open wallet"); - user = user.get({ plain: true }); - user.payments = payments; - user.account = account.get({ plain: true }); + user.account_id = account.id; + await user.save(); + let payments = await db.Payment.findAll({ + where: { + account_id: id + }, + order: [["id", "DESC"]], + limit: 12, + include: { + model: db.Account, + as: "account" + } + }); - emit(user.username, "account", user.account); - emit(user.username, "user", user); + user = user.get({ plain: true }); + user.payments = payments; + user.account = account.get({ plain: true }); - res.send(user); - } catch (e) { - err("problem switching account", e.message); - return res.status(500).send("There was a problem switching accounts"); - } - }) + emit(user.username, "account", user.account); + emit(user.username, "user", user); + + res.send(user); + } catch (e) { + err("problem switching account", e.message); + return res.status(500).send("There was a problem switching accounts"); + } +}); app.get("/vapidPublicKey", function(req, res) { res.send(config.vapid.publicKey); }); -app.post( - "/subscribe", - auth, - async function(req, res) { - let { subscriptions } = req.user; - let { subscription } = req.body; - if (!subscriptions) subscriptions = []; - if ( - !subscriptions.find( - s => JSON.stringify(s) === JSON.stringify(subscription) - ) - ) - subscriptions.push(subscription); - req.user.subscriptions = subscriptions; - l("subscribing", req.user.username); - await req.user.save(); - res.sendStatus(201); - }) +app.post("/subscribe", auth, async function(req, res) { + let { subscriptions } = req.user; + let { subscription } = req.body; + if (!subscriptions) subscriptions = []; + if ( + !subscriptions.find(s => JSON.stringify(s) === JSON.stringify(subscription)) + ) + subscriptions.push(subscription); + req.user.subscriptions = subscriptions; + l("subscribing", req.user.username); + await req.user.save(); + res.sendStatus(201); +}); let redeeming = {}; -app.post( - "/redeem", - optionalAuth, - async function(req, res) { - const { redeemcode } = req.body; - try { - await db.transaction(async transaction => { - if (redeeming[redeemcode]) fail("redemption in progress"); - redeeming[redeemcode] = true; - if (!redeemcode) fail("no code provided"); +app.post("/redeem", optionalAuth, async function(req, res) { + const { redeemcode } = req.body; + try { + await db.transaction(async transaction => { + if (redeeming[redeemcode]) fail("redemption in progress"); + redeeming[redeemcode] = true; + if (!redeemcode) fail("no code provided"); - let { user } = req; + let { user } = req; - const source = await db.Payment.findOne({ - where: { - redeemcode: req.body.redeemcode - }, - include: { - model: db.Account, - as: "account" - }, - lock: transaction.LOCK.UPDATE, - transaction - }); + const source = await db.Payment.findOne({ + where: { + redeemcode: req.body.redeemcode + }, + include: { + model: db.Account, + as: "account" + }, + lock: transaction.LOCK.UPDATE, + transaction + }); - l("redeeming", redeemcode); + l("redeeming", redeemcode); - if (!source) fail("Invalid code"); - if (source.redeemed) fail("Voucher has already been redeemed"); - let { amount } = source; - amount = -amount; + if (!source) fail("Invalid code"); + if (source.redeemed) fail("Voucher has already been redeemed"); + let { amount } = source; + amount = -amount; - if (!user) { - const ip = - req.headers["x-forwarded-for"] || req.connection.remoteAddress; + if (!user) { + const ip = + req.headers["x-forwarded-for"] || req.connection.remoteAddress; - user = await register( - { - username: redeemcode.substr(0, 8), - password: "" - }, - ip, - false - ); + user = await register( + { + username: redeemcode.substr(0, 8), + password: "" + }, + ip, + false + ); - let payload = { username: user.username }; - let token = jwt.sign(payload, config.jwt); - res.cookie("token", token, { - expires: new Date(Date.now() + 432000000) - }); + let payload = { username: user.username }; + let token = jwt.sign(payload, config.jwt); + res.cookie("token", token, { + expires: new Date(Date.now() + 432000000) + }); - delete redeeming[redeemcode]; - return res.send({ user }); - } + delete redeeming[redeemcode]; + return res.send({ user }); + } - let account = await getAccount(source.account.asset, user, transaction); - let { hash, memo, confirmed, fee, network } = source; + let account = await getAccount(source.account.asset, user, transaction); + let { hash, memo, confirmed, fee, network } = source; - source.redeemed = true; - await source.save({ transaction }); + source.redeemed = true; + await source.save({ transaction }); - let payment = await db.Payment.create( - { - amount, - account_id: account.id, - user_id: user.id, - hash: "Voucher " + redeemcode, - memo, - rate: rates[user.currency], - currency: user.currency, - confirmed, - network, - received: true, - fee - }, - { transaction } - ); + let payment = await db.Payment.create( + { + amount, + account_id: account.id, + user_id: user.id, + hash: "Voucher " + redeemcode, + memo, + rate: store.rates[user.currency], + currency: user.currency, + confirmed, + network, + received: true, + fee + }, + { transaction } + ); - await account.increment({ balance: amount }, { transaction }); - await account.reload({ transaction }); + await account.increment({ balance: amount }, { transaction }); + await account.reload({ transaction }); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); - emit(user.username, "payment", payment); - emit(user.username, "account", account); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + emit(user.username, "payment", payment); + emit(user.username, "account", account); - res.send({ payment }); - }); - } catch (e) { - delete redeeming[redeemcode]; - err("problem redeeming", e.message); - return res.status(500).send("There was a problem redeeming the voucher"); - } - }) + res.send({ payment }); + }); + } catch (e) { + delete redeeming[redeemcode]; + err("problem redeeming", e.message); + return res.status(500).send("There was a problem redeeming the voucher"); + } +}); -app.post( - "/checkRedeemCode", - auth, - async function(req, res) { - const { redeemcode } = req.body; +app.post("/checkRedeemCode", auth, async function(req, res) { + const { redeemcode } = req.body; - const payment = await db.Payment.findOne({ where: { redeemcode } }); - res.send(payment); - }) + const payment = await db.Payment.findOne({ where: { redeemcode } }); + res.send(payment); +}); -app.post( - "/password", - auth, - async function(req, res) { - const { user } = req; - const { password } = req.body; +app.post("/password", auth, async function(req, res) { + const { user } = req; + const { password } = req.body; - if (!user.password) return res.send(true); - res.send(await bcrypt.compare(password, user.password)); - }) + if (!user.password) return res.send(true); + res.send(await bcrypt.compare(password, user.password)); +}); -app.get( - "/isInternal", - auth, - async function(req, res) { - let { user } = req; - let { address } = req.query; - if (!address) throw new Error("Address not provided"); +app.get("/isInternal", auth, async function(req, res) { + let { user } = req; + let { address } = req.query; + if (!address) throw new Error("Address not provided"); - let invoice = await db.Invoice.findOne({ - where: { address }, - include: { - attributes: ["username"], - model: db.User, - as: "user" - } - }); + let invoice = await db.Invoice.findOne({ + where: { address }, + include: { + attributes: ["username"], + model: db.User, + as: "user" + } + }); - if (invoice) { - let info; - try { - info = await bc.getAddressInfo(address); - } catch (e) { - info = await lq.getAddressInfo(address); - } - if (info.ismine) { - emit(user.username, "to", invoice.user); - return res.send(true); - } + if (invoice) { + let info; + try { + info = await bc.getAddressInfo(address); + } catch (e) { + info = await lq.getAddressInfo(address); + } + if (info.ismine) { + emit(user.username, "to", invoice.user); + return res.send(true); } + } - res.send(false); - }) + res.send(false); +}); -app.get( - "/invoices", - auth, - async function(req, res) { - let invoices = await db.Invoice.findAll({ - where: { user_id: req.user.id } - }); - res.send(invoices); +app.get("/invoices", auth, async function(req, res) { + let invoices = await db.Invoice.findAll({ + where: { user_id: req.user.id } }); + res.send(invoices); +}); -app.post( - "/signMessage", - auth, - async function(req, res) { - let { address, message } = req.body; +app.post("/signMessage", auth, async function(req, res) { + let { address, message } = req.body; - let invoices = await db.Invoice.findAll({ - where: { user_id: req.user.id } - }); + let invoices = await db.Invoice.findAll({ + where: { user_id: req.user.id } + }); - if (invoices.find(i => i.address === address)) { - if (config.bitcoin.walletpass) - await bc.walletPassphrase(config.bitcoin.walletpass, 300); - return res.send(await bc.signMessage(address, message)); - } + if (invoices.find(i => i.address === address)) { + if (config.bitcoin.walletpass) + await bc.walletPassphrase(config.bitcoin.walletpass, 300); + return res.send(await bc.signMessage(address, message)); + } - res.status(500).send("Address not found for user"); - }) - */ + res.status(500).send("Address not found for user"); +}); |
