1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-26 12:29:06 +01:00

Include trade.value in calculation of displayed network fees (#9621)

* Ensure that trade.value fees are included in displayed network fees

* Remove unused getTotalEthCost function

* Remove unused getTotalEthCost function

* Update ui/app/pages/swaps/swaps.util.js

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

* Lint fix

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
Dan J Miller 2020-10-27 16:32:21 -02:30 committed by GitHub
parent a8cb6fb4f6
commit a4f817e171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 24 deletions

View File

@ -82,6 +82,9 @@
"affirmAgree": {
"message": "I Agree"
},
"aggregatorFeeCost": {
"message": "Aggregator network fee"
},
"alertDisableTooltip": {
"message": "This can be changed in \"Settings > Alerts\""
},
@ -129,6 +132,9 @@
"message": "MetaMask",
"description": "The name of the application"
},
"approvalAndAggregatorTxFeeCost": {
"message": "Approval and aggregator network fee"
},
"approvalTxGasCost": {
"message": "Approval Tx Gas Cost"
},
@ -1685,9 +1691,6 @@
"swapFinalizing": {
"message": "Finalizing..."
},
"swapGasFeeSummary": {
"message": "The gas fee covers the cost of processing your swap and storing it on the Ethereum network. MetaMask does not profit from this fee."
},
"swapGetQuotes": {
"message": "Get quotes"
},
@ -1736,6 +1739,9 @@
"message": "$1 quotes available",
"description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen"
},
"swapNetworkFeeSummary": {
"message": "The network fee covers the cost of processing your swap and storing it on the Ethereum network. MetaMask does not profit from this fee."
},
"swapNewQuoteIn": {
"message": "New quotes in $1",
"description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00"

View File

@ -31,7 +31,7 @@ import {
import { SUBMITTED_STATUS } from '../../../helpers/constants/transactions'
import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes'
import { getRenderableGasFeesForQuote } from '../swaps.util'
import { getRenderableNetworkFeesForQuote } from '../swaps.util'
import SwapsFooter from '../swaps-footer'
import SwapFailureIcon from './swap-failure-icon'
import SwapSuccessIcon from './swap-success-icon'
@ -70,8 +70,17 @@ export default function AwaitingSwap ({
let feeinFiat
if (usedQuote && tradeTxParams) {
const renderableGasFees = getRenderableGasFeesForQuote(usedQuote.gasEstimateWithRefund || usedQuote.averageGas, approveTxParams?.gas || '0x0', tradeTxParams.gasPrice, currentCurrency, conversionRate)
feeinFiat = renderableGasFees.feeinFiat?.slice(1)
const renderableNetworkFees = getRenderableNetworkFeesForQuote(
usedQuote.gasEstimateWithRefund || usedQuote.averageGas,
approveTxParams?.gas || '0x0',
tradeTxParams.gasPrice,
currentCurrency,
conversionRate,
tradeTxParams.value,
sourceTokenInfo?.symbol,
usedQuote.sourceAmount,
)
feeinFiat = renderableNetworkFees.feeinFiat?.slice(1)
}
const quotesExpiredEvent = useNewMetricEvent({

View File

@ -26,7 +26,7 @@ export default function FeeCard ({
position="top"
contentText={(
<>
<p className="fee-card__info-tooltip-paragraph">{ t('swapGasFeeSummary') }</p>
<p className="fee-card__info-tooltip-paragraph">{ t('swapNetworkFeeSummary') }</p>
<p className="fee-card__info-tooltip-paragraph">{ t('swapEstimatedNetworkFeeSummary', [
<span className="fee-card__bold" key="fee-card-bold-1">
{ t('swapEstimatedNetworkFee') }

View File

@ -6,6 +6,7 @@ import { ETH_SWAPS_TOKEN_OBJECT } from '../../helpers/constants/swaps'
import { calcTokenValue, calcTokenAmount } from '../../helpers/utils/token-util'
import { constructTxParams, toPrecisionWithoutTrailingZeros } from '../../helpers/utils/util'
import { decimalToHex, getValueFromWeiHex } from '../../helpers/utils/conversions.util'
import { subtractCurrencies } from '../../helpers/utils/conversion-util'
import { formatCurrency } from '../../helpers/utils/confirm-tx.util'
import fetchWithCache from '../../helpers/utils/fetch-with-cache'
@ -265,17 +266,34 @@ export async function fetchTokenBalance (address, userAddress) {
return usersToken
}
export function getRenderableGasFeesForQuote (tradeGas, approveGas, gasPrice, currentCurrency, conversionRate) {
export function getRenderableNetworkFeesForQuote (
tradeGas,
approveGas,
gasPrice,
currentCurrency,
conversionRate,
tradeValue,
sourceSymbol,
sourceAmount,
) {
const totalGasLimitForCalculation = (new BigNumber(tradeGas || '0x0', 16)).plus(approveGas || '0x0', 16).toString(16)
const gasTotalInWeiHex = calcGasTotal(totalGasLimitForCalculation, gasPrice)
const nonGasFee = new BigNumber(tradeValue, 16)
.minus(sourceSymbol === 'ETH' ? sourceAmount : 0, 10)
.toString(16)
const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16)
.plus(nonGasFee, 16)
.toString(16)
const ethFee = getValueFromWeiHex({
value: gasTotalInWeiHex,
value: totalWeiCost,
toDenomination: 'ETH',
numberOfDecimals: 5,
})
const rawNetworkFees = getValueFromWeiHex({
value: gasTotalInWeiHex,
value: totalWeiCost,
toCurrency: currentCurrency,
conversionRate,
numberOfDecimals: 2,
@ -286,6 +304,7 @@ export function getRenderableGasFeesForQuote (tradeGas, approveGas, gasPrice, cu
rawEthFee: ethFee,
feeInFiat: formattedNetworkFee,
feeInEth: `${ethFee} ETH`,
nonGasFee,
}
}
@ -302,6 +321,7 @@ export function quotesToRenderableData (quotes, gasPrice, conversionRate, curren
gasEstimateWithRefund,
averageGas,
fee,
trade,
} = quote
const sourceValue = calcTokenAmount(sourceAmount, sourceTokenInfo.decimals || 18).toString(10)
const destinationValue = calcTokenAmount(destinationAmount, destinationTokenInfo.decimals || 18).toPrecision(8)
@ -311,7 +331,7 @@ export function quotesToRenderableData (quotes, gasPrice, conversionRate, curren
rawNetworkFees,
rawEthFee,
feeInEth,
} = getRenderableGasFeesForQuote(
} = getRenderableNetworkFeesForQuote(
(
gasEstimateWithRefund ||
decimalToHex(averageGas || 800000)
@ -320,6 +340,9 @@ export function quotesToRenderableData (quotes, gasPrice, conversionRate, curren
gasPrice,
currentCurrency,
conversionRate,
trade.value,
sourceTokenInfo.symbol,
sourceAmount,
)
const slippageMultiplier = (new BigNumber(100 - slippage)).div(100)

View File

@ -67,7 +67,7 @@ import MainQuoteSummary from '../main-quote-summary'
import { calcGasTotal } from '../../send/send.utils'
import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util'
import ActionableMessage from '../actionable-message'
import { quotesToRenderableData, getRenderableGasFeesForQuote } from '../swaps.util'
import { quotesToRenderableData, getRenderableNetworkFeesForQuote } from '../swaps.util'
import { useTokenTracker } from '../../../hooks/useTokenTracker'
import { QUOTES_EXPIRED_ERROR } from '../../../helpers/constants/swaps'
import CountdownTimer from '../countdown-timer'
@ -99,7 +99,7 @@ export default function ViewQuote () {
// Select necessary data
const tradeTxParams = useSelector(getSwapsTradeTxParams)
const { gasPrice } = tradeTxParams || {}
const { gasPrice, value: tradeValue } = tradeTxParams || {}
const customMaxGas = useSelector(getCustomSwapsGas)
const tokenConversionRates = useSelector(getTokenExchangeRates)
const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates)
@ -161,12 +161,6 @@ export default function ViewQuote () {
calcTokenAmount(approveValue, selectedFromToken.decimals).toFixed(9)
)
const approveGas = approveTxParams?.gas
const approveGasTotal = calcGasTotal(approveGas || '0x0', gasPrice)
const approveGasTotalInEth = getValueFromWeiHex({
value: approveGasTotal,
toDenomination: 'ETH',
numberOfDecimals: 4,
})
const renderablePopoverData = useMemo(() => {
return quotesToRenderableData(
@ -203,23 +197,30 @@ export default function ViewQuote () {
sourceTokenIconUrl,
} = renderableDataForUsedQuote
const { feeInFiat, feeInEth } = getRenderableGasFeesForQuote(
const { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote(
usedGasLimit,
approveGas,
gasPrice,
currentCurrency,
conversionRate,
tradeValue,
sourceTokenSymbol,
usedQuote.sourceAmount,
)
const {
feeInFiat: maxFeeInFiat,
feeInEth: maxFeeInEth,
} = getRenderableGasFeesForQuote(
nonGasFee,
} = getRenderableNetworkFeesForQuote(
maxGasLimit,
approveGas,
gasPrice,
currentCurrency,
conversionRate,
tradeValue,
sourceTokenSymbol,
usedQuote.sourceAmount,
)
const tokenCost = (new BigNumber(usedQuote.sourceAmount))
@ -378,6 +379,26 @@ export default function ViewQuote () {
}))
}
const nonGasFeeIsPositive = (new BigNumber(nonGasFee, 16)).gt(0)
const approveGasTotal = calcGasTotal(approveGas || '0x0', gasPrice)
const extraNetworkFeeTotalInHexWEI = (new BigNumber(nonGasFee, 16))
.plus(approveGasTotal, 16)
.toString(16)
const extraNetworkFeeTotalInEth = getValueFromWeiHex({
value: extraNetworkFeeTotalInHexWEI,
toDenomination: 'ETH',
numberOfDecimals: 4,
})
let extraInfoRowLabel = ''
if (approveGas && nonGasFeeIsPositive) {
extraInfoRowLabel = t('approvalAndAggregatorTxFeeCost')
} else if (approveGas) {
extraInfoRowLabel = t('approvalTxGasCost')
} else if (nonGasFeeIsPositive) {
extraInfoRowLabel = t('aggregatorFeeCost')
}
const onFeeCardMaxRowClick = () => dispatch(showModal({
name: 'CUSTOMIZE_GAS',
txData: { txParams: { ...tradeTxParams, gas: maxGasLimit } },
@ -389,10 +410,10 @@ export default function ViewQuote () {
),
customTotalSupplement: approveGasTotal,
extraInfoRow: (
approveGas
extraInfoRowLabel
? {
label: t('approvalTxGasCost'),
value: t('amountInEth', [approveGasTotalInEth]),
label: extraInfoRowLabel,
value: t('amountInEth', [extraNetworkFeeTotalInEth]),
}
: null
),