|
|
|
@ -10,8 +10,10 @@ import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount'; |
|
|
|
|
import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; |
|
|
|
|
import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; |
|
|
|
|
import { usePrevious } from '../../../hooks/usePrevious'; |
|
|
|
|
import { useGasFeeInputs } from '../../../hooks/useGasFeeInputs'; |
|
|
|
|
import { MetaMetricsContext } from '../../../contexts/metametrics.new'; |
|
|
|
|
import FeeCard from '../fee-card'; |
|
|
|
|
import EditGasPopover from '../../../components/app/edit-gas-popover/edit-gas-popover.component'; |
|
|
|
|
import { |
|
|
|
|
FALLBACK_GAS_MULTIPLIER, |
|
|
|
|
getQuotes, |
|
|
|
@ -21,7 +23,9 @@ import { |
|
|
|
|
setBalanceError, |
|
|
|
|
getQuotesLastFetched, |
|
|
|
|
getBalanceError, |
|
|
|
|
getCustomSwapsGas, |
|
|
|
|
getCustomSwapsGas, // Gas limit.
|
|
|
|
|
getCustomMaxFeePerGas, |
|
|
|
|
getCustomMaxPriorityFeePerGas, |
|
|
|
|
getDestinationTokenInfo, |
|
|
|
|
getUsedSwapsGasPrice, |
|
|
|
|
getTopQuote, |
|
|
|
@ -41,7 +45,11 @@ import { |
|
|
|
|
isHardwareWallet, |
|
|
|
|
getHardwareWalletType, |
|
|
|
|
} from '../../../selectors'; |
|
|
|
|
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask'; |
|
|
|
|
import { |
|
|
|
|
getNativeCurrency, |
|
|
|
|
getTokens, |
|
|
|
|
isEIP1559Network, |
|
|
|
|
} from '../../../ducks/metamask/metamask'; |
|
|
|
|
|
|
|
|
|
import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util'; |
|
|
|
|
|
|
|
|
@ -68,6 +76,9 @@ import { |
|
|
|
|
decimalToHex, |
|
|
|
|
hexToDecimal, |
|
|
|
|
getValueFromWeiHex, |
|
|
|
|
decGWEIToHexWEI, |
|
|
|
|
hexWEIToDecGWEI, |
|
|
|
|
addHexes, |
|
|
|
|
} from '../../../helpers/utils/conversions.util'; |
|
|
|
|
import MainQuoteSummary from '../main-quote-summary'; |
|
|
|
|
import { calcGasTotal } from '../../send/send.utils'; |
|
|
|
@ -79,6 +90,7 @@ import { |
|
|
|
|
} from '../swaps.util'; |
|
|
|
|
import { useTokenTracker } from '../../../hooks/useTokenTracker'; |
|
|
|
|
import { QUOTES_EXPIRED_ERROR } from '../../../../shared/constants/swaps'; |
|
|
|
|
import { EDIT_GAS_MODES } from '../../../../shared/constants/gas'; |
|
|
|
|
import CountdownTimer from '../countdown-timer'; |
|
|
|
|
import SwapsFooter from '../swaps-footer'; |
|
|
|
|
import ViewQuotePriceDifference from './view-quote-price-difference'; |
|
|
|
@ -94,6 +106,7 @@ export default function ViewQuote() { |
|
|
|
|
const [selectQuotePopoverShown, setSelectQuotePopoverShown] = useState(false); |
|
|
|
|
const [warningHidden, setWarningHidden] = useState(false); |
|
|
|
|
const [originalApproveAmount, setOriginalApproveAmount] = useState(null); |
|
|
|
|
const [showEditGasPopover, setShowEditGasPopover] = useState(false); |
|
|
|
|
|
|
|
|
|
const [ |
|
|
|
|
acknowledgedPriceDifference, |
|
|
|
@ -116,12 +129,15 @@ export default function ViewQuote() { |
|
|
|
|
// Select necessary data
|
|
|
|
|
const gasPrice = useSelector(getUsedSwapsGasPrice); |
|
|
|
|
const customMaxGas = useSelector(getCustomSwapsGas); |
|
|
|
|
const customMaxFeePerGas = useSelector(getCustomMaxFeePerGas); |
|
|
|
|
const customMaxPriorityFeePerGas = useSelector(getCustomMaxPriorityFeePerGas); |
|
|
|
|
const tokenConversionRates = useSelector(getTokenExchangeRates); |
|
|
|
|
const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates); |
|
|
|
|
const { balance: ethBalance } = useSelector(getSelectedAccount); |
|
|
|
|
const conversionRate = useSelector(conversionRateSelector); |
|
|
|
|
const currentCurrency = useSelector(getCurrentCurrency); |
|
|
|
|
const swapsTokens = useSelector(getTokens); |
|
|
|
|
const EIP1559Network = useSelector(isEIP1559Network); |
|
|
|
|
const balanceError = useSelector(getBalanceError); |
|
|
|
|
const fetchParams = useSelector(getFetchParams); |
|
|
|
|
const approveTxParams = useSelector(getApproveTxParams); |
|
|
|
@ -134,6 +150,13 @@ export default function ViewQuote() { |
|
|
|
|
const chainId = useSelector(getCurrentChainId); |
|
|
|
|
const nativeCurrencySymbol = useSelector(getNativeCurrency); |
|
|
|
|
|
|
|
|
|
let gasFeeInputs; |
|
|
|
|
if (EIP1559Network) { |
|
|
|
|
// For Swaps we want to get 'high' estimations by default.
|
|
|
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
|
|
|
gasFeeInputs = useGasFeeInputs('high'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const { isBestQuote } = usedQuote; |
|
|
|
|
|
|
|
|
|
const fetchParamsSourceToken = fetchParams?.sourceToken; |
|
|
|
@ -154,7 +177,30 @@ export default function ViewQuote() { |
|
|
|
|
: `0x${decimalToHex(usedQuote?.maxGas || 0)}`; |
|
|
|
|
const maxGasLimit = customMaxGas || nonCustomMaxGasLimit; |
|
|
|
|
|
|
|
|
|
const gasTotalInWeiHex = calcGasTotal(maxGasLimit, gasPrice); |
|
|
|
|
let maxFeePerGas; |
|
|
|
|
let maxPriorityFeePerGas; |
|
|
|
|
let baseAndPriorityFeePerGas; |
|
|
|
|
|
|
|
|
|
if (EIP1559Network) { |
|
|
|
|
const { |
|
|
|
|
maxFeePerGas: suggestedMaxFeePerGas, |
|
|
|
|
maxPriorityFeePerGas: suggestedMaxPriorityFeePerGas, |
|
|
|
|
gasFeeEstimates: { estimatedBaseFee = '0' }, |
|
|
|
|
} = gasFeeInputs; |
|
|
|
|
maxFeePerGas = customMaxFeePerGas || decGWEIToHexWEI(suggestedMaxFeePerGas); |
|
|
|
|
maxPriorityFeePerGas = |
|
|
|
|
customMaxPriorityFeePerGas || |
|
|
|
|
decGWEIToHexWEI(suggestedMaxPriorityFeePerGas); |
|
|
|
|
baseAndPriorityFeePerGas = addHexes( |
|
|
|
|
decGWEIToHexWEI(estimatedBaseFee), |
|
|
|
|
maxPriorityFeePerGas, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const gasTotalInWeiHex = calcGasTotal( |
|
|
|
|
maxGasLimit, |
|
|
|
|
EIP1559Network ? maxFeePerGas : gasPrice, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const { tokensWithBalances } = useTokenTracker(swapsTokens, true); |
|
|
|
|
const balanceToken = |
|
|
|
@ -185,7 +231,7 @@ export default function ViewQuote() { |
|
|
|
|
const renderablePopoverData = useMemo(() => { |
|
|
|
|
return quotesToRenderableData( |
|
|
|
|
quotes, |
|
|
|
|
gasPrice, |
|
|
|
|
EIP1559Network ? baseAndPriorityFeePerGas : gasPrice, |
|
|
|
|
conversionRate, |
|
|
|
|
currentCurrency, |
|
|
|
|
approveGas, |
|
|
|
@ -195,6 +241,8 @@ export default function ViewQuote() { |
|
|
|
|
}, [ |
|
|
|
|
quotes, |
|
|
|
|
gasPrice, |
|
|
|
|
baseAndPriorityFeePerGas, |
|
|
|
|
EIP1559Network, |
|
|
|
|
conversionRate, |
|
|
|
|
currentCurrency, |
|
|
|
|
approveGas, |
|
|
|
@ -221,7 +269,7 @@ export default function ViewQuote() { |
|
|
|
|
const { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote({ |
|
|
|
|
tradeGas: usedGasLimit, |
|
|
|
|
approveGas, |
|
|
|
|
gasPrice, |
|
|
|
|
gasPrice: EIP1559Network ? baseAndPriorityFeePerGas : gasPrice, |
|
|
|
|
currentCurrency, |
|
|
|
|
conversionRate, |
|
|
|
|
tradeValue, |
|
|
|
@ -238,7 +286,7 @@ export default function ViewQuote() { |
|
|
|
|
} = getRenderableNetworkFeesForQuote({ |
|
|
|
|
tradeGas: maxGasLimit, |
|
|
|
|
approveGas, |
|
|
|
|
gasPrice, |
|
|
|
|
gasPrice: EIP1559Network ? maxFeePerGas : gasPrice, |
|
|
|
|
currentCurrency, |
|
|
|
|
conversionRate, |
|
|
|
|
tradeValue, |
|
|
|
@ -455,7 +503,10 @@ export default function ViewQuote() { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const nonGasFeeIsPositive = new BigNumber(nonGasFee, 16).gt(0); |
|
|
|
|
const approveGasTotal = calcGasTotal(approveGas || '0x0', gasPrice); |
|
|
|
|
const approveGasTotal = calcGasTotal( |
|
|
|
|
approveGas || '0x0', |
|
|
|
|
EIP1559Network ? baseAndPriorityFeePerGas : gasPrice, |
|
|
|
|
); |
|
|
|
|
const extraNetworkFeeTotalInHexWEI = new BigNumber(nonGasFee, 16) |
|
|
|
|
.plus(approveGasTotal, 16) |
|
|
|
|
.toString(16); |
|
|
|
@ -474,26 +525,29 @@ export default function ViewQuote() { |
|
|
|
|
extraInfoRowLabel = t('aggregatorFeeCost'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const onFeeCardMaxRowClick = () => |
|
|
|
|
dispatch( |
|
|
|
|
showModal({ |
|
|
|
|
name: 'CUSTOMIZE_METASWAP_GAS', |
|
|
|
|
value: tradeValue, |
|
|
|
|
customGasLimitMessage: approveGas |
|
|
|
|
? t('extraApprovalGas', [hexToDecimal(approveGas)]) |
|
|
|
|
: '', |
|
|
|
|
customTotalSupplement: approveGasTotal, |
|
|
|
|
extraInfoRow: extraInfoRowLabel |
|
|
|
|
? { |
|
|
|
|
label: extraInfoRowLabel, |
|
|
|
|
value: `${extraNetworkFeeTotalInEth} ${nativeCurrencySymbol}`, |
|
|
|
|
} |
|
|
|
|
: null, |
|
|
|
|
initialGasPrice: gasPrice, |
|
|
|
|
initialGasLimit: maxGasLimit, |
|
|
|
|
minimumGasLimit: new BigNumber(nonCustomMaxGasLimit, 16).toNumber(), |
|
|
|
|
}), |
|
|
|
|
); |
|
|
|
|
const onFeeCardMaxRowClick = () => { |
|
|
|
|
EIP1559Network |
|
|
|
|
? setShowEditGasPopover(true) |
|
|
|
|
: dispatch( |
|
|
|
|
showModal({ |
|
|
|
|
name: 'CUSTOMIZE_METASWAP_GAS', |
|
|
|
|
value: tradeValue, |
|
|
|
|
customGasLimitMessage: approveGas |
|
|
|
|
? t('extraApprovalGas', [hexToDecimal(approveGas)]) |
|
|
|
|
: '', |
|
|
|
|
customTotalSupplement: approveGasTotal, |
|
|
|
|
extraInfoRow: extraInfoRowLabel |
|
|
|
|
? { |
|
|
|
|
label: extraInfoRowLabel, |
|
|
|
|
value: `${extraNetworkFeeTotalInEth} ${nativeCurrencySymbol}`, |
|
|
|
|
} |
|
|
|
|
: null, |
|
|
|
|
initialGasPrice: gasPrice, |
|
|
|
|
initialGasLimit: maxGasLimit, |
|
|
|
|
minimumGasLimit: new BigNumber(nonCustomMaxGasLimit, 16).toNumber(), |
|
|
|
|
}), |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const tokenApprovalTextComponent = ( |
|
|
|
|
<span key="swaps-view-quote-approve-symbol-1" className="view-quote__bold"> |
|
|
|
@ -590,6 +644,10 @@ export default function ViewQuote() { |
|
|
|
|
const isShowingWarning = |
|
|
|
|
showInsufficientWarning || shouldShowPriceDifferenceWarning; |
|
|
|
|
|
|
|
|
|
const onCloseEditGasPopover = () => { |
|
|
|
|
setShowEditGasPopover(false); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div className="view-quote"> |
|
|
|
|
<div |
|
|
|
@ -607,6 +665,24 @@ export default function ViewQuote() { |
|
|
|
|
onQuoteDetailsIsOpened={quoteDetailsOpened} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
{showEditGasPopover && EIP1559Network && ( |
|
|
|
|
<EditGasPopover |
|
|
|
|
transaction={{ |
|
|
|
|
txParams: { |
|
|
|
|
maxFeePerGas, |
|
|
|
|
maxPriorityFeePerGas, |
|
|
|
|
gas: maxGasLimit, |
|
|
|
|
}, |
|
|
|
|
}} |
|
|
|
|
minimumGasLimit={usedGasLimit} |
|
|
|
|
defaultEstimateToUse="high" |
|
|
|
|
mode={EDIT_GAS_MODES.SWAPS} |
|
|
|
|
confirmButtonText={t('submit')} |
|
|
|
|
onClose={onCloseEditGasPopover} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
<div |
|
|
|
|
className={classnames('view-quote__warning-wrapper', { |
|
|
|
|
'view-quote__warning-wrapper--thin': !isShowingWarning, |
|
|
|
@ -676,6 +752,8 @@ export default function ViewQuote() { |
|
|
|
|
: memoizedTokenConversionRates[destinationToken.address] |
|
|
|
|
} |
|
|
|
|
chainId={chainId} |
|
|
|
|
EIP1559Network={EIP1559Network} |
|
|
|
|
maxPriorityFeePerGasDecGWEI={hexWEIToDecGWEI(maxPriorityFeePerGas)} |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
@ -697,8 +775,8 @@ export default function ViewQuote() { |
|
|
|
|
balanceError || |
|
|
|
|
tokenBalanceUnavailable || |
|
|
|
|
disableSubmissionDueToPriceWarning || |
|
|
|
|
gasPrice === null || |
|
|
|
|
gasPrice === undefined |
|
|
|
|
(EIP1559Network && baseAndPriorityFeePerGas === undefined) || |
|
|
|
|
(!EIP1559Network && (gasPrice === null || gasPrice === undefined)) |
|
|
|
|
} |
|
|
|
|
className={isShowingWarning && 'view-quote__thin-swaps-footer'} |
|
|
|
|
showTopBorder |
|
|
|
|