From e343c8b07794a86156601efebe58b443b15b10da Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 17 Jun 2021 17:05:09 -0400 Subject: add fee to total --- routes/liquid/send.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'routes') diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 19b7344f..6455736c 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -75,12 +75,12 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { await faucet.reload({ transaction }); await faucet.save({ transaction }); } - - total += fee - covered; } + + total += fee - covered; } - if (limit && total > limit) + if (limit && total > limit + fee) throw new Error("Tx amount exceeds authorized amount"); if (asset !== btc || total) { -- cgit v1.2.3 From de06cbf6141679b2e10ca01bee1e372efc356c91 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 24 Jun 2021 02:52:33 -0400 Subject: only send on-chain after db transaction --- routes/bitcoin/send.js | 55 +++++++++++++++++++++++++------------------------- routes/liquid/fee.js | 7 +------ routes/liquid/send.js | 28 ++++++++++++++----------- routes/payments.js | 12 +++++++---- 4 files changed, 52 insertions(+), 50 deletions(-) (limited to 'routes') diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index cab79e06..470889b3 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -1,4 +1,3 @@ -const bitcoin = require("bitcoinjs-lib"); const btc = config.liquid.btcasset; module.exports = ah(async (req, res) => { @@ -32,10 +31,10 @@ module.exports = ah(async (req, res) => { total = total - change + fee; let amount = total - fee; - let params; + let account, params; try { await db.transaction(async transaction => { - let account = await db.Account.findOne({ + account = await db.Account.findOne({ where: { id: user.account_id }, @@ -62,38 +61,38 @@ module.exports = ah(async (req, res) => { await account.decrement({ balance: total }, { transaction }); await account.reload({ transaction }); + }); - params = { - amount: -amount, - fee, - memo, - account_id: account.id, - user_id: user.id, - rate: app.get("rates")[user.currency], - currency: user.currency, - address, - confirmed: true, - received: false, - network: "bitcoin" - }; + params = { + amount: -amount, + fee, + memo, + account_id: account.id, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + address, + confirmed: true, + received: false, + network: "bitcoin" + }; - if (config.bitcoin.walletpass) - await bc.walletPassphrase(config.bitcoin.walletpass, 300); + if (config.bitcoin.walletpass) + await bc.walletPassphrase(config.bitcoin.walletpass, 300); - hex = (await bc.signRawTransactionWithWallet(hex)).hex; - params.hash = await bc.sendRawTransaction(hex); + hex = (await bc.signRawTransactionWithWallet(hex)).hex; + params.hash = await bc.sendRawTransaction(hex); - let payment = await db.Payment.create(params, { transaction }); + let payment = await db.Payment.create(params); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); - emit(user.username, "payment", payment); - res.send(payment); + emit(user.username, "payment", payment); + res.send(payment); - payments.push(params.hash); - l.info("sent bitcoin", user.username, total); - }); + payments.push(params.hash); + l.info("sent bitcoin", user.username, total); } catch (e) { l.error("error sending bitcoin", e.message); return res.status(500).send(e.message); diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index 2070873a..a6c29f41 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -3,11 +3,6 @@ const buildTx = require("../../lib/buildliquidtx"); liquidTx = async ({ address, asset, amount, feeRate, replaceable, user }) => { let tx, fee; let node = lq; - /* - if (asset === config.liquid.btcasset) { - node = rare; - } - */ if (user.account.pubkey) { let psbt = await buildTx({ @@ -81,7 +76,7 @@ module.exports = ah(async (req, res) => { let tx = await liquidTx({ ...req.body, user: req.user }) res.send(tx); } catch (e) { - l.error("error estimating liquid fee", e.message, e.stack); + l.error("error estimating liquid fee", e.message); return res.status(500).send(e.message); } }); diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 6455736c..13f77d26 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -1,5 +1,6 @@ const btc = config.liquid.btcasset; const lcad = config.liquid.cadasset; +const { Transaction } = require("liquidjs-lib"); sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { if (amount > 10000000) throw new Error("Amount too large"); @@ -48,7 +49,8 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { const assets = Object.keys(totals); const payments = []; - return db.transaction(async transaction => { + let main, signed; + await db.transaction(async transaction => { for (let i = 0; i < assets.length; i++) { let asset = assets[i]; let amount = totals[asset]; @@ -132,16 +134,11 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { } } - if (config.liquid.walletpass) - await lq.walletPassphrase(config.liquid.walletpass, 300); + signed = await lq.signRawTransactionWithWallet( + await lq.blindRawTransaction(tx.hex) + ); + let txid = Transaction.fromHex(signed.hex).getId(); - let blinded = await lq.blindRawTransaction(tx.hex); - let signed = await lq.signRawTransactionWithWallet(blinded); - let txid = await lq.sendRawTransaction(signed.hex); - - l.info("sent liquid tx", txid, address); - - let main; for (let i = 0; i < assets.length; i++) { p = payments[i]; if (p) { @@ -157,15 +154,22 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { emit(user.username, "account", main.account); emit(user.username, "payment", main); - return main; }); + + if (config.liquid.walletpass) + await lq.walletPassphrase(config.liquid.walletpass, 300); + + let txid = await lq.sendRawTransaction(signed.hex); + l.info("sent liquid tx", txid, address); + + return main; }; module.exports = ah(async (req, res) => { let { user } = req; try { - res.send(await sendLiquid({...req.body, user })); + res.send(await sendLiquid({ ...req.body, user })); } catch (e) { l.error("problem sending liquid", user.username, e.message); return res.status(500).send(e); diff --git a/routes/payments.js b/routes/payments.js index e8e94d8a..86c0dd15 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -138,10 +138,14 @@ ah(async () => { require("./liquid/receive"); setTimeout(async () => { - const address = await lq.getNewAddress(); - const { hdkeypath } = await lq.getAddressInfo(address); - const parts = hdkeypath.split("/"); - app.set("lqAddressIndex", parts[parts.length - 1].slice(0, -1)); + try { + const address = await lq.getNewAddress(); + const { hdkeypath } = await lq.getAddressInfo(address); + const parts = hdkeypath.split("/"); + app.set("lqAddressIndex", parts[parts.length - 1].slice(0, -1)); + } catch(e) { + console.log("Problem getting liquid address", e.message); + } }, 50); } -- cgit v1.2.3 From 3ff26389ca9854d7d34ed28d3f034b2d32938872 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 24 Jun 2021 06:32:21 -0400 Subject: invoice amount validation --- routes/invoices.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'routes') diff --git a/routes/invoices.js b/routes/invoices.js index cc8549e1..93528d60 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -27,6 +27,10 @@ app.post( let { liquidAddress, invoice, user, tx } = req.body; let { blindkey } = invoice; + if (invoice.amount < 0) throw new Error("amount out of range"); + if (invoice.tip > invoice.amount || invoice.tip > 1000000 || invoice.tip < 0) + throw new Error("tip amount out of range"); + if (liquidAddress) { l.info("conversion request for", liquidAddress, invoice.text); convert[invoice.text] = { address: liquidAddress, tx }; @@ -43,7 +47,7 @@ app.post( if (!user) throw new Error("user not provided"); if (!invoice.currency) invoice.currency = user.currency; if (!invoice.rate) invoice.rate = app.get("rates")[invoice.currency]; - if (invoice.tip > invoice.amount || invoice.tip > 1000000) throw new Error("tip is too large") + invoice.user_id = user.id; invoice.account_id = user.account_id; @@ -54,7 +58,7 @@ app.post( invoice.amount, invoice.tip, invoice.currency, - `${invoice.text.substr(0, 8)}..${invoice.text.substr(-6)}`, + `${invoice.text.substr(0, 8)}..${invoice.text.substr(-6)}` ); if (!invoice.tip) invoice.tip = 0; -- cgit v1.2.3 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/payments.js | 2 +- routes/users.js | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'routes') diff --git a/routes/payments.js b/routes/payments.js index 86c0dd15..fe8092a9 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -144,7 +144,7 @@ ah(async () => { const parts = hdkeypath.split("/"); app.set("lqAddressIndex", parts[parts.length - 1].slice(0, -1)); } catch(e) { - console.log("Problem getting liquid address", e.message); + l.warn("Problem getting liquid address index", e.message); } }, 50); } 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 556b133ffbd4591b49626c821d7602e09e97a1f2 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 8 Jul 2021 15:15:14 -0400 Subject: throw instead of returning to abort db transaction --- routes/send.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'routes') diff --git a/routes/send.js b/routes/send.js index 579e70b4..3aec9fb6 100644 --- a/routes/send.js +++ b/routes/send.js @@ -45,7 +45,7 @@ module.exports = ah(async (req, res, next) => { }; if (!username) { - return res.status(500).send("Vouchers temporarily disabled"); + throw new Error("Vouchers temporarily disabled"); l.info("creating redeemable payment"); params.redeemcode = uuidv4(); params.hash = `${req.get("origin")}/redeem/${params.redeemcode}`; -- 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') 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 1fbae57bb9540b1c116efc367809ac01ae2e9df2 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 3 Aug 2021 04:47:20 -0400 Subject: move lightning invoice fetch out of db transaction --- routes/lightning/receive.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'routes') diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index 55193d2d..492320d3 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -1,20 +1,18 @@ const handlePayment = async msg => { + if (!msg.settled) return; let account, total, user; - try { - await db.transaction(async transaction => { - if (!msg.settled) return; - const invoice = await db.Invoice.findOne({ - where: { - text: msg.payment_request - } - }); + const invoice = await db.Invoice.findOne({ + where: { + text: msg.payment_request + } + }); - if (!invoice) - return l.warn( - "received lightning with no invoice", - msg.payment_request - ); + if (!invoice) + return l.warn("received lightning with no invoice", msg.payment_request); + + try { + await db.transaction(async transaction => { const { text: hash, currency, memo, rate, tip, user_id } = invoice; const amount = parseInt(msg.amt_paid_sat) - tip; @@ -83,7 +81,12 @@ const handlePayment = async msg => { let c = convert[msg.payment_request]; if (msg.payment_request && c) { - l.info("lightning detected for conversion request", msg.payment_request, c.address, user.username); + l.info( + "lightning detected for conversion request", + msg.payment_request, + c.address, + user.username + ); user.account = account; -- cgit v1.2.3