diff options
| author | Adam Soltys <[email protected]> | 2019-06-22 10:27:39 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2019-06-22 10:27:39 -0700 |
| commit | cb30426a5053345396b6ec1705fbf239df16f4c3 (patch) | |
| tree | 66f89b2e0fb309a4026ff7c6cfdc52519850da9d /index.js | |
| parent | f0dd12d6007ad49288ddd7f1872cb70d66da0fe3 (diff) | |
| download | coinos-server-cb30426a5053345396b6ec1705fbf239df16f4c3.tar.gz coinos-server-cb30426a5053345396b6ec1705fbf239df16f4c3.zip | |
use prettier and upstream bolt11
Diffstat (limited to 'index.js')
| -rw-r--r-- | index.js | 1067 |
1 files changed, 533 insertions, 534 deletions
@@ -1,195 +1,194 @@ -import { Client } from 'authy-client' -import axios from 'axios' -import bcrypt from 'bcrypt' -import bodyParser from 'body-parser' -import bolt11 from 'bolt11' -import compression from 'compression' -import cookieParser from 'cookie-parser' -import BitcoinCore from 'bitcoin-core' -import cors from 'cors' -import express from 'express' -import fb from 'fb' -import graphqlHTTP from 'express-graphql' -import io from 'socket.io' -import jwt from 'jsonwebtoken' -import morgan from 'morgan' -import mailgun from 'mailgun-js' -import uuidv4 from 'uuid/v4' -import reverse from 'buffer-reverse' -import Sequelize from 'sequelize' -import zmq from 'zeromq' +import { Client } from "authy-client"; +import axios from "axios"; +import bcrypt from "bcrypt"; +import bodyParser from "body-parser"; +import bolt11 from "bolt11"; +import compression from "compression"; +import cookieParser from "cookie-parser"; +import BitcoinCore from "bitcoin-core"; +import cors from "cors"; +import express from "express"; +import fb from "fb"; +import graphqlHTTP from "express-graphql"; +import io from "socket.io"; +import jwt from "jsonwebtoken"; +import morgan from "morgan"; +import mailgun from "mailgun-js"; +import uuidv4 from "uuid/v4"; +import reverse from "buffer-reverse"; +import Sequelize from "sequelize"; +import zmq from "zeromq"; -import authyVerify from './authy' -import config from './config' -import whitelist from './whitelist' -import createLnrpc from './lib/createLnrpc' +import authyVerify from "./authy"; +import config from "./config"; +import whitelist from "./whitelist"; +import createLnrpc from "./lib/createLnrpc"; -const bitcoin = require('bitcoinjs-lib') -const l = console.log +const bitcoin = require("bitcoinjs-lib"); +const l = console.log; /* eslint-disable-next-line */ const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); const authy = new Client({ key: config.authy.key }); (async () => { - debugger; - const lna = await createLnrpc(config.lna) - const lnb = await createLnrpc(config.lnb) - const bc = new BitcoinCore(config.bitcoin) + const lna = await createLnrpc(config.lna); + const lnb = await createLnrpc(config.lnb); + const bc = new BitcoinCore(config.bitcoin); - const app = express() - app.enable('trust proxy') - app.use(bodyParser.urlencoded({ extended: true })) - app.use(bodyParser.json()) - app.use(cookieParser()) - app.use(cors({ credentials: true, origin: 'http://*:*' })) - app.use(compression()) - app.use(morgan('combined')) + const app = express(); + app.enable("trust proxy"); + app.use(bodyParser.urlencoded({ extended: true })); + app.use(bodyParser.json()); + app.use(cookieParser()); + app.use(cors({ credentials: true, origin: "http://*:*" })); + app.use(compression()); + app.use(morgan("combined")); - const server = require('http').Server(app) - const socket = io(server, { origins: '*:*' }) - const db = await require('./db')(lna) - const passport = require('./passport')(db) - const auth = passport.authenticate('jwt', { session: false }) - const sids = {} - const seen = [] + const server = require("http").Server(app); + const socket = io(server, { origins: "*:*" }); + const db = await require("./db")(lna); + const passport = require("./passport")(db); + const auth = passport.authenticate("jwt", { session: false }); + const sids = {}; + const seen = []; - app.use(passport.initialize()) + app.use(passport.initialize()); app.use( - '/graphql', + "/graphql", auth, graphqlHTTP({ schema: db.gqlschema, - graphiql: true, + graphiql: true }) - ) + ); socket.use((socket, next) => { try { - let token = socket.handshake.query.token - let user = jwt.decode(token).username - socket.request.user = user - sids[user] ? sids[user].push(socket.id) : (sids[user] = [socket.id]) - sids[socket.id] = user + let token = socket.handshake.query.token; + let user = jwt.decode(token).username; + socket.request.user = user; + sids[user] ? sids[user].push(socket.id) : (sids[user] = [socket.id]); + sids[socket.id] = user; } catch (e) { - l(e) + l(e); } - next() - }) + next(); + }); - socket.sockets.on('connect', async socket => { - socket.emit('connected') - if (app.get('rates')) socket.emit('rate', app.get('rates').ask) - socket.on('getuser', async (data, callback) => { + socket.sockets.on("connect", async socket => { + socket.emit("connected"); + if (app.get("rates")) socket.emit("rate", app.get("rates").ask); + socket.on("getuser", async (data, callback) => { /* eslint-disable-next-line */ callback( await db.User.findOne({ where: { - username: socket.request.user, - }, + username: socket.request.user + } }) - ) - }) + ); + }); - socket.on('disconnect', s => { - let user = sids[socket.id] - sids[user].splice(sids[user].indexOf(socket.id), 1) - delete sids[socket.id] - }) - }) + socket.on("disconnect", s => { + let user = sids[socket.id]; + sids[user].splice(sids[user].indexOf(socket.id), 1); + delete sids[socket.id]; + }); + }); const emit = (username, msg, data) => { - if (data.username !== undefined) data = pick(data, ...whitelist) + if (data.username !== undefined) data = pick(data, ...whitelist); - if (!sids[username]) return + if (!sids[username]) return; sids[username].map((sid, i) => { try { - socket.to(sid).emit(msg, data) + socket.to(sid).emit(msg, data); } catch (e) { - sids[username].splice(i, 1) + sids[username].splice(i, 1); } - }) - } + }); + }; const handlePayment = async msg => { - if (!msg.settled) return + if (!msg.settled) return; let payment = await db.Payment.findOne({ - include: { model: db.User, as: 'user' }, + include: { model: db.User, as: "user" }, where: { - hash: msg.payment_request, - }, - }) + hash: msg.payment_request + } + }); - if (!payment) return + if (!payment) return; - payment.received = true - payment.user.balance += parseInt(msg.value) - payment.rate = app.get('rates').ask + payment.received = true; + payment.user.balance += parseInt(msg.value); + payment.rate = app.get("rates").ask; - await payment.save() - await payment.user.save() - payments.push(msg.payment_request) + await payment.save(); + await payment.user.save(); + payments.push(msg.payment_request); - emit(payment.user.username, 'invoice', msg) - emit(payment.user.username, 'user', payment.user) - } + emit(payment.user.username, "invoice", msg); + emit(payment.user.username, "user", payment.user); + }; - const invoices = lna.subscribeInvoices({}) - invoices.on('data', handlePayment) + const invoices = lna.subscribeInvoices({}); + invoices.on("data", handlePayment); - const invoicesb = lnb.subscribeInvoices({}) - invoicesb.on('data', handlePayment) + const invoicesb = lnb.subscribeInvoices({}); + invoicesb.on("data", handlePayment); - const zmqRawBlock = zmq.socket('sub') - zmqRawBlock.connect(config.bitcoin.zmqrawblock) - zmqRawBlock.subscribe('rawblock') + const zmqRawBlock = zmq.socket("sub"); + zmqRawBlock.connect(config.bitcoin.zmqrawblock); + zmqRawBlock.subscribe("rawblock"); - const zmqRawTx = zmq.socket('sub') - zmqRawTx.connect(config.bitcoin.zmqrawtx) - zmqRawTx.subscribe('rawtx') + const zmqRawTx = zmq.socket("sub"); + zmqRawTx.connect(config.bitcoin.zmqrawtx); + zmqRawTx.subscribe("rawtx"); - const addresses = {} + const addresses = {}; await db.User.findAll({ - attributes: ['username', 'address'], + attributes: ["username", "address"] }).map(u => { - addresses[u.address] = u.username - }) + addresses[u.address] = u.username; + }); const payments = (await db.Payment.findAll({ - attributes: ['hash'], - })).map(p => p.hash) + attributes: ["hash"] + })).map(p => p.hash); - zmqRawTx.on('message', async (topic, message, sequence) => { - message = message.toString('hex') + zmqRawTx.on("message", async (topic, message, sequence) => { + message = message.toString("hex"); - let tx = bitcoin.Transaction.fromHex(message) - let hash = reverse(tx.getHash()).toString('hex') + let tx = bitcoin.Transaction.fromHex(message); + let hash = reverse(tx.getHash()).toString("hex"); - if (payments.includes(hash)) return + if (payments.includes(hash)) return; tx.outs.map(async o => { try { - let network = config.bitcoin.network - if (network === 'mainnet') { - network = 'bitcoin' + let network = config.bitcoin.network; + if (network === "mainnet") { + network = "bitcoin"; } let address = bitcoin.address.fromOutputScript( o.script, bitcoin.networks[network] - ) + ); if (Object.keys(addresses).includes(address)) { try { - payments.push(hash) + payments.push(hash); let user = await db.User.findOne({ where: { - username: addresses[address], - }, - }) + username: addresses[address] + } + }); let invoices = await db.Payment.findAll({ limit: 1, @@ -197,143 +196,143 @@ const authy = new Client({ key: config.authy.key }); hash: address, received: null, amount: { - [Sequelize.Op.gt]: 0, - }, + [Sequelize.Op.gt]: 0 + } }, - order: [['createdAt', 'DESC']], - }) + order: [["createdAt", "DESC"]] + }); - let tip = null - if (invoices.length) tip = invoices[0].tip + let tip = null; + if (invoices.length) tip = invoices[0].tip; - let confirmed = false + let confirmed = false; if (user.friend) { - user.balance += o.value - confirmed = true + user.balance += o.value; + confirmed = true; } else { - user.pending += o.value + user.pending += o.value; } - await user.save() - emit(user.username, 'user', user) + await user.save(); + emit(user.username, "user", user); await db.Payment.create({ user_id: user.id, hash, amount: o.value, - currency: 'CAD', - rate: app.get('rates').ask, + currency: "CAD", + rate: app.get("rates").ask, received: true, tip, - confirmed, - }) + confirmed + }); - emit(user.username, 'tx', message) + emit(user.username, "tx", message); } catch (e) { - l(e) + l(e); } } } catch (e) {} - }) - }) + }); + }); - zmqRawBlock.on('message', async (topic, message, sequence) => { - topic = topic.toString('utf8') - message = message.toString('hex') + zmqRawBlock.on("message", async (topic, message, sequence) => { + topic = topic.toString("utf8"); + message = message.toString("hex"); switch (topic) { - case 'rawblock': { - let block = bitcoin.Block.fromHex(message) - l('block', block.getHash().toString('hex')) + case "rawblock": { + let block = bitcoin.Block.fromHex(message); + l("block", block.getHash().toString("hex")); await db.Payment.findAll({ - include: { model: db.User, as: 'user' }, - where: { confirmed: false }, + include: { model: db.User, as: "user" }, + where: { confirmed: false } }).map(async p => { if ((await bc.getRawTransaction(p.hash, true)).confirmations > 0) { - let user = p.user - p.confirmed = true - user.balance += p.amount - user.pending -= p.amount - await user.save() - await p.save() - emit(user.username, 'user', user) + let user = p.user; + p.confirmed = true; + user.balance += p.amount; + user.pending -= p.amount; + await user.save(); + await p.save(); + emit(user.username, "user", user); } - }) + }); - socket.emit('block', message) - break + socket.emit("block", message); + break; } } - }) + }); - app.post('/register', async (req, res) => { - let err = m => res.status(500).send(m) - let user = req.body - if (!user.username) return err('Username required') - if (user.password.length < 2) return err('Password too short') + app.post("/register", async (req, res) => { + let err = m => res.status(500).send(m); + let user = req.body; + if (!user.username) return err("Username required"); + if (user.password.length < 2) return err("Password too short"); - let exists = await db.User.count({ where: { username: user.username } }) - if (exists) return err('Username taken') + let exists = await db.User.count({ where: { username: user.username } }); + if (exists) return err("Username taken"); - user.address = (await lna.newAddress({ type: 1 }, lna.meta)).address - user.password = await bcrypt.hash(user.password, 1) - user.name = user.username - addresses[user.address] = user.username + user.address = (await lna.newAddress({ type: 1 }, lna.meta)).address; + user.password = await bcrypt.hash(user.password, 1); + user.name = user.username; + addresses[user.address] = user.username; - await db.User.create(user) - res.send(pick(user, ...whitelist)) - }) + await db.User.create(user); + res.send(pick(user, ...whitelist)); + }); const requestEmail = async user => { - user.emailToken = uuidv4() - await user.save() + user.emailToken = uuidv4(); + await user.save(); - let mg = mailgun(config.mailgun) + let mg = mailgun(config.mailgun); let msg = { - from: 'CoinOS <[email protected]>', + from: "CoinOS <[email protected]>", to: user.email, - subject: 'CoinOS Email Verification', - html: `Visit <a href="https://coinos.io/verifyEmail/${user.username}/${user.emailToken}">https://coinos.io/verify/${user.username}/${user.emailToken}</a> to verify your email address.`, - } + subject: "CoinOS Email Verification", + html: `Visit <a href="https://coinos.io/verifyEmail/${user.username}/${user.emailToken}">https://coinos.io/verify/${user.username}/${user.emailToken}</a> to verify your email address.` + }; try { - mg.messages().send(msg) + mg.messages().send(msg); } catch (e) { - l(e) + l(e); } - } + }; const requestPhone = async user => { - user.phoneToken = Math.floor(100000 + Math.random() * 900000) - await user.save() - const client = require('twilio')( + user.phoneToken = Math.floor(100000 + Math.random() * 900000); + await user.save(); + const client = require("twilio")( config.twilio.sid, config.twilio.authToken - ) + ); await client.messages.create({ body: user.phoneToken, from: config.twilio.number, - to: user.phone, - }) - } + to: user.phone + }); + }; - app.post('/requestEmail', auth, async (req, res) => { - req.user.email = req.body.email - await requestEmail(req.user) - res.end() - }) + app.post("/requestEmail", auth, async (req, res) => { + req.user.email = req.body.email; + await requestEmail(req.user); + res.end(); + }); - app.post('/requestPhone', auth, async (req, res) => { - req.user.phone = req.body.phone - await requestPhone(req.user) - res.end() - }) + app.post("/requestPhone", auth, async (req, res) => { + req.user.phone = req.body.phone; + await requestPhone(req.user); + res.end(); + }); - app.post('/user', auth, async (req, res) => { - let { user } = req + app.post("/user", auth, async (req, res) => { + let { user } = req; let { email, phone, @@ -341,201 +340,201 @@ const authy = new Client({ key: config.authy.key }); pin, pinconfirm, password, - passconfirm, - } = req.body + passconfirm + } = req.body; - if (user.email !== email && require('email-validator').validate(email)) { - user.email = email - user.emailVerified = false - requestEmail(user) + if (user.email !== email && require("email-validator").validate(email)) { + user.email = email; + user.emailVerified = false; + requestEmail(user); } if (user.phone !== phone) { - user.phone = phone - user.phoneVerified = false - requestPhone(user) + user.phone = phone; + user.phoneVerified = false; + requestPhone(user); } - user.email = email - user.phone = phone - user.twofa = twofa + user.email = email; + user.phone = phone; + user.twofa = twofa; - console.log(user.twofa, email, phone) + console.log(user.twofa, email, phone); if (password && password === passconfirm) { - user.password = await bcrypt.hash(password, 1) + user.password = await bcrypt.hash(password, 1); } - if (pin && pin === pinconfirm) user.pin = await bcrypt.hash(pin, 1) + if (pin && pin === pinconfirm) user.pin = await bcrypt.hash(pin, 1); if (twofa && !user.authyId && user.phoneVerified) { try { - let r = await authy.registerUser({ countryCode: 'CA', email, phone }) - user.authyId = r.user.id + let r = await authy.registerUser({ countryCode: "CA", email, phone }); + user.authyId = r.user.id; } catch (e) { - l(e) + l(e); } } - await user.save() - emit(req.user.username, 'user', req.user) - res.send(user) - }) + await user.save(); + emit(req.user.username, "user", req.user); + res.send(user); + }); - app.post('/forgot', async (req, res) => { - let { user } = req - let mg = mailgun(config.mailgun) + app.post("/forgot", async (req, res) => { + let { user } = req; + let mg = mailgun(config.mailgun); let msg = { - from: 'CoinOS <[email protected]>', + from: "CoinOS <[email protected]>", to: user.email, - subject: 'CoinOS Password Reset', - html: `Visit <a href="https://coinos.io/reset/${user.username}/${user.token}">https://coinos.io/reset/${user.username}/${user.token}</a> to reset your password.`, - } + subject: "CoinOS Password Reset", + html: `Visit <a href="https://coinos.io/reset/${user.username}/${user.token}">https://coinos.io/reset/${user.username}/${user.token}</a> to reset your password.` + }; try { - mg.messages().send(msg) + mg.messages().send(msg); } catch (e) { - l(e) + l(e); } - }) + }); - app.get('/verifyEmail/:username/:token', auth, async (req, res) => { + app.get("/verifyEmail/:username/:token", auth, async (req, res) => { let user = await db.User.findOne({ where: { username: req.params.username, - emailToken: req.params.token, - }, - }) + emailToken: req.params.token + } + }); if (user) { - user.emailVerified = true - await user.save() + user.emailVerified = true; + await user.save(); - emit(user.username, 'user', user) - emit(user.username, 'emailVerified', true) + emit(user.username, "user", user); + emit(user.username, "emailVerified", true); - res.end() + res.end(); } else { - res.status(500).send('invalid token or username') + res.status(500).send("invalid token or username"); } - }) + }); - app.get('/verifyPhone/:username/:token', auth, async (req, res) => { + app.get("/verifyPhone/:username/:token", auth, async (req, res) => { let user = await db.User.findOne({ where: { username: req.params.username, - phoneToken: req.params.token, - }, - }) + phoneToken: req.params.token + } + }); - console.log(user, req.params) + console.log(user, req.params); if (user) { - user.phoneVerified = true - await user.save() + user.phoneVerified = true; + await user.save(); - emit(user.username, 'user', user) - emit(user.username, 'phoneVerified', true) - res.end() + emit(user.username, "user", user); + emit(user.username, "phoneVerified", true); + res.end(); } else { - res.status(500).send('invalid token or username') + res.status(500).send("invalid token or username"); } - }) + }); - app.post('/openchannel', auth, async (req, res) => { - let err = m => res.status(500).send(m) + app.post("/openchannel", auth, async (req, res) => { + let err = m => res.status(500).send(m); if (req.user.balance < 10000) { - return err('Need at least 10000 satoshis for channel opening') + return err("Need at least 10000 satoshis for channel opening"); } - let pending = await lna.pendingChannels({}, lna.meta) + let pending = await lna.pendingChannels({}, lna.meta); let busypeers = pending.pending_open_channels.map( c => c.channel.remote_node_pub - ) - let peer = lna.channelpeers.find(p => !busypeers.includes(p)) - let sent = false + ); + let peer = lna.channelpeers.find(p => !busypeers.includes(p)); + let sent = false; - l('channeling') + l("channeling"); if (!peer) { res .status(500) - .send('All peers have pending channel requests, try again later') - return + .send("All peers have pending channel requests, try again later"); + return; } try { - let amount = Math.min(req.user.balance, 16777216) + let amount = Math.min(req.user.balance, 16777216); let openchannel = async (peer, amount) => { let channel = await lna.openChannel({ - node_pubkey: new Buffer(peer, 'hex'), - local_funding_amount: amount, - }) + node_pubkey: new Buffer(peer, "hex"), + local_funding_amount: amount + }); - channel.on('data', async data => { - if (sent || !data.chan_pending) return - req.user.balance += amount - req.user.balance -= amount - req.user.channel = reverse(data.chan_pending.txid).toString('hex') - await req.user.save() - emit(req.user.username, 'user', req.user) - res.send(data) - sent = true - }) + channel.on("data", async data => { + if (sent || !data.chan_pending) return; + req.user.balance += amount; + req.user.balance -= amount; + req.user.channel = reverse(data.chan_pending.txid).toString("hex"); + await req.user.save(); + emit(req.user.username, "user", req.user); + res.send(data); + sent = true; + }); - channel.on('error', err => { - l('channel error', peer, err) - let msg = err.message + channel.on("error", err => { + l("channel error", peer, err); + let msg = err.message; if ( - msg.startsWith('Multiple') || - msg.startsWith('You gave') || - msg.startsWith('peer') + msg.startsWith("Multiple") || + msg.startsWith("You gave") || + msg.startsWith("peer") ) { - busypeers.push(peer) - peer = lna.channelpeers.find(p => !busypeers.includes(p)) + busypeers.push(peer); + peer = lna.channelpeers.find(p => !busypeers.includes(p)); if (peer) { - return openchannel(peer, amount) + return openchannel(peer, amount); } else { return res .status(500) .send( "All peers are busy, couldn't open a channel, wait a few blocks and try again" - ) + ); } } - if (msg.startsWith('not enough')) { - msg = 'Server wallet is busy. Wait for a block and try again' + if (msg.startsWith("not enough")) { + msg = "Server wallet is busy. Wait for a block and try again"; } - return res.status(500).send(msg) - }) - } + return res.status(500).send(msg); + }); + }; - openchannel(peer, amount) + openchannel(peer, amount); } catch (err) { - l('rpc error', peer, err) - return res.status(500).send(err) + l("rpc error", peer, err); + return res.status(500).send(err); } - }) + }); - app.get('/channels', auth, async (req, res) => { - return res.send(await lna.listChannels()) - }) + app.get("/channels", auth, async (req, res) => { + return res.send(await lna.listChannels()); + }); - app.get('/peers', auth, async (req, res) => { - return res.send(await lna.listPeers()) - }) + app.get("/peers", auth, async (req, res) => { + return res.send(await lna.listPeers()); + }); - app.post('/sendPayment', auth, async (req, res) => { - let hash = req.body.payreq - let payreq = bolt11.decode(hash) - l('sending lightning', req.user.username, payreq.satoshis) + app.post("/sendPayment", auth, async (req, res) => { + let hash = req.body.payreq; + let payreq = bolt11.decode(hash); + l("sending lightning", req.user.username, payreq.satoshis); if (seen.includes(hash)) { - return res.status(500).send("Invoice has been paid, can't pay again") + return res.status(500).send("Invoice has been paid, can't pay again"); } try { @@ -543,56 +542,56 @@ const authy = new Client({ key: config.authy.key }); let { balance } = await db.User.findOne( { where: { - username: req.user.username, - }, + username: req.user.username + } }, { transaction } - ) + ); if (balance < payreq.satoshis) { - throw new Error() + throw new Error(); } - req.user.balance -= payreq.satoshis - await req.user.save({ transaction }) - }) + req.user.balance -= payreq.satoshis; + await req.user.save({ transaction }); + }); } catch (e) { - return res.status(500).send('Not enough satoshis') + return res.status(500).send("Not enough satoshis"); } - const stream = lna.sendPayment(lna.meta, {}) - stream.write({ payment_request: req.body.payreq }) + const stream = lna.sendPayment(lna.meta, {}); + stream.write({ payment_request: req.body.payreq }); - stream.on('data', async m => { + stream.on("data", async m => { if (m.payment_error) { - res.status(500).send(m.payment_error) + res.status(500).send(m.payment_error); } else { - if (seen.includes(m.payment_preimage)) return - seen.push(m.payment_preimage) + if (seen.includes(m.payment_preimage)) return; + seen.push(m.payment_preimage); - let total = parseInt(m.payment_route.total_amt) - req.user.balance -= total - payreq.satoshis + let total = parseInt(m.payment_route.total_amt); + req.user.balance -= total - payreq.satoshis; await db.transaction(async transaction => { - await req.user.save({ transaction }) + await req.user.save({ transaction }); await db.Payment.create( { amount: -total, user_id: req.user.id, hash, - rate: app.get('rates').ask, - currency: 'CAD', + rate: app.get("rates").ask, + currency: "CAD" }, { transaction } - ) - }) + ); + }); - emit(req.user.username, 'user', req.user) + emit(req.user.username, "user", req.user); if (payreq.payeeNodeKey === config.lnb.id) { - let invoice = await lna.addInvoice({ value: payreq.satoshis }) - let payback = lnb.sendPayment(lnb.meta, {}) + let invoice = await lna.addInvoice({ value: payreq.satoshis }); + let payback = lnb.sendPayment(lnb.meta, {}); /* eslint-disable-next-line */ let { payment_request } = invoice; @@ -600,89 +599,89 @@ const authy = new Client({ key: config.authy.key }); payback.write({ payment_request }); } - seen.push(hash) - res.send(m) + seen.push(hash); + res.send(m); } - }) + }); - stream.on('error', e => { - let msg = e.message + stream.on("error", e => { + let msg = e.message; - res.status(500).send(msg) - }) - }) + res.status(500).send(msg); + }); + }); - app.get('/friends', auth, async (req, res) => { + app.get("/friends", auth, async (req, res) => { try { let friends = (await fb.api( `/${req.user.username}/friends?access_token=${req.user.fbtoken}` - )).data + )).data; friends = await Promise.all( friends.map(async f => { let pic = (await fb.api( `/${f.id}/picture?redirect=false&type=small&access_token=${req.user.fbtoken}` - )).data - f.pic = pic.url - return f + )).data; + f.pic = pic.url; + return f; }) - ) + ); - res.send(friends) + res.send(friends); } catch (e) { res .status(500) - .send('There was a problem getting your facebook friends: ', e) + .send("There was a problem getting your facebook friends: ", e); } - }) + }); - app.post('/payUser', auth, async (req, res) => { - let { payuser, amount } = req.body + app.post("/payUser", auth, async (req, res) => { + let { payuser, amount } = req.body; let user = await db.User.findOne({ where: { - username: payuser, - }, - }) + username: payuser + } + }); if (!user) { return res .status(500) - .send("Couldn't find the user you're trying to pay") + .send("Couldn't find the user you're trying to pay"); } - let err = m => res.status(500).send(m) + let err = m => res.status(500).send(m); - let invoice + let invoice; try { - invoice = await lnb.addInvoice({ value: amount }) + invoice = await lnb.addInvoice({ value: amount }); } catch (e) { - return err(e.message) + return err(e.message); } - let hash = invoice.payment_request + let hash = invoice.payment_request; await db.Payment.create({ user_id: user.id, hash, amount, - currency: 'CAD', - rate: app.get('rates').ask, - tip: 0, - }) + currency: "CAD", + rate: app.get("rates").ask, + tip: 0 + }); - req.url = '/sendPayment' - req.body.payreq = invoice.payment_request - return app._router.handle(req, res) - }) + req.url = "/sendPayment"; + req.body.payreq = invoice.payment_request; + return app._router.handle(req, res); + }); - app.post('/sendCoins', auth, async (req, res) => { - const MINFEE = 3000 + app.post("/sendCoins", auth, async (req, res) => { + const MINFEE = 3000; - let { address, amount } = req.body + let { address, amount } = req.body; - l('sending coins', req.user.username, amount, address) + l("sending coins", req.user.username, amount, address); if (amount === req.user.balance) { - amount = req.user.balance - MINFEE + amount = req.user.balance - MINFEE; } try { @@ -690,281 +689,281 @@ const authy = new Client({ key: config.authy.key }); let { balance } = await db.User.findOne( { where: { - username: req.user.username, - }, + username: req.user.username + } }, { transaction } - ) + ); if (amount > balance) { - l('amount exceeds balance', amount, balance) - throw new Error('insufficient funds') + l("amount exceeds balance", amount, balance); + throw new Error("insufficient funds"); } - req.user.balance -= parseInt(amount) + 10000 - await req.user.save({ transaction }) - }) + req.user.balance -= parseInt(amount) + 10000; + await req.user.save({ transaction }); + }); } catch (e) { - return res.status(500).send('Not enough satoshis') + return res.status(500).send("Not enough satoshis"); } try { - await bc.walletPassphrase(config.bitcoin.walletpass, 300) - l('sending transaction') + await bc.walletPassphrase(config.bitcoin.walletpass, 300); + l("sending transaction"); let txid = await bc.sendToAddress( address, (amount / 100000000).toFixed(8) - ) - l('transaction sent', txid) - let txhex = await bc.getRawTransaction(txid) - let tx = bitcoin.Transaction.fromHex(txhex) + ); + l("transaction sent", txid); + let txhex = await bc.getRawTransaction(txid); + let tx = bitcoin.Transaction.fromHex(txhex); let inputTotal = await tx.ins.reduce(async (a, input) => { - let h = await bc.getRawTransaction(reverse(input.hash).toString('hex')) - return a + bitcoin.Transaction.fromHex(h).outs[input.index].value - }, 0) - let outputTotal = tx.outs.reduce((a, b) => a + b.value, 0) + let h = await bc.getRawTransaction(reverse(input.hash).toString("hex")); + return a + bitcoin.Transaction.fromHex(h).outs[input.index].value; + }, 0); + let outputTotal = tx.outs.reduce((a, b) => a + b.value, 0); - let fees = inputTotal - outputTotal - let total = Math.min(parseInt(amount) + fees, req.user.balance) - req.user.balance += 10000 - fees - if (req.user.balance < 0) req.user.balance = 0 + let fees = inputTotal - outputTotal; + let total = Math.min(parseInt(amount) + fees, req.user.balance); + req.user.balance += 10000 - fees; + if (req.user.balance < 0) req.user.balance = 0; await db.transaction(async transaction => { - await req.user.save({ transaction }) - emit(req.user.username, 'user', req.user) + await req.user.save({ transaction }); + emit(req.user.username, "user", req.user); await db.Payment.create( { amount: -total, user_id: req.user.id, hash: txid, - rate: app.get('rates').ask, - currency: 'CAD', + rate: app.get("rates").ask, + currency: "CAD" }, { transaction } - ) - }) + ); + }); - res.send({ txid, tx, amount, fees }) + res.send({ txid, tx, amount, fees }); } catch (e) { - l(e) - res.status(500).send(e.message) + l(e); + res.status(500).send(e.message); } - }) + }); - app.post('/addInvoice', auth, async (req, res) => { - let err = m => res.status(500).send(m) - let { amount, address, tip } = req.body + app.post("/addInvoice", auth, async (req, res) => { + let err = m => res.status(500).send(m); + let { amount, address, tip } = req.body; - let invoice + let invoice; try { - invoice = await lnb.addInvoice({ value: amount }) + invoice = await lnb.addInvoice({ value: amount }); } catch (e) { - return err(e.message) + return err(e.message); } - let hash = invoice.payment_request - if (address) hash = address + let hash = invoice.payment_request; + if (address) hash = address; await db.Payment.create({ user_id: req.user.id, hash, amount, - currency: 'CAD', - rate: app.get('rates').ask, - tip, - }) + currency: "CAD", + rate: app.get("rates").ask, + tip + }); - res.send(invoice) - }) + res.send(invoice); + }); let fetchRates; (fetchRates = async () => { try { let res = await axios.get( - 'https://api.kraken.com/0/public/Ticker?pair=XBTCAD' - ) - let ask = res.data.result.XXBTZCAD.c[0] - let now = new Date() - let ts = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}` - l(ts, 'ask price:', ask) - app.set('rates', { ask }) - socket.emit('rate', ask) + "https://api.kraken.com/0/public/Ticker?pair=XBTCAD" + ); + let ask = res.data.result.XXBTZCAD.c[0]; + let now = new Date(); + let ts = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`; + l(ts, "ask price:", ask); + app.set("rates", { ask }); + socket.emit("rate", ask); } catch (e) { - l(e) + l(e); } - setTimeout(fetchRates, 3000) - })() + setTimeout(fetchRates, 3000); + })(); - app.get('/rates', (req, res) => { - res.send(app.get('rates')) - }) + app.get("/rates", (req, res) => { + res.send(app.get("rates")); + }); - app.post('/login', async (req, res) => { + app.post("/login", async (req, res) => { try { let user = await db.User.findOne({ where: { - username: req.body.username, - }, - }) + username: req.body.username + } + }); if ( !user || !(await bcrypt.compare(req.body.password, user.password)) || (user.twofa && !(await authyVerify(user))) ) { - return res.status(401).end() + return res.status(401).end(); } - 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) }); - user = pick(user, ...whitelist) - res.send({ user, token }) + user = pick(user, ...whitelist); + res.send({ user, token }); } catch (err) { - res.status(401).end() + res.status(401).end(); } - }) + }); - app.post('/facebookLogin', async (req, res) => { - let { accessToken, userID } = req.body + app.post("/facebookLogin", async (req, res) => { + let { accessToken, userID } = req.body; - let url = `https://graph.facebook.com/debug_token?input_token=${accessToken}&access_token=${config.facebook.appToken}` - let check = await axios.get(url) - if (!check.data.data.is_valid) return res.status(401).end() + let url = `https://graph.facebook.com/debug_token?input_token=${accessToken}&access_token=${config.facebook.appToken}`; + let check = await axios.get(url); + if (!check.data.data.is_valid) return res.status(401).end(); try { let user = await db.User.findOne({ where: { - username: req.body.userID, - }, - }) + username: req.body.userID + } + }); if (!user) { - user = await db.User.create(user) - user.username = userID - user.name = (await fb.api(`/me?access_token=${accessToken}`)).name - user.address = (await lna.newAddress({ type: 1 }, lna.meta)).address - user.password = await bcrypt.hash(accessToken, 1) - user.balance = 0 - user.pending = 0 + user = await db.User.create(user); + user.username = userID; + user.name = (await fb.api(`/me?access_token=${accessToken}`)).name; + user.address = (await lna.newAddress({ type: 1 }, lna.meta)).address; + user.password = await bcrypt.hash(accessToken, 1); + user.balance = 0; + user.pending = 0; let friends = (await fb.api( `/${userID}/friends?access_token=${accessToken}` - )).data + )).data; if (friends.find(f => f.id === config.facebook.specialFriend)) { - user.friend = true - user.limit = 200 + user.friend = true; + user.limit = 200; } - await user.save() - addresses[user.address] = user.username + await user.save(); + addresses[user.address] = user.username; } user.pic = (await fb.api( `/me/picture?access_token=${accessToken}&redirect=false` - )).data.url - user.fbtoken = accessToken - await user.save() + )).data.url; + user.fbtoken = accessToken; + await user.save(); - if (user.twofa && !(await authyVerify(user))) res.status(401).end() + if (user.twofa && !(await authyVerify(user))) res.status(401).end(); - let payload = { username: user.username } - let token = jwt.sign(payload, config.jwt) - res.cookie('token', token, { expires: new Date(Date.now() + 432000000) }) - res.send({ user, token }) + let payload = { username: user.username }; + let token = jwt.sign(payload, config.jwt); + res.cookie("token", token, { expires: new Date(Date.now() + 432000000) }); + res.send({ user, token }); } catch (err) { - l(err) - res.status(401).end() + l(err); + res.status(401).end(); } - }) + }); - app.post('/buy', auth, async (req, res) => { - const stripe = require('stripe')(config.stripe) - const { token, amount, sat } = req.body - let dollarAmount = parseInt(amount / 100) + app.post("/buy", auth, async (req, res) => { + const stripe = require("stripe")(config.stripe); + const { token, amount, sat } = req.body; + let dollarAmount = parseInt(amount / 100); - if (dollarAmount > req.user.limit) return res.status(500).end() + if (dollarAmount > req.user.limit) return res.status(500).end(); try { const charge = await stripe.charges.create({ amount, - currency: 'cad', - description: 'Bitcoin', - source: token, - }) + currency: "cad", + description: "Bitcoin", + source: token + }); - req.user.balance += parseInt(sat) - req.user.limit -= dollarAmount - await req.user.save() - emit(req.user.username, 'user', req.user) + req.user.balance += parseInt(sat); + req.user.limit -= dollarAmount; + await req.user.save(); + emit(req.user.username, "user", req.user); await db.Payment.create({ user_id: req.user.id, hash: charge.balance_transaction, amount: parseInt(sat), - currency: 'CAD', - rate: app.get('rates').ask, + currency: "CAD", + rate: app.get("rates").ask, received: true, - tip: 0, - }) + tip: 0 + }); - res.send(`Bought ${amount}`) + res.send(`Bought ${amount}`); } catch (e) { - console.log(e) - res.status(500).send(e) + console.log(e); + res.status(500).send(e); } - }) + }); - app.post('/order', auth, async (req, res) => { + app.post("/order", auth, async (req, res) => { await db.Order.create({ amount: 1, price: 2, - type: 'BUY', - pair: 'BTC/CAD', - }) - }) + type: "BUY", + pair: "BTC/CAD" + }); + }); - app.get('/me', async (req, res) => { + app.get("/me", async (req, res) => { let data = (await fb.api( - '/me/picture?access_token=EAAEIFqWk3ZAwBAEUfxQdH3T5CBKXmU8d7jQ5OTJBJZBiU1ZAp76lO26nh57WolM4R4JoKks9BCc49s8VrlEm2Ub1GlZCEzVD9fGxzUiranXDErDmR5gDUPKX3BhCsGA649a4hmbldRwKFTsmZCGZCergm9ACspKdTZB0WgFgA9wEdemIRIXuwCygNrymmKDh0Wd8nmoT4Hj3wZDZD&redirect=false' - )).data - res.send(data.url) - }) + "/me/picture?access_token=EAAEIFqWk3ZAwBAEUfxQdH3T5CBKXmU8d7jQ5OTJBJZBiU1ZAp76lO26nh57WolM4R4JoKks9BCc49s8VrlEm2Ub1GlZCEzVD9fGxzUiranXDErDmR5gDUPKX3BhCsGA649a4hmbldRwKFTsmZCGZCergm9ACspKdTZB0WgFgA9wEdemIRIXuwCygNrymmKDh0Wd8nmoT4Hj3wZDZD&redirect=false" + )).data; + res.send(data.url); + }); - app.get('/exchanges', async (req, res) => { + app.get("/exchanges", async (req, res) => { let r = await axios.get( - 'https://min-api.cryptocompare.com/data/v2/all/exchanges?fsym=BTC&api_key=6dc6d605ac45dcdbbc44d67111a2f03ba42ca8f54c5d4bf21069d2d3e99a89f0' - ) - res.send(r.data) - }) + "https://min-api.cryptocompare.com/data/v2/all/exchanges?fsym=BTC&api_key=6dc6d605ac45dcdbbc44d67111a2f03ba42ca8f54c5d4bf21069d2d3e99a89f0" + ); + res.send(r.data); + }); - app.get('/currencies', async (req, res) => { - res.send(['CAD', 'USD']) - }) + app.get("/currencies", async (req, res) => { + res.send(["CAD", "USD"]); + }); - app.get('/balance/:address', async (req, res) => { - let network = config.bitcoin.network === 'mainnet' ? 'main' : 'test3' - let { address } = req.params + app.get("/balance/:address", async (req, res) => { + let network = config.bitcoin.network === "mainnet" ? "main" : "test3"; + let { address } = req.params; try { res.send( (await axios.get( `https://api.blockcypher.com/v1/btc/${network}/addrs/${address}/balance` )).data - ) + ); } catch (e) { - res.status(500).send('Problem getting address balance') + res.status(500).send("Problem getting address balance"); } - }) + }); - app.use(function (err, req, res, next) { - res.status(500) - res.send('An error occurred') - l(err.stack) - return res.end() - }) + app.use(function(err, req, res, next) { + res.status(500); + res.send("An error occurred"); + l(err.stack); + return res.end(); + }); - server.listen(config.port) -})() + server.listen(config.port); +})(); |
