1
0
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:
Daniel 2022-07-28 15:56:15 +02:00 committed by GitHub
parent 6723608173
commit f31bac9fbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 38 deletions

View File

@ -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);
} }

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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)

View File

@ -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 (