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

Using EIP-1559 V2 for approve transaction flow (#12906)

This commit is contained in:
Jyoti Puri 2021-12-06 22:09:35 +05:30 committed by GitHub
parent a6bb503e52
commit 6fc9b6b7a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 414 additions and 329 deletions

View File

@ -13,6 +13,7 @@
@import 'connected-status-indicator/index'; @import 'connected-status-indicator/index';
@import 'edit-gas-display/index'; @import 'edit-gas-display/index';
@import 'edit-gas-display-education/index'; @import 'edit-gas-display-education/index';
@import 'edit-gas-fee-button/index';
@import 'edit-gas-fee-popover/index'; @import 'edit-gas-fee-popover/index';
@import 'edit-gas-fee-popover/edit-gas-item/index'; @import 'edit-gas-fee-popover/edit-gas-item/index';
@import 'edit-gas-fee-popover/network-statistics/index'; @import 'edit-gas-fee-popover/network-statistics/index';

View File

@ -0,0 +1,73 @@
import React from 'react';
import PropTypes from 'prop-types';
import { COLORS } from '../../../helpers/constants/design-system';
import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas';
import { useGasFeeContext } from '../../../contexts/gasFee';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { useTransactionModalContext } from '../../../contexts/transaction-modal';
import InfoTooltip from '../../ui/info-tooltip/info-tooltip';
import Typography from '../../ui/typography/typography';
export default function EditGasFeeButton({ userAcknowledgedGasMissing }) {
const t = useI18nContext();
const {
gasLimit,
hasSimulationError,
estimateUsed,
maxFeePerGas,
maxPriorityFeePerGas,
supportsEIP1559V2,
transaction,
} = useGasFeeContext();
const { openModal } = useTransactionModalContext();
const editEnabled =
!hasSimulationError || userAcknowledgedGasMissing === true;
if (!supportsEIP1559V2 || !estimateUsed || !editEnabled) {
return null;
}
return (
<div className="edit-gas-fee-button">
<button onClick={() => openModal('editGasFee')}>
<span className="edit-gas-fee-button__icon">
{`${PRIORITY_LEVEL_ICON_MAP[estimateUsed]} `}
</span>
<span className="edit-gas-fee-button__label">{t(estimateUsed)}</span>
<i className="fas fa-chevron-right asset-list-item__chevron-right" />
</button>
{estimateUsed === 'custom' && (
<button onClick={() => openModal('advancedGasFee')}>{t('edit')}</button>
)}
{estimateUsed === 'dappSuggested' && (
<InfoTooltip
contentText={
<div className="edit-gas-fee-button__tooltip">
<Typography fontSize="12px" color={COLORS.GREY}>
{t('dappSuggestedTooltip', [transaction.origin])}
</Typography>
<Typography fontSize="12px">
<b>{t('maxBaseFee')}</b>
{maxFeePerGas}
</Typography>
<Typography fontSize="12px">
<b>{t('maxPriorityFee')}</b>
{maxPriorityFeePerGas}
</Typography>
<Typography fontSize="12px">
<b>{t('gasLimit')}</b>
{gasLimit}
</Typography>
</div>
}
position="top"
/>
)}
</div>
);
}
EditGasFeeButton.propTypes = {
userAcknowledgedGasMissing: PropTypes.bool,
};

View File

@ -0,0 +1,140 @@
import React from 'react';
import { screen } from '@testing-library/react';
import {
GAS_ESTIMATE_TYPES,
PRIORITY_LEVELS,
} from '../../../../shared/constants/gas';
import { TRANSACTION_ENVELOPE_TYPES } from '../../../../shared/constants/transaction';
import { GasFeeContextProvider } from '../../../contexts/gasFee';
import { renderWithProvider } from '../../../../test/jest';
import mockEstimates from '../../../../test/data/mock-estimates.json';
import mockState from '../../../../test/data/mock-state.json';
import configureStore from '../../../store/store';
import EditGasFeeButton from './edit-gas-fee-button';
jest.mock('../../../store/actions', () => ({
disconnectGasFeeEstimatePoller: jest.fn(),
getGasFeeEstimatesAndStartPolling: jest
.fn()
.mockImplementation(() => Promise.resolve()),
addPollingTokenToAppState: jest.fn(),
}));
const render = ({ componentProps, contextProps } = {}) => {
const store = configureStore({
metamask: {
...mockState.metamask,
accounts: {
[mockState.metamask.selectedAddress]: {
address: mockState.metamask.selectedAddress,
balance: '0x1F4',
},
},
gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET],
},
});
return renderWithProvider(
<GasFeeContextProvider {...contextProps}>
<EditGasFeeButton {...componentProps} />
</GasFeeContextProvider>,
store,
);
};
describe('EditGasFeeButton', () => {
beforeEach(() => {
process.env.EIP_1559_V2 = true;
});
afterEach(() => {
process.env.EIP_1559_V2 = false;
});
it('should render edit link with text low if low gas estimates are selected', () => {
render({ contextProps: { transaction: { userFeeLevel: 'low' } } });
expect(screen.queryByText('🐢')).toBeInTheDocument();
expect(screen.queryByText('Low')).toBeInTheDocument();
});
it('should render edit link with text market if medium gas estimates are selected', () => {
render({ contextProps: { transaction: { userFeeLevel: 'medium' } } });
expect(screen.queryByText('🦊')).toBeInTheDocument();
expect(screen.queryByText('Market')).toBeInTheDocument();
});
it('should render edit link with text agressive if high gas estimates are selected', () => {
render({ contextProps: { transaction: { userFeeLevel: 'high' } } });
expect(screen.queryByText('🦍')).toBeInTheDocument();
expect(screen.queryByText('Aggressive')).toBeInTheDocument();
});
it('should render edit link with text Site suggested if site suggested estimated are used', () => {
render({
contextProps: {
transaction: {
userFeeLevel: PRIORITY_LEVELS.DAPP_SUGGESTED,
dappSuggestedGasFees: { maxFeePerGas: 1, maxPriorityFeePerGas: 1 },
txParams: { maxFeePerGas: 1, maxPriorityFeePerGas: 1 },
},
},
});
expect(screen.queryByText('🌐')).toBeInTheDocument();
expect(screen.queryByText('Site suggested')).toBeInTheDocument();
expect(document.getElementsByClassName('info-tooltip')).toHaveLength(1);
});
it('should render edit link with text advance if custom gas estimates are used', () => {
render({
contextProps: {
defaultEstimateToUse: 'custom',
},
});
expect(screen.queryByText('⚙')).toBeInTheDocument();
expect(screen.queryByText('Advanced')).toBeInTheDocument();
expect(screen.queryByText('Edit')).toBeInTheDocument();
});
it('should not render edit link if transaction has simulation error and prop userAcknowledgedGasMissing is false', () => {
render({
contextProps: {
transaction: {
simulationFails: true,
userFeeLevel: 'low',
},
},
componentProps: { userAcknowledgedGasMissing: false },
});
expect(screen.queryByRole('button')).not.toBeInTheDocument();
expect(screen.queryByText('Low')).not.toBeInTheDocument();
});
it('should render edit link if userAcknowledgedGasMissing is true even if transaction has simulation error', () => {
render({
contextProps: {
transaction: {
simulationFails: true,
userFeeLevel: 'low',
},
},
componentProps: { userAcknowledgedGasMissing: true },
});
expect(screen.queryByRole('button')).toBeInTheDocument();
expect(screen.queryByText('Low')).toBeInTheDocument();
});
it('should render null for legacy transactions', () => {
const { container } = render({
contextProps: {
transaction: {
userFeeLevel: 'low',
txParams: { type: TRANSACTION_ENVELOPE_TYPES.LEGACY },
},
},
});
expect(container.firstChild).toBeNull();
});
});

