1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 18:00:18 +01:00

EIP-1559 - Fall back to gasLimit and gasPrice for hardware wallets (#11716)

This commit is contained in:
David Walsh 2021-08-02 17:52:18 -05:00 committed by GitHub
parent 8481c4b6be
commit c8b3dfe4e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 197 additions and 128 deletions

View File

@ -187,7 +187,7 @@ export default class TransactionController extends EventEmitter {
async getEIP1559Compatibility(fromAddress) {
const currentNetworkIsCompatible = await this._getCurrentNetworkEIP1559Compatibility();
const fromAccountIsCompatible = this._getCurrentAccountEIP1559Compatibility(
const fromAccountIsCompatible = await this._getCurrentAccountEIP1559Compatibility(
fromAddress,
);
return currentNetworkIsCompatible && fromAccountIsCompatible;
@ -506,7 +506,9 @@ export default class TransactionController extends EventEmitter {
async _getDefaultGasFees(txMeta, eip1559Compatibility) {
if (
(!eip1559Compatibility && txMeta.txParams.gasPrice) ||
(txMeta.txParams.maxFeePerGas && txMeta.txParams.maxPriorityFeePerGas)
(eip1559Compatibility &&
txMeta.txParams.maxFeePerGas &&
txMeta.txParams.maxPriorityFeePerGas)
) {
return {};
}
@ -857,8 +859,8 @@ export default class TransactionController extends EventEmitter {
? TRANSACTION_ENVELOPE_TYPES.FEE_MARKET
: TRANSACTION_ENVELOPE_TYPES.LEGACY;
const txParams = {
type,
...txMeta.txParams,
type,
chainId,
gasLimit: txMeta.txParams.gas,
};

View File

@ -2059,10 +2059,10 @@ export default class MetamaskController extends EventEmitter {
* client utilities for EIP-1559
* @returns {boolean} true if the keyring type supports EIP-1559
*/
getCurrentAccountEIP1559Compatibility(fromAddress) {
async getCurrentAccountEIP1559Compatibility(fromAddress) {
const address =
fromAddress || this.preferencesController.getSelectedAddress();
const keyring = this.keyringController.getKeyringForAccount(address);
const keyring = await this.keyringController.getKeyringForAccount(address);
return (
keyring.type !== KEYRING_TYPES.LEDGER &&
keyring.type !== KEYRING_TYPES.TREZOR

View File

@ -2,7 +2,6 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { isEIP1559Network } from '../../../ducks/metamask/metamask';
import { I18nContext } from '../../../contexts/i18n';
import Typography from '../../ui/typography/typography';
import {
@ -16,6 +15,7 @@ import {
GAS_RECOMMENDATIONS,
} from '../../../../shared/constants/gas';
import { getGasFormErrorText } from '../../../helpers/constants/gas';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
export default function AdvancedGasControls({
estimateToUse,
@ -33,15 +33,16 @@ export default function AdvancedGasControls({
maxPriorityFeeFiat,
maxFeeFiat,
gasErrors,
networkSupportsEIP1559,
minimumGasLimit,
}) {
const t = useContext(I18nContext);
const networkSupports1559 = useSelector(isEIP1559Network);
const networkAndAccountSupport1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const suggestedValues = {};
if (networkSupportsEIP1559) {
if (networkAndAccountSupport1559) {
suggestedValues.maxFeePerGas =
gasFeeEstimates?.[estimateToUse]?.suggestedMaxFeePerGas ||
gasFeeEstimates?.gasPrice;
@ -62,7 +63,7 @@ export default function AdvancedGasControls({
}
const showFeeMarketFields =
networkSupports1559 &&
networkAndAccountSupport1559 &&
(gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET ||
gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE);
@ -194,5 +195,4 @@ AdvancedGasControls.propTypes = {
maxFeeFiat: PropTypes.string,
gasErrors: PropTypes.object,
minimumGasLimit: PropTypes.number,
networkSupportsEIP1559: PropTypes.object,
};

View File

@ -10,8 +10,10 @@ import {
import Button from '../../ui/button';
import Typography from '../../ui/typography/typography';
import { isEIP1559Network } from '../../../ducks/metamask/metamask';
import { getIsMainnet } from '../../../selectors';
import {
getIsMainnet,
checkNetworkAndAccountSupports1559,
} from '../../../selectors';
import {
COLORS,
@ -66,8 +68,10 @@ export default function EditGasDisplay({
estimatesUnavailableWarning,
}) {
const t = useContext(I18nContext);
const supportsEIP1559 = useSelector(isEIP1559Network);
const isMainnet = useSelector(getIsMainnet);
const networkAndAccountSupport1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const dappSuggestedAndTxParamGasFeesAreTheSame = areDappSuggestedAndTxParamGasFeesTheSame(
transaction,
@ -79,11 +83,9 @@ export default function EditGasDisplay({
dappSuggestedAndTxParamGasFeesAreTheSame,
);
const networkSupports1559 = useSelector(isEIP1559Network);
const showTopError = balanceError || estimatesUnavailableWarning;
const showRadioButtons =
networkSupports1559 &&
networkAndAccountSupport1559 &&
gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET &&
!requireDappAcknowledgement &&
![EDIT_GAS_MODES.SPEED_UP, EDIT_GAS_MODES.CANCEL].includes(mode);
@ -138,12 +140,12 @@ export default function EditGasDisplay({
)}
<TransactionTotalBanner
total={
networkSupports1559 || isMainnet
networkAndAccountSupport1559 || isMainnet
? `~ ${estimatedMinimumFiat}`
: estimatedMaximumNative
}
detail={
networkSupports1559 &&
networkAndAccountSupport1559 &&
estimatedMaximumFiat !== undefined &&
t('editGasTotalBannerSubtitle', [
<Typography
@ -230,11 +232,10 @@ export default function EditGasDisplay({
gasErrors={gasErrors}
onManualChange={onManualChange}
minimumGasLimit={minimumGasLimit}
networkSupportsEIP1559={supportsEIP1559}
/>
)}
</div>
{networkSupports1559 &&
{networkAndAccountSupport1559 &&
!requireDappAcknowledgement &&
showEducationButton && (
<div className="edit-gas-display__education">

View File

@ -1,7 +1,6 @@
import React, { useCallback, useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { isEIP1559Network } from '../../../ducks/metamask/metamask';
import { useGasFeeInputs } from '../../../hooks/useGasFeeInputs';
import { useShouldAnimateGasEstimations } from '../../../hooks/useShouldAnimateGasEstimations';
@ -28,6 +27,7 @@ import {
updateCustomSwapsEIP1559GasParams,
} from '../../../store/actions';
import LoadingHeartBeat from '../../ui/loading-heartbeat';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
export default function EditGasPopover({
popoverTitle = '',
@ -42,12 +42,14 @@ export default function EditGasPopover({
const t = useContext(I18nContext);
const dispatch = useDispatch();
const showSidebar = useSelector((state) => state.appState.sidebar.isOpen);
const networkSupports1559 = useSelector(isEIP1559Network);
const networkAndAccountSupport1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const shouldAnimate = useShouldAnimateGasEstimations();
const showEducationButton =
mode === EDIT_GAS_MODES.MODIFY_IN_PLACE && networkSupports1559;
mode === EDIT_GAS_MODES.MODIFY_IN_PLACE && networkAndAccountSupport1559;
const [showEducationContent, setShowEducationContent] = useState(false);
const [warning] = useState(null);
@ -86,7 +88,7 @@ export default function EditGasPopover({
} = useGasFeeInputs(defaultEstimateToUse, transaction, minimumGasLimit, mode);
const [showAdvancedForm, setShowAdvancedForm] = useState(
!estimateToUse || hasGasErrors,
!estimateToUse || hasGasErrors || !networkAndAccountSupport1559,
);
/**
@ -110,7 +112,7 @@ export default function EditGasPopover({
closePopover();
}
const newGasSettings = networkSupports1559
const newGasSettings = networkAndAccountSupport1559
? {
gas: decimalToHex(gasLimit),
gasLimit: decimalToHex(gasLimit),
@ -145,7 +147,7 @@ export default function EditGasPopover({
break;
case EDIT_GAS_MODES.SWAPS:
// This popover component should only be used for the "FEE_MARKET" type in Swaps.
if (networkSupports1559) {
if (networkAndAccountSupport1559) {
dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings));
}
break;
@ -163,7 +165,7 @@ export default function EditGasPopover({
gasPrice,
maxFeePerGas,
maxPriorityFeePerGas,
networkSupports1559,
networkAndAccountSupport1559,
]);
let title = t('editGasTitle');

View File

@ -38,6 +38,7 @@ import {
getSelectedAddress,
getTargetAccount,
getIsNonStandardEthChain,
checkNetworkAndAccountSupports1559,
} from '../../selectors';
import {
disconnectGasFeeEstimatePoller,
@ -73,8 +74,8 @@ import {
getGasEstimateType,
getTokens,
getUnapprovedTxs,
isEIP1559Network,
} from '../metamask/metamask';
import { resetEnsResolution } from '../ens';
import {
isBurnAddress,
@ -409,7 +410,7 @@ export const initializeSendState = createAsyncThunk(
const state = thunkApi.getState();
const isNonStandardEthChain = getIsNonStandardEthChain(state);
const chainId = getCurrentChainId(state);
const eip1559support = isEIP1559Network(state);
const eip1559support = checkNetworkAndAccountSupports1559(state);
const {
send: { asset, stage, recipient, amount, draftTransaction },
metamask,

View File

@ -1085,8 +1085,18 @@ describe('Send Slice', () => {
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
gasFeeEstimates: {},
networkDetails: {
EIPS: {},
EIPS: {
1559: true,
},
},
selectedAddress: '0xAddress',
identities: { '0xAddress': { address: '0xAddress' } },
keyrings: [
{
type: 'HD Key Tree',
accounts: ['0xAddress'],
},
],
accounts: {
'0xAddress': {
address: '0xAddress',
@ -1098,13 +1108,11 @@ describe('Send Slice', () => {
'0xAddress': '0x0',
},
},
selectedAddress: '0xAddress',
provider: {
chainId: '0x4',
},
},
send: initialState,
gas: {
basicEstimateStatus: 'LOADING',
basicEstimatesStatus: {

View File

@ -57,6 +57,7 @@ import {
getCurrentChainId,
isHardwareWallet,
getHardwareWalletType,
checkNetworkAndAccountSupports1559,
} from '../../selectors';
import {
ERROR_FETCHING_QUOTES,
@ -66,7 +67,7 @@ import {
SWAPS_FETCH_ORDER_CONFLICT,
} from '../../../shared/constants/swaps';
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
import { isEIP1559Network, getGasFeeEstimates } from '../metamask/metamask';
import { getGasFeeEstimates } from '../metamask/metamask';
const GAS_PRICES_LOADING_STATES = {
INITIAL: 'INITIAL',
@ -511,7 +512,9 @@ export const fetchQuotesAndSetQuoteState = (
const hardwareWalletUsed = isHardwareWallet(state);
const hardwareWalletType = getHardwareWalletType(state);
const EIP1559Network = isEIP1559Network(state);
const networkAndAccountSupports1559 = checkNetworkAndAccountSupports1559(
state,
);
metaMetricsEvent({
event: 'Quotes Requested',
category: 'swaps',
@ -553,7 +556,7 @@ export const fetchQuotesAndSetQuoteState = (
),
);
const gasPriceFetchPromise = EIP1559Network
const gasPriceFetchPromise = networkAndAccountSupports1559
? null // For EIP 1559 we can get gas prices via "useGasFeeEstimates".
: dispatch(fetchAndSetSwapsGasPriceInfo());
@ -627,7 +630,9 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
const state = getState();
const chainId = getCurrentChainId(state);
const hardwareWalletUsed = isHardwareWallet(state);
const EIP1559Network = isEIP1559Network(state);
const networkAndAccountSupports1559 = checkNetworkAndAccountSupports1559(
state,
);
let swapsLivenessForNetwork = {
swapsFeatureIsLive: false,
useNewSwapsApi: false,
@ -667,7 +672,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
let maxPriorityFeePerGas;
let baseAndPriorityFeePerGas;
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
const {
high: { suggestedMaxFeePerGas, suggestedMaxPriorityFeePerGas },
estimatedBaseFee = '0',
@ -702,7 +707,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
const usedGasPrice = getUsedSwapsGasPrice(state);
usedTradeTxParams.gas = maxGasLimit;
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
usedTradeTxParams.maxFeePerGas = maxFeePerGas;
usedTradeTxParams.maxPriorityFeePerGas = maxPriorityFeePerGas;
delete usedTradeTxParams.gasPrice;
@ -724,7 +729,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
const gasEstimateTotalInUSD = getValueFromWeiHex({
value: calcGasTotal(
totalGasLimitEstimate,
EIP1559Network ? baseAndPriorityFeePerGas : usedGasPrice,
networkAndAccountSupports1559 ? baseAndPriorityFeePerGas : usedGasPrice,
),
toCurrency: 'usd',
conversionRate: usdConversionRate,
@ -757,7 +762,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: getHardwareWalletType(state),
};
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
swapMetaData.max_fee_per_gas = maxFeePerGas;
swapMetaData.max_priority_fee_per_gas = maxPriorityFeePerGas;
swapMetaData.base_and_priority_fee_per_gas = baseAndPriorityFeePerGas;
@ -792,7 +797,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
}
if (approveTxParams) {
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
approveTxParams.maxFeePerGas = maxFeePerGas;
approveTxParams.maxPriorityFeePerGas = maxPriorityFeePerGas;
delete approveTxParams.gasPrice;

View File

@ -4,8 +4,8 @@ import {
getEstimatedGasFeeTimeBounds,
getGasEstimateType,
getGasFeeEstimates,
isEIP1559Network,
} from '../ducks/metamask/metamask';
import { checkNetworkAndAccountSupports1559 } from '../selectors';
import { useSafeGasEstimatePolling } from './useSafeGasEstimatePolling';
/**
@ -35,7 +35,9 @@ import { useSafeGasEstimatePolling } from './useSafeGasEstimatePolling';
* @returns {GasFeeEstimates} - GasFeeEstimates object
*/
export function useGasFeeEstimates() {
const supportsEIP1559 = useSelector(isEIP1559Network);
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const gasEstimateType = useSelector(getGasEstimateType);
const gasFeeEstimates = useSelector(getGasFeeEstimates);
const estimatedGasFeeTimeBounds = useSelector(getEstimatedGasFeeTimeBounds);
@ -49,8 +51,9 @@ export function useGasFeeEstimates() {
gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE;
const isGasEstimatesLoading =
gasEstimateType === GAS_ESTIMATE_TYPES.NONE ||
(supportsEIP1559 && !isEIP1559TolerableEstimateType) ||
(!supportsEIP1559 && gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET);
(networkAndAccountSupports1559 && !isEIP1559TolerableEstimateType) ||
(!networkAndAccountSupports1559 &&
gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET);
return {
gasFeeEstimates,

View File

@ -5,8 +5,8 @@ import createRandomId from '../../shared/modules/random-id';
import {
getGasEstimateType,
getGasFeeEstimates,
isEIP1559Network,
} from '../ducks/metamask/metamask';
import { checkNetworkAndAccountSupports1559 } from '../selectors';
import {
disconnectGasFeeEstimatePoller,
getGasFeeEstimatesAndStartPolling,
@ -28,7 +28,7 @@ jest.mock('react-redux', () => {
});
const DEFAULT_OPTS = {
isEIP1559Network: false,
checkNetworkAndAccountSupports1559: false,
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
gasFeeEstimates: {
low: '10',
@ -38,8 +38,11 @@ const DEFAULT_OPTS = {
};
const generateUseSelectorRouter = (opts = DEFAULT_OPTS) => (selector) => {
if (selector === isEIP1559Network) {
return opts.isEIP1559Network ?? DEFAULT_OPTS.isEIP1559Network;
if (selector === checkNetworkAndAccountSupports1559) {
return (
opts.checkNetworkAndAccountSupports1559 ??
DEFAULT_OPTS.checkNetworkAndAccountSupports1559
);
}
if (selector === getGasEstimateType) {
return opts.gasEstimateType ?? DEFAULT_OPTS.gasEstimateType;
@ -137,7 +140,7 @@ describe('useGasFeeEstimates', () => {
};
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: true,
checkNetworkAndAccountSupports1559: true,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
gasFeeEstimates,
}),
@ -176,7 +179,7 @@ describe('useGasFeeEstimates', () => {
it('indicates that gas estimates are loading when gasEstimateType is not FEE_MARKET or ETH_GASPRICE, but network supports EIP-1559', () => {
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: true,
checkNetworkAndAccountSupports1559: true,
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
gasFeeEstimates: {
gasPrice: '10',
@ -219,7 +222,7 @@ describe('useGasFeeEstimates', () => {
};
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: false,
checkNetworkAndAccountSupports1559: false,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
gasFeeEstimates,
}),

View File

@ -18,7 +18,11 @@ import {
getMinimumGasTotalInHexWei,
} from '../../shared/modules/gas.utils';
import { PRIMARY, SECONDARY } from '../helpers/constants/common';
import { isEIP1559Network } from '../ducks/metamask/metamask';
import {
checkNetworkAndAccountSupports1559,
getShouldShowFiat,
getSelectedAccount,
} from '../selectors';
import {
hexWEIToDecGWEI,
@ -28,7 +32,7 @@ import {
addHexes,
} from '../helpers/utils/conversions.util';
import { GAS_FORM_ERRORS } from '../helpers/constants/gas';
import { getShouldShowFiat, getSelectedAccount } from '../selectors';
import { useCurrencyDisplay } from './useCurrencyDisplay';
import { useGasFeeEstimates } from './useGasFeeEstimates';
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
@ -103,11 +107,11 @@ function getMatchingEstimateFromGasFees(
maxFeePerGas,
maxPriorityFeePerGas,
gasPrice,
supportsEIP1559,
networkAndAccountSupports1559,
) {
return (
findKey(gasFeeEstimates, (estimate) => {
if (supportsEIP1559) {
if (networkAndAccountSupports1559) {
return (
Number(estimate?.suggestedMaxPriorityFeePerGas) ===
Number(maxPriorityFeePerGas) &&
@ -171,12 +175,13 @@ export function useGasFeeInputs(
editGasMode,
) {
const { balance: ethBalance } = useSelector(getSelectedAccount);
const networkSupportsEIP1559 = useSelector(isEIP1559Network);
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
// We need to know whether to show fiat conversions or not, so that we can
// default our fiat values to empty strings if showing fiat is not wanted or
// possible.
const showFiat = useSelector(getShouldShowFiat);
const supportsEIP1559 = useSelector(isEIP1559Network);
// We need to know the current network's currency and its decimal precision
// to calculate the amount to display to the user.
@ -231,7 +236,7 @@ export function useGasFeeInputs(
maxFeePerGas,
maxPriorityFeePerGas,
gasPrice,
supportsEIP1559,
networkAndAccountSupports1559,
)
: defaultEstimateToUse,
);
@ -271,7 +276,7 @@ export function useGasFeeInputs(
const gasSettings = {
gasLimit: decimalToHex(gasLimit),
};
if (networkSupportsEIP1559) {
if (networkAndAccountSupports1559) {
gasSettings.maxFeePerGas = maxFeePerGasToUse
? decGWEIToHexWEI(maxFeePerGasToUse)
: decGWEIToHexWEI(gasPriceToUse || '0');
@ -404,7 +409,7 @@ export function useGasFeeInputs(
case GAS_ESTIMATE_TYPES.LEGACY:
case GAS_ESTIMATE_TYPES.ETH_GASPRICE:
case GAS_ESTIMATE_TYPES.NONE:
if (networkSupportsEIP1559) {
if (networkAndAccountSupports1559) {
estimatesUnavailableWarning = true;
}
break;

View File

@ -3,18 +3,19 @@ import { useSelector } from 'react-redux';
import { GAS_ESTIMATE_TYPES } from '../../shared/constants/gas';
import { multiplyCurrencies } from '../../shared/modules/conversion.utils';
import {
isEIP1559Network,
getConversionRate,
getNativeCurrency,
} from '../ducks/metamask/metamask';
import { ETH, PRIMARY } from '../helpers/constants/common';
import {
checkNetworkAndAccountSupports1559,
getCurrentCurrency,
getShouldShowFiat,
txDataSelector,
getSelectedAccount,
} from '../selectors';
import { ETH, PRIMARY } from '../helpers/constants/common';
import { useGasFeeEstimates } from './useGasFeeEstimates';
import { useGasFeeInputs } from './useGasFeeInputs';
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
@ -104,9 +105,9 @@ const HIGH_FEE_MARKET_ESTIMATE_RETURN_VALUE = {
estimatedGasFeeTimeBounds: {},
};
const generateUseSelectorRouter = ({ isEIP1559NetworkResponse } = {}) => (
selector,
) => {
const generateUseSelectorRouter = ({
checkNetworkAndAccountSupports1559Response,
} = {}) => (selector) => {
if (selector === getConversionRate) {
return MOCK_ETH_USD_CONVERSION_RATE;
}
@ -131,8 +132,8 @@ const generateUseSelectorRouter = ({ isEIP1559NetworkResponse } = {}) => (
balance: '0x440aa47cc2556',
};
}
if (selector === isEIP1559Network) {
return isEIP1559NetworkResponse;
if (selector === checkNetworkAndAccountSupports1559) {
return checkNetworkAndAccountSupports1559Response;
}
return undefined;
};
@ -186,7 +187,9 @@ describe('useGasFeeInputs', () => {
it('updates values when user modifies gasPrice', () => {
useSelector.mockImplementation(
generateUseSelectorRouter({ isEIP1559NetworkResponse: false }),
generateUseSelectorRouter({
checkNetworkAndAccountSupports1559Response: false,
}),
);
const { result } = renderHook(() => useGasFeeInputs());
expect(result.current.gasPrice).toBe(
@ -253,7 +256,9 @@ describe('useGasFeeInputs', () => {
it('updates values when user modifies maxFeePerGas', () => {
useSelector.mockImplementation(
generateUseSelectorRouter({ isEIP1559NetworkResponse: true }),
generateUseSelectorRouter({
checkNetworkAndAccountSupports1559Response: true,
}),
);
const { result } = renderHook(() => useGasFeeInputs());
expect(result.current.maxFeePerGas).toBe(
@ -311,7 +316,9 @@ describe('useGasFeeInputs', () => {
() => HIGH_FEE_MARKET_ESTIMATE_RETURN_VALUE,
);
useSelector.mockImplementation(
generateUseSelectorRouter({ isEIP1559NetworkResponse: true }),
generateUseSelectorRouter({
checkNetworkAndAccountSupports1559Response: true,
}),
);
});

View File

@ -27,14 +27,12 @@ import {
getNoGasPriceFetched,
getIsEthGasPriceFetched,
getShouldShowFiat,
checkNetworkAndAccountSupports1559,
} from '../../selectors';
import { getMostRecentOverviewPage } from '../../ducks/history/history';
import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import {
updateTransactionGasFees,
isEIP1559Network,
} from '../../ducks/metamask/metamask';
import { updateTransactionGasFees } from '../../ducks/metamask/metamask';
import ConfirmTransactionBase from './confirm-transaction-base.component';
const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
@ -61,7 +59,7 @@ const mapStateToProps = (state, ownProps) => {
} = ownProps;
const { id: paramsTransactionId } = params;
const isMainnet = getIsMainnet(state);
const supportsEIP1599 = isEIP1559Network(state);
const supportsEIP1599 = checkNetworkAndAccountSupports1559(state);
const { confirmTransaction, metamask } = state;
const {
ensResolutionsByAddress,

View File

@ -29,7 +29,7 @@ export default class SendContent extends Component {
gasIsExcessive: PropTypes.bool.isRequired,
isEthGasPrice: PropTypes.bool,
noGasPrice: PropTypes.bool,
isEIP1559Network: PropTypes.bool,
networkAndAccountSupports1559: PropTypes.bool,
};
render() {
@ -40,7 +40,7 @@ export default class SendContent extends Component {
isEthGasPrice,
noGasPrice,
isAssetSendable,
isEIP1559Network,
networkAndAccountSupports1559,
} = this.props;
let gasError;
@ -59,7 +59,7 @@ export default class SendContent extends Component {
{this.maybeRenderAddContact()}
<SendAssetRow />
<SendAmountRow />
{!isEIP1559Network && <SendGasRow />}
{!networkAndAccountSupports1559 && <SendGasRow />}
{this.props.showHexData && <SendHexDataRow />}
</div>
</PageContainerContent>

View File

@ -14,7 +14,7 @@ describe('SendContent Component', () => {
const defaultProps = {
showHexData: true,
gasIsExcessive: false,
isEIP1559Network: true,
networkAndAccountSupports1559: true,
};
beforeEach(() => {

View File

@ -4,8 +4,8 @@ import {
getAddressBookEntry,
getIsEthGasPriceFetched,
getNoGasPriceFetched,
checkNetworkAndAccountSupports1559,
} from '../../../selectors';
import { isEIP1559Network } from '../../../ducks/metamask/metamask';
import { getIsAssetSendable, getSendTo } from '../../../ducks/send';
import * as actions from '../../../store/actions';
@ -25,7 +25,7 @@ function mapStateToProps(state) {
isEthGasPrice: getIsEthGasPriceFetched(state),
noGasPrice: getNoGasPriceFetched(state),
to,
isEIP1559Network: isEIP1559Network(state),
networkAndAccountSupports1559: checkNetworkAndAccountSupports1559(state),
};
}

View File

@ -48,6 +48,13 @@ const baseStore = {
medium: '1',
fast: '2',
},
selectedAddress: '0x0',
keyrings: [
{
type: 'HD Key Tree',
accounts: ['0x0'],
},
],
networkDetails: {
EIPS: {},
},
@ -72,7 +79,7 @@ const baseStore = {
accounts: {
'0x0': { balance: '0x0', address: '0x0' },
},
identities: { '0x0': {} },
identities: { '0x0': { address: '0x0' } },
},
};

View File

@ -37,7 +37,7 @@ export default function FeeCard({
onQuotesClick,
tokenConversionRate,
chainId,
EIP1559Network,
networkAndAccountSupports1559,
maxPriorityFeePerGasDecGWEI,
maxFeePerGasDecGWEI,
}) {
@ -96,7 +96,7 @@ export default function FeeCard({
</div>
</div>
<div className="fee-card__main">
{EIP1559Network && (
{networkAndAccountSupports1559 && (
<TransactionDetail
rows={[
<TransactionDetailItem
@ -172,7 +172,7 @@ export default function FeeCard({
]}
/>
)}
{!EIP1559Network && (
{!networkAndAccountSupports1559 && (
<div
className="fee-card__row-header"
data-testid="fee-card__row-header"
@ -221,7 +221,7 @@ export default function FeeCard({
</div>
</div>
)}
{!EIP1559Network && (
{!networkAndAccountSupports1559 && (
<div
className="fee-card__row-header"
onClick={() => onFeeCardMaxRowClick()}
@ -304,7 +304,7 @@ FeeCard.propTypes = {
numberOfQuotes: PropTypes.number.isRequired,
tokenConversionRate: PropTypes.number,
chainId: PropTypes.string.isRequired,
EIP1559Network: PropTypes.bool.isRequired,
networkAndAccountSupports1559: PropTypes.bool.isRequired,
maxPriorityFeePerGasDecGWEI: PropTypes.string,
maxFeePerGasDecGWEI: PropTypes.string,
};

View File

@ -58,7 +58,7 @@ const createProps = (customProps = {}) => {
onQuotesClick: jest.fn(),
tokenConversionRate: 0.015,
chainId: MAINNET_CHAIN_ID,
EIP1559Network: false,
networkAndAccountSupports1559: false,
...customProps,
};
};
@ -89,7 +89,7 @@ describe('FeeCard', () => {
it('renders the component with EIP-1559 enabled', () => {
const store = configureMockStore(middleware)(createSwapsMockStore());
const props = createProps({
EIP1559Network: true,
networkAndAccountSupports1559: true,
maxPriorityFeePerGasDecGWEI: '3',
maxFeePerGasDecGWEI: '4',
});

View File

@ -36,7 +36,10 @@ import {
getUseNewSwapsApi,
getFromToken,
} from '../../ducks/swaps/swaps';
import { isEIP1559Network } from '../../ducks/metamask/metamask';
import {
checkNetworkAndAccountSupports1559,
currentNetworkTxListSelector,
} from '../../selectors';
import {
AWAITING_SIGNATURES_ROUTE,
AWAITING_SWAP_ROUTE,
@ -62,7 +65,7 @@ import {
setBackgroundSwapRouteState,
setSwapsErrorKey,
} from '../../store/actions';
import { currentNetworkTxListSelector } from '../../selectors';
import { useNewMetricEvent } from '../../hooks/useMetricEvent';
import { useGasFeeEstimates } from '../../hooks/useGasFeeEstimates';
import FeatureToggledRoute from '../../helpers/higher-order-components/feature-toggled-route';
@ -112,10 +115,12 @@ export default function Swap() {
const chainId = useSelector(getCurrentChainId);
const isSwapsChain = useSelector(getIsSwapsChain);
const useNewSwapsApi = useSelector(getUseNewSwapsApi);
const EIP1559Network = useSelector(isEIP1559Network);
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const fromToken = useSelector(getFromToken);
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
// This will pre-load gas fees before going to the View Quote page.
// eslint-disable-next-line react-hooks/rules-of-hooks
useGasFeeEstimates();
@ -195,14 +200,20 @@ export default function Swap() {
dispatch(setAggregatorMetadata(newAggregatorMetadata));
},
);
if (!EIP1559Network) {
if (!networkAndAccountSupports1559) {
dispatch(fetchAndSetSwapsGasPriceInfo(chainId));
}
return () => {
dispatch(prepareToLeaveSwaps());
};
}
}, [dispatch, chainId, isFeatureFlagLoaded, useNewSwapsApi, EIP1559Network]);
}, [
dispatch,
chainId,
isFeatureFlagLoaded,
useNewSwapsApi,
networkAndAccountSupports1559,
]);
const hardwareWalletUsed = useSelector(isHardwareWallet);
const hardwareWalletType = useSelector(getHardwareWalletType);

View File

@ -659,7 +659,7 @@ export function getSwapsTokensReceivedFromTxMeta(
chainId,
) {
const txReceipt = txMeta?.txReceipt;
const EIP1559Network =
const networkAndAccountSupports1559 =
txMeta?.txReceipt?.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET;
if (isSwapsDefaultTokenSymbol(tokenSymbol, chainId)) {
if (
@ -675,7 +675,7 @@ export function getSwapsTokensReceivedFromTxMeta(
if (approvalTxMeta && approvalTxMeta.txReceipt) {
approvalTxGasCost = calcGasTotal(
approvalTxMeta.txReceipt.gasUsed,
EIP1559Network
networkAndAccountSupports1559
? approvalTxMeta.txReceipt.effectiveGasPrice // Base fee + priority fee.
: approvalTxMeta.txParams.gasPrice,
);
@ -683,7 +683,9 @@ export function getSwapsTokensReceivedFromTxMeta(
const gasCost = calcGasTotal(
txReceipt.gasUsed,
EIP1559Network ? txReceipt.effectiveGasPrice : txMeta.txParams.gasPrice,
networkAndAccountSupports1559
? txReceipt.effectiveGasPrice
: txMeta.txParams.gasPrice,
);
const totalGasCost = new BigNumber(gasCost, 16)
.plus(approvalTxGasCost, 16)

View File

@ -44,12 +44,9 @@ import {
getCurrentChainId,
isHardwareWallet,
getHardwareWalletType,
checkNetworkAndAccountSupports1559,
} from '../../../selectors';
import {
getNativeCurrency,
getTokens,
isEIP1559Network,
} from '../../../ducks/metamask/metamask';
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask';
import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util';
@ -137,7 +134,9 @@ export default function ViewQuote() {
const conversionRate = useSelector(conversionRateSelector);
const currentCurrency = useSelector(getCurrentCurrency);
const swapsTokens = useSelector(getTokens);
const EIP1559Network = useSelector(isEIP1559Network);
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const balanceError = useSelector(getBalanceError);
const fetchParams = useSelector(getFetchParams);
const approveTxParams = useSelector(getApproveTxParams);
@ -151,7 +150,7 @@ export default function ViewQuote() {
const nativeCurrencySymbol = useSelector(getNativeCurrency);
let gasFeeInputs;
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
// For Swaps we want to get 'high' estimations by default.
// eslint-disable-next-line react-hooks/rules-of-hooks
gasFeeInputs = useGasFeeInputs('high');
@ -181,7 +180,7 @@ export default function ViewQuote() {
let maxPriorityFeePerGas;
let baseAndPriorityFeePerGas;
if (EIP1559Network) {
if (networkAndAccountSupports1559) {
const {
maxFeePerGas: suggestedMaxFeePerGas,
maxPriorityFeePerGas: suggestedMaxPriorityFeePerGas,
@ -199,7 +198,7 @@ export default function ViewQuote() {
const gasTotalInWeiHex = calcGasTotal(
maxGasLimit,
EIP1559Network ? maxFeePerGas : gasPrice,
networkAndAccountSupports1559 ? maxFeePerGas : gasPrice,
);
const { tokensWithBalances } = useTokenTracker(swapsTokens, true);
@ -231,7 +230,7 @@ export default function ViewQuote() {
const renderablePopoverData = useMemo(() => {
return quotesToRenderableData(
quotes,
EIP1559Network ? baseAndPriorityFeePerGas : gasPrice,
networkAndAccountSupports1559 ? baseAndPriorityFeePerGas : gasPrice,
conversionRate,
currentCurrency,
approveGas,
@ -242,7 +241,7 @@ export default function ViewQuote() {
quotes,
gasPrice,
baseAndPriorityFeePerGas,
EIP1559Network,
networkAndAccountSupports1559,
conversionRate,
currentCurrency,
approveGas,
@ -269,7 +268,9 @@ export default function ViewQuote() {
const { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote({
tradeGas: usedGasLimit,
approveGas,
gasPrice: EIP1559Network ? baseAndPriorityFeePerGas : gasPrice,
gasPrice: networkAndAccountSupports1559
? baseAndPriorityFeePerGas
: gasPrice,
currentCurrency,
conversionRate,
tradeValue,
@ -286,7 +287,7 @@ export default function ViewQuote() {
} = getRenderableNetworkFeesForQuote({
tradeGas: maxGasLimit,
approveGas,
gasPrice: EIP1559Network ? maxFeePerGas : gasPrice,
gasPrice: networkAndAccountSupports1559 ? maxFeePerGas : gasPrice,
currentCurrency,
conversionRate,
tradeValue,
@ -505,7 +506,7 @@ export default function ViewQuote() {
const nonGasFeeIsPositive = new BigNumber(nonGasFee, 16).gt(0);
const approveGasTotal = calcGasTotal(
approveGas || '0x0',
EIP1559Network ? baseAndPriorityFeePerGas : gasPrice,
networkAndAccountSupports1559 ? baseAndPriorityFeePerGas : gasPrice,
);
const extraNetworkFeeTotalInHexWEI = new BigNumber(nonGasFee, 16)
.plus(approveGasTotal, 16)
@ -526,7 +527,7 @@ export default function ViewQuote() {
}
const onFeeCardMaxRowClick = () => {
EIP1559Network
networkAndAccountSupports1559
? setShowEditGasPopover(true)
: dispatch(
showModal({
@ -666,7 +667,7 @@ export default function ViewQuote() {
/>
)}
{showEditGasPopover && EIP1559Network && (
{showEditGasPopover && networkAndAccountSupports1559 && (
<EditGasPopover
transaction={{
txParams: {
@ -752,7 +753,7 @@ export default function ViewQuote() {
: memoizedTokenConversionRates[destinationToken.address]
}
chainId={chainId}
EIP1559Network={EIP1559Network}
networkAndAccountSupports1559={networkAndAccountSupports1559}
maxPriorityFeePerGasDecGWEI={hexWEIToDecGWEI(maxPriorityFeePerGas)}
maxFeePerGasDecGWEI={hexWEIToDecGWEI(maxFeePerGas)}
/>
@ -776,8 +777,10 @@ export default function ViewQuote() {
balanceError ||
tokenBalanceUnavailable ||
disableSubmissionDueToPriceWarning ||
(EIP1559Network && baseAndPriorityFeePerGas === undefined) ||
(!EIP1559Network && (gasPrice === null || gasPrice === undefined))
(networkAndAccountSupports1559 &&
baseAndPriorityFeePerGas === undefined) ||
(!networkAndAccountSupports1559 &&
(gasPrice === null || gasPrice === undefined))
}
className={isShowingWarning && 'view-quote__thin-swaps-footer'}
showTopBorder

View File

@ -14,7 +14,6 @@ import {
getGasEstimateType,
getGasFeeEstimates,
getNativeCurrency,
isEIP1559Network,
} from '../ducks/metamask/metamask';
import { TRANSACTION_ENVELOPE_TYPES } from '../../shared/constants/transaction';
import { decGWEIToHexWEI } from '../helpers/utils/conversions.util';
@ -25,6 +24,7 @@ import {
} from '../../shared/modules/gas.utils';
import { getAveragePriceEstimateInHexWEI } from './custom-gas';
import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors';
import { checkNetworkAndAccountSupports1559 } from '.';
const unapprovedTxsSelector = (state) => state.metamask.unapprovedTxs;
const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs;
@ -231,13 +231,15 @@ export const transactionFeeSelector = function (state, txData) {
const nativeCurrency = getNativeCurrency(state);
const gasFeeEstimates = getGasFeeEstimates(state) || {};
const gasEstimateType = getGasEstimateType(state);
const networkSupportsEIP1559 = isEIP1559Network(state);
const networkAndAccountSupportsEIP1559 = checkNetworkAndAccountSupports1559(
state,
);
const gasEstimationObject = {
gasLimit: txData.txParams?.gas ?? '0x0',
};
if (networkSupportsEIP1559) {
if (networkAndAccountSupportsEIP1559) {
const { medium = {}, gasPrice = '0' } = gasFeeEstimates;
if (txData.txParams?.type === TRANSACTION_ENVELOPE_TYPES.LEGACY) {
gasEstimationObject.gasPrice =

View File

@ -27,6 +27,7 @@ import { DAY } from '../../shared/constants/time';
import {
getNativeCurrency,
getConversionRate,
isEIP1559Network,
} from '../ducks/metamask/metamask';
/**
@ -80,6 +81,18 @@ export function getCurrentKeyring(state) {
return keyring;
}
export function isEIP1559Account(state) {
// Neither hardware wallet supports 1559 at this time
return !isHardwareWallet(state);
}
export function checkNetworkAndAccountSupports1559(state) {
const networkSupports1559 = isEIP1559Network(state);
const accountSupports1559 = isEIP1559Account(state);
return networkSupports1559 && accountSupports1559;
}
/**
* Checks if the current wallet is a hardware wallet.
* @param {Object} state

View File

@ -21,10 +21,7 @@ import {
} from '../selectors';
import { computeEstimatedGasLimit, resetSendState } from '../ducks/send';
import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account';
import {
getUnconnectedAccountAlertEnabledness,
isEIP1559Network,
} from '../ducks/metamask/metamask';
import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask';
import { LISTED_CONTRACT_ADDRESSES } from '../../shared/constants/tokens';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import * as actionConstants from './actionConstants';
@ -1069,7 +1066,6 @@ export function updateMetamaskState(newState) {
payload: {
gasFeeEstimates: newState.gasFeeEstimates,
gasEstimateType: newState.gasEstimateType,
isEIP1559Network: isEIP1559Network({ metamask: newState }),
},
});
}