aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2019-12-31 22:12:26 -0800
committerAdam Soltys <[email protected]>2019-12-31 22:12:29 -0800
commit3b841f05921311cf149b7987d76738fcb053a52e (patch)
tree7314c78627dcacc1a5d54066b834005755bb9631
parentae5e489e8a21293ae3f4d9a3e1940a62ddd01011 (diff)
downloadcoinos-server-3b841f05921311cf149b7987d76738fcb053a52e.tar.gz
coinos-server-3b841f05921311cf149b7987d76738fcb053a52e.zip
better payment detection logic
-rw-r--r--bitcoinPayments.js103
-rw-r--r--lightningPayments.js12
-rw-r--r--sendCoins.js34
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);
}
};