1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Support for type 0 transaction (#12252)

Support for type 0 transaction
This commit is contained in:
Jyoti Puri 2021-10-06 23:59:57 +05:30 committed by GitHub
parent 3a5538bd50
commit fc41321470
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 250 additions and 116 deletions

View File

@ -405,8 +405,9 @@ export default class TransactionController extends EventEmitter {
* @returns {Promise<object>} resolves with txMeta * @returns {Promise<object>} resolves with txMeta
*/ */
async addTxGasDefaults(txMeta, getCodeResponse) { async addTxGasDefaults(txMeta, getCodeResponse) {
const eip1559Compatibility = await this.getEIP1559Compatibility(); const eip1559Compatibility =
txMeta.txParams.type !== TRANSACTION_ENVELOPE_TYPES.LEGACY &&
(await this.getEIP1559Compatibility());
const { const {
gasPrice: defaultGasPrice, gasPrice: defaultGasPrice,
maxFeePerGas: defaultMaxFeePerGas, maxFeePerGas: defaultMaxFeePerGas,

View File

@ -525,6 +525,58 @@ describe('Transaction Controller', function () {
stub2.restore(); stub2.restore();
}); });
it('should not add maxFeePerGas and maxPriorityFeePerGas to type-0 transactions', async function () {
const TEST_GASPRICE = '0x12a05f200';
const stub1 = sinon
.stub(txController, 'getEIP1559Compatibility')
.returns(true);
const stub2 = sinon
.stub(txController, '_getDefaultGasFees')
.callsFake(() => ({ gasPrice: TEST_GASPRICE }));
txController.txStateManager._addTransactionsToState([
{
id: 1,
status: TRANSACTION_STATUSES.UNAPPROVED,
metamaskNetworkId: currentNetworkId,
txParams: {
to: VALID_ADDRESS,
from: VALID_ADDRESS_TWO,
type: '0x0',
},
history: [{}],
},
]);
const txMeta = {
id: 1,
txParams: {
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
to: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
type: '0x0',
},
history: [{}],
};
providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' };
providerResultStub.eth_estimateGas = '5209';
const txMetaWithDefaults = await txController.addTxGasDefaults(txMeta);
assert.equal(
txMetaWithDefaults.txParams.maxFeePerGas,
undefined,
'should not have maxFeePerGas',
);
assert.equal(
txMetaWithDefaults.txParams.maxPriorityFeePerGas,
undefined,
'should not have max priority fee per gas',
);
stub1.restore();
stub2.restore();
});
it('should not add gasPrice if the fee data is available from the dapp', async function () { it('should not add gasPrice if the fee data is available from the dapp', async function () {
const TEST_GASPRICE = '0x12a05f200'; const TEST_GASPRICE = '0x12a05f200';
const TEST_MAX_FEE_PER_GAS = '0x12a05f200'; const TEST_MAX_FEE_PER_GAS = '0x12a05f200';

View File

@ -6,7 +6,6 @@ import { I18nContext } from '../../../contexts/i18n';
import FormField from '../../ui/form-field'; import FormField from '../../ui/form-field';
import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas'; import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
import { getGasFormErrorText } from '../../../helpers/constants/gas'; import { getGasFormErrorText } from '../../../helpers/constants/gas';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
import { getIsGasEstimatesLoading } from '../../../ducks/metamask/metamask'; import { getIsGasEstimatesLoading } from '../../../ducks/metamask/metamask';
export default function AdvancedGasControls({ export default function AdvancedGasControls({
@ -24,15 +23,13 @@ export default function AdvancedGasControls({
maxFeeFiat, maxFeeFiat,
gasErrors, gasErrors,
minimumGasLimit, minimumGasLimit,
supportsEIP1559,
}) { }) {
const t = useContext(I18nContext); const t = useContext(I18nContext);
const networkAndAccountSupport1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const isGasEstimatesLoading = useSelector(getIsGasEstimatesLoading); const isGasEstimatesLoading = useSelector(getIsGasEstimatesLoading);
const showFeeMarketFields = const showFeeMarketFields =
networkAndAccountSupport1559 && supportsEIP1559 &&
(gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET || (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET ||
gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE || gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE ||
isGasEstimatesLoading); isGasEstimatesLoading);
@ -131,4 +128,5 @@ AdvancedGasControls.propTypes = {
maxFeeFiat: PropTypes.string, maxFeeFiat: PropTypes.string,
gasErrors: PropTypes.object, gasErrors: PropTypes.object,
minimumGasLimit: PropTypes.string, minimumGasLimit: PropTypes.string,
supportsEIP1559: PropTypes.bool,
}; };

View File

@ -0,0 +1,39 @@
import React from 'react';
import configureMockStore from 'redux-mock-store';
import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
import { renderWithProvider } from '../../../../test/jest/rendering';
import AdvancedGasControls from './advanced-gas-controls.component';
const renderComponent = (props) => {
const store = configureMockStore([])({ metamask: { identities: [] } });
return renderWithProvider(<AdvancedGasControls {...props} />, store);
};
describe('AdvancedGasControls Component', () => {
it('should render correctly', () => {
expect(() => {
renderComponent();
}).not.toThrow();
});
it('should not render maxFee and maxPriorityFee inputs if supportsEIP1559 is false', () => {
const { queryByText } = renderComponent({ supportsEIP1559: false });
expect(queryByText('Gas Limit')).toBeInTheDocument();
expect(queryByText('Gas price')).toBeInTheDocument();
expect(queryByText('Max fee')).not.toBeInTheDocument();
expect(queryByText('Max priority fee')).not.toBeInTheDocument();
});
it('should render maxFee and maxPriorityFee inputs if supportsEIP1559 is true', () => {
const { queryByText } = renderComponent({
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
supportsEIP1559: true,
});
expect(queryByText('Gas price')).not.toBeInTheDocument();
expect(queryByText('Gas Limit')).toBeInTheDocument();
expect(queryByText('Max fee')).toBeInTheDocument();
expect(queryByText('Max priority fee')).toBeInTheDocument();
});
});

View File

@ -22,6 +22,7 @@ import {
FONT_WEIGHT, FONT_WEIGHT,
} from '../../../helpers/constants/design-system'; } from '../../../helpers/constants/design-system';
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util'; import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
import InfoTooltip from '../../ui/info-tooltip'; import InfoTooltip from '../../ui/info-tooltip';
import ErrorMessage from '../../ui/error-message'; import ErrorMessage from '../../ui/error-message';
@ -73,17 +74,15 @@ export default function EditGasDisplay({
const scrollRef = useRef(null); const scrollRef = useRef(null);
const isMainnet = useSelector(getIsMainnet); const isMainnet = useSelector(getIsMainnet);
const networkAndAccountSupport1559 = useSelector( const supportsEIP1559 =
checkNetworkAndAccountSupports1559, useSelector(checkNetworkAndAccountSupports1559) &&
); !isLegacyTransaction(transaction.txParams);
const showAdvancedInlineGasIfPossible = useSelector( const showAdvancedInlineGasIfPossible = useSelector(
getAdvancedInlineGasShown, getAdvancedInlineGasShown,
); );
const [showAdvancedForm, setShowAdvancedForm] = useState( const [showAdvancedForm, setShowAdvancedForm] = useState(
!estimateToUse || !estimateToUse || estimateToUse === 'custom' || !supportsEIP1559,
estimateToUse === 'custom' ||
!networkAndAccountSupport1559,
); );
const [hideRadioButtons, setHideRadioButtons] = useState( const [hideRadioButtons, setHideRadioButtons] = useState(
showAdvancedInlineGasIfPossible, showAdvancedInlineGasIfPossible,
@ -109,7 +108,7 @@ export default function EditGasDisplay({
(balanceError || estimatesUnavailableWarning) && (balanceError || estimatesUnavailableWarning) &&
(!isGasEstimatesLoading || txParamsHaveBeenCustomized); (!isGasEstimatesLoading || txParamsHaveBeenCustomized);
const radioButtonsEnabled = const radioButtonsEnabled =
networkAndAccountSupport1559 && supportsEIP1559 &&
gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET && gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET &&
!requireDappAcknowledgement; !requireDappAcknowledgement;
@ -163,12 +162,12 @@ export default function EditGasDisplay({
)} )}
<TransactionTotalBanner <TransactionTotalBanner
total={ total={
(networkAndAccountSupport1559 || isMainnet) && estimatedMinimumFiat (supportsEIP1559 || isMainnet) && estimatedMinimumFiat
? `~ ${estimatedMinimumFiat}` ? `~ ${estimatedMinimumFiat}`
: estimatedMinimumNative : estimatedMinimumNative
} }
detail={ detail={
networkAndAccountSupport1559 && supportsEIP1559 &&
estimatedMaximumFiat !== undefined && ( estimatedMaximumFiat !== undefined && (
<> <>
<Typography <Typography
@ -188,7 +187,8 @@ export default function EditGasDisplay({
) )
} }
timing={ timing={
hasGasErrors === false && ( hasGasErrors === false &&
supportsEIP1559 && (
<GasTiming <GasTiming
maxFeePerGas={maxFeePerGas} maxFeePerGas={maxFeePerGas}
maxPriorityFeePerGas={maxPriorityFeePerGas} maxPriorityFeePerGas={maxPriorityFeePerGas}
@ -281,18 +281,17 @@ export default function EditGasDisplay({
gasErrors={gasErrors} gasErrors={gasErrors}
onManualChange={onManualChange} onManualChange={onManualChange}
minimumGasLimit={minimumGasLimit} minimumGasLimit={minimumGasLimit}
supportsEIP1559={supportsEIP1559}
/> />
)} )}
</div> </div>
{networkAndAccountSupport1559 && {supportsEIP1559 && !requireDappAcknowledgement && showEducationButton && (
!requireDappAcknowledgement && <div className="edit-gas-display__education">
showEducationButton && ( <button onClick={onEducationClick}>
<div className="edit-gas-display__education"> {t('editGasEducationButtonText')}
<button onClick={onEducationClick}> </button>
{t('editGasEducationButtonText')} </div>
</button> )}
</div>
)}
<div ref={scrollRef} className="edit-gas-display__scroll-bottom" /> <div ref={scrollRef} className="edit-gas-display__scroll-bottom" />
</div> </div>
); );

View File

@ -29,6 +29,7 @@ import {
import LoadingHeartBeat from '../../ui/loading-heartbeat'; import LoadingHeartBeat from '../../ui/loading-heartbeat';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors'; import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees'; import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees';
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
export default function EditGasPopover({ export default function EditGasPopover({
popoverTitle = '', popoverTitle = '',
@ -42,9 +43,9 @@ export default function EditGasPopover({
}) { }) {
const t = useContext(I18nContext); const t = useContext(I18nContext);
const dispatch = useDispatch(); const dispatch = useDispatch();
const networkAndAccountSupport1559 = useSelector( const supportsEIP1559 =
checkNetworkAndAccountSupports1559, useSelector(checkNetworkAndAccountSupports1559) &&
); !isLegacyTransaction(transaction?.txParams);
const gasLoadingAnimationIsShowing = useSelector( const gasLoadingAnimationIsShowing = useSelector(
getGasLoadingAnimationIsShowing, getGasLoadingAnimationIsShowing,
); );
@ -52,7 +53,7 @@ export default function EditGasPopover({
const showEducationButton = const showEducationButton =
(mode === EDIT_GAS_MODES.MODIFY_IN_PLACE || (mode === EDIT_GAS_MODES.MODIFY_IN_PLACE ||
mode === EDIT_GAS_MODES.SWAPS) && mode === EDIT_GAS_MODES.SWAPS) &&
networkAndAccountSupport1559; supportsEIP1559;
const [showEducationContent, setShowEducationContent] = useState(false); const [showEducationContent, setShowEducationContent] = useState(false);
const [warning] = useState(null); const [warning] = useState(null);
@ -132,7 +133,7 @@ export default function EditGasPopover({
closePopover(); closePopover();
} }
const newGasSettings = networkAndAccountSupport1559 const newGasSettings = supportsEIP1559
? { ? {
gas: decimalToHex(gasLimit), gas: decimalToHex(gasLimit),
gasLimit: decimalToHex(gasLimit), gasLimit: decimalToHex(gasLimit),
@ -149,7 +150,7 @@ export default function EditGasPopover({
const cleanTransactionParams = { ...updatedTransaction.txParams }; const cleanTransactionParams = { ...updatedTransaction.txParams };
if (networkAndAccountSupport1559) { if (supportsEIP1559) {
delete cleanTransactionParams.gasPrice; delete cleanTransactionParams.gasPrice;
} }
@ -182,7 +183,7 @@ export default function EditGasPopover({
break; break;
case EDIT_GAS_MODES.SWAPS: case EDIT_GAS_MODES.SWAPS:
// This popover component should only be used for the "FEE_MARKET" type in Swaps. // This popover component should only be used for the "FEE_MARKET" type in Swaps.
if (networkAndAccountSupport1559) { if (supportsEIP1559) {
dispatch(updateSwapsUserFeeLevel(estimateToUse || 'custom')); dispatch(updateSwapsUserFeeLevel(estimateToUse || 'custom'));
dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings)); dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings));
} }
@ -201,7 +202,7 @@ export default function EditGasPopover({
gasPrice, gasPrice,
maxFeePerGas, maxFeePerGas,
maxPriorityFeePerGas, maxPriorityFeePerGas,
networkAndAccountSupport1559, supportsEIP1559,
estimateToUse, estimateToUse,
estimatedBaseFee, estimatedBaseFee,
]); ]);

View File

@ -8,6 +8,7 @@ import {
TRANSACTION_TYPES, TRANSACTION_TYPES,
TRANSACTION_GROUP_STATUSES, TRANSACTION_GROUP_STATUSES,
TRANSACTION_STATUSES, TRANSACTION_STATUSES,
TRANSACTION_ENVELOPE_TYPES,
} from '../../../shared/constants/transaction'; } from '../../../shared/constants/transaction';
import { addCurrencies } from '../../../shared/modules/conversion.utils'; import { addCurrencies } from '../../../shared/modules/conversion.utils';
import fetchWithCache from './fetch-with-cache'; import fetchWithCache from './fetch-with-cache';
@ -161,6 +162,10 @@ export function sumHexes(...args) {
return addHexPrefix(total); return addHexPrefix(total);
} }
export function isLegacyTransaction(txParams) {
return txParams.type === TRANSACTION_ENVELOPE_TYPES.LEGACY;
}
/** /**
* Returns a status key for a transaction. Requires parsing the txMeta.txReceipt on top of * Returns a status key for a transaction. Requires parsing the txMeta.txReceipt on top of
* txMeta.status because txMeta.status does not reflect on-chain errors. * txMeta.status because txMeta.status does not reflect on-chain errors.

View File

@ -2,6 +2,7 @@ import {
TRANSACTION_TYPES, TRANSACTION_TYPES,
TRANSACTION_GROUP_STATUSES, TRANSACTION_GROUP_STATUSES,
TRANSACTION_STATUSES, TRANSACTION_STATUSES,
TRANSACTION_ENVELOPE_TYPES,
} from '../../../shared/constants/transaction'; } from '../../../shared/constants/transaction';
import * as utils from './transactions.util'; import * as utils from './transactions.util';
@ -59,4 +60,19 @@ describe('Transactions utils', () => {
}); });
}); });
}); });
describe('isLegacyTransaction', () => {
it('should return true if transaction is type-0', () => {
expect(
utils.isLegacyTransaction({ type: TRANSACTION_ENVELOPE_TYPES.LEGACY }),
).toStrictEqual(true);
});
it('should return false if transaction is not type-0', () => {
expect(
utils.isLegacyTransaction({
type: TRANSACTION_ENVELOPE_TYPES.FEE_MARKET,
}),
).toStrictEqual(false);
});
});
}); });

View File

@ -37,6 +37,7 @@ import {
bnLessThanEqualTo, bnLessThanEqualTo,
} from '../helpers/utils/util'; } from '../helpers/utils/util';
import { GAS_FORM_ERRORS } from '../helpers/constants/gas'; import { GAS_FORM_ERRORS } from '../helpers/constants/gas';
import { isLegacyTransaction } from '../helpers/utils/transactions.util';
import { useCurrencyDisplay } from './useCurrencyDisplay'; import { useCurrencyDisplay } from './useCurrencyDisplay';
import { useGasFeeEstimates } from './useGasFeeEstimates'; import { useGasFeeEstimates } from './useGasFeeEstimates';
@ -155,9 +156,9 @@ export function useGasFeeInputs(
editGasMode, editGasMode,
) { ) {
const { balance: ethBalance } = useSelector(getSelectedAccount); const { balance: ethBalance } = useSelector(getSelectedAccount);
const networkAndAccountSupports1559 = useSelector( const supportsEIP1559 =
checkNetworkAndAccountSupports1559, useSelector(checkNetworkAndAccountSupports1559) &&
); !isLegacyTransaction(transaction?.txParams);
// We need to know whether to show fiat conversions or not, so that we can // 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 // default our fiat values to empty strings if showing fiat is not wanted or
// possible. // possible.
@ -188,13 +189,13 @@ export function useGasFeeInputs(
} = useGasFeeEstimates(); } = useGasFeeEstimates();
const [initialMaxFeePerGas] = useState( const [initialMaxFeePerGas] = useState(
networkAndAccountSupports1559 && !transaction?.txParams?.maxFeePerGas supportsEIP1559 && !transaction?.txParams?.maxFeePerGas
? Number(hexWEIToDecGWEI(transaction?.txParams?.gasPrice)) ? Number(hexWEIToDecGWEI(transaction?.txParams?.gasPrice))
: Number(hexWEIToDecGWEI(transaction?.txParams?.maxFeePerGas)), : Number(hexWEIToDecGWEI(transaction?.txParams?.maxFeePerGas)),
); );
const [initialMaxPriorityFeePerGas] = useState( const [initialMaxPriorityFeePerGas] = useState(
networkAndAccountSupports1559 && supportsEIP1559 && !transaction?.txParams?.maxPriorityFeePerGas
!transaction?.txParams?.maxPriorityFeePerGas
? initialMaxFeePerGas ? initialMaxFeePerGas
: Number(hexWEIToDecGWEI(transaction?.txParams?.maxPriorityFeePerGas)), : Number(hexWEIToDecGWEI(transaction?.txParams?.maxPriorityFeePerGas)),
); );
@ -277,7 +278,9 @@ export function useGasFeeInputs(
); );
const gasPriceToUse = const gasPriceToUse =
gasPrice !== null && gasPrice !== null &&
(gasPriceHasBeenManuallySet || gasPriceEstimatesHaveNotChanged) (gasPriceHasBeenManuallySet ||
gasPriceEstimatesHaveNotChanged ||
isLegacyTransaction(transaction?.txParams))
? gasPrice ? gasPrice
: getGasPriceEstimate( : getGasPriceEstimate(
gasFeeEstimates, gasFeeEstimates,
@ -294,7 +297,7 @@ export function useGasFeeInputs(
const gasSettings = { const gasSettings = {
gasLimit: decimalToHex(gasLimit), gasLimit: decimalToHex(gasLimit),
}; };
if (networkAndAccountSupports1559) { if (supportsEIP1559) {
gasSettings.maxFeePerGas = maxFeePerGasToUse gasSettings.maxFeePerGas = maxFeePerGasToUse
? decGWEIToHexWEI(maxFeePerGasToUse) ? decGWEIToHexWEI(maxFeePerGasToUse)
: decGWEIToHexWEI(gasPriceToUse || '0'); : decGWEIToHexWEI(gasPriceToUse || '0');
@ -396,7 +399,7 @@ export function useGasFeeInputs(
// This ensures these are applied when the api fails to return a fee market type // This ensures these are applied when the api fails to return a fee market type
// It is okay if these errors get overwritten below, as those overwrites can only // It is okay if these errors get overwritten below, as those overwrites can only
// happen when the estimate api is live. // happen when the estimate api is live.
if (networkAndAccountSupports1559) { if (supportsEIP1559) {
if (bnLessThanEqualTo(maxPriorityFeePerGasToUse, 0)) { if (bnLessThanEqualTo(maxPriorityFeePerGasToUse, 0)) {
gasErrors.maxPriorityFee = GAS_FORM_ERRORS.MAX_PRIORITY_FEE_BELOW_MINIMUM; gasErrors.maxPriorityFee = GAS_FORM_ERRORS.MAX_PRIORITY_FEE_BELOW_MINIMUM;
} else if (bnGreaterThan(maxPriorityFeePerGasToUse, maxFeePerGasToUse)) { } else if (bnGreaterThan(maxPriorityFeePerGasToUse, maxFeePerGasToUse)) {
@ -404,67 +407,53 @@ export function useGasFeeInputs(
} }
} }
switch (gasEstimateType) { if (supportsEIP1559 && gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
case GAS_ESTIMATE_TYPES.FEE_MARKET: if (bnLessThanEqualTo(maxPriorityFeePerGasToUse, 0)) {
if (bnLessThanEqualTo(maxPriorityFeePerGasToUse, 0)) { gasErrors.maxPriorityFee = GAS_FORM_ERRORS.MAX_PRIORITY_FEE_BELOW_MINIMUM;
gasErrors.maxPriorityFee = } else if (
GAS_FORM_ERRORS.MAX_PRIORITY_FEE_BELOW_MINIMUM; !isGasEstimatesLoading &&
} else if ( bnLessThan(
!isGasEstimatesLoading && maxPriorityFeePerGasToUse,
bnLessThan( gasFeeEstimates?.low?.suggestedMaxPriorityFeePerGas,
maxPriorityFeePerGasToUse, )
gasFeeEstimates?.low?.suggestedMaxPriorityFeePerGas, ) {
) gasWarnings.maxPriorityFee = GAS_FORM_ERRORS.MAX_PRIORITY_FEE_TOO_LOW;
) { } else if (bnGreaterThan(maxPriorityFeePerGasToUse, maxFeePerGasToUse)) {
gasWarnings.maxPriorityFee = GAS_FORM_ERRORS.MAX_PRIORITY_FEE_TOO_LOW; gasErrors.maxFee = GAS_FORM_ERRORS.MAX_FEE_IMBALANCE;
} else if (bnGreaterThan(maxPriorityFeePerGasToUse, maxFeePerGasToUse)) { } else if (
gasErrors.maxFee = GAS_FORM_ERRORS.MAX_FEE_IMBALANCE; gasFeeEstimates?.high &&
} else if ( bnGreaterThan(
gasFeeEstimates?.high && maxPriorityFeePerGasToUse,
bnGreaterThan( gasFeeEstimates.high.suggestedMaxPriorityFeePerGas *
maxPriorityFeePerGasToUse, HIGH_FEE_WARNING_MULTIPLIER,
gasFeeEstimates.high.suggestedMaxPriorityFeePerGas * )
HIGH_FEE_WARNING_MULTIPLIER, ) {
) gasWarnings.maxPriorityFee =
) { GAS_FORM_ERRORS.MAX_PRIORITY_FEE_HIGH_WARNING;
gasWarnings.maxPriorityFee = }
GAS_FORM_ERRORS.MAX_PRIORITY_FEE_HIGH_WARNING;
}
if ( if (
!isGasEstimatesLoading && !isGasEstimatesLoading &&
bnLessThan( bnLessThan(maxFeePerGasToUse, gasFeeEstimates?.low?.suggestedMaxFeePerGas)
maxFeePerGasToUse, ) {
gasFeeEstimates?.low?.suggestedMaxFeePerGas, gasWarnings.maxFee = GAS_FORM_ERRORS.MAX_FEE_TOO_LOW;
) } else if (
) { gasFeeEstimates?.high &&
gasWarnings.maxFee = GAS_FORM_ERRORS.MAX_FEE_TOO_LOW; bnGreaterThan(
} else if ( maxFeePerGasToUse,
gasFeeEstimates?.high && gasFeeEstimates.high.suggestedMaxFeePerGas *
bnGreaterThan( HIGH_FEE_WARNING_MULTIPLIER,
maxFeePerGasToUse, )
gasFeeEstimates.high.suggestedMaxFeePerGas * ) {
HIGH_FEE_WARNING_MULTIPLIER, gasWarnings.maxFee = GAS_FORM_ERRORS.MAX_FEE_HIGH_WARNING;
) }
) { } else if (supportsEIP1559) {
gasWarnings.maxFee = GAS_FORM_ERRORS.MAX_FEE_HIGH_WARNING; estimatesUnavailableWarning = true;
} } else if (
break; (!supportsEIP1559 || transaction?.txParams?.gasPrice) &&
case GAS_ESTIMATE_TYPES.LEGACY: bnLessThanEqualTo(gasPriceToUse, 0)
case GAS_ESTIMATE_TYPES.ETH_GASPRICE: ) {
case GAS_ESTIMATE_TYPES.NONE: gasErrors.gasPrice = GAS_FORM_ERRORS.GAS_PRICE_TOO_LOW;
if (networkAndAccountSupports1559) {
estimatesUnavailableWarning = true;
}
if (
(!networkAndAccountSupports1559 || transaction?.txParams?.gasPrice) &&
bnLessThanEqualTo(gasPriceToUse, 0)
) {
gasErrors.gasPrice = GAS_FORM_ERRORS.GAS_PRICE_TOO_LOW;
}
break;
default:
break;
} }
// Determine if we have any errors which should block submission // Determine if we have any errors which should block submission

View File

@ -2,6 +2,7 @@ import { act, renderHook } from '@testing-library/react-hooks';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { GAS_ESTIMATE_TYPES } from '../../shared/constants/gas'; import { GAS_ESTIMATE_TYPES } from '../../shared/constants/gas';
import { multiplyCurrencies } from '../../shared/modules/conversion.utils'; import { multiplyCurrencies } from '../../shared/modules/conversion.utils';
import { TRANSACTION_ENVELOPE_TYPES } from '../../shared/constants/transaction';
import { import {
getConversionRate, getConversionRate,
getNativeCurrency, getNativeCurrency,
@ -223,6 +224,31 @@ describe('useGasFeeInputs', () => {
}); });
}); });
describe('when transaction is type-0', () => {
beforeEach(() => {
useGasFeeEstimates.mockImplementation(
() => FEE_MARKET_ESTIMATE_RETURN_VALUE,
);
useSelector.mockImplementation(generateUseSelectorRouter());
});
it('returns gasPrice appropriately, and "0" for EIP1559 fields', () => {
const { result } = renderHook(() =>
useGasFeeInputs('medium', {
txParams: {
value: '3782DACE9D90000',
gasLimit: '0x5028',
gasPrice: '0x5028',
type: TRANSACTION_ENVELOPE_TYPES.LEGACY,
},
}),
);
expect(result.current.gasPrice).toBe(0.00002052);
expect(result.current.maxFeePerGas).toBe('0');
expect(result.current.maxPriorityFeePerGas).toBe('0');
expect(result.current.hasBlockingGasErrors).toBeUndefined();
});
});
describe('when using EIP 1559 API for estimation', () => { describe('when using EIP 1559 API for estimation', () => {
beforeEach(() => { beforeEach(() => {
useGasFeeEstimates.mockImplementation( useGasFeeEstimates.mockImplementation(
@ -260,7 +286,9 @@ describe('useGasFeeInputs', () => {
checkNetworkAndAccountSupports1559Response: true, checkNetworkAndAccountSupports1559Response: true,
}), }),
); );
const { result } = renderHook(() => useGasFeeInputs()); const { result } = renderHook(() =>
useGasFeeInputs(null, { txParams: {}, userFeeLevel: 'medium' }),
);
expect(result.current.maxFeePerGas).toBe( expect(result.current.maxFeePerGas).toBe(
FEE_MARKET_ESTIMATE_RETURN_VALUE.gasFeeEstimates.medium FEE_MARKET_ESTIMATE_RETURN_VALUE.gasFeeEstimates.medium
.suggestedMaxFeePerGas, .suggestedMaxFeePerGas,

View File

@ -128,6 +128,7 @@ export default class ConfirmTransactionBase extends Component {
showLedgerSteps: PropTypes.bool.isRequired, showLedgerSteps: PropTypes.bool.isRequired,
isFirefox: PropTypes.bool.isRequired, isFirefox: PropTypes.bool.isRequired,
nativeCurrency: PropTypes.string, nativeCurrency: PropTypes.string,
supportsEIP1559: PropTypes.bool,
}; };
state = { state = {
@ -309,6 +310,7 @@ export default class ConfirmTransactionBase extends Component {
isMainnet, isMainnet,
showLedgerSteps, showLedgerSteps,
isFirefox, isFirefox,
supportsEIP1559,
} = this.props; } = this.props;
const { t } = this.context; const { t } = this.context;
@ -541,15 +543,17 @@ export default class ConfirmTransactionBase extends Component {
) : ( ) : (
'' ''
)} )}
<GasTiming {supportsEIP1559 && (
maxPriorityFeePerGas={hexWEIToDecGWEI( <GasTiming
maxPriorityFeePerGas || maxPriorityFeePerGas={hexWEIToDecGWEI(
txData.txParams.maxPriorityFeePerGas, maxPriorityFeePerGas ||
)} txData.txParams.maxPriorityFeePerGas,
maxFeePerGas={hexWEIToDecGWEI( )}
maxFeePerGas || txData.txParams.maxFeePerGas, maxFeePerGas={hexWEIToDecGWEI(
)} maxFeePerGas || txData.txParams.maxFeePerGas,
/> )}
/>
)}
</> </>
} }
/>, />,

View File

@ -47,6 +47,7 @@ import {
getNativeCurrency, getNativeCurrency,
} from '../../ducks/metamask/metamask'; } from '../../ducks/metamask/metamask';
import { getGasLoadingAnimationIsShowing } from '../../ducks/app/app'; import { getGasLoadingAnimationIsShowing } from '../../ducks/app/app';
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import ConfirmTransactionBase from './confirm-transaction-base.component'; import ConfirmTransactionBase from './confirm-transaction-base.component';
let customNonceValue = ''; let customNonceValue = '';
@ -66,7 +67,6 @@ const mapStateToProps = (state, ownProps) => {
} = ownProps; } = ownProps;
const { id: paramsTransactionId } = params; const { id: paramsTransactionId } = params;
const isMainnet = getIsMainnet(state); const isMainnet = getIsMainnet(state);
const supportsEIP1599 = checkNetworkAndAccountSupports1559(state);
const isGasEstimatesLoading = getIsGasEstimatesLoading(state); const isGasEstimatesLoading = getIsGasEstimatesLoading(state);
const gasLoadingAnimationIsShowing = getGasLoadingAnimationIsShowing(state); const gasLoadingAnimationIsShowing = getGasLoadingAnimationIsShowing(state);
@ -122,6 +122,8 @@ const mapStateToProps = (state, ownProps) => {
const toEns = ensResolutionsByAddress[checksummedAddress] || ''; const toEns = ensResolutionsByAddress[checksummedAddress] || '';
const toNickname = addressBookObject ? addressBookObject.name : ''; const toNickname = addressBookObject ? addressBookObject.name : '';
const transactionStatus = transaction ? transaction.status : ''; const transactionStatus = transaction ? transaction.status : '';
const supportsEIP1559 =
checkNetworkAndAccountSupports1559(state) && !isLegacyTransaction(txParams);
const { const {
hexTransactionAmount, hexTransactionAmount,
@ -163,7 +165,7 @@ const mapStateToProps = (state, ownProps) => {
} }
customNonceValue = getCustomNonceValue(state); customNonceValue = getCustomNonceValue(state);
const isEthGasPrice = getIsEthGasPriceFetched(state); const isEthGasPrice = getIsEthGasPriceFetched(state);
const noGasPrice = !supportsEIP1599 && getNoGasPriceFetched(state); const noGasPrice = !supportsEIP1559 && getNoGasPriceFetched(state);
const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state); const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state);
const gasFeeIsCustom = const gasFeeIsCustom =
fullTxData.userFeeLevel === 'custom' || fullTxData.userFeeLevel === 'custom' ||
@ -210,7 +212,7 @@ const mapStateToProps = (state, ownProps) => {
isMainnet, isMainnet,
isEthGasPrice, isEthGasPrice,
noGasPrice, noGasPrice,
supportsEIP1599, supportsEIP1559,
gasIsLoading: isGasEstimatesLoading || gasLoadingAnimationIsShowing, gasIsLoading: isGasEstimatesLoading || gasLoadingAnimationIsShowing,
useNativeCurrencyAsPrimaryCurrency, useNativeCurrencyAsPrimaryCurrency,
maxFeePerGas: gasEstimationObject.maxFeePerGas, maxFeePerGas: gasEstimationObject.maxFeePerGas,