diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 54c20bcf509e..7fe78bbb23bc 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2393,6 +2393,9 @@ "layer1Fees": { "message": "Layer 1 fees" }, + "layer2Fees": { + "message": "Layer 2 fees" + }, "learnCancelSpeeedup": { "message": "Learn how to $1", "description": "$1 is link to cancel or speed up transactions" @@ -3351,9 +3354,6 @@ "operationFailed": { "message": "Operation Failed" }, - "optimismFees": { - "message": "Optimism fees" - }, "optional": { "message": "Optional" }, diff --git a/app/images/scroll.svg b/app/images/scroll.svg new file mode 100644 index 000000000000..456c75922ac5 --- /dev/null +++ b/app/images/scroll.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index d86867a5a305..81757f96f975 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -2366,6 +2366,7 @@ "@metamask/transaction-controller>nonce-tracker": true, "@metamask/utils": true, "bn.js": true, + "browserify>buffer": true, "eth-method-registry": true, "fast-json-patch": true, "lodash": true, diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 75a5faba1d86..42d8160d11c3 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -2679,6 +2679,7 @@ "@metamask/transaction-controller>nonce-tracker": true, "@metamask/utils": true, "bn.js": true, + "browserify>buffer": true, "eth-method-registry": true, "fast-json-patch": true, "lodash": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index a8e881cd18c6..351ec8943991 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -2731,6 +2731,7 @@ "@metamask/transaction-controller>nonce-tracker": true, "@metamask/utils": true, "bn.js": true, + "browserify>buffer": true, "eth-method-registry": true, "fast-json-patch": true, "lodash": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 25893ed6f42a..7e8395383cc8 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -2646,6 +2646,7 @@ "@metamask/transaction-controller>nonce-tracker": true, "@metamask/utils": true, "bn.js": true, + "browserify>buffer": true, "eth-method-registry": true, "fast-json-patch": true, "lodash": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index b8cd1da55d24..410d351cb10c 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -2785,6 +2785,7 @@ "@metamask/transaction-controller>nonce-tracker": true, "@metamask/utils": true, "bn.js": true, + "browserify>buffer": true, "eth-method-registry": true, "fast-json-patch": true, "lodash": true, diff --git a/package.json b/package.json index 675be77958df..63a295bcb450 100644 --- a/package.json +++ b/package.json @@ -323,7 +323,7 @@ "@metamask/snaps-rpc-methods": "^8.0.0", "@metamask/snaps-sdk": "^4.0.1", "@metamask/snaps-utils": "^7.1.0", - "@metamask/transaction-controller": "^28.0.0", + "@metamask/transaction-controller": "^28.1.0", "@metamask/user-operation-controller": "^6.0.0", "@metamask/utils": "^8.2.1", "@ngraveio/bc-ur": "^1.1.12", diff --git a/shared/constants/network.ts b/shared/constants/network.ts index fc99a4518ddf..b22b0a51ceb8 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -151,6 +151,8 @@ export const CHAIN_IDS = { ARBITRUM_GOERLI: '0x66eed', BLAST: '0x13e31', FILECOIN: '0x13a', + SCROLL: '0x82750', + SCROLL_SEPOLIA: '0x8274f', } as const; const CHAINLIST_CHAIN_IDS_MAP = { @@ -246,6 +248,8 @@ export const GNOSIS_DISPLAY_NAME = 'Gnosis'; export const ZK_SYNC_ERA_DISPLAY_NAME = 'zkSync Era Mainnet'; export const BASE_DISPLAY_NAME = 'Base Mainnet'; export const AURORA_ETH_DISPLAY_NAME = 'Aurora'; +export const SCROLL_DISPLAY_NAME = 'Scroll'; +export const SCROLL_SEPOLIA_DISPLAY_NAME = 'Scroll Sepolia'; export const infuraProjectId = process.env.INFURA_PROJECT_ID; export const getRpcUrl = ({ @@ -422,6 +426,7 @@ export const VELAS_EVM_MAINNET_IMAGE_URL = './images/velas.svg'; export const ZKATANA_MAINNET_IMAGE_URL = './images/zkatana.png'; export const ZORA_MAINNET_IMAGE_URL = './images/zora.svg'; export const FILECOIN_MAINNET_IMAGE_URL = './images/filecoin.svg'; +export const SCROLL_IMAGE_URL = './images/scroll.svg'; export const INFURA_PROVIDER_TYPES = [ NETWORK_TYPES.MAINNET, @@ -523,6 +528,8 @@ export const NETWORK_TO_NAME_MAP = { [CHAIN_IDS.LOCALHOST]: LOCALHOST_DISPLAY_NAME, [CHAIN_IDS.OPTIMISM]: OPTIMISM_DISPLAY_NAME, [CHAIN_IDS.POLYGON]: POLYGON_DISPLAY_NAME, + [CHAIN_IDS.SCROLL]: SCROLL_DISPLAY_NAME, + [CHAIN_IDS.SCROLL_SEPOLIA]: SCROLL_SEPOLIA_DISPLAY_NAME, [CHAIN_IDS.SEPOLIA]: SEPOLIA_DISPLAY_NAME, } as const; @@ -745,6 +752,8 @@ export const CHAIN_ID_TOKEN_IMAGE_MAP = { [CHAIN_IDS.GNOSIS]: GNOSIS_TOKEN_IMAGE_URL, [CHAIN_IDS.FANTOM]: FTM_TOKEN_IMAGE_URL, [CHAIN_IDS.FILECOIN]: FILECOIN_MAINNET_IMAGE_URL, + [CHAIN_IDS.SCROLL]: SCROLL_IMAGE_URL, + [CHAIN_IDS.SCROLL_SEPOLIA]: SCROLL_IMAGE_URL, } as const; export const INFURA_BLOCKED_KEY = 'countryBlocked'; @@ -886,6 +895,8 @@ export const BUYABLE_CHAINS_MAP: { | typeof CHAIN_IDS.ARBITRUM_GOERLI | typeof CHAIN_IDS.BLAST | typeof CHAIN_IDS.FILECOIN + | typeof CHAIN_IDS.SCROLL + | typeof CHAIN_IDS.SCROLL_SEPOLIA >]: BuyableChainSettings; } = { [CHAIN_IDS.MAINNET]: { diff --git a/test/data/mock-send-state.json b/test/data/mock-send-state.json index badc99d28341..5519a55165c8 100644 --- a/test/data/mock-send-state.json +++ b/test/data/mock-send-state.json @@ -1262,7 +1262,7 @@ "gasIsSetInModal": false, "gasPriceEstimate": "0x0", "gasLimitMinimum": "0x5208", - "gasTotalForLayer1": "0x0", + "gasTotalForLayer1": null, "recipientMode": "CONTACT_LIST", "recipientInput": "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b", "selectedAccount": { diff --git a/ui/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/components/app/transaction-breakdown/transaction-breakdown.component.js index 6d4bfd3fa9eb..ebf2d932c20f 100644 --- a/ui/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -29,7 +29,6 @@ export default class TransactionBreakdown extends PureComponent { priorityFee: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), hexGasTotal: PropTypes.string, isEIP1559Transaction: PropTypes.bool, - isMultiLayerFeeNetwork: PropTypes.bool, l1HexGasTotal: PropTypes.string, }; @@ -55,7 +54,6 @@ export default class TransactionBreakdown extends PureComponent { priorityFee, hexGasTotal, isEIP1559Transaction, - isMultiLayerFeeNetwork, l1HexGasTotal, } = this.props; return ( @@ -81,7 +79,7 @@ export default class TransactionBreakdown extends PureComponent { )} - {isMultiLayerFeeNetwork && ( + {l1HexGasTotal && ( {showFiat && ( { getHexGasTotal({ gasLimit, gasPrice: usedGasPrice })) || '0x0'; - let totalInHex = sumHexes(hexGasTotal, value); - - const isMultiLayerFeeNetwork = - getIsMultiLayerFeeNetwork(state) && l1HexGasTotal !== undefined; - - if (isMultiLayerFeeNetwork) { - totalInHex = sumHexes(totalInHex, l1HexGasTotal); - } + const totalInHex = sumHexes(hexGasTotal, value, l1HexGasTotal ?? 0); return { nativeCurrency: getNativeCurrency(state), @@ -62,7 +52,6 @@ const mapStateToProps = (state, ownProps) => { priorityFee, baseFee: baseFeePerGas, isEIP1559Transaction: isEIP1559Transaction(transaction), - isMultiLayerFeeNetwork, l1HexGasTotal, }; }; diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index f9d40a6de3ae..015021b9da97 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -40,7 +40,6 @@ import { getUseTokenDetection, getTokenList, getAddressBookEntryOrAccountName, - getIsMultiLayerFeeNetwork, getEnsResolutionByAddress, getSelectedAccount, getSelectedInternalAccount, @@ -460,7 +459,7 @@ export const initialState = { gasIsSetInModal: false, gasPriceEstimate: '0x0', gasLimitMinimum: GAS_LIMITS.SIMPLE, - gasTotalForLayer1: '0x0', + gasTotalForLayer1: null, recipientMode: RECIPIENT_SEARCH_MODES.CONTACT_LIST, recipientInput: '', selectedAccount: { @@ -508,32 +507,28 @@ export const computeEstimatedGasLimit = createAsyncThunk( const draftTransaction = send.draftTransactions[send.currentTransactionUUID]; const unapprovedTxs = getUnapprovedTransactions(state); - const isMultiLayerFeeNetwork = getIsMultiLayerFeeNetwork(state); const transaction = unapprovedTxs[draftTransaction.id]; const isNonStandardEthChain = getIsNonStandardEthChain(state); const chainId = getCurrentChainId(state); const selectedAccount = getSelectedInternalAccountWithBalance(state); - let gasTotalForLayer1; - if (isMultiLayerFeeNetwork) { - gasTotalForLayer1 = await thunkApi.dispatch( - getLayer1GasFee({ - transactionParams: { - gasPrice: draftTransaction.gas.gasPrice, - gas: draftTransaction.gas.gasLimit, - to: draftTransaction.recipient.address?.toLowerCase(), - value: - send.amountMode === AMOUNT_MODES.MAX - ? send.selectedAccount.balance - : draftTransaction.amount.value, - from: send.selectedAccount.address, - data: draftTransaction.userInputHexData, - type: '0x0', - }, - chainId, - }), - ); - } + const gasTotalForLayer1 = await thunkApi.dispatch( + getLayer1GasFee({ + transactionParams: { + gasPrice: draftTransaction.gas.gasPrice, + gas: draftTransaction.gas.gasLimit, + to: draftTransaction.recipient.address?.toLowerCase(), + value: + send.amountMode === AMOUNT_MODES.MAX + ? send.selectedAccount.balance + : draftTransaction.amount.value, + from: send.selectedAccount.address, + data: draftTransaction.userInputHexData, + type: '0x0', + }, + chainId, + }), + ); if ( send.stage !== SEND_STAGES.EDIT || @@ -934,7 +929,7 @@ const slice = createSlice({ const _gasTotal = new Numeric( draftTransaction.gas.gasTotal || '0x0', 16, - ).add(new Numeric(state.gasTotalForLayer1 || '0x0', 16)); + ).add(new Numeric(state.gasTotalForLayer1 ?? '0x0', 16)); amount = new Numeric(draftTransaction.asset.balance, 16) .minus(_gasTotal) @@ -2783,3 +2778,7 @@ export function isSendFormInvalid(state) { export function getSendStage(state) { return state[name].stage; } + +export function hasSendLayer1GasFee(state) { + return state[name].gasTotalForLayer1 !== null; +} diff --git a/ui/ducks/send/send.test.js b/ui/ducks/send/send.test.js index 8b65c13a00a3..e2bc32e8b1a1 100644 --- a/ui/ducks/send/send.test.js +++ b/ui/ducks/send/send.test.js @@ -144,6 +144,9 @@ describe('Send Slice', () => { jest .spyOn(Actions, 'updateTransactionGasFees') .mockImplementation(() => ({ type: 'UPDATE_TRANSACTION_GAS_FEES' })); + jest + .spyOn(Actions, 'getLayer1GasFee') + .mockReturnValue({ type: 'GET_LAYER_1_GAS_FEE' }); }); describe('Reducers', () => { @@ -1622,10 +1625,11 @@ describe('Send Slice', () => { expect(actionResult[2].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[3].type).toStrictEqual( + expect(actionResult[3].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[4].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[4].type).toStrictEqual( + expect(actionResult[5].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); @@ -1771,10 +1775,11 @@ describe('Send Slice', () => { expect(actionResult[2].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[3].type).toStrictEqual( + expect(actionResult[3].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[4].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[4].type).toStrictEqual( + expect(actionResult[5].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); @@ -1830,16 +1835,17 @@ describe('Send Slice', () => { const actionResult = store.getActions(); - expect(actionResult).toHaveLength(5); + expect(actionResult).toHaveLength(6); expect(actionResult[0].type).toStrictEqual('send/addHistoryEntry'); expect(actionResult[1].type).toStrictEqual('send/updateSendAmount'); expect(actionResult[2].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[3].type).toStrictEqual( + expect(actionResult[3].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[4].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[4].type).toStrictEqual( + expect(actionResult[5].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); @@ -1915,7 +1921,7 @@ describe('Send Slice', () => { const actionResult = store.getActions(); - expect(actionResult).toHaveLength(5); + expect(actionResult).toHaveLength(6); expect(actionResult[0]).toMatchObject({ type: 'send/addHistoryEntry', @@ -1935,10 +1941,11 @@ describe('Send Slice', () => { expect(actionResult[2].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[3].type).toStrictEqual( + expect(actionResult[3].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[4].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[4].type).toStrictEqual( + expect(actionResult[5].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); @@ -1974,7 +1981,7 @@ describe('Send Slice', () => { const actionResult = store.getActions(); - expect(actionResult).toHaveLength(7); + expect(actionResult).toHaveLength(8); expect(actionResult[0].type).toStrictEqual('SHOW_LOADING_INDICATION'); expect(actionResult[1].type).toStrictEqual('HIDE_LOADING_INDICATION'); expect(actionResult[2]).toMatchObject({ @@ -2000,10 +2007,11 @@ describe('Send Slice', () => { expect(actionResult[4].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[5].type).toStrictEqual( + expect(actionResult[5].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[6].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[6].type).toStrictEqual( + expect(actionResult[7].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); @@ -2418,7 +2426,7 @@ describe('Send Slice', () => { await store.dispatch(resetRecipientInput()); const actionResult = store.getActions(); - expect(actionResult).toHaveLength(12); + expect(actionResult).toHaveLength(13); expect(actionResult[0]).toMatchObject({ type: 'send/addHistoryEntry', payload: 'sendFlow - user cleared recipient input', @@ -2443,16 +2451,17 @@ describe('Send Slice', () => { expect(actionResult[7].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[8].type).toStrictEqual( + expect(actionResult[8].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[9].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[9].type).toStrictEqual( + expect(actionResult[10].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); - expect(actionResult[10].type).toStrictEqual( + expect(actionResult[11].type).toStrictEqual( 'DNS/resetDomainResolution', ); - expect(actionResult[11].type).toStrictEqual( + expect(actionResult[12].type).toStrictEqual( 'send/validateRecipientUserInput', ); }); @@ -2588,7 +2597,7 @@ describe('Send Slice', () => { const actionResult = store.getActions(); - expect(actionResult).toHaveLength(6); + expect(actionResult).toHaveLength(7); expect(actionResult[0].type).toStrictEqual('send/updateAmountMode'); expect(actionResult[1].type).toStrictEqual('send/updateSendAmount'); expect(actionResult[2]).toMatchObject({ @@ -2598,10 +2607,11 @@ describe('Send Slice', () => { expect(actionResult[3].type).toStrictEqual( 'send/computeEstimatedGasLimit/pending', ); - expect(actionResult[4].type).toStrictEqual( + expect(actionResult[4].type).toStrictEqual('GET_LAYER_1_GAS_FEE'); + expect(actionResult[5].type).toStrictEqual( 'metamask/gas/SET_CUSTOM_GAS_LIMIT', ); - expect(actionResult[5].type).toStrictEqual( + expect(actionResult[6].type).toStrictEqual( 'send/computeEstimatedGasLimit/fulfilled', ); }); diff --git a/ui/pages/confirmations/components/approve-content-card/approve-content-card.stories.js b/ui/pages/confirmations/components/approve-content-card/approve-content-card.stories.js index a2b85806f29d..0555c48425a4 100644 --- a/ui/pages/confirmations/components/approve-content-card/approve-content-card.stories.js +++ b/ui/pages/confirmations/components/approve-content-card/approve-content-card.stories.js @@ -36,7 +36,7 @@ export default { renderDataContent: { control: 'boolean', }, - isMultiLayerFeeNetwork: { + hasLayer1GasFee: { control: 'boolean', }, ethTransactionTotal: { @@ -80,7 +80,7 @@ export default { supportsEIP1559: false, renderTransactionDetailsContent: true, renderDataContent: false, - isMultiLayerFeeNetwork: false, + hasLayer1GasFee: false, ethTransactionTotal: '0.0012', nativeCurrency: 'GoerliETH', hexTransactionTotal: '0x44364c5bb0000', diff --git a/ui/pages/confirmations/components/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js b/ui/pages/confirmations/components/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js index db5cfa9651f5..e826cd42f248 100644 --- a/ui/pages/confirmations/components/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js +++ b/ui/pages/confirmations/components/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js @@ -5,7 +5,6 @@ import { useSelector } from 'react-redux'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { getIsMainnet, - getIsMultiLayerFeeNetwork, getPreferences, getUnapprovedTransactions, getUseCurrencyRateCheck, @@ -40,7 +39,6 @@ const ConfirmLegacyGasDisplay = ({ 'data-testid': dataTestId } = {}) => { // state selectors const isMainnet = useSelector(getIsMainnet); - const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const useCurrencyRateCheck = useSelector(getUseCurrencyRateCheck); const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences); const nativeCurrency = useSelector(getNativeCurrency); @@ -54,8 +52,10 @@ const ConfirmLegacyGasDisplay = ({ 'data-testid': dataTestId } = {}) => { const { hexMinimumTransactionFee, hexMaximumTransactionFee } = useSelector( (state) => transactionFeeSelector(state, transaction), ); + const { layer1GasFee } = txData; + const hasLayer1GasFee = layer1GasFee !== undefined; - if (isMultiLayerFeeNetwork) { + if (hasLayer1GasFee) { return [ { - const store = configureStore({ ...state, ...contextProps }); +const render = (state = mmState) => { + const store = configureStore(state); return renderWithProvider(, store); }; @@ -85,6 +84,7 @@ describe('ConfirmLegacyGasDisplay', () => { it('should render label and gas details with draftTransaction', async () => { render({ + ...mmState, send: { currentTransactionUUID: '1d40b578-6184-4607-8513-762c24d0a19b', draftTransactions: { @@ -98,6 +98,7 @@ describe('ConfirmLegacyGasDisplay', () => { maxPriorityFeePerGas: '0x0', wasManuallyEdited: false, }, + transactionType: '0x0', }, }, }, @@ -110,44 +111,18 @@ describe('ConfirmLegacyGasDisplay', () => { }); }); - it('should contain L1 L2 fee details for optimism', async () => { - mmState.metamask.providerConfig.chainId = CHAIN_IDS.OPTIMISM; - mmState.confirmTransaction.txData.chainId = CHAIN_IDS.OPTIMISM; - const state = { - metamask: { - ...mmState.metamask, - providerConfig: { - ...mmState.metamask.providerConfig, - chainId: CHAIN_IDS.OPTIMISM, - }, - }, + it('should contain L1 L2 fee details', async () => { + render({ + ...mmState, confirmTransaction: { ...mmState.confirmTransaction, txData: { ...mmState.confirmTransaction.txData, - chainId: CHAIN_IDS.OPTIMISM, + layer1GasFee: '0x1', }, }, - }; - render( - { - send: { - currentTransactionUUID: '1d40b578-6184-4607-8513-762c24d0a19b', - draftTransactions: { - '1d40b578-6184-4607-8513-762c24d0a19b': { - gas: { - error: null, - gasLimit: '0x5208', - gasPrice: '0x3b9aca00', - gasTotal: '0x157c9fbb9a000', - wasManuallyEdited: false, - }, - }, - }, - }, - }, - state, - ); + }); + await waitFor(() => { expect(screen.queryByText('Layer 1 fees')).toBeInTheDocument(); expect(screen.queryByText('Layer 2 gas fee')).toBeInTheDocument(); diff --git a/ui/pages/confirmations/components/fee-details-component/fee-details-component.js b/ui/pages/confirmations/components/fee-details-component/fee-details-component.js index 47549fbbdaba..73216ceae6dc 100644 --- a/ui/pages/confirmations/components/fee-details-component/fee-details-component.js +++ b/ui/pages/confirmations/components/fee-details-component/fee-details-component.js @@ -18,10 +18,7 @@ import { Text, } from '../../../../components/component-library'; import TransactionDetailItem from '../transaction-detail-item/transaction-detail-item.component'; -import { - getIsMultiLayerFeeNetwork, - getPreferences, -} from '../../../../selectors'; +import { getPreferences } from '../../../../selectors'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import LoadingHeartBeat from '../../../../components/ui/loading-heartbeat'; import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display/user-preferenced-currency-display.component'; @@ -37,7 +34,6 @@ export default function FeeDetailsComponent({ const layer1GasFee = txData?.layer1GasFee ?? null; const [expandFeeDetails, setExpandFeeDetails] = useState(false); - const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences); const t = useI18nContext(); @@ -45,12 +41,8 @@ export default function FeeDetailsComponent({ const { minimumCostInHexWei: hexMinimumTransactionFee } = useGasFeeContext(); const getTransactionFeeTotal = useMemo(() => { - if (isMultiLayerFeeNetwork) { - return addHexes(hexMinimumTransactionFee, layer1GasFee || 0); - } - - return hexMinimumTransactionFee; - }, [isMultiLayerFeeNetwork, hexMinimumTransactionFee, layer1GasFee]); + return addHexes(hexMinimumTransactionFee, layer1GasFee ?? 0); + }, [hexMinimumTransactionFee, layer1GasFee]); const renderTotalDetailText = useCallback( (value) => { @@ -86,6 +78,8 @@ export default function FeeDetailsComponent({ [txData, useNativeCurrencyAsPrimaryCurrency], ); + const hasLayer1GasFee = layer1GasFee !== null; + return ( <> - {!hideGasDetails && isMultiLayerFeeNetwork && ( + {!hideGasDetails && hasLayer1GasFee && ( - {isMultiLayerFeeNetwork && ( + {hasLayer1GasFee && ( )} - {isMultiLayerFeeNetwork && layer1GasFee && ( + {layer1GasFee && ( { let result; await act( - async () => (result = renderWithProvider(, store)), + async () => + (result = renderWithProvider( + , + store, + )), ); return result; @@ -56,7 +60,7 @@ describe('FeeDetailsComponent', () => { await act(async () => { screen.getByRole('button').click(); }); - expect(screen.getAllByTitle('0 ETH')).toHaveLength(2); + expect(screen.getAllByTitle('0 ETH')).toHaveLength(3); expect(screen.getAllByTitle('0 ETH')[0]).toBeInTheDocument(); }); diff --git a/ui/pages/confirmations/components/gas-details-item/gas-details-item.js b/ui/pages/confirmations/components/gas-details-item/gas-details-item.js index 27b7eae302c9..a392dbfdb536 100644 --- a/ui/pages/confirmations/components/gas-details-item/gas-details-item.js +++ b/ui/pages/confirmations/components/gas-details-item/gas-details-item.js @@ -8,7 +8,6 @@ import { TextColor } from '../../../../helpers/constants/design-system'; import { PRIMARY, SECONDARY } from '../../../../helpers/constants/common'; import { PriorityLevels } from '../../../../../shared/constants/gas'; import { - getIsMultiLayerFeeNetwork, getPreferences, getTxData, getUseCurrencyRateCheck, @@ -36,7 +35,6 @@ const GasDetailsItem = ({ }) => { const t = useI18nContext(); - const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const txData = useSelector(getTxData); const { layer1GasFee } = txData; @@ -60,20 +58,20 @@ const GasDetailsItem = ({ const useCurrencyRateCheck = useSelector(getUseCurrencyRateCheck); const getTransactionFeeTotal = useMemo(() => { - if (isMultiLayerFeeNetwork) { - return sumHexes(hexMinimumTransactionFee, layer1GasFee || 0); + if (layer1GasFee) { + return sumHexes(hexMinimumTransactionFee, layer1GasFee); } return hexMinimumTransactionFee; - }, [isMultiLayerFeeNetwork, hexMinimumTransactionFee, layer1GasFee]); + }, [hexMinimumTransactionFee, layer1GasFee]); const getMaxTransactionFeeTotal = useMemo(() => { - if (isMultiLayerFeeNetwork) { - return sumHexes(hexMaximumTransactionFee, layer1GasFee || 0); + if (layer1GasFee) { + return sumHexes(hexMaximumTransactionFee, layer1GasFee); } return hexMaximumTransactionFee; - }, [isMultiLayerFeeNetwork, hexMaximumTransactionFee, layer1GasFee]); + }, [hexMaximumTransactionFee, layer1GasFee]); if (hasSimulationError && !userAcknowledgedGasMissing) { return null; diff --git a/ui/pages/confirmations/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirmations/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index afecd575f099..a057069cc20d 100644 --- a/ui/pages/confirmations/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/pages/confirmations/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -78,7 +78,7 @@ export default class ConfirmApproveContent extends Component { isContract: PropTypes.bool, hexTransactionTotal: PropTypes.string, hexMinimumTransactionFee: PropTypes.string, - isMultiLayerFeeNetwork: PropTypes.bool, + hasLayer1GasFee: PropTypes.bool, supportsEIP1559: PropTypes.bool, assetName: PropTypes.string, tokenId: PropTypes.string, @@ -158,7 +158,7 @@ export default class ConfirmApproveContent extends Component { hexTransactionTotal, hexMinimumTransactionFee, txData, - isMultiLayerFeeNetwork, + hasLayer1GasFee, supportsEIP1559, userAcknowledgedGasMissing, renderSimulationFailureWarning, @@ -166,7 +166,7 @@ export default class ConfirmApproveContent extends Component { useNativeCurrencyAsPrimaryCurrency, } = this.props; if ( - !isMultiLayerFeeNetwork && + !hasLayer1GasFee && supportsEIP1559 && !renderSimulationFailureWarning ) { @@ -178,7 +178,7 @@ export default class ConfirmApproveContent extends Component { } return (
- {isMultiLayerFeeNetwork ? ( + {hasLayer1GasFee ? (
{ const hardwareWalletRequiresConnection = doesAddressRequireLedgerHidConnection(state, fromAddress); - const isMultiLayerFeeNetwork = getIsMultiLayerFeeNetwork(state); const isUsingPaymaster = getIsUsingPaymaster(state); let isSigningOrSubmitting = Boolean( @@ -327,7 +325,6 @@ const mapStateToProps = (state, ownProps) => { showLedgerSteps: fromAddressIsLedger, nativeCurrency, hardwareWalletRequiresConnection, - isMultiLayerFeeNetwork, chainId, isBuyableChain, useCurrencyRateCheck: getUseCurrencyRateCheck(state), diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js index 2a29003e4b16..8064e88ae3a8 100644 --- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js +++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js @@ -346,6 +346,7 @@ describe('Confirm Transaction Base', () => { txData: { ...baseStore.confirmTransaction.txData, chainId: CHAIN_IDS.OPTIMISM, + layer1GasFee: '0x1', }, }, }; diff --git a/ui/pages/confirmations/send/send-content/send-content.component.js b/ui/pages/confirmations/send/send-content/send-content.component.js index bbf70d28071d..97340b404db3 100644 --- a/ui/pages/confirmations/send/send-content/send-content.component.js +++ b/ui/pages/confirmations/send/send-content/send-content.component.js @@ -34,7 +34,7 @@ export default class SendContent extends Component { recipient: PropTypes.object, acknowledgeRecipientWarning: PropTypes.func, recipientWarningAcknowledged: PropTypes.bool, - isMultiLayerFeeNetwork: PropTypes.bool, + hasLayer1GasFee: PropTypes.bool, }; render() { @@ -49,7 +49,7 @@ export default class SendContent extends Component { assetError, recipient, recipientWarningAcknowledged, - isMultiLayerFeeNetwork, + hasLayer1GasFee, } = this.props; let gasError; @@ -82,7 +82,7 @@ export default class SendContent extends Component { {networkOrAccountNotSupports1559 ? : null} {showHexData ? : null} - {!isMultiLayerFeeNetwork && } + {!hasLayer1GasFee && }
); diff --git a/ui/pages/confirmations/send/send-content/send-content.container.js b/ui/pages/confirmations/send/send-content/send-content.container.js index f944e1677e4c..72d25deb333b 100644 --- a/ui/pages/confirmations/send/send-content/send-content.container.js +++ b/ui/pages/confirmations/send/send-content/send-content.container.js @@ -3,7 +3,6 @@ import { getIsEthGasPriceFetched, getNoGasPriceFetched, checkNetworkOrAccountNotSupports1559, - getIsMultiLayerFeeNetwork, } from '../../../../selectors'; import { getIsBalanceInsufficient, @@ -12,6 +11,7 @@ import { getRecipient, acknowledgeRecipientWarning, getRecipientWarningAcknowledgement, + hasSendLayer1GasFee, } from '../../../../ducks/send'; import SendContent from './send-content.component'; @@ -30,7 +30,7 @@ function mapStateToProps(state) { assetError: getAssetError(state), recipient, recipientWarningAcknowledged, - isMultiLayerFeeNetwork: getIsMultiLayerFeeNetwork(state), + hasLayer1GasFee: hasSendLayer1GasFee(state), }; } diff --git a/ui/pages/confirmations/token-allowance/token-allowance.js b/ui/pages/confirmations/token-allowance/token-allowance.js index d169644e492e..e8d6bbf5bbbe 100644 --- a/ui/pages/confirmations/token-allowance/token-allowance.js +++ b/ui/pages/confirmations/token-allowance/token-allowance.js @@ -90,7 +90,6 @@ export default function TokenAllowance({ hexTransactionTotal, hexMinimumTransactionFee, txData, - isMultiLayerFeeNetwork, supportsEIP1559, userAddress, tokenAddress, @@ -531,7 +530,6 @@ export default function TokenAllowance({ renderTransactionDetailsContent noBorder={useNonceField || !showFullTxDetails} supportsEIP1559={supportsEIP1559} - isMultiLayerFeeNetwork={isMultiLayerFeeNetwork} ethTransactionTotal={ethTransactionTotal} nativeCurrency={nativeCurrency} fullTxData={fullTxData} @@ -706,10 +704,6 @@ TokenAllowance.propTypes = { * Current transaction */ txData: PropTypes.object, - /** - * Is multi-layer fee network or not - */ - isMultiLayerFeeNetwork: PropTypes.bool, /** * Is the enhanced gas fee enabled or not */ diff --git a/ui/pages/confirmations/token-allowance/token-allowance.stories-to-do.js b/ui/pages/confirmations/token-allowance/token-allowance.stories-to-do.js index fa9b52724817..9c08a176b4d4 100644 --- a/ui/pages/confirmations/token-allowance/token-allowance.stories-to-do.js +++ b/ui/pages/confirmations/token-allowance/token-allowance.stories-to-do.js @@ -33,9 +33,6 @@ export default { hexTransactionTotal: { control: 'text', }, - isMultiLayerFeeNetwork: { - control: 'text', - }, supportsEIP1559: { control: 'boolean', }, @@ -82,7 +79,6 @@ export default { ethTransactionTotal: '0.0012', fiatTransactionTotal: '1.6', hexTransactionTotal: '0x44364c5bb0000', - isMultiLayerFeeNetwork: false, supportsEIP1559: false, userAddress: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1', tokenAddress: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', diff --git a/ui/pages/confirmations/token-allowance/token-allowance.stories.js b/ui/pages/confirmations/token-allowance/token-allowance.stories.js index 57b984cd122d..ed6078bf2a87 100644 --- a/ui/pages/confirmations/token-allowance/token-allowance.stories.js +++ b/ui/pages/confirmations/token-allowance/token-allowance.stories.js @@ -19,7 +19,6 @@ const defaultArgs = { ethTransactionTotal: '0.0012', fiatTransactionTotal: '1.6', hexTransactionTotal: '0x44364c5bb0000', - isMultiLayerFeeNetwork: false, supportsEIP1559: false, userAddress: '0x9d0ba4ddac06032527b140912ec808ab9451b788', tokenAddress: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', @@ -161,9 +160,6 @@ export default { hexTransactionTotal: { control: 'text', }, - isMultiLayerFeeNetwork: { - control: 'boolean', - }, supportsEIP1559: { control: 'boolean', }, diff --git a/ui/pages/confirmations/token-allowance/token-allowance.test.js b/ui/pages/confirmations/token-allowance/token-allowance.test.js index 793d659d5f57..37e8a58b5e5c 100644 --- a/ui/pages/confirmations/token-allowance/token-allowance.test.js +++ b/ui/pages/confirmations/token-allowance/token-allowance.test.js @@ -179,7 +179,6 @@ describe('TokenAllowancePage', () => { ethTransactionTotal: '0.0012', fiatTransactionTotal: '1.6', hexTransactionTotal: '0x44364c5bb0000', - isMultiLayerFeeNetwork: false, supportsEIP1559: true, userAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAddress: '0x55797717b9947b31306f4aac7ad1365c6e3923bd', diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.js b/ui/pages/swaps/prepare-swap-page/review-quote.js index b1d68921358f..a2a471e19917 100644 --- a/ui/pages/swaps/prepare-swap-page/review-quote.js +++ b/ui/pages/swaps/prepare-swap-page/review-quote.js @@ -61,7 +61,6 @@ import { getHardwareWalletType, checkNetworkAndAccountSupports1559, getUSDConversionRate, - getIsMultiLayerFeeNetwork, } from '../../../selectors'; import { getSmartTransactionsOptInStatus, @@ -198,7 +197,6 @@ export default function ReviewQuote({ setReceiveToAmount }) { const { balance: ethBalance } = useSelector(getSelectedAccount, shallowEqual); const conversionRate = useSelector(conversionRateSelector); const USDConversionRate = useSelector(getUSDConversionRate); - const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const currentCurrency = useSelector(getCurrentCurrency); const swapsTokens = useSelector(getTokens, isEqual); const networkAndAccountSupports1559 = useSelector( @@ -988,7 +986,7 @@ export default function ReviewQuote({ setReceiveToAmount }) { ]); useEffect(() => { - if (!isMultiLayerFeeNetwork || !usedQuote?.multiLayerL1TradeFeeTotal) { + if (!usedQuote?.multiLayerL1TradeFeeTotal) { return; } const getEstimatedL1Fees = async () => { @@ -1019,13 +1017,7 @@ export default function ReviewQuote({ setReceiveToAmount }) { } }; getEstimatedL1Fees(); - }, [ - unsignedTransaction, - approveTxParams, - isMultiLayerFeeNetwork, - chainId, - usedQuote, - ]); + }, [unsignedTransaction, approveTxParams, chainId, usedQuote]); const destinationValue = calcTokenValue( destinationTokenValue, diff --git a/ui/pages/swaps/view-quote/view-quote.js b/ui/pages/swaps/view-quote/view-quote.js index 24f2d12a077b..3525cb457f94 100644 --- a/ui/pages/swaps/view-quote/view-quote.js +++ b/ui/pages/swaps/view-quote/view-quote.js @@ -62,7 +62,6 @@ import { getHardwareWalletType, checkNetworkAndAccountSupports1559, getUSDConversionRate, - getIsMultiLayerFeeNetwork, } from '../../../selectors'; import { getSmartTransactionsOptInStatus, @@ -170,7 +169,6 @@ export default function ViewQuote() { const { balance: ethBalance } = useSelector(getSelectedAccount, shallowEqual); const conversionRate = useSelector(conversionRateSelector); const USDConversionRate = useSelector(getUSDConversionRate); - const isMultiLayerFeeNetwork = useSelector(getIsMultiLayerFeeNetwork); const currentCurrency = useSelector(getCurrentCurrency); const swapsTokens = useSelector(getTokens, isEqual); const networkAndAccountSupports1559 = useSelector( @@ -890,7 +888,7 @@ export default function ViewQuote() { ]); useEffect(() => { - if (!isMultiLayerFeeNetwork || !usedQuote?.multiLayerL1TradeFeeTotal) { + if (!usedQuote?.multiLayerL1TradeFeeTotal) { return; } const getEstimatedL1Fees = async () => { @@ -921,13 +919,7 @@ export default function ViewQuote() { } }; getEstimatedL1Fees(); - }, [ - unsignedTransaction, - approveTxParams, - isMultiLayerFeeNetwork, - chainId, - usedQuote, - ]); + }, [unsignedTransaction, approveTxParams, chainId, usedQuote]); useEffect(() => { if (isSmartTransaction) { diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 8ddab3bf2617..6f66112c88b5 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -1991,36 +1991,6 @@ export const getAllEnabledNetworks = createDeepEqualSelector( }, ); -export function getIsOptimism(state) { - return ( - getCurrentChainId(state) === CHAIN_IDS.OPTIMISM || - getCurrentChainId(state) === CHAIN_IDS.OPTIMISM_TESTNET || - getCurrentChainId(state) === CHAIN_IDS.OPTIMISM_GOERLI - ); -} - -export function getIsBase(state) { - return ( - getCurrentChainId(state) === CHAIN_IDS.BASE || - getCurrentChainId(state) === CHAIN_IDS.BASE_TESTNET - ); -} - -export function getIsOpbnb(state) { - return ( - getCurrentChainId(state) === CHAIN_IDS.OPBNB || - getCurrentChainId(state) === CHAIN_IDS.OPBNB_TESTNET - ); -} - -export function getIsOpStack(state) { - return getIsOptimism(state) || getIsBase(state) || getIsOpbnb(state); -} - -export function getIsMultiLayerFeeNetwork(state) { - return getIsOpStack(state); -} - /** * To retrieve the maxBaseFee and priorityFee the user has set as default * diff --git a/yarn.lock b/yarn.lock index 0f2fc45c57d5..ebe4dd62b24f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5791,9 +5791,9 @@ __metadata: languageName: node linkType: hard -"@metamask/transaction-controller@npm:^28.0.0": - version: 28.0.0 - resolution: "@metamask/transaction-controller@npm:28.0.0" +"@metamask/transaction-controller@npm:^28.1.0": + version: 28.1.0 + resolution: "@metamask/transaction-controller@npm:28.1.0" dependencies: "@ethereumjs/common": "npm:^3.2.0" "@ethereumjs/tx": "npm:^4.2.0" @@ -5822,7 +5822,7 @@ __metadata: "@metamask/approval-controller": ^6.0.0 "@metamask/gas-fee-controller": ^15.0.0 "@metamask/network-controller": ^18.0.0 - checksum: 8ec07273410867265e60f338748a3c6da1333fcf26e24a6d8fb73d7ce6ec4c4693cb897471835c568684c98e14d46250d95971f81349190b70c9f38767c92bb5 + checksum: e043b74ba17ccf702226bf7bad4bd251d35485fc7d90da2108a5d188a0016bd1ed65a4b63e29c6395161c02964ac36936493d8cee43bfad147132fca17344df3 languageName: node linkType: hard @@ -24816,7 +24816,7 @@ __metadata: "@metamask/snaps-utils": "npm:^7.1.0" "@metamask/test-bundler": "npm:^1.0.0" "@metamask/test-dapp": "npm:^8.4.0" - "@metamask/transaction-controller": "npm:^28.0.0" + "@metamask/transaction-controller": "npm:^28.1.0" "@metamask/user-operation-controller": "npm:^6.0.0" "@metamask/utils": "npm:^8.2.1" "@ngraveio/bc-ur": "npm:^1.1.12"