aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZoltan <[email protected]>2021-09-22 18:59:06 +0300
committerZoltan <[email protected]>2021-09-22 18:59:06 +0300
commited3482fc15d3d8f8e8b3bceff7d473fd29601280 (patch)
tree0fc50475d353ddeddbb2ddbfe780abb4091c9b84
parent3e61c801fc3ca9644304c88f86adf5aa297aeef4 (diff)
downloadcoinos-server-ed3482fc15d3d8f8e8b3bceff7d473fd29601280.tar.gz
coinos-server-ed3482fc15d3d8f8e8b3bceff7d473fd29601280.zip
feat: added withdraw endpoint for bitcoin
-rw-r--r--lib/feetx.js19
-rw-r--r--routes/bitcoin/send.js61
-rw-r--r--routes/bitcoin/util/addPayment.js26
-rw-r--r--routes/bitcoin/util/decrementacc.js33
-rw-r--r--routes/bitcoin/withdraw.js21
-rw-r--r--routes/payments.js1
6 files changed, 106 insertions, 55 deletions
diff --git a/lib/feetx.js b/lib/feetx.js
new file mode 100644
index 00000000..26ade9da
--- /dev/null
+++ b/lib/feetx.js
@@ -0,0 +1,19 @@
+module.exports = async (txid) => {
+ const tx = await bc.getRawTransaction(txid);
+ const transaction = await bc.decodeRawTransaction(tx);
+ let valueIn = 0;
+ let valueOut = 0;
+
+ const txVin = await Promise.all(
+ transaction.vin.map(async o =>
+ await bc.decodeRawTransaction(
+ await bc.getRawTransaction(o.txid)
+ )
+ )
+ );
+
+ txVin.forEach(o => o.vout.forEach(o => valueIn += o.value));
+ transaction.vout.forEach(o => valueOut += o.value);
+
+ return toSats(valueIn - valueOut);
+}
diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js
index 470889b3..e0756662 100644
--- a/routes/bitcoin/send.js
+++ b/routes/bitcoin/send.js
@@ -1,4 +1,5 @@
-const btc = config.liquid.btcasset;
+const decrementAccount = require('./util/decrementacc');
+const addPayment = require('./util/addPayment');
module.exports = ah(async (req, res) => {
let { user } = req;
@@ -31,67 +32,17 @@ module.exports = ah(async (req, res) => {
total = total - change + fee;
let amount = total - fee;
- let account, params;
+ let account;
try {
- await db.transaction(async transaction => {
- account = await db.Account.findOne({
- where: {
- id: user.account_id
- },
- lock: transaction.LOCK.UPDATE,
- transaction
- });
-
- if (account.asset !== btc) {
- account = await db.Account.findOne({
- where: {
- user_id: user.id,
- asset: btc,
- pubkey: null
- },
- lock: transaction.LOCK.UPDATE,
- transaction
- });
- }
-
- if (total > account.balance) {
- l.error("amount exceeds balance", amount, fee, account.balance);
- throw new Error("Insufficient funds");
- }
-
- 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"
- };
+ account = await decrementAccount(user, amount);
if (config.bitcoin.walletpass)
await bc.walletPassphrase(config.bitcoin.walletpass, 300);
hex = (await bc.signRawTransactionWithWallet(hex)).hex;
- params.hash = await bc.sendRawTransaction(hex);
-
- let payment = await db.Payment.create(params);
-
- payment = payment.get({ plain: true });
- payment.account = account.get({ plain: true });
-
- emit(user.username, "payment", payment);
- res.send(payment);
+ const txid = await bc.sendRawTransaction(hex);
- payments.push(params.hash);
+ res.send(await addPayment(account, user, address, amount, memo, txid, fee));
l.info("sent bitcoin", user.username, total);
} catch (e) {
l.error("error sending bitcoin", e.message);
diff --git a/routes/bitcoin/util/addPayment.js b/routes/bitcoin/util/addPayment.js
new file mode 100644
index 00000000..077fc2ae
--- /dev/null
+++ b/routes/bitcoin/util/addPayment.js
@@ -0,0 +1,26 @@
+module.exports = async (account, user, address, amount, memo, hash, fee) => {
+ const params = {
+ amount: -amount,
+ memo,
+ fee,
+ hash,
+ address,
+ account_id: account.id,
+ user_id: user.id,
+ rate: app.get("rates")[user.currency],
+ currency: user.currency,
+ confirmed: true,
+ received: false,
+ network: "bitcoin",
+ };
+
+ let payment = await db.Payment.create(params);
+
+ payment = payment.get({ plain: true });
+ payment.account = account.get({ plain: true });
+
+ emit(user.username, "payment", payment);
+
+ payments.push(params.hash);
+ return payment;
+}
diff --git a/routes/bitcoin/util/decrementacc.js b/routes/bitcoin/util/decrementacc.js
new file mode 100644
index 00000000..a495435e
--- /dev/null
+++ b/routes/bitcoin/util/decrementacc.js
@@ -0,0 +1,33 @@
+const btc = config.liquid.btcasset;
+
+module.exports = async (user, total) => await db.transaction(async transaction => {
+ let account = await db.Account.findOne({
+ where: {
+ id: user.account_id
+ },
+ lock: transaction.LOCK.UPDATE,
+ transaction
+ });
+
+ if (account.asset !== btc) {
+ account = await db.Account.findOne({
+ where: {
+ user_id: user.id,
+ asset: btc,
+ pubkey: null
+ },
+ lock: transaction.LOCK.UPDATE,
+ transaction
+ });
+ }
+
+ if (total > account.balance) {
+ l.error("amount exceeds balance", total, account.balance);
+ throw new Error("Insufficient funds");
+ }
+
+ await account.decrement({ balance: total }, { transaction });
+ await account.reload({ transaction });
+
+ return account;
+});
diff --git a/routes/bitcoin/withdraw.js b/routes/bitcoin/withdraw.js
new file mode 100644
index 00000000..bd1c6b50
--- /dev/null
+++ b/routes/bitcoin/withdraw.js
@@ -0,0 +1,21 @@
+const getFee = require('../../lib/feetx');
+const decrementAccount = require('./util/decrementacc');
+const addPayment = require('./util/addPayment');
+
+module.exports = ah(async (req, res) => {
+ let {user} = req;
+ let {address, amount, memo} = req.body;
+
+ let account;
+ try {
+ account = await decrementAccount(user, amount);
+ const txid = await bc.sendToAddress(address, amount, 'withdrawal', memo, true);
+ const fee = await getFee(txid);
+
+ res.send(await addPayment(account, user, address, toSats(amount), memo, txid, fee));
+ l.info("withdraw bitcoin", user.username, amount);
+ } catch (e) {
+ l.error("error withdrawing bitcoin", e.message);
+ return res.status(500).send(e.message);
+ }
+});
diff --git a/routes/payments.js b/routes/payments.js
index c3abe657..dc651b39 100644
--- a/routes/payments.js
+++ b/routes/payments.js
@@ -142,6 +142,7 @@ ah(async () => {
app.post("/bitcoin/sweep", auth, require("./bitcoin/sweep"));
app.post("/bitcoin/fee", auth, require("./bitcoin/fee"));
app.post("/bitcoin/send", auth, require("./bitcoin/send"));
+ app.post("/bitcoin/withdraw", auth, require("./bitcoin/withdraw"));
require("./bitcoin/receive");
setTimeout(async () => {