aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--db/models/invoices.js11
-rw-r--r--routes/bitcoin/receive.js259
-rw-r--r--routes/invoices.js2
3 files changed, 141 insertions, 131 deletions
diff --git a/db/models/invoices.js b/db/models/invoices.js
index b13a9545..82e64427 100644
--- a/db/models/invoices.js
+++ b/db/models/invoices.js
@@ -129,7 +129,7 @@ const attributes = {
field: "address"
},
received: {
- type: DataTypes.STRING(255),
+ type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: 0,
primaryKey: false,
@@ -146,6 +146,15 @@ const attributes = {
comment: null,
field: "amount"
},
+ pending: {
+ type: DataTypes.DOUBLE,
+ allowNull: false,
+ defaultValue: 0,
+ primaryKey: false,
+ autoIncrement: false,
+ comment: null,
+ field: "pending"
+ },
webhook: {
type: DataTypes.TEXT,
allowNull: true,
diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js
index 714aa3b2..4ace1c2f 100644
--- a/routes/bitcoin/receive.js
+++ b/routes/bitcoin/receive.js
@@ -5,13 +5,13 @@ import { emit } from "$lib/sockets";
import store from "$lib/store";
import { notify } from "$lib/notifications";
import { callWebhook } from "$lib/webhooks";
-import reverse from 'buffer-reverse';
-import zmq from 'zeromq/v5-compat';
-import { Op } from '@sequelize/core';
-import { fromBase58 } from 'bip32';
-import bitcoin from 'bitcoinjs-lib';
+import reverse from "buffer-reverse";
+import zmq from "zeromq/v5-compat";
+import { Op } from "@sequelize/core";
+import { fromBase58 } from "bip32";
+import bitcoin from "bitcoinjs-lib";
import { sendLiquid } from "$routes/liquid/send";
-import { computeConversionFee } from './conversionFee';
+import { computeConversionFee } from "./conversionFee";
import { l, warn, err } from "$lib/logging";
const zmqRawBlock = zmq.socket("sub");
@@ -34,149 +34,149 @@ console.warn = () => {};
zmqRawTx.on("message", async (topic, message, sequence) => {
try {
- const hex = message.toString("hex");
- let tx = bitcoin.Transaction.fromHex(message);
+ const hex = message.toString("hex");
+ let tx = bitcoin.Transaction.fromHex(message);
- let hash = reverse(tx.getHash()).toString("hex");
-
- if (seen.includes(hash)) return;
- seen.push(hash);
- if (seen.length > 5000) seen.shift();
+ let hash = reverse(tx.getHash()).toString("hex");
- Promise.all(
- tx.outs.map(async o => {
- try {
- const { value } = o;
+ if (seen.includes(hash)) return;
+ seen.push(hash);
+ if (seen.length > 5000) seen.shift();
- let address;
+ Promise.all(
+ tx.outs.map(async o => {
try {
- address = bitcoin.address.fromOutputScript(o.script, network);
- } catch (e) {
- return;
- }
-
- if (
- Object.keys(store.addresses).includes(address) &&
- !store.change.includes(address)
- ) {
- await db.transaction(async transaction => {
- let user = await db.User.findOne({
- where: {
- username: store.addresses[address]
- },
- transaction
- });
+ const { value } = o;
- let invoice = await db.Invoice.findOne({
- where: {
- address,
- user_id: user.id,
- network: "bitcoin"
- },
- order: [["id", "DESC"]],
- include: {
- model: db.Account,
- as: "account"
- },
- transaction
- });
-
- if (!invoice) return;
-
- const currency = invoice ? invoice.currency : user.currency;
- const rate = invoice
- ? invoice.rate
- : store.rates[user.currency];
- const tip = invoice ? invoice.tip : 0;
- const memo = invoice ? invoice.memo : "";
-
- let confirmed = false;
+ let address;
+ try {
+ address = bitcoin.address.fromOutputScript(o.script, network);
+ } catch (e) {
+ return;
+ }
- let { account } = invoice;
+ if (
+ Object.keys(store.addresses).includes(address) &&
+ !store.change.includes(address)
+ ) {
+ await db.transaction(async transaction => {
+ let user = await db.User.findOne({
+ where: {
+ username: store.addresses[address]
+ },
+ transaction
+ });
- if (account.asset !== config.liquid.btcasset) {
- account = await db.Account.findOne({
+ let invoice = await db.Invoice.findOne({
where: {
+ address,
user_id: user.id,
- asset: config.liquid.btcasset,
- pubkey: null
+ network: "bitcoin"
+ },
+ order: [["id", "DESC"]],
+ include: {
+ model: db.Account,
+ as: "account"
},
transaction
});
- }
- await account.increment({ pending: value }, { transaction });
- await account.save({ transaction });
+ if (!invoice) return;
- if (config.bitcoin.walletpass)
- await bc.walletPassphrase(config.bitcoin.walletpass, 300);
+ const currency = invoice ? invoice.currency : user.currency;
+ const rate = invoice ? invoice.rate : store.rates[user.currency];
+ const tip = invoice ? invoice.tip : 0;
+ const memo = invoice ? invoice.memo : "";
- let totalOutputs = tx.outs.reduce((a, b) => a + b.value, 0);
- let totalInputs = 0;
- for (let i = 0; i < tx.ins.length; i++) {
- let { hash, index } = tx.ins[i];
- hash = reverse(hash).toString("hex");
- let hex = await bc.getRawTransaction(hash);
- let inputTx = bitcoin.Transaction.fromHex(hex);
- totalInputs += inputTx.outs[index].value;
- }
- let fee = totalInputs - totalOutputs;
+ let confirmed = false;
- let payment = await db.Payment.create(
- {
- account_id: account.id,
- user_id: user.id,
- hash,
- fee,
- memo,
- amount: value - tip,
- currency,
- rate,
- received: true,
- tip,
- confirmed,
- address,
- network: "bitcoin",
- invoice_id: invoice.id
- },
- { transaction }
- );
+ let { account } = invoice;
- payment = payment.get({ plain: true });
- payment.account = account.get({ plain: true });
- payment.invoice = invoice.get({ plain: true });
+ if (account.asset !== config.liquid.btcasset) {
+ account = await db.Account.findOne({
+ where: {
+ user_id: user.id,
+ asset: config.liquid.btcasset,
+ pubkey: null
+ },
+ transaction
+ });
+ }
- emit(user.username, "account", account);
- emit(user.username, "payment", payment);
- l("bitcoin detected", user.username, value);
- notify(user, `${value} SAT payment detected`);
- callWebhook(invoice, payment);
- });
+ await invoice.increment({ pending: value }, { transaction });
+ await invoice.save({ transaction });
+ await account.increment({ pending: value }, { transaction });
+ await account.save({ transaction });
+
+ if (config.bitcoin.walletpass)
+ await bc.walletPassphrase(config.bitcoin.walletpass, 300);
+
+ let totalOutputs = tx.outs.reduce((a, b) => a + b.value, 0);
+ let totalInputs = 0;
+ for (let i = 0; i < tx.ins.length; i++) {
+ let { hash, index } = tx.ins[i];
+ hash = reverse(hash).toString("hex");
+ let hex = await bc.getRawTransaction(hash);
+ let inputTx = bitcoin.Transaction.fromHex(hex);
+ totalInputs += inputTx.outs[index].value;
+ }
+ let fee = totalInputs - totalOutputs;
+
+ let payment = await db.Payment.create(
+ {
+ account_id: account.id,
+ user_id: user.id,
+ hash,
+ fee,
+ memo,
+ amount: value - tip,
+ currency,
+ rate,
+ received: true,
+ tip,
+ confirmed,
+ address,
+ network: "bitcoin",
+ invoice_id: invoice.id
+ },
+ { transaction }
+ );
+
+ payment = payment.get({ plain: true });
+ payment.account = account.get({ plain: true });
+ payment.invoice = invoice.get({ plain: true });
+
+ emit(user.username, "account", account);
+ emit(user.username, "payment", payment);
+ l("bitcoin detected", user.username, value);
+ notify(user, `${value} SAT payment detected`);
+ callWebhook(invoice, payment);
+ });
+ }
+ } catch (e) {
+ console.log("problem parsing bitcoin tx", e);
}
- } catch (e) {
- console.log("problem parsing bitcoin tx", e);
- }
- })
- );
- } catch(e) {
+ })
+ );
+ } catch (e) {
console.log("problem receiving bitcoin tx", e);
- }
+ }
});
zmqRawBlock.on("message", async (topic, message, sequence) => {
try {
- const payments = await db.Payment.findAll({
- where: { confirmed: false }
- });
+ const payments = await db.Payment.findAll({
+ where: { confirmed: false }
+ });
- let block = bitcoin.Block.fromHex(message.toString("hex"));
- block.transactions.map(tx => {
- let hash = reverse(tx.getHash()).toString("hex");
- if (payments.find(p => p.hash === hash)) queue[hash] = 1;
- });
- } catch(e) {
- console.log(e)
- }
+ let block = bitcoin.Block.fromHex(message.toString("hex"));
+ block.transactions.map(tx => {
+ let hash = reverse(tx.getHash()).toString("hex");
+ if (payments.find(p => p.hash === hash)) queue[hash] = 1;
+ });
+ } catch (e) {
+ console.log(e);
+ }
});
setInterval(async () => {
@@ -220,6 +220,11 @@ setInterval(async () => {
await account.save({ transaction });
await invoice.increment({ received: total }, { transaction });
+ await invoice.decrement(
+ { pending: Math.min(invoice.pending, total) },
+ { transaction }
+ );
+
await account.increment({ balance: total }, { transaction });
await account.decrement(
{ pending: Math.min(account.pending, total) },
@@ -270,10 +275,6 @@ setInterval(async () => {
});
}
} catch (e) {
- err(
- "problem processing queued bitcoin transaction",
- e.message,
- e.stack
- );
+ err("problem processing queued bitcoin transaction", e.message, e.stack);
}
}, 1000);
diff --git a/routes/invoices.js b/routes/invoices.js
index ebe4e6d5..198189b4 100644
--- a/routes/invoices.js
+++ b/routes/invoices.js
@@ -19,7 +19,7 @@ app.get("/invoice", async (req, res, next) => {
include: {
model: db.User,
as: "user",
- attributes: ["username", "currency"]
+ attributes: ["username", "currency", "profile"]
}
});