diff options
| author | Adam Soltys <[email protected]> | 2020-09-12 15:47:00 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-09-12 15:47:00 -0700 |
| commit | 3ae6e9e46956416164c4540881a3acb81aa0c672 (patch) | |
| tree | f28870ff7c787a3d54527909da8893380c6d66a9 | |
| parent | d712bf317f17e75f335c5c9a4a172f50c0ed4449 (diff) | |
| download | coinos-server-3ae6e9e46956416164c4540881a3acb81aa0c672.tar.gz coinos-server-3ae6e9e46956416164c4540881a3acb81aa0c672.zip | |
support rbf
| -rw-r--r-- | lib/buildliquidtx.js | 56 | ||||
| -rw-r--r-- | lib/buildtx.js | 4 | ||||
| -rw-r--r-- | routes/assets.js | 4 | ||||
| -rw-r--r-- | routes/bitcoin/broadcast.js | 2 | ||||
| -rw-r--r-- | routes/bitcoin/fee.js | 7 | ||||
| -rw-r--r-- | routes/bitcoin/receive.js | 5 | ||||
| -rw-r--r-- | routes/bitcoin/send.js | 2 | ||||
| -rw-r--r-- | routes/liquid/fee.js | 29 | ||||
| -rw-r--r-- | routes/lnurl.js | 4 | ||||
| -rw-r--r-- | routes/send.js | 2 |
10 files changed, 69 insertions, 46 deletions
diff --git a/lib/buildliquidtx.js b/lib/buildliquidtx.js index d84bdc0b..4dd3a16c 100644 --- a/lib/buildliquidtx.js +++ b/lib/buildliquidtx.js @@ -2,11 +2,20 @@ const axios = require("axios"); const liquid = require("liquidjs-lib"); const coinselect = require("coinselect"); const split = require("coinselect/split"); -const api = prod ? "https://blockstream.info/liquid/api" : "http://localhost:3002"; +const api = prod + ? "https://blockstream.info/liquid/api" + : "http://localhost:3002"; const SATS = 100000000; const network = prod ? liquid.networks["liquid"] : liquid.networks["regtest"]; -module.exports = async ({ address, asset, amount, feeRate, user }) => { +module.exports = async ({ + address, + asset, + amount, + feeRate, + replaceable, + user +}) => { const { btcasset: btc } = config.liquid; if (!feeRate) { @@ -17,13 +26,12 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { feeRate = Math.round(feeRate / 100); if (asset !== btc) feeRate = 0; - const payments = await db.Payment.findAll({ where: { received: true, account_id: user.account_id, - network: 'liquid', - }, + network: "liquid" + } }); let utxos = []; @@ -36,18 +44,21 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { } } - let feeInput = utxos.find((utxo) => utxo.asset === btc && utxo.value > 1000); - if (!feeInput) throw new Error("Insufficient balance, couldn't find an input to cover the fee"); + let feeInput = utxos.find(utxo => utxo.asset === btc && utxo.value > 1000); + if (!feeInput) + throw new Error( + "Insufficient balance, couldn't find an input to cover the fee" + ); - utxos = utxos.filter((utxo) => utxo.asset === asset); + utxos = utxos.filter(utxo => utxo.asset === asset); let feeChange = feeInput.value - 1000; let targets = [ { address, - value: amount, - }, + value: amount + } ]; let { inputs, outputs, fee } = coinselect(utxos, targets, feeRate); @@ -56,7 +67,7 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { "utxos", amount, feeRate, - utxos.map((u) => u.value), + utxos.map(u => u.value), inputs, outputs, fee @@ -82,7 +93,7 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { psbt = psbt.addOutput({ address, asset, - value, + value }); }); @@ -91,7 +102,7 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { psbt = psbt.addInput({ hash: txid, index: vout, - nonWitnessUtxo: Buffer.from((await lq.getTransaction(txid)).hex, "hex"), + nonWitnessUtxo: Buffer.from((await lq.getTransaction(txid)).hex, "hex") }); } @@ -100,25 +111,26 @@ module.exports = async ({ address, asset, amount, feeRate, user }) => { hash: feeInput.txid, index: feeInput.vout, nonWitnessUtxo: Buffer.from( - (await lq.getTransaction(feeInput.txid).hex), + await lq.getTransaction(feeInput.txid).hex, "hex" - ), + ) }); psbt.addOutput({ changeAddress, asset: btc, - value: feeChange, + value: feeChange }); } + psbt.addOutput({ + asset: btc, + script: Buffer.alloc(0), + value: fee, + nonce: Buffer.alloc(1, 0) + }); - psbt.addOutput({ - asset: btc, - script: Buffer.alloc(0), - value: fee, - nonce: Buffer.alloc(1, 0), - }); + if (replaceable) psbt.setInputSequence(0, 0xffffffff - 2); feeRate = Math.round(feeRate * 1000); psbt = psbt.toBase64(); diff --git a/lib/buildtx.js b/lib/buildtx.js index ef24ea19..0f63f641 100644 --- a/lib/buildtx.js +++ b/lib/buildtx.js @@ -8,7 +8,7 @@ const network = prod ? bitcoin.networks["bitcoin"] : bitcoin.networks["regtest"]; -module.exports = async ({ address, amount, feeRate, user }) => { +module.exports = async ({ address, amount, feeRate, replaceable, user }) => { if (!feeRate) feeRate = (await bc.estimateSmartFee(6)).feerate * SATS; feeRate = Math.round(feeRate / 1000); @@ -69,6 +69,8 @@ module.exports = async ({ address, amount, feeRate, user }) => { }); } + if (replaceable) psbt.setInputSequence(0, 0xffffffff - 2); + feeRate = Math.round(feeRate * 1000); psbt = psbt.toBase64(); diff --git a/routes/assets.js b/routes/assets.js index 35177d6c..06ad42dc 100644 --- a/routes/assets.js +++ b/routes/assets.js @@ -147,7 +147,7 @@ app.post("/assets", auth, ah(async (req, res) => { received: true, confirmed: false, address: asset_address, - network: "LBTC", + network: "liquid", }, { transaction } ); @@ -185,7 +185,7 @@ app.post("/assets", auth, ah(async (req, res) => { received: true, confirmed: false, address: token_address, - network: "LBTC", + network: "liquid", }, { transaction } ); diff --git a/routes/bitcoin/broadcast.js b/routes/bitcoin/broadcast.js index 4324e0d9..77b487de 100644 --- a/routes/bitcoin/broadcast.js +++ b/routes/bitcoin/broadcast.js @@ -16,7 +16,7 @@ module.exports = ah(async (req, res) => { currency: user.currency, confirmed: true, received: false, - network: "BTC", + network: "bitcoin", }); account.balance += payment.amount - payment.fee; diff --git a/routes/bitcoin/fee.js b/routes/bitcoin/fee.js index 3249004c..913c3e9b 100644 --- a/routes/bitcoin/fee.js +++ b/routes/bitcoin/fee.js @@ -2,12 +2,12 @@ const buildTx = require("../../lib/buildtx"); module.exports = ah(async (req, res) => { let { user } = req; - let { address, amount, feeRate } = req.body; + let { address, amount, feeRate, replaceable } = req.body; let tx, fee; if (user.account.pubkey) { try { - let psbt = await buildTx({ address, amount, feeRate, user }); + let psbt = await buildTx({ address, amount, feeRate, replaceable, user }); return res.send(psbt); } catch(e) { return res.status(500).send(e.message); @@ -36,10 +36,11 @@ module.exports = ah(async (req, res) => { let partial = await bc.createRawTransaction([], { [address]: (amount / SATS).toFixed(8), - }); + }, 0, replaceable); let params = { subtractFeeFromOutputs: amount === user.balance ? [0] : [], + replaceable, }; if (feeRate) params.feeRate = (feeRate / SATS).toFixed(8); diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index 63a34760..12eb760e 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -51,7 +51,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { const invoice = await db.Invoice.findOne({ where: { user_id: user.id, - network: "BTC" + network: "bitcoin" }, order: [["id", "DESC"]], include: { @@ -106,12 +106,13 @@ zmqRawTx.on("message", async (topic, message, sequence) => { tip, confirmed, address, - network: "BTC" + network: "bitcoin" }); payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); emit(user.username, "account", account); + emit(user.username, "payment", payment); l.info("bitcoin detected", user.username, value); notify(user, `${value} SAT payment detected`); diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index 5d22152e..f76329f9 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -65,7 +65,7 @@ module.exports = ah(async (req, res) => { address, confirmed: true, received: false, - network: "BTC" + network: "liquid" }; }); } catch (e) { diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index 6bf52afc..d8be6de8 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -2,25 +2,32 @@ const buildTx = require("../../lib/buildliquidtx"); module.exports = ah(async (req, res) => { let { user } = req; - let { address, asset, amount, feeRate } = req.body; + let { address, asset, amount, feeRate, replaceable } = req.body; let tx, fee; if (user.account.pubkey) { try { - let psbt = await buildTx({ address, asset, amount, feeRate, user }); + let psbt = await buildTx({ + address, + asset, + amount, + feeRate, + replaceable, + user + }); return res.send(psbt); - } catch(e) { + } catch (e) { return res.status(500).send(e.message); - } + } } let invoice = await db.Invoice.findOne({ where: { address }, include: { - attributes: ['username'], + attributes: ["username"], model: db.User, - as: 'user', - } + as: "user" + } }); if (invoice) { @@ -38,7 +45,7 @@ module.exports = ah(async (req, res) => { amount = parseInt(amount); let params = { - subtractFeeFromOutputs: amount === user.balance ? [0] : [], + subtractFeeFromOutputs: amount === user.balance ? [0] : [] }; let value = (amount / SATS).toFixed(8); @@ -49,12 +56,12 @@ module.exports = ah(async (req, res) => { tx = await lq.createRawTransaction( [], { - [address]: (amount / SATS).toFixed(8), + [address]: (amount / SATS).toFixed(8) }, 0, - false, + replaceable, { - [address]: asset, + [address]: asset } ); diff --git a/routes/lnurl.js b/routes/lnurl.js index f40da684..2649ea6d 100644 --- a/routes/lnurl.js +++ b/routes/lnurl.js @@ -100,7 +100,7 @@ app.post( currency: user.currency, amount: value, tip: 0, - network: "BTC", + network: "bitcoin", }); try { @@ -273,7 +273,7 @@ lnurlServer.bindToHook( currency: recipient.currency, amount, tip: 0, - network: "BTC", + network: "bitcoin", }); l.info("invoice created", invoice.text, invoice.amount); } diff --git a/routes/send.js b/routes/send.js index 3c7af263..c87e2c1a 100644 --- a/routes/send.js +++ b/routes/send.js @@ -70,7 +70,7 @@ module.exports = ah(async (req, res, next) => { const invoice = await db.Invoice.findOne({ where: { user_id: user.id, - network: "BTC" + network: "bitcoin" }, order: [["id", "DESC"]], include: { |
