From 3a85decd016e1f654fef05f331d5e43abba4589d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 28 Jun 2022 15:23:48 -0700 Subject: deduct conversion fee from lightning payments --- lib/send.js | 78 +++++++++++++++++++++++++++++++++++++++++++++----- routes/bitcoin/send.js | 4 ++- routes/liquid/send.js | 4 ++- 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/lib/send.js b/lib/send.js index 1f7e6369..247ad9f5 100644 --- a/lib/send.js +++ b/lib/send.js @@ -1,6 +1,11 @@ const bolt11 = require("bolt11"); const { Op } = require("sequelize"); +let { + computeConversionFee, + conversionFeeReceiver +} = require("../routes/lightning/conversionFee.js"); + send = async (amount, memo, hash, user) => { l.info("attempting lightning payment", user.username, amount, hash); @@ -11,7 +16,9 @@ send = async (amount, memo, hash, user) => { routingInfo.data.find(d => d.fee_proportional_millionths > 10000) ) { l.warn("fee rate too high", d.fee_proportional_millionths); - throw new Error("Couldn't find a suitable route to pay to your destination"); + throw new Error( + "Couldn't find a suitable route to pay to your destination" + ); } if (!amount || payreq.satoshis > amount) amount = payreq.satoshis; @@ -23,6 +30,8 @@ send = async (amount, memo, hash, user) => { let error, fee, total, preimage, payment; + let conversionFee = computeConversionFee(amount); + let conversionFeeDeduction; await db.transaction(async transaction => { l.info("starting lightning send transaction"); let account; @@ -30,7 +39,7 @@ send = async (amount, memo, hash, user) => { account = await db.Account.findOne({ where: { id: user.account.id, - pubkey: null, + pubkey: null }, lock: transaction.LOCK.UPDATE, transaction @@ -49,11 +58,19 @@ send = async (amount, memo, hash, user) => { transaction }); - if (!account || account.balance < amount) { + conversionFeeDeduction = Math.min( + account.lightning_credits, + conversionFee + ); + + if (!account || account.balance < amount + conversionFee) { throw new Error("Insufficient funds"); } - await account.decrement({ balance: amount }, { transaction }); + await account.decrement( + { balance: amount, lightning_credits: conversionFeeDeduction }, + { transaction } + ); await account.reload({ transaction }); l.info("debited account", account.id); @@ -102,7 +119,7 @@ send = async (amount, memo, hash, user) => { account = await db.Account.findOne({ where: { id: user.account.id, - pubkey: null, + pubkey: null }, lock: transaction.LOCK.UPDATE, transaction @@ -114,7 +131,7 @@ send = async (amount, memo, hash, user) => { asset: config.liquid.btcasset, pubkey: null, balance: { - [Op.gte]: fee + [Op.gte]: fee } }, lock: transaction.LOCK.UPDATE, @@ -127,6 +144,50 @@ send = async (amount, memo, hash, user) => { await account.decrement({ balance: fee }, { transaction }); await account.reload({ transaction }); + if (conversionFeeDeduction) { + conversionFee -= conversionFeeDeduction; + } + + let receiverAccount = await db.Account.findOne({ + where: { + "$user.username$": conversionFeeReceiver + }, + include: [ + { + model: db.User, + as: "user" + } + ], + lock: transaction.LOCK.UPDATE, + transaction + }); + + let fee_payment; + let fee_payment_id = null; + if (conversionFee) { + await receiverAccount.increment( + { balance: conversionFee }, + { transaction } + ); + await receiverAccount.reload({ transaction }); + fee_payment = await db.Payment.create( + { + amount: conversionFee, + fee: 0, + memo: "Lightning conversion 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 } + ); + fee_payment_id = fee_payment.id; + } + payment = await db.Payment.create( { amount: -(total - fee), @@ -139,15 +200,18 @@ send = async (amount, memo, hash, user) => { currency: user.currency, confirmed: true, network: "lightning", - fee + fee, + fee_payment_id }, { transaction } ); l.info("created payment record", payment.id); + payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); + payment.fee_payment = fee_payment && fee_payment.get({ plain: true }); emit(user.username, "account", payment.account); emit(user.username, "payment", payment); diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index 634b223b..0d0bf68b 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -91,11 +91,12 @@ module.exports = ah(async (req, res) => { transaction }); + let fee_payment; let fee_payment_id = null; if (conversionFee) { await receiverAccount.increment({ balance: conversionFee }, { transaction }); await receiverAccount.reload({ transaction }); - let fee_payment = await db.Payment.create({ + fee_payment = await db.Payment.create({ amount: conversionFee, fee: 0, memo: "Bitcoin conversion fee", @@ -136,6 +137,7 @@ module.exports = ah(async (req, res) => { payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); + payment.fee_payment = fee_payment && fee_payment.get({ plain: true }); emit(user.username, "payment", payment); res.send(payment); diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 254972ad..c3b37e94 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -155,11 +155,12 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { transaction }); + let fee_payment; let fee_payment_id = null; if (conversionFee) { await receiverAccount.increment({ balance: conversionFee }, { transaction }); await receiverAccount.reload({ transaction }); - let fee_payment = { + fee_payment = { amount: conversionFee, fee: 0, memo: "Liquid conversion fee", @@ -209,6 +210,7 @@ sendLiquid = async ({ asset, amount, user, address, memo, tx, limit }) => { p = await db.Payment.create(p, { transaction }); if (account.ticker !== "BTC" || !main) { main = p.get({ plain: true }); + main.fee_payment = fee_payment && fee_payment.get({ plain: true }); main.account = account.get({ plain: true }); } } -- cgit v1.2.3