From 19c3d021ead54c6bafc19b2b059896c88297a04b Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Sun, 12 Dec 2021 04:56:28 +0530 Subject: [PATCH] Using EIP-1559 V2 for swaps (#12966) --- app/_locales/en/messages.json | 6 + .../confirm-page-container.component.js | 8 +- .../edit-gas-fee-button.js | 29 +- .../edit-gas-fee-button.test.js | 12 + .../edit-gas-fee-popover.js | 19 +- .../edit-gas-fee-popover.test.js | 38 ++- .../edit-gas-item/edit-gas-item.js | 41 ++- .../edit-gas-item/edit-gas-item.test.js | 47 +++- .../edit-gas-item/index.scss | 1 + .../edit-gas-tooltip/edit-gas-tooltip.js | 35 ++- .../edit-gas-tooltip/edit-gas-tooltip.test.js | 13 +- .../transaction-detail.component.js | 8 +- ui/helpers/constants/gas.js | 1 + ui/hooks/gasFeeInput/test-utils.js | 10 + ui/hooks/gasFeeInput/useGasFeeInputs.js | 6 +- ui/hooks/gasFeeInput/useGasFeeInputs.test.js | 10 + ui/hooks/gasFeeInput/useMaxFeePerGasInput.js | 16 +- .../useMaxPriorityFeePerGasInput.js | 22 +- .../gasFeeInput/useTransactionFunctions.js | 28 +- ui/pages/confirm-approve/confirm-approve.js | 8 +- .../confirm-transaction-base.component.js | 1 - .../gas-details-item-title.js | 52 ++++ .../gas-details-item-title.scss | 9 + .../gas-details-item-title.test.js | 51 ++++ .../gas-details-item-title/index.js | 1 + .../gas-details-item/gas-details-item.js | 44 +-- .../gas-details-item/gas-details-item.scss | 8 - ui/pages/pages.scss | 1 + .../__snapshots__/fee-card.test.js.snap | 2 + ui/pages/swaps/fee-card/fee-card.js | 93 ++++--- ui/pages/swaps/fee-card/fee-card.test.js | 78 +++++- ui/pages/swaps/view-quote/view-quote.js | 261 ++++++++++-------- 32 files changed, 647 insertions(+), 312 deletions(-) create mode 100644 ui/pages/confirm-transaction-base/gas-details-item/gas-details-item-title/gas-details-item-title.js create mode 100644 ui/pages/confirm-transaction-base/gas-details-item/gas-details-item-title/gas-details-item-title.scss create mode 100644 ui/pages/confirm-transaction-base/gas-details-item/gas-details-item-title/gas-details-item-title.test.js create mode 100644 ui/pages/confirm-transaction-base/gas-details-item/gas-details-item-title/index.js 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 (