diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 3addb45ba..2572df224 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2899,6 +2899,12 @@ "swapSourceInfo": { "message": "We search multiple liquidity sources (exchanges, aggregators and professional market makers) to find the best rates and lowest network fees." }, + "swapSuggested": { + "message": "Swap suggested" + }, + "swapSuggestedGasSettingToolTipMessage": { + "message": "Swaps are complex and time sensitive transactions. We recommend this gas fee for a good balance between cost and confidence of a successful Swap." + }, "swapSwapFrom": { "message": "Swap from" }, diff --git a/ui/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js index 351a6e37d..dd5ef5ab2 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -258,8 +258,12 @@ export default class ConfirmPageContainer extends Component { transaction={currentTransaction} /> )} - - + {supportsEIP1559V2 && ( + <> + + + + )} ); diff --git a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js index 130082e86..8ce452cb9 100644 --- a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js +++ b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js @@ -1,7 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { COLORS } from '../../../helpers/constants/design-system'; +import { + EDIT_GAS_MODES, + PRIORITY_LEVELS, +} from '../../../../shared/constants/gas'; +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'; import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas'; import { useGasFeeContext } from '../../../contexts/gasFee'; import { useI18nContext } from '../../../hooks/useI18nContext'; @@ -12,6 +16,7 @@ import Typography from '../../ui/typography/typography'; export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { const t = useI18nContext(); const { + editGasMode, gasLimit, hasSimulationError, estimateUsed, @@ -28,13 +33,23 @@ export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { return null; } + let icon = estimateUsed; + let title = estimateUsed; + if ( + estimateUsed === PRIORITY_LEVELS.HIGH && + editGasMode === EDIT_GAS_MODES.SWAPS + ) { + icon = 'swapSuggested'; + title = 'swapSuggested'; + } + return (
{estimateUsed === 'custom' && ( @@ -44,18 +59,18 @@ export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { - + {t('dappSuggestedTooltip', [transaction.origin])} - + {t('maxBaseFee')} {maxFeePerGas} - + {t('maxPriorityFee')} {maxPriorityFeePerGas} - + {t('gasLimit')} {gasLimit} diff --git a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.test.js b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.test.js index 224e7a101..3a17ea070 100644 --- a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.test.js +++ b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.test.js @@ -2,6 +2,7 @@ import React from 'react'; import { screen } from '@testing-library/react'; import { + EDIT_GAS_MODES, GAS_ESTIMATE_TYPES, PRIORITY_LEVELS, } from '../../../../shared/constants/gas'; @@ -87,6 +88,17 @@ describe('EditGasFeeButton', () => { expect(document.getElementsByClassName('info-tooltip')).toHaveLength(1); }); + it('should render edit link with text swap suggested if high gas estimates are selected for swaps', () => { + render({ + contextProps: { + transaction: { userFeeLevel: 'high' }, + editGasMode: EDIT_GAS_MODES.SWAPS, + }, + }); + expect(screen.queryByText('🔄')).toBeInTheDocument(); + expect(screen.queryByText('Swap suggested')).toBeInTheDocument(); + }); + it('should render edit link with text advance if custom gas estimates are used', () => { render({ contextProps: { diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js index 1934bb1d1..fca821623 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js @@ -1,6 +1,9 @@ import React from 'react'; -import { PRIORITY_LEVELS } from '../../../../shared/constants/gas'; +import { + EDIT_GAS_MODES, + PRIORITY_LEVELS, +} from '../../../../shared/constants/gas'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { useTransactionModalContext } from '../../../contexts/transaction-modal'; import ErrorMessage from '../../ui/error-message'; @@ -15,7 +18,7 @@ import EditGasItem from './edit-gas-item'; import NetworkStatistics from './network-statistics'; const EditGasFeePopover = () => { - const { balanceError } = useGasFeeContext(); + const { balanceError, editGasMode } = useGasFeeContext(); const t = useI18nContext(); const { closeModal, currentModal } = useTransactionModalContext(); @@ -38,17 +41,23 @@ const EditGasFeePopover = () => { - + {editGasMode !== EDIT_GAS_MODES.SWAPS && ( + + )}
- + {editGasMode !== EDIT_GAS_MODES.SWAPS && ( + + )}
- + {editGasMode !== EDIT_GAS_MODES.SWAPS && ( + + )} { +const render = ({ txProps, contextProps } = {}) => { const store = configureStore({ metamask: { nativeCurrency: ETH, @@ -66,6 +67,7 @@ const render = (txProps) => { return renderWithProvider( , @@ -75,7 +77,7 @@ const render = (txProps) => { describe('EditGasFeePopover', () => { it('should renders low / medium / high options', () => { - render({ dappSuggestedGasFees: {} }); + render({ txProps: { dappSuggestedGasFees: {} } }); expect(screen.queryByText('🐢')).toBeInTheDocument(); expect(screen.queryByText('🦊')).toBeInTheDocument(); @@ -103,12 +105,40 @@ describe('EditGasFeePopover', () => { }); it('should not show insufficient balance message if transaction value is less than balance', () => { - render({ userFeeLevel: 'high', txParams: { value: '0x64' } }); + render({ txProps: { userFeeLevel: 'high', txParams: { value: '0x64' } } }); expect(screen.queryByText('Insufficient funds.')).not.toBeInTheDocument(); }); it('should show insufficient balance message if transaction value is more than balance', () => { - render({ userFeeLevel: 'high', txParams: { value: '0x5208' } }); + render({ + txProps: { userFeeLevel: 'high', txParams: { value: '0x5208' } }, + }); expect(screen.queryByText('Insufficient funds.')).toBeInTheDocument(); }); + + it('should not show low, aggressive and dapp-suggested options for swap', () => { + render({ + contextProps: { editGasMode: EDIT_GAS_MODES.SWAPS }, + }); + expect(screen.queryByText('🐢')).not.toBeInTheDocument(); + expect(screen.queryByText('🦊')).toBeInTheDocument(); + expect(screen.queryByText('🦍')).not.toBeInTheDocument(); + expect(screen.queryByText('🌐')).not.toBeInTheDocument(); + expect(screen.queryByText('🔄')).toBeInTheDocument(); + expect(screen.queryByText('⚙')).toBeInTheDocument(); + expect(screen.queryByText('Low')).not.toBeInTheDocument(); + expect(screen.queryByText('Market')).toBeInTheDocument(); + expect(screen.queryByText('Aggressive')).not.toBeInTheDocument(); + expect(screen.queryByText('Site')).not.toBeInTheDocument(); + expect(screen.queryByText('Swap suggested')).toBeInTheDocument(); + expect(screen.queryByText('Advanced')).toBeInTheDocument(); + }); + + it('should not show time estimates for swaps', () => { + render({ + contextProps: { editGasMode: EDIT_GAS_MODES.SWAPS }, + }); + expect(screen.queryByText('Time')).not.toBeInTheDocument(); + expect(screen.queryByText('Max fee')).toBeInTheDocument(); + }); }); diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.js b/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.js index 5ec52c3eb..64ee11b88 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.js @@ -4,7 +4,10 @@ import classNames from 'classnames'; import { useSelector } from 'react-redux'; import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils'; -import { PRIORITY_LEVELS } from '../../../../../shared/constants/gas'; +import { + EDIT_GAS_MODES, + PRIORITY_LEVELS, +} from '../../../../../shared/constants/gas'; import { PRIORITY_LEVEL_ICON_MAP } from '../../../../helpers/constants/gas'; import { PRIMARY } from '../../../../helpers/constants/common'; import { @@ -27,17 +30,19 @@ import { useCustomTimeEstimate } from './useCustomTimeEstimate'; const EditGasItem = ({ priorityLevel }) => { const { + editGasMode, estimateUsed, gasFeeEstimates, gasLimit, maxFeePerGas: maxFeePerGasValue, maxPriorityFeePerGas: maxPriorityFeePerGasValue, updateTransactionUsingGasFeeEstimates, - transaction: { dappSuggestedGasFees }, + transaction, } = useGasFeeContext(); const t = useI18nContext(); const advancedGasFeeValues = useSelector(getAdvancedGasFeeValues); const { closeModal, openModal } = useTransactionModalContext(); + const { dappSuggestedGasFees } = transaction; let maxFeePerGas; let maxPriorityFeePerGas; @@ -45,6 +50,8 @@ const EditGasItem = ({ priorityLevel }) => { if (gasFeeEstimates?.[priorityLevel]) { maxFeePerGas = gasFeeEstimates[priorityLevel].suggestedMaxFeePerGas; + maxPriorityFeePerGas = + gasFeeEstimates[priorityLevel].suggestedMaxPriorityFeePerGas; } else if ( priorityLevel === PRIORITY_LEVELS.DAPP_SUGGESTED && dappSuggestedGasFees @@ -105,6 +112,18 @@ const EditGasItem = ({ priorityLevel }) => { return null; } + let icon = priorityLevel; + let title = priorityLevel; + if (priorityLevel === PRIORITY_LEVELS.DAPP_SUGGESTED) { + title = 'dappSuggestedShortLabel'; + } else if ( + priorityLevel === PRIORITY_LEVELS.HIGH && + editGasMode === EDIT_GAS_MODES.SWAPS + ) { + icon = 'swapSuggested'; + title = 'swapSuggested'; + } + return (