aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2020-09-12 15:47:00 -0700
committerAdam Soltys <[email protected]>2020-09-12 15:47:00 -0700
commit3ae6e9e46956416164c4540881a3acb81aa0c672 (patch)
treef28870ff7c787a3d54527909da8893380c6d66a9
parentd712bf317f17e75f335c5c9a4a172f50c0ed4449 (diff)
downloadcoinos-server-3ae6e9e46956416164c4540881a3acb81aa0c672.tar.gz
coinos-server-3ae6e9e46956416164c4540881a3acb81aa0c672.zip
support rbf
-rw-r--r--lib/buildliquidtx.js56
-rw-r--r--lib/buildtx.js4
-rw-r--r--routes/assets.js4
-rw-r--r--routes/bitcoin/broadcast.js2
-rw-r--r--routes/bitcoin/fee.js7
-rw-r--r--routes/bitcoin/receive.js5
-rw-r--r--routes/bitcoin/send.js2
-rw-r--r--routes/liquid/fee.js29
-rw-r--r--routes/lnurl.js4
-rw-r--r--routes/send.js2
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: {