diff options
| author | Adrien Hopkins <[email protected]> | 2022-05-31 15:51:30 -0500 |
|---|---|---|
| committer | Adrien Hopkins <[email protected]> | 2022-05-31 15:51:30 -0500 |
| commit | bea6dda302df971dbf9b4797c95f169cce6dafb3 (patch) | |
| tree | dc806d941945f7ee5f3cee730393fdd175da55e3 /routes | |
| parent | ca7224037fb01ded28b51d765e040d5cad36183b (diff) | |
| parent | 510a3bf2f63cb6edbcc9ad24dacdf6faefd80c52 (diff) | |
| download | coinos-server-bea6dda302df971dbf9b4797c95f169cce6dafb3.tar.gz coinos-server-bea6dda302df971dbf9b4797c95f169cce6dafb3.zip | |
Merge branch 'feature-withdrawal-fee'
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/bitcoin/send.js | 101 | ||||
| -rw-r--r-- | routes/liquid/send.js | 2 |
2 files changed, 75 insertions, 28 deletions
diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index 9d64bb59..cf7e89ef 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -1,4 +1,6 @@ const btc = config.liquid.btcasset; +const withdrawalFeeMultiplier = 0.01; // 1% withdrawal fee +const withdrawalFeeReceiver = "coinosfees"; // account that receives the fees module.exports = ah(async (req, res) => { let { user } = req; @@ -29,10 +31,15 @@ module.exports = ah(async (req, res) => { total = total - change + fee; let amount = total - fee; - let account, params; + // get withdrawal fee + // 'total' refers to the total before the withdrawal fee + // (i.e. the total bitcoin that leaves this server) + let withdrawalFee = amount * withdrawalFeeMultiplier; + try { + // withdraw bitcoin await db.transaction(async transaction => { - account = await db.Account.findOne({ + let account = await db.Account.findOne({ where: { id: user.account_id }, @@ -55,45 +62,83 @@ module.exports = ah(async (req, res) => { if (total > account.balance) { l.error("amount exceeds balance", amount, fee, account.balance); throw new Error("low balance"); + } else if (total + withdrawalFee > account.balance) { + l.error("total (after withdrawal fee) exceeds balance", amount, fee, account.balance); + throw new Error("low balance (after withdrawal fee)"); } - await account.decrement({ balance: total }, { transaction }); + await account.decrement({ balance: (total + withdrawalFee) }, { 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" - }; + let receiverAccount = await db.Account.findOne({ + where: { + "$user.username$": withdrawalFeeReceiver + }, + include: [ + { + model: db.User, + as: "user" + }, + ], + lock: transaction.LOCK.UPDATE, + transaction + }); + + await receiverAccount.increment({ balance: withdrawalFee }, { transaction }); + await receiverAccount.reload({ transaction }); + let fee_payment = await db.Payment.create({ + amount: withdrawalFee, + fee: 0, + memo: "Bitcoin withdrawal fee", + account_id: receiverAccount.id, + user_id: receiverAccount.user_id, + rate: app.get("rates")[receiverAccount.user.currency], + currency: receiverAccount.user.currency, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + // record the external bitcoin transaction + // no need to record the withdrawal fee - since that is internal only + let 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", + fee_payment_id: fee_payment.id + }; - 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); + let payment = await db.Payment.create(params, { transaction }); - 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) { if (e.message.includes("Insufficient")) e.message = "The coinos server hot wallet has insufficient funds to complete the payment, try again later"; l.error("error sending bitcoin", e.message); + console.log(e); return res.status(500).send(e.message); } }); diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 59334103..6f3616e8 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -1,6 +1,8 @@ const btc = config.liquid.btcasset; const lcad = config.liquid.cadasset; const { Transaction } = require("liquidjs-lib"); +const withdrawalFeeMultiplier = 0.01; // 1% withdrawal fee +const withdrawalFeeReceiver = "coinosfees"; // 1% withdrawal fee sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { try { |
