diff options
| author | Adam Soltys <[email protected]> | 2019-12-31 22:12:26 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2019-12-31 22:12:29 -0800 |
| commit | 3b841f05921311cf149b7987d76738fcb053a52e (patch) | |
| tree | 7314c78627dcacc1a5d54066b834005755bb9631 | |
| parent | ae5e489e8a21293ae3f4d9a3e1940a62ddd01011 (diff) | |
| download | coinos-server-3b841f05921311cf149b7987d76738fcb053a52e.tar.gz coinos-server-3b841f05921311cf149b7987d76738fcb053a52e.zip | |
better payment detection logic
| -rw-r--r-- | bitcoinPayments.js | 103 | ||||
| -rw-r--r-- | lightningPayments.js | 12 | ||||
| -rw-r--r-- | sendCoins.js | 34 |
3 files changed, 84 insertions, 65 deletions
diff --git a/bitcoinPayments.js b/bitcoinPayments.js index c32d11c5..cdcfde5a 100644 --- a/bitcoinPayments.js +++ b/bitcoinPayments.js @@ -14,6 +14,8 @@ const zmqRawTx = zmq.socket("sub"); zmqRawTx.connect(config.bitcoin.zmqrawtx); zmqRawTx.subscribe("rawtx"); +let NETWORK = bitcoin.networks[config.bitcoin.network === "mainnet" ? "bitcoin" : config.bitcoin.network]; + module.exports = (app, bc, db, addresses, payments, emit) => { zmqRawTx.on("message", (topic, message, sequence) => { message = message.toString("hex"); @@ -25,16 +27,12 @@ module.exports = (app, bc, db, addresses, payments, emit) => { Promise.all( tx.outs.map(async o => { - let network = config.bitcoin.network; - if (network === "mainnet") { - network = "bitcoin"; - } let address; try { address = bitcoin.address.fromOutputScript( o.script, - bitcoin.networks[network] + NETWORK ); } catch (e) { return; @@ -52,7 +50,7 @@ module.exports = (app, bc, db, addresses, payments, emit) => { let invoices = await db.Payment.findAll({ limit: 1, where: { - hash: address, + address, received: null, amount: { [Sequelize.Op.gt]: 0 @@ -84,62 +82,71 @@ module.exports = (app, bc, db, addresses, payments, emit) => { rate: app.get("ask"), received: true, tip, - confirmed + confirmed, + address }); - l("tx", message); emit(user.username, "tx", message); } }) ); }); - zmqRawBlock.on("message", async (topic, message, sequence) => { - topic = topic.toString("utf8"); - message = message.toString("hex"); + let queue = {}; - switch (topic) { - case "rawblock": { - let block = bitcoin.Block.fromHex(message); - l("block", block.getHash().toString("hex")); + zmqRawBlock.on("message", async (topic, message, sequence) => { + const payments = await db.Payment.findAll({ + where: { confirmed: false } + }); - const processPayment = async (payment, transaction) => { - if ( - (await bc.getRawTransaction(payment.hash, true)).confirmations > 0 - ) { - let user = await db.User.findByPk(payment.user_id, { transaction }); - payment.confirmed = true; - user.balance += payment.amount; - user.pending -= payment.amount; - await user.save({ transaction }); - await payment.save({ transaction }); - emit(user.username, "user", user); - emit(user.username, "block", message); - } - }; + const addresses = payments.map(p => p.address); - const transaction = await db.transaction(); + let block = bitcoin.Block.fromHex(message.toString("hex")); + block.transactions.map(tx => { + tx.outs.map(o => { try { - const payments = await db.Payment.findAll({ - where: { confirmed: false }, - lock: transaction.LOCK.UPDATE, - transaction - }); - - await Promise.all( - payments.map(async payment => { - await processPayment(payment, transaction); - return; - }) - ); + let address = bitcoin.address.fromOutputScript(o.script, NETWORK); + if (addresses.includes(address)) { + queue[address] || (queue[address] = 0) + queue[address] += o.value; + } } catch (e) { - transaction.rollback(); + return; } + }) + }); + }); - await transaction.commit(); + setInterval(() => { + Object.keys(queue).map(async address => { + l(address); - break; - } - } - }); + let user = await db.User.findOne({ + where: { + username: addresses[address], + } + }); + + l(user.pending); + + const payments = await db.Payment.findAll({ + where: { confirmed: false, address } + }); + + 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); + } + })); + }); + }, 1000); }; diff --git a/lightningPayments.js b/lightningPayments.js index c12b8fcf..2d78551a 100644 --- a/lightningPayments.js +++ b/lightningPayments.js @@ -11,16 +11,18 @@ module.exports = (app, db, lna, lnb, emit, payments) => { if (!payment) return; + const { user } = payment; + payment.received = true; - payment.user.balance += parseInt(msg.value); - payment.rate = app.get("ask"); + user.balance += parseInt(msg.value); + payment.rate = app.get("rates")[user.currency]; await payment.save(); - await payment.user.save(); + await user.save(); payments.push(msg.payment_request); - emit(payment.user.username, "invoice", msg); - emit(payment.user.username, "user", payment.user); + emit(user.username, "invoice", msg); + emit(user.username, "user", user); }; const invoices = lna.subscribeInvoices({}); diff --git a/sendCoins.js b/sendCoins.js index 63f50355..67c545b9 100644 --- a/sendCoins.js +++ b/sendCoins.js @@ -7,20 +7,28 @@ const SATS = 100000000; module.exports = (app, bc, db, emit) => async (req, res) => { let { address, amount } = req.body; - amount = parseInt(amount); + let rawtex, hex, fee; - let rawtx = await bc.createRawTransaction([], { - [address]: (amount / SATS).toFixed(8) - }); - rawtx = await bc.fundRawTransaction(rawtx, { - subtractFeeFromOutputs: amount === req.user.balance ? [0] : [] - }); - let { hex, fee } = rawtx; - fee = parseInt(fee * SATS); + try { + amount = parseInt(amount); - l("sending coins", req.user.username, amount, address); + rawtx = await bc.createRawTransaction([], { + [address]: (amount / SATS).toFixed(8) + }); + + rawtx = await bc.fundRawTransaction(rawtx, { + subtractFeeFromOutputs: amount === req.user.balance ? [0] : [] + }); + + ({ hex, fee } = rawtx); + fee = parseInt(fee * SATS); + } catch (e) { + l(e); + return res.status(500).send(e.message); + } try { + l("sending coins", req.user.username, amount, address); await db.transaction(async transaction => { let { balance } = await db.User.findOne({ where: { @@ -39,6 +47,7 @@ module.exports = (app, bc, db, emit) => async (req, res) => { await req.user.save({ transaction }); }); } catch (e) { + l(e); return res.status(500).send("Not enough satoshis"); } @@ -64,7 +73,8 @@ module.exports = (app, bc, db, emit) => async (req, res) => { user_id: req.user.id, hash: txid, rate: app.get("ask"), - currency: "CAD" + currency: "CAD", + address }, { transaction } ); @@ -73,6 +83,6 @@ module.exports = (app, bc, db, emit) => async (req, res) => { res.send({ txid, tx, amount, fees: fee }); } catch (e) { l(e); - res.status(500).send(e.message); + return res.status(500).send(e.message); } }; |
