mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Performance improvements for Swaps (#15359)
This commit is contained in:
parent
6723608173
commit
f31bac9fbf
@ -71,5 +71,5 @@ export function toChecksumHexAddress(address) {
|
|||||||
// closely mimics the original behavior.
|
// closely mimics the original behavior.
|
||||||
return hexPrefixed;
|
return hexPrefixed;
|
||||||
}
|
}
|
||||||
return toChecksumAddress(addHexPrefix(address));
|
return toChecksumAddress(hexPrefixed);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { isEqual } from 'lodash';
|
||||||
import Jazzicon from '../jazzicon';
|
import Jazzicon from '../jazzicon';
|
||||||
|
|
||||||
import { getAssetImageURL } from '../../../helpers/utils/util';
|
import { getAssetImageURL } from '../../../helpers/utils/util';
|
||||||
import BlockieIdenticon from './blockieIdenticon';
|
import BlockieIdenticon from './blockieIdenticon';
|
||||||
|
|
||||||
@ -11,7 +13,7 @@ const getStyles = (diameter) => ({
|
|||||||
borderRadius: diameter / 2,
|
borderRadius: diameter / 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class Identicon extends PureComponent {
|
export default class Identicon extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
/**
|
/**
|
||||||
* Adds blue border around the Identicon used for selected account.
|
* Adds blue border around the Identicon used for selected account.
|
||||||
@ -134,6 +136,11 @@ export default class Identicon extends PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps) {
|
||||||
|
// We only want to re-render if props are different.
|
||||||
|
return !isEqual(nextProps, this.props);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
address,
|
address,
|
||||||
|
@ -40,28 +40,32 @@ export function getRenderableTokenData(
|
|||||||
useTokenDetection,
|
useTokenDetection,
|
||||||
) {
|
) {
|
||||||
const { symbol, name, address, iconUrl, string, balance, decimals } = token;
|
const { symbol, name, address, iconUrl, string, balance, decimals } = token;
|
||||||
|
let contractExchangeRate;
|
||||||
|
if (isSwapsDefaultTokenSymbol(symbol, chainId)) {
|
||||||
|
contractExchangeRate = 1;
|
||||||
|
} else if (string && conversionRate > 0) {
|
||||||
|
// This condition improves performance significantly.
|
||||||
|
contractExchangeRate = contractExchangeRates[toChecksumHexAddress(address)];
|
||||||
|
}
|
||||||
const formattedFiat =
|
const formattedFiat =
|
||||||
getTokenFiatAmount(
|
getTokenFiatAmount(
|
||||||
isSwapsDefaultTokenSymbol(symbol, chainId)
|
contractExchangeRate,
|
||||||
? 1
|
|
||||||
: contractExchangeRates[toChecksumHexAddress(address)],
|
|
||||||
conversionRate,
|
conversionRate,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
string,
|
string,
|
||||||
symbol,
|
symbol,
|
||||||
true,
|
true,
|
||||||
) || '';
|
) || '';
|
||||||
const rawFiat =
|
const rawFiat = formattedFiat
|
||||||
getTokenFiatAmount(
|
? getTokenFiatAmount(
|
||||||
isSwapsDefaultTokenSymbol(symbol, chainId)
|
contractExchangeRate,
|
||||||
? 1
|
conversionRate,
|
||||||
: contractExchangeRates[toChecksumHexAddress(address)],
|
currentCurrency,
|
||||||
conversionRate,
|
string,
|
||||||
currentCurrency,
|
symbol,
|
||||||
string,
|
false,
|
||||||
symbol,
|
)
|
||||||
false,
|
: '';
|
||||||
) || '';
|
|
||||||
|
|
||||||
// token from dynamic api list is fetched when useTokenDetection is true
|
// token from dynamic api list is fetched when useTokenDetection is true
|
||||||
// And since the token.address from allTokens is checksumaddress
|
// And since the token.address from allTokens is checksumaddress
|
||||||
@ -214,10 +218,10 @@ export function useTokensToSearch({
|
|||||||
}, [
|
}, [
|
||||||
memoizedTokensToSearch,
|
memoizedTokensToSearch,
|
||||||
memoizedUsersToken,
|
memoizedUsersToken,
|
||||||
|
memoizedTopTokens,
|
||||||
tokenConversionRates,
|
tokenConversionRates,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
memoizedTopTokens,
|
|
||||||
memoizedDefaultToken,
|
memoizedDefaultToken,
|
||||||
chainId,
|
chainId,
|
||||||
tokenList,
|
tokenList,
|
||||||
|
@ -141,12 +141,12 @@ export default function BuildQuote({
|
|||||||
const { sourceTokenInfo = {}, destinationTokenInfo = {} } =
|
const { sourceTokenInfo = {}, destinationTokenInfo = {} } =
|
||||||
fetchParams?.metaData || {};
|
fetchParams?.metaData || {};
|
||||||
const tokens = useSelector(getTokens, isEqual);
|
const tokens = useSelector(getTokens, isEqual);
|
||||||
const topAssets = useSelector(getTopAssets);
|
const topAssets = useSelector(getTopAssets, isEqual);
|
||||||
const fromToken = useSelector(getFromToken, isEqual);
|
const fromToken = useSelector(getFromToken, isEqual);
|
||||||
const fromTokenInputValue = useSelector(getFromTokenInputValue);
|
const fromTokenInputValue = useSelector(getFromTokenInputValue);
|
||||||
const fromTokenError = useSelector(getFromTokenError);
|
const fromTokenError = useSelector(getFromTokenError);
|
||||||
const maxSlippage = useSelector(getMaxSlippage);
|
const maxSlippage = useSelector(getMaxSlippage);
|
||||||
const toToken = useSelector(getToToken) || destinationTokenInfo;
|
const toToken = useSelector(getToToken, isEqual) || destinationTokenInfo;
|
||||||
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
|
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
|
||||||
const chainId = useSelector(getCurrentChainId);
|
const chainId = useSelector(getCurrentChainId);
|
||||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
||||||
|
@ -2,6 +2,7 @@ import React, { useContext, useEffect, useState } from 'react';
|
|||||||
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getBlockExplorerLink } from '@metamask/etherscan-link';
|
import { getBlockExplorerLink } from '@metamask/etherscan-link';
|
||||||
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
import {
|
import {
|
||||||
@ -71,22 +72,25 @@ export default function SmartTransactionStatus() {
|
|||||||
const t = useContext(I18nContext);
|
const t = useContext(I18nContext);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const fetchParams = useSelector(getFetchParams) || {};
|
const fetchParams = useSelector(getFetchParams, isEqual) || {};
|
||||||
const { destinationTokenInfo = {}, sourceTokenInfo = {} } =
|
const { destinationTokenInfo = {}, sourceTokenInfo = {} } =
|
||||||
fetchParams?.metaData || {};
|
fetchParams?.metaData || {};
|
||||||
const hardwareWalletUsed = useSelector(isHardwareWallet);
|
const hardwareWalletUsed = useSelector(isHardwareWallet);
|
||||||
const hardwareWalletType = useSelector(getHardwareWalletType);
|
const hardwareWalletType = useSelector(getHardwareWalletType);
|
||||||
const needsTwoConfirmations = true;
|
const needsTwoConfirmations = true;
|
||||||
const selectedQuote = useSelector(getSelectedQuote);
|
const selectedQuote = useSelector(getSelectedQuote, isEqual);
|
||||||
const topQuote = useSelector(getTopQuote);
|
const topQuote = useSelector(getTopQuote, isEqual);
|
||||||
const usedQuote = selectedQuote || topQuote;
|
const usedQuote = selectedQuote || topQuote;
|
||||||
const currentSmartTransactions = useSelector(getCurrentSmartTransactions);
|
const currentSmartTransactions = useSelector(
|
||||||
|
getCurrentSmartTransactions,
|
||||||
|
isEqual,
|
||||||
|
);
|
||||||
const smartTransactionsOptInStatus = useSelector(
|
const smartTransactionsOptInStatus = useSelector(
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const chainId = useSelector(getCurrentChainId);
|
const chainId = useSelector(getCurrentChainId);
|
||||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
|
||||||
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig);
|
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig, shallowEqual);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
const currentSmartTransactionsEnabled = useSelector(
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
getCurrentSmartTransactionsEnabled,
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
@ -252,14 +252,14 @@ const SWAP_GAS_PRICE_VALIDATOR = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function validateData(validators, object, urlUsed) {
|
function validateData(validators, object, urlUsed, logError = true) {
|
||||||
return validators.every(({ property, type, validator }) => {
|
return validators.every(({ property, type, validator }) => {
|
||||||
const types = type.split('|');
|
const types = type.split('|');
|
||||||
|
|
||||||
const valid =
|
const valid =
|
||||||
types.some((_type) => typeof object[property] === _type) &&
|
types.some((_type) => typeof object[property] === _type) &&
|
||||||
(!validator || validator(object[property]));
|
(!validator || validator(object[property]));
|
||||||
if (!valid) {
|
if (!valid && logError) {
|
||||||
log.error(
|
log.error(
|
||||||
`response to GET ${urlUsed} invalid for property ${property}; value was:`,
|
`response to GET ${urlUsed} invalid for property ${property}; value was:`,
|
||||||
object[property],
|
object[property],
|
||||||
@ -381,11 +381,12 @@ export async function fetchTokens(chainId) {
|
|||||||
{ method: 'GET', headers: clientIdHeader },
|
{ method: 'GET', headers: clientIdHeader },
|
||||||
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
||||||
);
|
);
|
||||||
|
const logError = false;
|
||||||
const filteredTokens = [
|
const filteredTokens = [
|
||||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId],
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId],
|
||||||
...tokens.filter((token) => {
|
...tokens.filter((token) => {
|
||||||
return (
|
return (
|
||||||
validateData(TOKEN_VALIDATORS, token, tokensUrl) &&
|
validateData(TOKEN_VALIDATORS, token, tokensUrl, logError) &&
|
||||||
!(
|
!(
|
||||||
isSwapsDefaultTokenSymbol(token.symbol, chainId) ||
|
isSwapsDefaultTokenSymbol(token.symbol, chainId) ||
|
||||||
isSwapsDefaultTokenAddress(token.address, chainId)
|
isSwapsDefaultTokenAddress(token.address, chainId)
|
||||||
|
@ -11,6 +11,7 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
import SelectQuotePopover from '../select-quote-popover';
|
import SelectQuotePopover from '../select-quote-popover';
|
||||||
import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount';
|
import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount';
|
||||||
@ -195,8 +196,8 @@ export default function ViewQuote() {
|
|||||||
(currentSmartTransactionsError !== 'not_enough_funds' ||
|
(currentSmartTransactionsError !== 'not_enough_funds' ||
|
||||||
currentSmartTransactionsErrorMessageDismissed)
|
currentSmartTransactionsErrorMessageDismissed)
|
||||||
);
|
);
|
||||||
const smartTransactionFees = useSelector(getSmartTransactionFees);
|
const smartTransactionFees = useSelector(getSmartTransactionFees, isEqual);
|
||||||
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig);
|
const swapsNetworkConfig = useSelector(getSwapsNetworkConfig, shallowEqual);
|
||||||
const unsignedTransaction = usedQuote.trade;
|
const unsignedTransaction = usedQuote.trade;
|
||||||
|
|
||||||
let gasFeeInputs;
|
let gasFeeInputs;
|
||||||
@ -751,15 +752,17 @@ export default function ViewQuote() {
|
|||||||
const isShowingWarning =
|
const isShowingWarning =
|
||||||
showInsufficientWarning || shouldShowPriceDifferenceWarning;
|
showInsufficientWarning || shouldShowPriceDifferenceWarning;
|
||||||
|
|
||||||
const isSwapButtonDisabled =
|
const isSwapButtonDisabled = Boolean(
|
||||||
submitClicked ||
|
submitClicked ||
|
||||||
balanceError ||
|
balanceError ||
|
||||||
tokenBalanceUnavailable ||
|
tokenBalanceUnavailable ||
|
||||||
disableSubmissionDueToPriceWarning ||
|
disableSubmissionDueToPriceWarning ||
|
||||||
(networkAndAccountSupports1559 && baseAndPriorityFeePerGas === undefined) ||
|
(networkAndAccountSupports1559 &&
|
||||||
(!networkAndAccountSupports1559 &&
|
baseAndPriorityFeePerGas === undefined) ||
|
||||||
(gasPrice === null || gasPrice === undefined)) ||
|
(!networkAndAccountSupports1559 &&
|
||||||
(currentSmartTransactionsEnabled && currentSmartTransactionsError);
|
(gasPrice === null || gasPrice === undefined)) ||
|
||||||
|
(currentSmartTransactionsEnabled && currentSmartTransactionsError),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
|
Loading…
Reference in New Issue
Block a user