From 4fd3fd116e0d76e8e82a21c9667794b825280432 Mon Sep 17 00:00:00 2001 From: shrpne Date: Thu, 18 Aug 2022 00:12:34 +0300 Subject: [PATCH] fix(hub): compensate minter-hub validation of amount not considering discount --- components/HubWithdrawForm.vue | 52 +- lang/ru.js | 1 + package-lock.json | 1582 ++++++++++++++++++-------------- package.json | 22 +- 4 files changed, 970 insertions(+), 687 deletions(-) diff --git a/components/HubWithdrawForm.vue b/components/HubWithdrawForm.vue index ca4d4345..76ebd94b 100644 --- a/components/HubWithdrawForm.vue +++ b/components/HubWithdrawForm.vue @@ -2,6 +2,7 @@ import Big from '~/assets/big.js'; import {validationMixin} from 'vuelidate'; import required from 'vuelidate/lib/validators/required.js'; +import minValue from 'vuelidate/lib/validators/maxValue.js'; import maxValue from 'vuelidate/lib/validators/maxValue.js'; import minLength from 'vuelidate/lib/validators/minLength.js'; import autosize from 'v-autosize'; @@ -139,9 +140,11 @@ export default { const inverseRate = new Big(this.hubFeeRate).div(new Big(1).minus(this.hubFeeRate)); return amount.times(inverseRate).toString(); }, + /* totalFee() { return new Big(this.coinFee).plus(this.hubFee).toString(); }, + */ amountToSend() { return new Big(this.form.amount || 0).plus(this.coinFee).plus(this.hubFee).toString(); }, @@ -170,6 +173,9 @@ export default { return maxAmount.toString(); } }, + minAmount() { + return getHubMinAmount(this.coinFee, this.hubFeeRate); + }, suggestionList() { return this.hubCoinList // show only available coins for selected network @@ -224,7 +230,7 @@ export default { amount: { required, // validAmount: isValidAmount, - minValue: (value) => value > 0, + minValue: minValue(this.minAmount), maxValue: maxValue(this.maxAmount || 0), }, }, @@ -375,6 +381,48 @@ export default { }, }, }; + +/** + * // Minter Hub not consider discount in amount validation, so we need compensate amount for discount difference + * @param {number|string} destinationNetworkFee + * @param {number|string} hubFeeRate + * @param {number|string} hubFeeBaseRate - hub fee rate without discount (0.01) + * @return {number|string} + */ +function getHubMinAmount(destinationNetworkFee, hubFeeRate, hubFeeBaseRate = 0.01) { + // minAmount = hubFeeBase - hubFee + // But while form.amount increase hubFee increase too, so we need to find such formAmount which will be equal minAmount, it will be maximum minAmount + + // Some 7 grade math below + // hubFeeBase = (destinationNetworkFee + formAmount) * (0.01 / (1 - 0.01)); + // hubFee = (destinationNetworkFee + formAmount) * (hubFeeRate / (1 - hubFeeRate)) + // define (a = hubFeeBaseRate; b = hubFeeRate) + // minAmount = (destinationNetworkFee + formAmount) * (a / (1 - a)) - (destinationNetworkFee + formAmount) * (b / (1 - b)) + // minAmount = (destinationNetworkFee + formAmount) * ((a / (1 - a) - (b / (1 - b)); + // minAmount = (destinationNetworkFee + formAmount) * x; + + // Let's calculate factor x + // x = a / (1 - a) - b / (1 - b) + // x = a * (1-b) / ((1-a)*(1-b)) - b * (1-a) / ((1-a)*(1-b)) + // x = (a * (1-b) - b * (1-a)) / ((1-a)*(1-b)) + // x = (a - ab - b + ab) / ((1-a)*(1-b)) + // x = (a - b) / ((1-a)*(1-b)) + // const factor = (hubFeeBaseRate - hubFeeRate) / ((1 - hubFeeBaseRate) * (1 - hubFeeRate)); + const factor = new Big(hubFeeBaseRate).minus(hubFeeRate).div(new Big(1).minus(hubFeeBaseRate).times(new Big(1).minus(hubFeeRate))).toString(); + + // We are finding formAmount equal to minAmount (fa = formAmount, dnf = destinationNetworkFee) + // fa = minAmount + // fa = (fa + dnf) * x + // fa = fa * x + dnf * x + // fa - fa * x = dnf * x + // fa * 1 - fa * x = dnf * x + // fa * (1 -x) = dnf * x + // fa = dnf * x / (1 - x) + // const minAmount = destinationNetworkFee * factor / (1 - factor); + const minAmount = new Big(destinationNetworkFee).times(factor).div(new Big(1).minus(factor)).toString(); + // add 1 pip because 0 will not pass validation too + return new Big(minAmount).plus(1e-18).toString(); +}