diff options
| author | Zoltan <[email protected]> | 2021-09-22 18:59:06 +0300 |
|---|---|---|
| committer | Zoltan <[email protected]> | 2021-09-22 18:59:06 +0300 |
| commit | ed3482fc15d3d8f8e8b3bceff7d473fd29601280 (patch) | |
| tree | 0fc50475d353ddeddbb2ddbfe780abb4091c9b84 | |
| parent | 3e61c801fc3ca9644304c88f86adf5aa297aeef4 (diff) | |
| download | coinos-server-ed3482fc15d3d8f8e8b3bceff7d473fd29601280.tar.gz coinos-server-ed3482fc15d3d8f8e8b3bceff7d473fd29601280.zip | |
feat: added withdraw endpoint for bitcoin
| -rw-r--r-- | lib/feetx.js | 19 | ||||
| -rw-r--r-- | routes/bitcoin/send.js | 61 | ||||
| -rw-r--r-- | routes/bitcoin/util/addPayment.js | 26 | ||||
| -rw-r--r-- | routes/bitcoin/util/decrementacc.js | 33 | ||||
| -rw-r--r-- | routes/bitcoin/withdraw.js | 21 | ||||
| -rw-r--r-- | routes/payments.js | 1 |
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 () => { |
