From b0e279aff714164a01ece9d2d933e4649d3ad48c Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 5 Jan 2020 18:39:30 -0800 Subject: queue on-chain payments --- addInvoice.js | 3 ++- bitcoinPayments.js | 67 ++++++++++++++++++++++------------------------------ db.js | 40 ++++--------------------------- index.js | 11 +-------- lightningPayments.js | 2 ++ payUser.js | 3 ++- schema.sql | 2 +- sendCoins.js | 3 ++- sendPayment.js | 3 ++- sockets.js | 32 +++++++++++++------------ stripe.js | 3 ++- 11 files changed, 63 insertions(+), 106 deletions(-) diff --git a/addInvoice.js b/addInvoice.js index eca884dd..c7336e0f 100644 --- a/addInvoice.js +++ b/addInvoice.js @@ -18,7 +18,8 @@ module.exports = (app, db, lnb) => async (req, res) => { amount, currency: "CAD", rate: app.get("rates").ask, - tip + tip, + confirmed: true, }); res.send(invoice); diff --git a/bitcoinPayments.js b/bitcoinPayments.js index cdcfde5a..cd9aa713 100644 --- a/bitcoinPayments.js +++ b/bitcoinPayments.js @@ -22,6 +22,7 @@ module.exports = (app, bc, db, addresses, payments, emit) => { let tx = bitcoin.Transaction.fromHex(message); let hash = reverse(tx.getHash()).toString("hex"); + console.log(hash); if (payments.includes(hash)) return; @@ -74,7 +75,7 @@ module.exports = (app, bc, db, addresses, payments, emit) => { await user.save(); emit(user.username, "user", user); - await db.Payment.create({ + const payment = await db.Payment.create({ user_id: user.id, hash, amount: o.value, @@ -86,6 +87,7 @@ module.exports = (app, bc, db, addresses, payments, emit) => { address }); + emit(user.username, "payment", payment); emit(user.username, "tx", message); } }) @@ -99,54 +101,41 @@ module.exports = (app, bc, db, addresses, payments, emit) => { where: { confirmed: false } }); - const addresses = payments.map(p => p.address); + const hashes = payments.map(p => p.hash); let block = bitcoin.Block.fromHex(message.toString("hex")); block.transactions.map(tx => { - tx.outs.map(o => { - try { - let address = bitcoin.address.fromOutputScript(o.script, NETWORK); - if (addresses.includes(address)) { - queue[address] || (queue[address] = 0) - queue[address] += o.value; - } - } catch (e) { - return; - } - }) + let hash = reverse(tx.getHash()).toString("hex"); + if (hashes.includes(hash)) queue[hash] = 1; }); }); - setInterval(() => { - Object.keys(queue).map(async address => { - l(address); + setInterval(async () => { + let arr = Object.keys(queue); + for (let i = 0; i < arr.length; i++) { + let hash = arr[i]; - let user = await db.User.findOne({ - where: { - username: addresses[address], - } - }); + let p = await db.Payment.findOne({ + include: [{ model: db.User, as: "user" }], + where: { hash, confirmed: 0 } + }) + + p.confirmed = 1; + + let user = await p.getUser(); + user.balance += p.amount; + user.pending -= p.amount; + emit(user.username, "user", user); - l(user.pending); + await user.save(); + await p.save(); - const payments = await db.Payment.findAll({ - where: { confirmed: false, address } + let payments = await db.Payment.findAll({ + where: { user_id: user.id } }); - await Promise.all(payments.map(async p => { - if (p.amount <= queue[address]) { - l(user.pending, p.amount, queue[address]); - queue[address] -= p.amount; - if (queue[address] <= 0) delete queue[address]; - p.confirmed = 1; - await p.save(); - user.balance += p.amount; - user.pending -= p.amount; - await user.save(); - emit(user.username, "user", user); - emit(user.username, "block", 1); - } - })); - }); + emit(user.username, "payments", payments); + delete queue[hash]; + } }, 1000); }; diff --git a/db.js b/db.js index b2372c89..c66bab30 100644 --- a/db.js +++ b/db.js @@ -1,22 +1,6 @@ const config = require("./config"); const Sequelize = require("sequelize"); const SequelizeAuto = require("sequelize-auto"); -const { - resolver, - defaultArgs, - defaultListArgs, - attributeFields -} = require("graphql-sequelize"); -const { - graphql, - GraphQLSchema, - GraphQLObjectType, - GraphQLInputObjectType, - GraphQLString, - GraphQLInt, - GraphQLNonNull, - GraphQLList -} = require("graphql"); const conf = config.db[process.env.NODE_ENV || "development"]; @@ -39,9 +23,6 @@ const db = new Sequelize(conf.database, conf.username, conf.password, { dialectOptions: { multipleStatements: true } }); -const gqlfields = {}; -const gqltypes = {}; - const p = new Promise((resolve, reject) => { return auto.run(() => { Object.keys(tables).forEach(k => { @@ -92,27 +73,14 @@ const p = new Promise((resolve, reject) => { } }; } - - gqltypes[t] = new GraphQLObjectType({ - name: t, - desc: t, - fields: Object.assign(typefields, attributeFields(db[k])) - }); - - gqlfields[t] = { - type: new GraphQLList(gqltypes[t]), - args: Object.assign({}, defaultArgs(db[k]), defaultListArgs()), - resolve: resolver(db[k], options) - }; }); - db.gqlschema = new GraphQLSchema({ - query: new GraphQLObjectType({ - name: "RootQueryType", - fields: gqlfields - }) + db["User"].hasMany(db["Payment"], { + as: "payments", + foreignKey: "user_id" }); + resolve(db); }); }); diff --git a/index.js b/index.js index 5a0c1df6..10741d27 100644 --- a/index.js +++ b/index.js @@ -4,10 +4,10 @@ const cookieParser = require("cookie-parser"); const BitcoinCore = require("bitcoin-core"); const cors = require("cors"); const express = require("express"); -const graphqlHTTP = require("express-graphql"); const morgan = require("morgan"); const config = require("./config"); +const bolt11 = require("bolt11"); const l = console.log; @@ -30,15 +30,6 @@ const l = console.log; app.use(passport.initialize()); - app.use( - "/graphql", - auth, - graphqlHTTP({ - schema: db.gqlschema, - graphiql: true - }) - ); - require("./rates")(app, socket); const seen = []; diff --git a/lightningPayments.js b/lightningPayments.js index 2d78551a..e7d84868 100644 --- a/lightningPayments.js +++ b/lightningPayments.js @@ -16,12 +16,14 @@ module.exports = (app, db, lna, lnb, emit, payments) => { payment.received = true; user.balance += parseInt(msg.value); payment.rate = app.get("rates")[user.currency]; + payment.confirmed = true; await payment.save(); await user.save(); payments.push(msg.payment_request); emit(user.username, "invoice", msg); + emit(user.username, "payment", payment); emit(user.username, "user", user); }; diff --git a/payUser.js b/payUser.js index cb2681a4..7a08f9a1 100644 --- a/payUser.js +++ b/payUser.js @@ -27,7 +27,8 @@ module.exports = (app, db, lnb) => async (req, res) => { amount, currency: "CAD", rate: app.get("rates").ask, - tip: 0 + tip: 0, + confirmed: true }); req.url = "/sendPayment"; diff --git a/schema.sql b/schema.sql index 57387069..38c37ea3 100644 --- a/schema.sql +++ b/schema.sql @@ -67,7 +67,7 @@ CREATE TABLE `payments` ( `received` tinyint(1) DEFAULT NULL, `amount` double DEFAULT NULL, `tip` double DEFAULT NULL, - `confirmed` tinyint(1) DEFAULT NULL, + `confirmed` tinyint(1) DEFAULT NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1611 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/sendCoins.js b/sendCoins.js index 67c545b9..b65fe94c 100644 --- a/sendCoins.js +++ b/sendCoins.js @@ -74,7 +74,8 @@ module.exports = (app, bc, db, emit) => async (req, res) => { hash: txid, rate: app.get("ask"), currency: "CAD", - address + address, + confirmed: true }, { transaction } ); diff --git a/sendPayment.js b/sendPayment.js index ee2f2c90..c5ce7ea3 100644 --- a/sendPayment.js +++ b/sendPayment.js @@ -56,7 +56,8 @@ module.exports = (app, db, emit, seen, lna, lnb) => async (req, res) => { user_id: req.user.id, hash, rate: app.get("ask"), - currency: "CAD" + currency: "CAD", + confirmed: true }, { transaction } ); diff --git a/sockets.js b/sockets.js index a6f84073..09be6526 100644 --- a/sockets.js +++ b/sockets.js @@ -10,6 +10,19 @@ module.exports = (app, db, server) => { const socket = io(server, { origins: "*:*" }); const sids = {}; + const emit = (username, msg, data) => { + if (data.username !== undefined) data = pick(data, ...whitelist); + + if (!sids[username]) return; + sids[username].map((sid, i) => { + try { + socket.to(sid).emit(msg, data); + } catch (e) { + sids[username].splice(i, 1); + } + }); + }; + socket.use((socket, next) => { try { let token = socket.handshake.query.token; @@ -28,13 +41,15 @@ module.exports = (app, db, server) => { if (app.get("rates")) socket.emit("rate", app.get("rates").ask); socket.on("getuser", async (data, callback) => { /* eslint-disable-next-line */ - callback( + const user = await db.User.findOne({ + include: [{ model: db.Payment, as: "payments" }], where: { username: socket.request.user } }) - ); + + callback(user); }); socket.on("disconnect", s => { @@ -44,18 +59,5 @@ module.exports = (app, db, server) => { }); }); - const emit = (username, msg, data) => { - if (data.username !== undefined) data = pick(data, ...whitelist); - - if (!sids[username]) return; - sids[username].map((sid, i) => { - try { - socket.to(sid).emit(msg, data); - } catch (e) { - sids[username].splice(i, 1); - } - }); - }; - return [socket, emit]; }; diff --git a/stripe.js b/stripe.js index 090def4b..c22b4419 100644 --- a/stripe.js +++ b/stripe.js @@ -29,7 +29,8 @@ module.exports = (auth, app, db, emit) => { currency: "CAD", rate: app.get("rates").ask, received: true, - tip: 0 + tip: 0, + confirmed: true, }); res.send(`Bought ${amount}`); -- cgit v1.2.3