aboutsummaryrefslogtreecommitdiffstats
path: root/bitcoinPayments.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2019-09-15 23:05:26 -0700
committerAdam Soltys <[email protected]>2019-09-15 23:05:26 -0700
commit765c6a42135b9334b616c26b22c816edd06e382a (patch)
tree05da4f343358fb5e9a9083e348783f0fab973dd8 /bitcoinPayments.js
parent087fdd27f3683a1deb9376b7a72aa608e6fd8e6a (diff)
downloadcoinos-server-765c6a42135b9334b616c26b22c816edd06e382a.tar.gz
coinos-server-765c6a42135b9334b616c26b22c816edd06e382a.zip
refactor
Diffstat (limited to 'bitcoinPayments.js')
-rw-r--r--bitcoinPayments.js131
1 files changed, 131 insertions, 0 deletions
diff --git a/bitcoinPayments.js b/bitcoinPayments.js
new file mode 100644
index 00000000..479298b8
--- /dev/null
+++ b/bitcoinPayments.js
@@ -0,0 +1,131 @@
+const reverse = require("buffer-reverse");
+const zmq = require("zeromq");
+const config = require("./config");
+const Sequelize = require("sequelize");
+
+const bitcoin = require("bitcoinjs-lib");
+const l = console.log;
+
+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");
+
+module.exports = (app, bc, db, addresses, payments, emit) => {
+ zmqRawTx.on("message", (topic, message, sequence) => {
+ message = message.toString("hex");
+
+ let tx = bitcoin.Transaction.fromHex(message);
+ let hash = reverse(tx.getHash()).toString("hex");
+
+ if (payments.includes(hash)) return;
+
+ 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]
+ );
+ } catch (e) {
+ return;
+ }
+
+ if (Object.keys(addresses).includes(address)) {
+ payments.push(hash);
+
+ let user = await db.User.findOne({
+ where: {
+ username: addresses[address]
+ }
+ });
+
+ let invoices = await db.Payment.findAll({
+ limit: 1,
+ where: {
+ hash: address,
+ received: null,
+ amount: {
+ [Sequelize.Op.gt]: 0
+ }
+ },
+ order: [["createdAt", "DESC"]]
+ });
+
+ let tip = null;
+ if (invoices.length) tip = invoices[0].tip;
+
+ let confirmed = false;
+
+ if (user.friend) {
+ user.balance += o.value;
+ confirmed = true;
+ } else {
+ user.pending += o.value;
+ }
+
+ 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,
+ received: true,
+ tip,
+ confirmed
+ });
+
+ l("tx", message);
+ emit(user.username, "tx", message);
+ }
+ })
+ );
+ });
+
+ 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"));
+
+ const processPayment = async p => {
+ if ((await bc.getRawTransaction(p.hash, true)).confirmations > 0) {
+ let user = await db.User.findByPk(p.user_id);
+ l(user.pending);
+ p.confirmed = true;
+ user.balance += p.amount;
+ user.pending -= p.amount;
+ await user.save();
+ await p.save();
+ emit(user.username, "user", user);
+ emit(user.username, "block", message);
+ }
+ };
+
+ await db.Payment.findAll({
+ where: { confirmed: false }
+ }).reduce(async (prev, payment) => {
+ const result = await prev;
+ return [...result, await processPayment(payment)];
+ }, Promise.resolve([]));
+
+ break;
+ }
+ }
+ });
+};