From 9e6091525bfa1e068fa4592b48acd8fa9d8a7fc5 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 30 Jun 2021 14:59:30 -0400 Subject: handle address failure --- routes/users.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'routes/users.js') diff --git a/routes/users.js b/routes/users.js index 09ba5d43..25a737ce 100644 --- a/routes/users.js +++ b/routes/users.js @@ -160,7 +160,8 @@ app.post( return res.status(500).send("Username taken"); } else { sockets[username] = sockets[user.username]; - if (user.username !== username) l.info("changing username", user.username, username); + if (user.username !== username) + l.info("changing username", user.username, username); user.username = username; token = jwt.sign({ username }, config.jwt); @@ -335,10 +336,7 @@ app.post( (user.password && !(await bcrypt.compare(req.body.password, user.password))) ) { - l.warn( - "invalid username or password attempt", - req.body.username - ); + l.warn("invalid username or password attempt", req.body.username); return res.status(401).end(); } @@ -438,11 +436,22 @@ app.get( : config.liquid.network ]; type = "p2sh"; - + // async request to node to bump its internal index but don't use result - lq.getNewAddress().catch(console.error); + lq.getNewAddress().catch((e) => l.warn("Problem bumping liquid address index", e.message)) i = parseInt(app.get("lqAddressIndex")); + + if (!i) { + const { hdkeypath } = await lq.getAddressInfo( + await lq.getNewAddress() + ); + const parts = hdkeypath.split("/"); + i = parts[parts.length - 1].slice(0, -1); + } + + if (!i) throw new Error("Problem generating address"); + hd = fromBase58(config.liquid.masterkey, n).derivePath(`m/0'/0'/${i}'`); app.set("lqAddressIndex", i + 1); } else { -- cgit v1.2.3 From 29956a035056c76b3329792feb9a7fb3d7c8ec0e Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 8 Jul 2021 15:17:06 -0400 Subject: only convert btc --- routes/liquid/fee.js | 2 ++ routes/liquid/receive.js | 6 +++--- routes/users.js | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'routes/users.js') diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index a6c29f41..fad69f13 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -59,6 +59,8 @@ liquidTx = async ({ address, asset, amount, feeRate, replaceable, user }) => { } ); + l.info("funding tx for fee estimate", tx); + tx = await node.fundRawTransaction(tx, params); let blinded = await node.blindRawTransaction(tx.hex); diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 05ecc21f..9d8923eb 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -287,9 +287,9 @@ setInterval(async () => { for (let i = 0; i < arr.length; i++) { const hash = arr[i]; - let account, address, user, total; + let account, address, user, total, p; await db.transaction(async transaction => { - let p = await db.Payment.findOne({ + p = await db.Payment.findOne({ where: { hash, confirmed: 0, received: 1 }, include: [ { @@ -343,7 +343,7 @@ setInterval(async () => { }); let c = convert[address]; - if (address && c) { + if (address && c && p.account.asset === network.assetHash) { l.info("liquid detected for conversion request", address, c.address, user.username); user.account = account; diff --git a/routes/users.js b/routes/users.js index 25a737ce..558d476d 100644 --- a/routes/users.js +++ b/routes/users.js @@ -438,7 +438,9 @@ app.get( type = "p2sh"; // async request to node to bump its internal index but don't use result - lq.getNewAddress().catch((e) => l.warn("Problem bumping liquid address index", e.message)) + lq.getNewAddress().catch(e => + l.warn("Problem bumping liquid address index", e.message) + ); i = parseInt(app.get("lqAddressIndex")); -- cgit v1.2.3 From 7f427d1c9e229bfd70e913db451a873ce561b8db Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Aug 2021 14:58:01 -0700 Subject: fix zmq 6 syntax --- routes/bitcoin/receive.js | 6 +- routes/liquid/receive.js | 383 +++++++++++++++++++++++----------------------- routes/users.js | 2 +- 3 files changed, 199 insertions(+), 192 deletions(-) (limited to 'routes/users.js') diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index 572987cc..2e8114dd 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -7,7 +7,7 @@ const bitcoin = require("bitcoinjs-lib"); const zmqRawBlock = new zmq.Subscriber(); zmqRawBlock.connect(config.bitcoin.zmqrawblock); -zmqRawBlock.subscribe("rawtx"); +zmqRawBlock.subscribe("rawblock"); const zmqRawTx = new zmq.Subscriber(); zmqRawTx.connect(config.bitcoin.zmqrawtx); @@ -18,7 +18,7 @@ const network = config.bitcoin.network === "mainnet" ? "bitcoin" : config.bitcoin.network ]; -let queue = {}; +const queue = {}; (async () => { for await (const [topic, message] of zmqRawTx) { @@ -127,7 +127,9 @@ let queue = {}; }) ); } +})(); +(async () => { for await (const [topic, message] of zmqRawBlock) { const payments = await db.Payment.findAll({ where: { confirmed: false }, diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 2c88075c..a30ff985 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -1,6 +1,6 @@ const axios = require("axios"); const reverse = require("buffer-reverse"); -const zmq = require("zeromq/v5-compat"); +const zmq = require("zeromq"); const { Op } = require("sequelize"); const { fromBase58 } = require("bip32"); const bitcoin = require("bitcoinjs-lib"); @@ -15,7 +15,7 @@ const getAccount = async (params, transaction) => { let account = await db.Account.findOne({ where: params, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if (account) { @@ -37,12 +37,12 @@ const getAccount = async (params, transaction) => { const existing = await db.Account.findOne({ where: { asset, - pubkey + pubkey, }, order: [["id", "ASC"]], limit: 1, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); if (existing) { @@ -57,228 +57,233 @@ const getAccount = async (params, transaction) => { return db.Account.create(params, { transaction }); }; -const zmqRawBlock = zmq.socket("sub"); +const zmqRawBlock = new zmq.Subscriber(); zmqRawBlock.connect(config.liquid.zmqrawblock); zmqRawBlock.subscribe("rawblock"); -const zmqRawTx = zmq.socket("sub"); +const zmqRawTx = new zmq.Subscriber(); zmqRawTx.connect(config.liquid.zmqrawtx); zmqRawTx.subscribe("rawtx"); -zmqRawTx.on("message", async (topic, message, sequence) => { - const hex = message.toString("hex"); +const queue = {}; - let unblinded, tx, blinded; - try { - unblinded = await lq.unblindRawTransaction(hex); - tx = await lq.decodeRawTransaction(unblinded.hex); - blinded = await lq.decodeRawTransaction(hex); - } catch (e) { - return console.log(e); - } +(async () => { + for await (const [topic, message] of zmqRawTx) { + const hex = message.toString("hex"); - if (payments.includes(blinded.txid)) return; - - Promise.all( - tx.vout.map(async o => { - try { - if (!(o.scriptPubKey && o.scriptPubKey.addresses)) return; - - const { asset } = o; - const value = toSats(o.value); - const address = o.scriptPubKey.addresses[0]; - - if ( - Object.keys(addresses).includes(address) && - !change.includes(address) - ) { - await db.transaction(async transaction => { - let user = await getUser(addresses[address], transaction); - - let invoice = await db.Invoice.findOne({ - where: { - unconfidential: address, - user_id: user.id, - network: "liquid" - }, - order: [["id", "DESC"]] - }); + let unblinded, tx, blinded; + try { + unblinded = await lq.unblindRawTransaction(hex); + tx = await lq.decodeRawTransaction(unblinded.hex); + blinded = await lq.decodeRawTransaction(hex); + } catch (e) { + return console.log(e); + } - if (!invoice) return; + if (payments.includes(blinded.txid)) return; - let confirmed = 0; + Promise.all( + tx.vout.map(async (o) => { + try { + if (!(o.scriptPubKey && o.scriptPubKey.addresses)) return; - let account = await db.Account.findOne({ - where: { - id: invoice.account_id - }, - lock: transaction.LOCK.UPDATE, - transaction - }); + const { asset } = o; + const value = toSats(o.value); + const address = o.scriptPubKey.addresses[0]; - if ( - account.asset === asset && - (!account.pubkey || account.network === "liquid") - ) { - await account.increment({ pending: value }, { transaction }); - await account.reload({ transaction }); - } else { - account = await getAccount( - { - seed: account.seed, - path: account.path, + if ( + Object.keys(addresses).includes(address) && + !change.includes(address) + ) { + await db.transaction(async (transaction) => { + let user = await getUser(addresses[address], transaction); + + let invoice = await db.Invoice.findOne({ + where: { + unconfidential: address, user_id: user.id, - asset, - pubkey: account.pubkey, - pending: value, - index: 0 + network: "liquid", }, - transaction - ); - } + order: [["id", "DESC"]], + }); - if (config.liquid.walletpass) - await lq.walletPassphrase(config.liquid.walletpass, 300); - - await user.save({ transaction }); - - const currency = invoice ? invoice.currency : user.currency; - const rate = invoice - ? invoice.rate - : app.get("rates")[user.currency]; - const tip = invoice ? invoice.tip : 0; - const memo = invoice ? invoice.memo : ""; - - let payment = await db.Payment.create( - { - account_id: account.id, - user_id: user.id, - hash: blinded.txid, - amount: value - tip, - currency, - memo, - rate, - received: true, - tip, - confirmed, - address, - network: "liquid", - invoice_id: invoice.id - }, - { transaction } - ); + if (!invoice) return; - payments.push(blinded.txid); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); - - emit(user.username, "payment", payment); - emit(user.username, "account", payment.account); - l.info("liquid detected", address, user.username, asset, value); - notify(user, `${value} SAT payment detected`); - callWebhook(invoice, payment); - }); - } - } catch (e) { - l.error("Problem processing transaction", e.message, e.stack); - } - }) - ); -}); + let confirmed = 0; -let queue = {}; - -zmqRawBlock.on("message", async (topic, message, sequence) => { - try { - const payments = await db.Payment.findAll({ - where: { confirmed: 0 } - }); - - const block = Block.fromHex(message.toString("hex"), true); - - let hash, json; + let account = await db.Account.findOne({ + where: { + id: invoice.account_id, + }, + lock: transaction.LOCK.UPDATE, + transaction, + }); + + if ( + account.asset === asset && + (!account.pubkey || account.network === "liquid") + ) { + await account.increment({ pending: value }, { transaction }); + await account.reload({ transaction }); + } else { + account = await getAccount( + { + seed: account.seed, + path: account.path, + user_id: user.id, + asset, + pubkey: account.pubkey, + pending: value, + index: 0, + }, + transaction + ); + } + + if (config.liquid.walletpass) + await lq.walletPassphrase(config.liquid.walletpass, 300); + + await user.save({ transaction }); + + const currency = invoice ? invoice.currency : user.currency; + const rate = invoice + ? invoice.rate + : app.get("rates")[user.currency]; + const tip = invoice ? invoice.tip : 0; + const memo = invoice ? invoice.memo : ""; + + let payment = await db.Payment.create( + { + account_id: account.id, + user_id: user.id, + hash: blinded.txid, + amount: value - tip, + currency, + memo, + rate, + received: true, + tip, + confirmed, + address, + network: "liquid", + invoice_id: invoice.id, + }, + { transaction } + ); - hash = await lq.getBlockHash(block.height); - json = await lq.getBlock(hash, 2); + payments.push(blinded.txid); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); - json.tx.map(async tx => { - if (issuances[tx.txid]) { - await db.transaction(async transaction => { - const { - user_id, - asset, - asset_amount, - asset_payment_id, - token, - token_amount, - token_payment_id - } = issuances[tx.txid]; + emit(user.username, "payment", payment); + emit(user.username, "account", payment.account); + l.info("liquid detected", address, user.username, asset, value); + notify(user, `${value} SAT payment detected`); + callWebhook(invoice, payment); + }); + } + } catch (e) { + l.error("Problem processing transaction", e.message, e.stack); + } + }) + ); + } +})(); + +(async () => { + for await (const [topic, message] of zmqRawBlock) { + console.log(message); + try { + const payments = await db.Payment.findAll({ + where: { confirmed: 0 }, + }); - const user = await getUserById(user_id); + const block = Block.fromHex(message.toString("hex"), true); - let account = await db.Account.findOne({ - where: { user_id, asset }, - lock: transaction.LOCK.UPDATE, - transaction - }); - account.balance = asset_amount * SATS; - account.pending = 0; - await account.save({ transaction }); + let hash, json; - let payment = await db.Payment.findOne({ - where: { id: asset_payment_id }, - include: { - model: db.Account, - as: "account" - }, - lock: transaction.LOCK.UPDATE, - transaction - }); + hash = await lq.getBlockHash(block.height); + json = await lq.getBlock(hash, 2); - payment.confirmed = true; - await payment.save({ transaction }); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); + json.tx.map(async (tx) => { + if (issuances[tx.txid]) { + await db.transaction(async (transaction) => { + const { + user_id, + asset, + asset_amount, + asset_payment_id, + token, + token_amount, + token_payment_id, + } = issuances[tx.txid]; - emit(user.username, "account", account); - emit(user.username, "payment", payment); + const user = await getUserById(user_id); - if (token) { - account = await db.Account.findOne({ - where: { user_id, asset: token }, + let account = await db.Account.findOne({ + where: { user_id, asset }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); - account.balance = token_amount * SATS; + account.balance = asset_amount * SATS; account.pending = 0; await account.save({ transaction }); - payment = await db.Payment.findOne({ - where: { id: token_payment_id }, + let payment = await db.Payment.findOne({ + where: { id: asset_payment_id }, include: { model: db.Account, - as: "account" + as: "account", }, lock: transaction.LOCK.UPDATE, - transaction + transaction, }); payment.confirmed = true; await payment.save({ transaction }); - payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); emit(user.username, "account", account); emit(user.username, "payment", payment); - } - }); - } else if (payments.find(p => p.hash === tx.txid)) queue[tx.txid] = 1; - }); - } catch (e) { - return console.log(e); + + if (token) { + account = await db.Account.findOne({ + where: { user_id, asset: token }, + lock: transaction.LOCK.UPDATE, + transaction, + }); + account.balance = token_amount * SATS; + account.pending = 0; + await account.save({ transaction }); + + payment = await db.Payment.findOne({ + where: { id: token_payment_id }, + include: { + model: db.Account, + as: "account", + }, + lock: transaction.LOCK.UPDATE, + transaction, + }); + + payment.confirmed = true; + await payment.save({ transaction }); + + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + + emit(user.username, "account", account); + emit(user.username, "payment", payment); + } + }); + } else if (payments.find((p) => p.hash === tx.txid)) queue[tx.txid] = 1; + }); + } catch (e) { + return console.log(e); + } } -}); +})(); setInterval(async () => { try { @@ -288,25 +293,25 @@ setInterval(async () => { const hash = arr[i]; let account, address, user, total, p; - await db.transaction(async transaction => { + await db.transaction(async (transaction) => { p = await db.Payment.findOne({ where: { hash, confirmed: 0, received: 1 }, include: [ { model: db.Account, - as: "account" + as: "account", }, { model: db.Invoice, - as: "invoice" + as: "invoice", }, { model: db.User, - as: "user" - } + as: "user", + }, ], lock: transaction.LOCK.UPDATE, - transaction + transaction, }); ({ account, address, user } = p); @@ -362,7 +367,7 @@ setInterval(async () => { address: c.address, amount: total - 100, user, - limit: total + limit: total, }); } } diff --git a/routes/users.js b/routes/users.js index 23f016c7..24138fb6 100644 --- a/routes/users.js +++ b/routes/users.js @@ -5,7 +5,7 @@ const authenticator = require("otplib").authenticator; const getAccount = require("../lib/account"); const Sequelize = require("sequelize"); const bitcoin = require("bitcoinjs-lib"); -const liquid = require("@asoltys/liquidjs-lib"); +// const liquid = require("@asoltys/liquidjs-lib"); const { fromBase58, fromPrivateKey } = require("bip32"); const { Mutex } = require("async-mutex"); const bip32 = require("bip32"); -- cgit v1.2.3 From 3eebf4fa82fdbd2026eeaa1d6615366f24d498f3 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Aug 2021 20:18:33 -0700 Subject: remove comments --- lib/persist.js | 2 -- routes/users.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'routes/users.js') diff --git a/lib/persist.js b/lib/persist.js index 54e7e209..a2febf68 100644 --- a/lib/persist.js +++ b/lib/persist.js @@ -7,8 +7,6 @@ module.exports = (path, initial = {}) => { } catch(e) {} } - // console.log("initial", path, initial); - return new Proxy(initial, { set(obj, prop, value) { fs.writeFileSync( diff --git a/routes/users.js b/routes/users.js index 24138fb6..23f016c7 100644 --- a/routes/users.js +++ b/routes/users.js @@ -5,7 +5,7 @@ const authenticator = require("otplib").authenticator; const getAccount = require("../lib/account"); const Sequelize = require("sequelize"); const bitcoin = require("bitcoinjs-lib"); -// const liquid = require("@asoltys/liquidjs-lib"); +const liquid = require("@asoltys/liquidjs-lib"); const { fromBase58, fromPrivateKey } = require("bip32"); const { Mutex } = require("async-mutex"); const bip32 = require("bip32"); -- cgit v1.2.3