View File

@ -0,0 +1 @@
export { default } from './edit-gas-fee-button';

View File

@ -0,0 +1,48 @@
.edit-gas-fee-button {
display: flex;
align-items: baseline;
justify-content: flex-end;
button {
@include H7;
display: flex;
align-items: baseline;
color: $primary-1;
background: transparent;
border: 0;
padding-inline-end: 0;
white-space: pre;
}
i {
color: $primary-1;
margin-right: 2px;
}
&__icon {
font-size: 16px;
}
&__label {
font-size: 12px;
margin-right: 8px;
}
.info-tooltip {
align-self: center;
margin-left: 6px;
}
&__tooltip {
p {
color: $Grey-500;
}
b {
color: $neutral-black;
display: inline-block;
min-width: 60%;
}
}
}

View File

@ -44,15 +44,15 @@ const EditGasItem = ({ priorityLevel }) => {
if (gasFeeEstimates?.[priorityLevel]) { if (gasFeeEstimates?.[priorityLevel]) {
maxFeePerGas = gasFeeEstimates[priorityLevel].suggestedMaxFeePerGas; maxFeePerGas = gasFeeEstimates[priorityLevel].suggestedMaxFeePerGas;
maxPriorityFeePerGas =
gasFeeEstimates[priorityLevel].suggestedMaxPriorityFeePerGas;
} else if ( } else if (
priorityLevel === PRIORITY_LEVELS.DAPP_SUGGESTED && priorityLevel === PRIORITY_LEVELS.DAPP_SUGGESTED &&
dappSuggestedGasFees dappSuggestedGasFees
) { ) {
maxFeePerGas = hexWEIToDecGWEI(dappSuggestedGasFees.maxFeePerGas); maxFeePerGas = hexWEIToDecGWEI(
dappSuggestedGasFees.maxFeePerGas || dappSuggestedGasFees.gasPrice,
);
maxPriorityFeePerGas = hexWEIToDecGWEI( maxPriorityFeePerGas = hexWEIToDecGWEI(
dappSuggestedGasFees.maxPriorityFeePerGas, dappSuggestedGasFees.maxPriorityFeePerGas || maxFeePerGas,
); );
} else if (priorityLevel === PRIORITY_LEVELS.CUSTOM) { } else if (priorityLevel === PRIORITY_LEVELS.CUSTOM) {
if (estimateUsed === PRIORITY_LEVELS.CUSTOM) { if (estimateUsed === PRIORITY_LEVELS.CUSTOM) {

View File

@ -118,7 +118,10 @@ describe('EditGasItem', () => {
it('should renders site gas estimate option for priorityLevel dappSuggested', () => { it('should renders site gas estimate option for priorityLevel dappSuggested', () => {
renderComponent( renderComponent(
{ priorityLevel: 'dappSuggested' }, { priorityLevel: 'dappSuggested' },
{ dappSuggestedGasFees: DAPP_SUGGESTED_ESTIMATE }, {
dappSuggestedGasFees: DAPP_SUGGESTED_ESTIMATE,
txParams: { gas: '0x5208', ...DAPP_SUGGESTED_ESTIMATE },
},
); );
expect( expect(
screen.queryByRole('button', { name: 'dappSuggested' }), screen.queryByRole('button', { name: 'dappSuggested' }),

View File

@ -16,72 +16,6 @@
} }
} }
&-edit-V2 {
display: flex;
align-items: baseline;
justify-content: flex-end;
padding-top: 20px;
button {
@include H7;
display: flex;
align-items: baseline;
color: $primary-1;
background: transparent;
border: 0;
padding-inline-end: 0;
position: relative;
white-space: pre;
}
&__edit-button {
margin-left: 8px;
}
i {
color: $primary-1;
margin-right: 2px;
}
&__icon {
@include Paragraph;
line-height: 1;
position: absolute;
left: -16px;
top: 0;
&-custom {
font-size: 1.35rem;
left: -12px;
top: -2px;
}
}
&__label {
font-size: 12px;
margin-right: 8px;
}
.info-tooltip {
align-self: center;
margin-left: 6px;
}
&__tooltip {
p {
color: $Grey-500;
}
b {
color: $neutral-black;
display: inline-block;
min-width: 60%;
}
}
}
&-rows { &-rows {
margin-top: 10px; margin-top: 10px;
} }

View File

@ -2,14 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useGasFeeContext } from '../../../contexts/gasFee'; import { useGasFeeContext } from '../../../contexts/gasFee';
import { useTransactionModalContext } from '../../../contexts/transaction-modal';
import InfoTooltip from '../../ui/info-tooltip/info-tooltip';
import Typography from '../../ui/typography/typography';
import TransactionDetailItem from '../transaction-detail-item/transaction-detail-item.component';
import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system';
import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas';
import { useI18nContext } from '../../../hooks/useI18nContext'; import { useI18nContext } from '../../../hooks/useI18nContext';
import Box from '../../ui/box';
import EditGasFeeButton from '../edit-gas-fee-button';
import TransactionDetailItem from '../transaction-detail-item/transaction-detail-item.component';
export default function TransactionDetail({ export default function TransactionDetail({
rows = [], rows = [],
@ -17,89 +14,18 @@ export default function TransactionDetail({
userAcknowledgedGasMissing, userAcknowledgedGasMissing,
}) { }) {
const t = useI18nContext(); const t = useI18nContext();
const { const { supportsEIP1559V2 } = useGasFeeContext();
gasLimit,
hasSimulationError,
estimateUsed,
maxFeePerGas,
maxPriorityFeePerGas,
supportsEIP1559V2,
transaction,
} = useGasFeeContext();
const { openModal } = useTransactionModalContext();
if (supportsEIP1559V2 && estimateUsed) {
const editEnabled = !hasSimulationError || userAcknowledgedGasMissing;
if (!editEnabled) return null;
return ( return (
<div className="transaction-detail"> <div className="transaction-detail">
<div className="transaction-detail-edit-V2"> {supportsEIP1559V2 && (
<button onClick={() => openModal('editGasFee')}> <Box display="flex" justifyContent="flex-end" paddingTop={5}>
<span <EditGasFeeButton
className={`transaction-detail-edit-V2__icon transaction-detail-edit-V2__icon-${estimateUsed}`} userAcknowledgedGasMissing={userAcknowledgedGasMissing}
>
{`${PRIORITY_LEVEL_ICON_MAP[estimateUsed]} `}
</span>
<span className="transaction-detail-edit-V2__label">
{t(estimateUsed)}
</span>
<i className="fas fa-chevron-right asset-list-item__chevron-right" />
</button>
{estimateUsed === 'custom' && (
<button
onClick={() => openModal('advancedGasFee')}
className="transaction-detail__edit-button"
>
{t('edit')}
</button>
)}
{estimateUsed === 'dappSuggested' && (
<InfoTooltip
contentText={
<div className="transaction-detail-edit-V2__tooltip">
<Typography
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
color={COLORS.GREY}
>
{t('dappSuggestedTooltip', [transaction.origin])}
</Typography>
<Typography
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>
<strong>{t('maxBaseFee')}</strong>
{maxFeePerGas}
</Typography>
<Typography
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>
<strong>{t('maxPriorityFee')}</strong>
{maxPriorityFeePerGas}
</Typography>
<Typography
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>
<strong>{t('gasLimit')}</strong>
{gasLimit}
</Typography>
</div>
}
position="top"
/> />
</Box>
)} )}
</div> {!supportsEIP1559V2 && onEdit && (
<div className="transaction-detail-rows">{rows}</div>
</div>
);
}
return (
<div className="transaction-detail">
{onEdit && (
<div className="transaction-detail-edit"> <div className="transaction-detail-edit">
<button onClick={onEdit}>{t('edit')}</button> <button onClick={onEdit}>{t('edit')}</button>
</div> </div>

View File

@ -1,10 +1,7 @@
import React from 'react'; import React from 'react';
import { screen } from '@testing-library/react'; import { screen } from '@testing-library/react';
import { import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
GAS_ESTIMATE_TYPES,
PRIORITY_LEVELS,
} from '../../../../shared/constants/gas';
import { TRANSACTION_ENVELOPE_TYPES } from '../../../../shared/constants/transaction'; import { TRANSACTION_ENVELOPE_TYPES } from '../../../../shared/constants/transaction';
import { GasFeeContextProvider } from '../../../contexts/gasFee'; import { GasFeeContextProvider } from '../../../contexts/gasFee';
@ -67,72 +64,6 @@ describe('TransactionDetail', () => {
expect(screen.queryByText('Low')).toBeInTheDocument(); expect(screen.queryByText('Low')).toBeInTheDocument();
}); });
it('should render edit link with text markey if medium gas estimates are selected', () => {
render({ contextProps: { transaction: { userFeeLevel: 'medium' } } });
expect(screen.queryByText('🦊')).toBeInTheDocument();
expect(screen.queryByText('Market')).toBeInTheDocument();
});
it('should render edit link with text agressive if high gas estimates are selected', () => {
render({ contextProps: { transaction: { userFeeLevel: 'high' } } });
expect(screen.queryByText('🦍')).toBeInTheDocument();
expect(screen.queryByText('Aggressive')).toBeInTheDocument();
});
it('should render edit link with text Site suggested if site suggested estimated are used', () => {
render({
contextProps: {
transaction: {
userFeeLevel: PRIORITY_LEVELS.DAPP_SUGGESTED,
dappSuggestedGasFees: { maxFeePerGas: 1, maxPriorityFeePerGas: 1 },
txParams: { maxFeePerGas: 1, maxPriorityFeePerGas: 1 },
},
},
});
expect(screen.queryByText('🌐')).toBeInTheDocument();
expect(screen.queryByText('Site suggested')).toBeInTheDocument();
expect(document.getElementsByClassName('info-tooltip')).toHaveLength(1);
});
it('should render edit link with text advance if custom gas estimates are used', () => {
render({
contextProps: {
defaultEstimateToUse: 'custom',
},
});
expect(screen.queryByText('⚙')).toBeInTheDocument();
expect(screen.queryByText('Advanced')).toBeInTheDocument();
expect(screen.queryByText('Edit')).toBeInTheDocument();
});
it('should not render edit link if transaction has simulation error and prop userAcknowledgedGasMissing is false', () => {
render({
contextProps: {
transaction: {
simulationFails: true,
userFeeLevel: 'low',
},
},
componentProps: { userAcknowledgedGasMissing: false },
});
expect(screen.queryByRole('button')).not.toBeInTheDocument();
expect(screen.queryByText('Low')).not.toBeInTheDocument();
});
it('should render edit link if userAcknowledgedGasMissing is true even if transaction has simulation error', () => {
render({
contextProps: {
transaction: {
simulationFails: true,
userFeeLevel: 'low',
},
},
componentProps: { userAcknowledgedGasMissing: true },
});
expect(screen.queryByRole('button')).toBeInTheDocument();
expect(screen.queryByText('Low')).toBeInTheDocument();
});
it('should render edit link with text edit for legacy transactions', () => { it('should render edit link with text edit for legacy transactions', () => {
render({ render({
contextProps: { contextProps: {

View File

@ -12,6 +12,7 @@ export const TransactionModalContextProvider = ({
actionKey, actionKey,
children, children,
methodData, methodData,
captureEventEnabled = true,
}) => { }) => {
const [openModals, setOpenModals] = useState([]); const [openModals, setOpenModals] = useState([]);
const metricsEvent = useMetaMetricsContext(); const metricsEvent = useMetaMetricsContext();
@ -28,7 +29,7 @@ export const TransactionModalContextProvider = ({
recipientKnown: null, recipientKnown: null,
functionType: functionType:
actionKey || actionKey ||
getMethodName(methodData.name) || getMethodName(methodData?.name) ||
TRANSACTION_TYPES.CONTRACT_INTERACTION, TRANSACTION_TYPES.CONTRACT_INTERACTION,
origin, origin,
}, },
@ -49,7 +50,7 @@ export const TransactionModalContextProvider = ({
const openModal = (modalName) => { const openModal = (modalName) => {
if (openModals.includes(modalName)) return; if (openModals.includes(modalName)) return;
captureEvent(); captureEventEnabled && captureEvent();
const modals = [...openModals]; const modals = [...openModals];
modals.push(modalName); modals.push(modalName);
setOpenModals(modals); setOpenModals(modals);
@ -77,4 +78,5 @@ TransactionModalContextProvider.propTypes = {
actionKey: PropTypes.string, actionKey: PropTypes.string,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
methodData: PropTypes.object, methodData: PropTypes.object,
captureEventEnabled: PropTypes.bool,
}; };

View File

@ -11,6 +11,7 @@ import { ellipsify } from '../../send/send.utils';
import Typography from '../../../components/ui/typography'; import Typography from '../../../components/ui/typography';
import Box from '../../../components/ui/box'; import Box from '../../../components/ui/box';
import Button from '../../../components/ui/button'; import Button from '../../../components/ui/button';
import EditGasFeeButton from '../../../components/app/edit-gas-fee-button';
import MetaFoxLogo from '../../../components/ui/metafox-logo'; import MetaFoxLogo from '../../../components/ui/metafox-logo';
import Identicon from '../../../components/ui/identicon'; import Identicon from '../../../components/ui/identicon';
import MultiLayerFeeMessage from '../../../components/app/multilayer-fee-message'; import MultiLayerFeeMessage from '../../../components/app/multilayer-fee-message';
@ -64,6 +65,7 @@ export default class ConfirmApproveContent extends Component {
isContract: PropTypes.bool, isContract: PropTypes.bool,
hexTransactionTotal: PropTypes.string, hexTransactionTotal: PropTypes.string,
isMultiLayerFeeNetwork: PropTypes.bool, isMultiLayerFeeNetwork: PropTypes.bool,
supportsEIP1559V2: PropTypes.bool,
}; };
state = { state = {
@ -76,11 +78,13 @@ export default class ConfirmApproveContent extends Component {
symbol, symbol,
title, title,
showEdit, showEdit,
showAdvanceGasFeeOptions = false,
onEditClick, onEditClick,
content, content,
footer, footer,
noBorder, noBorder,
}) { }) {
const { supportsEIP1559V2 } = this.props;
const { t } = this.context; const { t } = this.context;
return ( return (
<div <div
@ -97,7 +101,7 @@ export default class ConfirmApproveContent extends Component {
<div className="confirm-approve-content__card-header__title"> <div className="confirm-approve-content__card-header__title">
{title} {title}
</div> </div>
{showEdit && ( {showEdit && (!showAdvanceGasFeeOptions || !supportsEIP1559V2) && (
<Box width={BLOCK_SIZES.ONE_SIXTH}> <Box width={BLOCK_SIZES.ONE_SIXTH}>
<Button <Button
type="link" type="link"
@ -108,6 +112,9 @@ export default class ConfirmApproveContent extends Component {
</Button> </Button>
</Box> </Box>
)} )}
{showEdit && showAdvanceGasFeeOptions && supportsEIP1559V2 && (
<EditGasFeeButton />
)}
</div> </div>
)} )}
<div className="confirm-approve-content__card-content">{content}</div> <div className="confirm-approve-content__card-content">{content}</div>
@ -445,6 +452,7 @@ export default class ConfirmApproveContent extends Component {
symbol: <i className="fa fa-tag" />, symbol: <i className="fa fa-tag" />,
title: t('transactionFee'), title: t('transactionFee'),
showEdit: true, showEdit: true,
showAdvanceGasFeeOptions: true,
onEditClick: showCustomizeGasModal, onEditClick: showCustomizeGasModal,
content: this.renderTransactionDetailsContent(), content: this.renderTransactionDetailsContent(),
noBorder: useNonceField || !showFullTxDetails, noBorder: useNonceField || !showFullTxDetails,

View File

@ -15,6 +15,8 @@ import {
getTokenValueParam, getTokenValueParam,
} from '../../helpers/utils/token-util'; } from '../../helpers/utils/token-util';
import { readAddressAsContract } from '../../../shared/modules/contract-utils'; import { readAddressAsContract } from '../../../shared/modules/contract-utils';
import { GasFeeContextProvider } from '../../contexts/gasFee';
import { TransactionModalContextProvider } from '../../contexts/transaction-modal';
import { useTokenTracker } from '../../hooks/useTokenTracker'; import { useTokenTracker } from '../../hooks/useTokenTracker';
import { import {
getTokens, getTokens,
@ -32,13 +34,14 @@ import {
getCurrentChainId, getCurrentChainId,
getRpcPrefsForCurrentProvider, getRpcPrefsForCurrentProvider,
getIsMultiLayerFeeNetwork, getIsMultiLayerFeeNetwork,
checkNetworkAndAccountSupports1559,
} from '../../selectors'; } from '../../selectors';
import { useApproveTransaction } from '../../hooks/useApproveTransaction'; import { useApproveTransaction } from '../../hooks/useApproveTransaction';
import { currentNetworkTxListSelector } from '../../selectors/transactions'; import { currentNetworkTxListSelector } from '../../selectors/transactions';
import Loading from '../../components/ui/loading-screen'; import AdvancedGasFeePopover from '../../components/app/advanced-gas-fee-popover';
import EditGasFeePopover from '../../components/app/edit-gas-fee-popover';
import EditGasPopover from '../../components/app/edit-gas-popover/edit-gas-popover.component'; import EditGasPopover from '../../components/app/edit-gas-popover/edit-gas-popover.component';
import Loading from '../../components/ui/loading-screen';
import { isEqualCaseInsensitive } from '../../helpers/utils/util'; import { isEqualCaseInsensitive } from '../../helpers/utils/util';
import { getCustomTxParamsData } from './confirm-approve.util'; import { getCustomTxParamsData } from './confirm-approve.util';
import ConfirmApproveContent from './confirm-approve-content'; import ConfirmApproveContent from './confirm-approve-content';
@ -47,6 +50,10 @@ const isAddressLedgerByFromAddress = (address) => (state) => {
return isAddressLedger(state, address); return isAddressLedger(state, address);
}; };
// eslint-disable-next-line prefer-destructuring
const EIP_1559_V2_ENABLED =
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
export default function ConfirmApprove() { export default function ConfirmApprove() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { id: paramsTransactionId } = useParams(); const { id: paramsTransactionId } = useParams();
@ -66,6 +73,9 @@ export default function ConfirmApprove() {
const chainId = useSelector(getCurrentChainId); const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork);
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
const fromAddressIsLedger = useSelector(isAddressLedgerByFromAddress(from)); const fromAddressIsLedger = useSelector(isAddressLedgerByFromAddress(from));
@ -79,6 +89,9 @@ export default function ConfirmApprove() {
hexTransactionTotal, hexTransactionTotal,
} = useSelector((state) => transactionFeeSelector(state, transaction)); } = useSelector((state) => transactionFeeSelector(state, transaction));
const supportsEIP1559V2 =
EIP_1559_V2_ENABLED && networkAndAccountSupports1559;
const currentToken = (tokens && const currentToken = (tokens &&
tokens.find(({ address }) => tokens.find(({ address }) =>
isEqualCaseInsensitive(tokenAddress, address), isEqualCaseInsensitive(tokenAddress, address),
@ -163,13 +176,14 @@ export default function ConfirmApprove() {
return tokenSymbol === undefined ? ( return tokenSymbol === undefined ? (
<Loading /> <Loading />
) : ( ) : (
<GasFeeContextProvider transaction={transaction}>
<ConfirmTransactionBase <ConfirmTransactionBase
toAddress={toAddress} toAddress={toAddress}
identiconAddress={tokenAddress} identiconAddress={tokenAddress}
showAccountInHeader showAccountInHeader
title={tokensText} title={tokensText}
contentComponent={ contentComponent={
<> <TransactionModalContextProvider captureEventEnabled={false}>
<ConfirmApproveContent <ConfirmApproveContent
decimals={decimals} decimals={decimals}
siteImage={siteImage} siteImage={siteImage}
@ -246,18 +260,22 @@ export default function ConfirmApprove() {
rpcPrefs={rpcPrefs} rpcPrefs={rpcPrefs}
isContract={isContract} isContract={isContract}
isMultiLayerFeeNetwork={isMultiLayerFeeNetwork} isMultiLayerFeeNetwork={isMultiLayerFeeNetwork}
supportsEIP1559V2={supportsEIP1559V2}
/> />
{showCustomizeGasPopover && ( {showCustomizeGasPopover && !supportsEIP1559V2 && (
<EditGasPopover <EditGasPopover
onClose={closeCustomizeGasPopover} onClose={closeCustomizeGasPopover}
mode={EDIT_GAS_MODES.MODIFY_IN_PLACE} mode={EDIT_GAS_MODES.MODIFY_IN_PLACE}
transaction={transaction} transaction={transaction}
/> />
)} )}
</> <EditGasFeePopover />
<AdvancedGasFeePopover />
</TransactionModalContextProvider>
} }
hideSenderToRecipient hideSenderToRecipient
customTxParamsData={customData} customTxParamsData={customData}
/> />
</GasFeeContextProvider>
); );
} }