diff --git a/.storybook/test-data.js b/.storybook/test-data.js index f538ee255..a8bf65c9b 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -1,5 +1,7 @@ import { draftTransactionInitialState } from '../ui/ducks/send'; import { KeyringType } from '../shared/constants/keyring'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; const state = { invalidCustomNetwork: { @@ -164,6 +166,15 @@ const state = { 1559: true, }, }, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { + 1559: true, + }, + status: NetworkStatus.Available, + }, + }, gasFeeEstimates: '0x5208', swapsState: { quotes: {}, @@ -1599,7 +1610,7 @@ const state = { }, }; -export const networkList = [ +export const networkList = [ { blockExplorerUrl: 'https://etherscan.io', chainId: '0x1', @@ -1673,6 +1684,6 @@ export const networkList = [ rpcUrl: 'https://polygon-rpc.com', ticker: 'MATIC', }, -] +]; export default state; diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 295428813..a2225aa59 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -149,9 +149,12 @@ export default class SwapsController { this.ethersProvider = new Web3Provider(provider); this._currentNetworkId = networkController.state.networkId; onNetworkStateChange(() => { - const { networkId, networkStatus } = networkController.state; + const { networkId, networksMetadata, selectedNetworkClientId } = + networkController.state; + const selectedNetworkStatus = + networksMetadata[selectedNetworkClientId]?.status; if ( - networkStatus === NetworkStatus.Available && + selectedNetworkStatus === NetworkStatus.Available && networkId !== this._currentNetworkId ) { this._currentNetworkId = networkId; diff --git a/app/scripts/controllers/swaps.test.js b/app/scripts/controllers/swaps.test.js index a17d131ca..b68a8dfb4 100644 --- a/app/scripts/controllers/swaps.test.js +++ b/app/scripts/controllers/swaps.test.js @@ -4,6 +4,7 @@ import sinon from 'sinon'; import { BigNumber } from '@ethersproject/bignumber'; import { mapValues } from 'lodash'; import BigNumberjs from 'bignumber.js'; +import { NetworkType } from '@metamask/controller-utils'; import { CHAIN_IDS, NETWORK_IDS, @@ -102,7 +103,13 @@ function getMockNetworkController() { return { state: { networkId: NETWORK_IDS.GOERLI, - networkStatus: NetworkStatus.Available, + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, }, }; } @@ -224,7 +231,13 @@ describe('SwapsController', function () { networkController.state = { networkId: NETWORK_IDS.MAINNET, - networkStatus: NetworkStatus.Available, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, }; networkStateChangeListener(); @@ -256,7 +269,13 @@ describe('SwapsController', function () { networkController.state = { networkId: null, - networkStatus: NetworkStatus.Unknown, + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Unknown, + }, + }, }; networkStateChangeListener(); @@ -288,7 +307,13 @@ describe('SwapsController', function () { networkController.state = { networkId: NETWORK_IDS.GOERLI, - networkStatus: NetworkStatus.Available, + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, }; networkStateChangeListener(); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2487aab05..bc865aa67 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1168,7 +1168,10 @@ export default class MetamaskController extends EventEmitter { getCurrentAccountEIP1559Compatibility: this.getCurrentAccountEIP1559Compatibility.bind(this), getNetworkId: () => this.networkController.state.networkId, - getNetworkStatus: () => this.networkController.state.networkStatus, + getNetworkStatus: () => + this.networkController.state.networksMetadata?.[ + this.networkController.state.selectedNetworkClientId + ]?.status, onNetworkStateChange: (listener) => { networkControllerMessenger.subscribe( 'NetworkController:stateChange', @@ -2089,8 +2092,10 @@ export default class MetamaskController extends EventEmitter { updatePublicConfigStore(this.getState()); function updatePublicConfigStore(memState) { + const networkStatus = + memState.networksMetadata[memState.selectedNetworkClientId]?.status; const { chainId } = networkController.state.providerConfig; - if (memState.networkStatus === NetworkStatus.Available) { + if (networkStatus === NetworkStatus.Available) { publicConfigStore.putState(selectPublicState(chainId, memState)); } } diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 02d7b1f50..b4fadf9d4 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -15,6 +15,7 @@ import { METAMASK_STALELIST_FILE, METAMASK_HOTLIST_DIFF_FILE, } from '@metamask/phishing-controller'; +import { NetworkType } from '@metamask/controller-utils'; import { TransactionStatus } from '../../shared/constants/transaction'; import createTxMeta from '../../test/lib/createTxMeta'; import { NETWORK_TYPES } from '../../shared/constants/network'; @@ -160,9 +161,13 @@ const firstTimeState = { id: NETWORK_CONFIGURATION_ID_1, }, }, - networkDetails: { - EIPS: { - 1559: false, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { + 1559: false, + }, + status: 'available', }, }, }, diff --git a/app/scripts/migrations/094.test.ts b/app/scripts/migrations/094.test.ts new file mode 100644 index 000000000..f37d46c81 --- /dev/null +++ b/app/scripts/migrations/094.test.ts @@ -0,0 +1,443 @@ +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; +import { migrate, version } from './094'; + +describe('migration #94', () => { + it('should update the version metadata', async () => { + const oldStorage = { + meta: { + version: 93, + }, + data: {}, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.meta).toStrictEqual({ + version, + }); + }); + + it('should return state unaltered if there is no network controller state', async () => { + const oldData = { + other: 'data', + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should return state unaltered if there is no network controller providerConfig state', async () => { + const oldData = { + other: 'data', + NetworkController: { + networkConfigurations: { + id1: { + foo: 'bar', + }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should return state unaltered if there is a providerConfig.id value in state but it is not a string', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + ticker: 'NET', + type: NetworkType.rpc, + chainId: '0x189123', + nickname: 'A Network', + id: { not: 'a string' }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should return state unaltered if there is a providerConfig.type value in state but it equals NetworkType.rpc and there is no providerConfig.id value in state', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + ticker: 'ETH', + type: NetworkType.rpc, + chainId: '0x189123', + nickname: 'A Network', + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should add a selectedNetworkClientId property and a default networksMetadata object to the NetworkController state if there is a providerConfig.id value in state and it is a string (and there are no networkStatus or networkDetails values)', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + ticker: 'NET', + type: NetworkType.rpc, + chainId: '0x189123', + nickname: 'A Network', + id: 'test-network-client-id', + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data.NetworkController).toStrictEqual({ + providerConfig: { + ticker: 'NET', + type: NetworkType.rpc, + chainId: '0x189123', + nickname: 'A Network', + id: 'test-network-client-id', + }, + networksMetadata: { + 'test-network-client-id': { + EIPS: {}, + status: NetworkStatus.Unknown, + }, + }, + selectedNetworkClientId: 'test-network-client-id', + }); + }); + + it('should add a selectedNetworkClientId property and a default networksMetadata object to the NetworkController state if there is a providerConfig.type value in state and it is not NetworkType.rpc (and there are no networkStatus or networkDetails values)', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + ticker: 'sepoliaETH', + type: NetworkType.sepolia, + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data.NetworkController).toStrictEqual({ + providerConfig: { + ticker: 'sepoliaETH', + type: NetworkType.sepolia, + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networksMetadata: { + [NetworkType.sepolia]: { + EIPS: {}, + status: NetworkStatus.Unknown, + }, + }, + selectedNetworkClientId: NetworkType.sepolia, + }); + }); + + it('should migrate networkStatus into networksMetadata keyed by the active providerConfig.id value, calling the new value "status" and deleting the root networkStatus value', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networkStatus: NetworkStatus.Available, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networksMetadata: { + 'test-network-client-id': { + status: NetworkStatus.Available, + EIPS: {}, + }, + }, + selectedNetworkClientId: 'test-network-client-id', + }, + }); + }); + + it('should migrate networkStatus into networksMetadata keyed by the active providerConfig.type value (if providerConfig.type is not NetworkType.rpc), calling the new value "status" and deleting the root networkStatus value', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networkStatus: NetworkStatus.Available, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networksMetadata: { + [NetworkType.sepolia]: { + status: NetworkStatus.Available, + EIPS: {}, + }, + }, + selectedNetworkClientId: NetworkType.sepolia, + }, + }); + }); + + it('should migrate the contents of networkDetails into networksMetadata keyed by the active providerConfig.id value, and delete the root networkDetails value', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networkDetails: { + EIPS: { 1559: false }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networksMetadata: { + 'test-network-client-id': { + status: NetworkStatus.Unknown, + EIPS: { + 1559: false, + }, + }, + }, + selectedNetworkClientId: 'test-network-client-id', + }, + }); + }); + + it('should migrate the contents of networkDetails into networksMetadata keyed by the active providerConfig.type (if providerConfig.type does not equal NetworkType.rpc) value, and delete the root networkDetails value', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networkDetails: { + EIPS: { 1559: false }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networksMetadata: { + [NetworkType.sepolia]: { + status: NetworkStatus.Unknown, + EIPS: { 1559: false }, + }, + }, + selectedNetworkClientId: NetworkType.sepolia, + }, + }); + }); + + it('should migrate both networkStatus and networkDetails state into networksMetadata keyed by the active providerConfig.id value', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networkStatus: NetworkStatus.Available, + networkDetails: { + EIPS: { 1559: false }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.rpc, + chainId: '0x9393', + nickname: 'Funky Town Chain', + ticker: 'ETH', + id: 'test-network-client-id', + }, + networksMetadata: { + 'test-network-client-id': { + status: NetworkStatus.Available, + EIPS: { 1559: false }, + }, + }, + selectedNetworkClientId: 'test-network-client-id', + }, + }); + }); + + it('should migrate both networkStatus and networkDetails state into networksMetadata keyed by the active providerConfig.type (if providerConfig.type does not equal NetworkType.rpc)', async () => { + const oldData = { + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networkStatus: NetworkStatus.Available, + networkDetails: { + EIPS: { 1559: false }, + }, + }, + }; + const oldStorage = { + meta: { + version: 93, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + type: NetworkType.sepolia, + ticker: 'sepoliaETH', + chainId: '0xaa36a7', + nickname: 'Sepolia TestNet', + }, + networksMetadata: { + [NetworkType.sepolia]: { + status: NetworkStatus.Available, + EIPS: { 1559: false }, + }, + }, + selectedNetworkClientId: NetworkType.sepolia, + }, + }); + }); +}); diff --git a/app/scripts/migrations/094.ts b/app/scripts/migrations/094.ts new file mode 100644 index 000000000..78fbe9641 --- /dev/null +++ b/app/scripts/migrations/094.ts @@ -0,0 +1,89 @@ +import { cloneDeep } from 'lodash'; +import { hasProperty, isObject } from '@metamask/utils'; +import { NetworkStatus } from '@metamask/network-controller'; +import { NetworkType } from '@metamask/controller-utils'; + +export const version = 94; + +/** + * Migrate NetworkDetails & NetworkStatus state on the NetworkConroller to NetworksMetadata and add selectedNetworkClientId + * + * @param originalVersionedData - Versioned MetaMask extension state, exactly what we persist to dist. + * @param originalVersionedData.meta - State metadata. + * @param originalVersionedData.meta.version - The current state version. + * @param originalVersionedData.data - The persisted MetaMask state, keyed by controller. + * @returns Updated versioned MetaMask extension state. + */ +export async function migrate(originalVersionedData: { + meta: { version: number }; + data: Record; +}) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + versionedData.data = transformState(versionedData.data); + return versionedData; +} + +function transformState(state: Record) { + if ( + hasProperty(state, 'NetworkController') && + isObject(state.NetworkController) && + hasProperty(state.NetworkController, 'providerConfig') && + isObject(state.NetworkController.providerConfig) && + (hasProperty(state.NetworkController.providerConfig, 'id') || + (hasProperty(state.NetworkController.providerConfig, 'type') && + state.NetworkController.providerConfig.type !== NetworkType.rpc)) + ) { + const selectedNetworkClientId = + state.NetworkController.providerConfig.id || + state.NetworkController.providerConfig.type; + + if ( + !selectedNetworkClientId || + typeof selectedNetworkClientId !== 'string' + ) { + return state; + } + + const networksMetadata = { + [selectedNetworkClientId]: { + EIPS: {}, + status: NetworkStatus.Unknown, + }, + }; + + if ( + hasProperty(state.NetworkController, 'networkDetails') && + isObject(state.NetworkController.networkDetails) + ) { + const { networkDetails } = state.NetworkController; + + if (networkDetails.EIPS && isObject(networkDetails.EIPS)) { + networksMetadata[selectedNetworkClientId].EIPS = { + ...networkDetails.EIPS, + }; + } + + delete state.NetworkController.networkDetails; + } + + if ( + hasProperty(state.NetworkController, 'networkStatus') && + typeof state.NetworkController.networkStatus === 'string' + ) { + networksMetadata[selectedNetworkClientId].status = state.NetworkController + .networkStatus as NetworkStatus; + delete state.NetworkController.networkStatus; + } + + return { + ...state, + NetworkController: { + ...state.NetworkController, + networksMetadata, + selectedNetworkClientId, + }, + }; + } + return state; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index e16ed99bc..de5b11744 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -97,6 +97,7 @@ import * as m090 from './090'; import * as m091 from './091'; import * as m092 from './092'; import * as m093 from './093'; +import * as m094 from './094'; const migrations = [ m002, @@ -191,5 +192,6 @@ const migrations = [ m091, m092, m093, + m094, ]; export default migrations; diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 8b59c2148..a02644c04 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -858,6 +858,12 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/eth-query": { + "packages": { + "eth-query>json-rpc-random-id": true, + "watchify>xtend": true + } + }, "@metamask/controller-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -1663,6 +1669,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/controller-utils>@metamask/eth-query": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1670,7 +1677,6 @@ "@metamask/network-controller>@metamask/utils": true, "@metamask/network-controller>eth-block-tracker": true, "browserify>assert": true, - "eth-query": true, "eth-rpc-errors": true, "json-rpc-engine": true, "uuid": true diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index c970ace4e..01e56f8b9 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -858,6 +858,12 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/eth-query": { + "packages": { + "eth-query>json-rpc-random-id": true, + "watchify>xtend": true + } + }, "@metamask/controller-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -1814,6 +1820,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/controller-utils>@metamask/eth-query": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1821,7 +1828,6 @@ "@metamask/network-controller>@metamask/utils": true, "@metamask/network-controller>eth-block-tracker": true, "browserify>assert": true, - "eth-query": true, "eth-rpc-errors": true, "json-rpc-engine": true, "uuid": true diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index c970ace4e..01e56f8b9 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -858,6 +858,12 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/eth-query": { + "packages": { + "eth-query>json-rpc-random-id": true, + "watchify>xtend": true + } + }, "@metamask/controller-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -1814,6 +1820,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/controller-utils>@metamask/eth-query": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1821,7 +1828,6 @@ "@metamask/network-controller>@metamask/utils": true, "@metamask/network-controller>eth-block-tracker": true, "browserify>assert": true, - "eth-query": true, "eth-rpc-errors": true, "json-rpc-engine": true, "uuid": true diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 8b59c2148..a02644c04 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -858,6 +858,12 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/eth-query": { + "packages": { + "eth-query>json-rpc-random-id": true, + "watchify>xtend": true + } + }, "@metamask/controller-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -1663,6 +1669,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/controller-utils>@metamask/eth-query": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1670,7 +1677,6 @@ "@metamask/network-controller>@metamask/utils": true, "@metamask/network-controller>eth-block-tracker": true, "browserify>assert": true, - "eth-query": true, "eth-rpc-errors": true, "json-rpc-engine": true, "uuid": true diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index ba5ab1fb5..6b526f97a 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1086,6 +1086,12 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/eth-query": { + "packages": { + "eth-query>json-rpc-random-id": true, + "watchify>xtend": true + } + }, "@metamask/controller-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -1891,6 +1897,7 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/controller-utils>@metamask/eth-query": true, "@metamask/eth-json-rpc-middleware": true, "@metamask/network-controller>@metamask/eth-json-rpc-infura": true, "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, @@ -1898,7 +1905,6 @@ "@metamask/network-controller>@metamask/utils": true, "@metamask/network-controller>eth-block-tracker": true, "browserify>assert": true, - "eth-query": true, "eth-rpc-errors": true, "json-rpc-engine": true, "uuid": true diff --git a/package.json b/package.json index 4e9ae618c..23f872073 100644 --- a/package.json +++ b/package.json @@ -252,7 +252,7 @@ "@metamask/logo": "^3.1.1", "@metamask/message-manager": "^7.0.2", "@metamask/metamask-eth-abis": "^3.0.0", - "@metamask/network-controller": "^11.0.0", + "@metamask/network-controller": "^12.0.0", "@metamask/notification-controller": "^3.0.0", "@metamask/obs-store": "^8.1.0", "@metamask/permission-controller": "^4.0.0", diff --git a/test/data/mock-send-state.json b/test/data/mock-send-state.json index 0193c3ce5..21ab228d9 100644 --- a/test/data/mock-send-state.json +++ b/test/data/mock-send-state.json @@ -154,9 +154,13 @@ "address": "0xeb9e64b93097bc15f01f13eae97015c57ab64823" } }, - "networkDetails": { - "EIPS": { - "1559": true + "selectedNetworkClientId": "goerli", + "networksMetadata": { + "goerli": { + "EIPS": { + "1559": true + }, + "status": "available" } }, "frequentRpcListDetail": [], diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 77d17841f..1095058d0 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -110,7 +110,6 @@ "showIncomingTransactions": true }, "networkId": "5", - "networkStatus": "available", "providerConfig": { "type": "rpc", "chainId": "0x5", @@ -172,9 +171,11 @@ "address": "0xeb9e64b93097bc15f01f13eae97015c57ab64823" } }, - "networkDetails": { - "EIPS": { - "1559": true + "selectedNetworkClientId": "goerli", + "networksMetadata": { + "goerli": { + "EIPS": { "1559": true }, + "status": "available" } }, "frequentRpcListDetail": [], diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 6d5d850b0..3c1415e53 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -4,6 +4,7 @@ const { } = require('@metamask/snaps-utils'); const { merge } = require('lodash'); const { toHex } = require('@metamask/controller-utils'); +const { NetworkStatus } = require('@metamask/network-controller'); const { CHAIN_IDS } = require('../../shared/constants/network'); const { ACTION_QUEUE_METRICS_E2E_TEST, @@ -219,7 +220,13 @@ function defaultFixture() { }, NetworkController: { networkId: '1337', - networkStatus: 'available', + selectedNetworkClientId: 'networkConfigurationId', + networksMetadata: { + networkConfigurationId: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, providerConfig: { chainId: CHAIN_IDS.LOCALHOST, nickname: 'Localhost 8545', @@ -352,7 +359,13 @@ function onboardingFixture() { }, NetworkController: { networkId: '1337', - networkStatus: 'available', + selectedNetworkClientId: 'networkConfigurationId', + networksMetadata: { + networkConfigurationId: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, providerConfig: { ticker: 'ETH', type: 'rpc', diff --git a/test/jest/mock-store.js b/test/jest/mock-store.js index ef05b7ba3..3b1823edb 100644 --- a/test/jest/mock-store.js +++ b/test/jest/mock-store.js @@ -1,3 +1,5 @@ +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { CHAIN_IDS } from '../../shared/constants/network'; import { KeyringType } from '../../shared/constants/keyring'; @@ -132,13 +134,18 @@ export const createSwapsMockStore = () => { swapsSTXLoading: false, }, metamask: { - networkDetails: { - EIPS: { - 1559: false, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { + 1559: false, + }, + status: NetworkStatus.Available, }, }, providerConfig: { chainId: CHAIN_IDS.MAINNET, + ticker: 'ETH', }, cachedBalances: { [CHAIN_IDS.MAINNET]: 5, diff --git a/ui/components/app/confirm-gas-display/confirm-gas-display.test.js b/ui/components/app/confirm-gas-display/confirm-gas-display.test.js index 6e96fb3f4..2851e84f7 100644 --- a/ui/components/app/confirm-gas-display/confirm-gas-display.test.js +++ b/ui/components/app/confirm-gas-display/confirm-gas-display.test.js @@ -1,6 +1,8 @@ import React from 'react'; import { screen } from '@testing-library/react'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { GasEstimateTypes } from '../../../../shared/constants/gas'; import mockEstimates from '../../../../test/data/mock-estimates.json'; import mockState from '../../../../test/data/mock-state.json'; @@ -71,9 +73,13 @@ describe('ConfirmGasDisplay', () => { render({ contextProps: { metamask: { - networkDetails: { - EIPS: { - 1559: false, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { + 1559: false, + }, + status: NetworkStatus.Available, }, }, }, diff --git a/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js index 9edd0c53b..5f808c299 100644 --- a/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js @@ -1,6 +1,8 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; +import { NetworkStatus } from '@metamask/network-controller'; +import { NetworkType } from '@metamask/controller-utils'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import ConfirmDetailRow from '.'; @@ -14,6 +16,13 @@ describe('Confirm Detail Row Component', () => { preferences: { useNativeCurrencyAsPrimaryCurrency: true, }, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, }, }; diff --git a/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js index cca653ded..c6c74fa26 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js @@ -1,5 +1,7 @@ import React from 'react'; import configureStore from 'redux-mock-store'; +import { NetworkStatus } from '@metamask/network-controller'; +import { NetworkType } from '@metamask/controller-utils'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import ConfirmPageContainerHeader from '.'; @@ -12,11 +14,17 @@ jest.mock('../../../../../app/scripts/lib/util', () => ({ describe('Confirm Detail Row Component', () => { const mockState = { metamask: { - networkStatus: 'available', providerConfig: { type: 'rpc', chainId: '0x5', }, + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, }, }; diff --git a/ui/components/app/modals/account-details-modal/account-details-modal.test.js b/ui/components/app/modals/account-details-modal/account-details-modal.test.js index 259da80ca..6b365c5de 100644 --- a/ui/components/app/modals/account-details-modal/account-details-modal.test.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.test.js @@ -2,6 +2,8 @@ import React from 'react'; import configureMockState from 'redux-mock-store'; import { fireEvent } from '@testing-library/react'; import thunk from 'redux-thunk'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import mockState from '../../../../../test/data/mock-state.json'; import { @@ -88,6 +90,7 @@ describe('Account Details Modal', () => { }, providerConfig: { chainId: '0x99', + ticker: 'ETH', }, }, }; @@ -168,9 +171,13 @@ describe('Account Details Modal', () => { address: '0xeb9e64b93097bc15f01f13eae97015c57ab64823', }, }, - networkDetails: { - EIPS: { - 1559: true, + networksMetadata: { + selectedNetworkClientId: NetworkType.mainnet, + [NetworkType.mainnet]: { + EIPS: { + 1559: false, + }, + status: NetworkStatus.Available, }, }, frequentRpcListDetail: [], diff --git a/ui/components/app/transaction-alerts/transaction-alerts.stories.js b/ui/components/app/transaction-alerts/transaction-alerts.stories.js index 701764f26..ad7692d91 100644 --- a/ui/components/app/transaction-alerts/transaction-alerts.stories.js +++ b/ui/components/app/transaction-alerts/transaction-alerts.stories.js @@ -2,6 +2,8 @@ import React from 'react'; import { Provider } from 'react-redux'; import { keccak } from 'ethereumjs-util'; import { cloneDeep } from 'lodash'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { GasFeeContextProvider } from '../../../contexts/gasFee'; import configureStore from '../../../store/store'; import testData from '../../../../.storybook/test-data'; @@ -58,11 +60,15 @@ const customStore = ({ networkCongestion: isNetworkBusy ? 1 : 0.1, }, // supportsEIP1559 - networkDetails: { - ...testData?.metamask?.networkDetails, - EIPS: { - ...testData?.metamask?.networkDetails?.EIPS, - 1159: Boolean(supportsEIP1559), + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + ...testData?.metamask?.networksMetadata, + [NetworkType.mainnet]: { + EIPS: { + ...testData?.metamask?.networksMetadata?.EIPS, + 1559: Boolean(supportsEIP1559), + }, + status: NetworkStatus.Available, }, }, // pendingTransactions diff --git a/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js index 30f4183ad..a3514f525 100644 --- a/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -1,6 +1,8 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import sinon from 'sinon'; +import { NetworkStatus } from '@metamask/network-controller'; +import { NetworkType } from '@metamask/controller-utils'; import { TransactionStatus } from '../../../shared/constants/transaction'; import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck'; @@ -344,7 +346,13 @@ describe('Confirm Transaction Duck', () => { conversionRate: 468.58, currentCurrency: 'usd', networkId: '5', - networkStatus: 'available', + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, providerConfig: { chainId: '0x5', }, diff --git a/ui/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js index 832c08d4c..2ba6b365a 100644 --- a/ui/ducks/metamask/metamask.js +++ b/ui/ducks/metamask/metamask.js @@ -9,6 +9,7 @@ import { accountsWithSendEtherInfoSelector, checkNetworkAndAccountSupports1559, getAddressBook, + getSelectedNetworkClientId, getUseCurrencyRateCheck, } from '../../selectors'; import { updateTransactionGasFees } from '../../store/actions'; @@ -308,7 +309,11 @@ export function getUnapprovedTxs(state) { * @param state */ export function isNotEIP1559Network(state) { - return state.metamask.networkDetails?.EIPS[1559] === false; + const selectedNetworkClientId = getSelectedNetworkClientId(state); + return ( + state.metamask.networksMetadata[selectedNetworkClientId].EIPS[1559] === + false + ); } /** @@ -317,7 +322,11 @@ export function isNotEIP1559Network(state) { * @param state */ export function isEIP1559Network(state) { - return state.metamask.networkDetails?.EIPS[1559] === true; + const selectedNetworkClientId = getSelectedNetworkClientId(state); + return ( + state.metamask.networksMetadata?.[selectedNetworkClientId].EIPS[1559] === + true + ); } export function getGasEstimateType(state) { diff --git a/ui/ducks/metamask/metamask.test.js b/ui/ducks/metamask/metamask.test.js index 1370bf9a6..38efb3ff1 100644 --- a/ui/ducks/metamask/metamask.test.js +++ b/ui/ducks/metamask/metamask.test.js @@ -1,3 +1,5 @@ +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { TransactionStatus } from '../../../shared/constants/transaction'; import * as actionConstants from '../../store/actionConstants'; import reduceMetamask, { @@ -42,7 +44,13 @@ describe('MetaMask Reducers', () => { nativeCurrency: 'ETH', useCurrencyRateCheck: true, networkId: '5', - networkStatus: 'available', + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: {}, + status: NetworkStatus.Available, + }, + }, providerConfig: { type: 'testnet', chainId: '0x5', @@ -104,9 +112,6 @@ describe('MetaMask Reducers', () => { gasPrice: '4a817c800', }, }, - networkDetails: { - EIPS: { 1559: true }, - }, }, {}, ), @@ -354,15 +359,21 @@ describe('MetaMask Reducers', () => { ...mockState, metamask: { ...mockState.metamask, - networkDetails: { - EIPS: { 1559: false }, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { + 1559: false, + }, + status: 'available', + }, }, }, }), ).toStrictEqual(true); }); - it('should return false if networkDetails.EIPS.1559 is not false', () => { + it('should return false if networksMetadata[selectedNetworkClientId].EIPS.1559 is not false', () => { expect(isNotEIP1559Network(mockState)).toStrictEqual(false); expect( @@ -370,8 +381,12 @@ describe('MetaMask Reducers', () => { ...mockState, metamask: { ...mockState.metamask, - networkDetails: { - EIPS: { 1559: undefined }, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { 1559: true }, + status: 'available', + }, }, }, }), diff --git a/ui/ducks/send/send.test.js b/ui/ducks/send/send.test.js index 340d447db..fa85ee1da 100644 --- a/ui/ducks/send/send.test.js +++ b/ui/ducks/send/send.test.js @@ -2,6 +2,8 @@ import sinon from 'sinon'; import createMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { BigNumber } from '@ethersproject/bignumber'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { CONTRACT_ADDRESS_ERROR, INSUFFICIENT_FUNDS_ERROR, @@ -1272,9 +1274,13 @@ describe('Send Slice', () => { metamask: { gasEstimateType: GasEstimateTypes.none, gasFeeEstimates: {}, - networkDetails: { - EIPS: { - 1559: true, + selectedNetworkClientId: NetworkType.goerli, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: { + 1559: true, + }, + status: NetworkStatus.Available, }, }, selectedAddress: mockAddress1, @@ -1298,6 +1304,7 @@ describe('Send Slice', () => { }, providerConfig: { chainId: '0x5', + ticker: 'ETH', }, useTokenDetection: true, tokenList: { diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js index 7a079ece4..ebcee960f 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js @@ -3,6 +3,8 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { fireEvent } from '@testing-library/react'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { renderWithProvider } from '../../../test/lib/render-helpers'; import { setBackgroundConnection } from '../../../test/jest'; import { INITIAL_SEND_STATE_FOR_EXISTING_DRAFT } from '../../../test/jest/mocks'; @@ -85,8 +87,12 @@ const baseStore = { }, ], networkId: mockNetworkId, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, tokens: [], preferences: { @@ -253,10 +259,12 @@ describe('Confirm Transaction Base', () => { }, }, gasEstimateType: GasEstimateTypes.feeMarket, - networkDetails: { - ...mockedStore.metamask.networkDetails, - EIPS: { - 1559: true, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + ...mockedStore.metamask.networksMetadata, + [NetworkType.mainnet]: { + EIPS: { 1559: true }, + status: NetworkStatus.Available, }, }, customGas: { @@ -324,10 +332,14 @@ describe('Confirm Transaction Base', () => { }, }, gasEstimateType: GasEstimateTypes.feeMarket, - networkDetails: { - ...mockedStore.metamask.networkDetails, - EIPS: { - 1559: true, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + ...mockedStore.metamask.networksMetadata, + [NetworkType.mainnet]: { + EIPS: { + 1559: true, + }, + status: NetworkStatus.Available, }, }, customGas: { diff --git a/ui/pages/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap b/ui/pages/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap index e294686d8..a840236c8 100644 --- a/ui/pages/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap +++ b/ui/pages/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap @@ -18,16 +18,14 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = `
- - Attempting to connect to blockchain. - +
- - Attempting to connect to blockchain. - + - - Attempting to connect to blockchain. - + - - Attempting to connect to blockchain. - + { configureMockStore(middleware)({ metamask: { gasEstimateType: GasEstimateTypes.none, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: 'available', + }, }, }, send: INITIAL_SEND_STATE_FOR_EXISTING_DRAFT, @@ -36,8 +41,12 @@ describe('AmountMaxButton Component', () => { const store = configureMockStore(middleware)({ metamask: { gasEstimateType: GasEstimateTypes.ethGasPrice, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: 'available', + }, }, }, send: getInitialSendStateWithExistingTxState({ @@ -59,8 +68,12 @@ describe('AmountMaxButton Component', () => { const store = configureMockStore(middleware)({ metamask: { gasEstimateType: GasEstimateTypes.ethGasPrice, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: 'available', + }, }, }, send: { diff --git a/ui/pages/send/send.test.js b/ui/pages/send/send.test.js index 0713cbe81..fd1c3537c 100644 --- a/ui/pages/send/send.test.js +++ b/ui/pages/send/send.test.js @@ -2,6 +2,7 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { useLocation } from 'react-router-dom'; +import { NetworkType } from '@metamask/controller-utils'; import { SEND_STAGES, startNewDraftTransaction } from '../../ducks/send'; import { domainInitialState } from '../../ducks/domains'; import { CHAIN_IDS } from '../../../shared/constants/network'; @@ -85,8 +86,12 @@ const baseStore = { accounts: ['0x0'], }, ], - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: 'available', + }, }, tokens: [], preferences: { diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.test.js b/ui/pages/swaps/prepare-swap-page/review-quote.test.js index 1624f5a98..e02cb3d0b 100644 --- a/ui/pages/swaps/prepare-swap-page/review-quote.test.js +++ b/ui/pages/swaps/prepare-swap-page/review-quote.test.js @@ -2,6 +2,7 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +import { NetworkType } from '@metamask/controller-utils'; import { renderWithProvider, createSwapsMockStore, @@ -62,9 +63,11 @@ describe('ReviewQuote', () => { it('renders the component with EIP-1559 enabled', () => { const state = createSwapsMockStore(); - state.metamask.networkDetails = { - EIPS: { - 1559: true, + state.metamask.selectedNetworkClientId = NetworkType.mainnet; + state.metamask.networksMetadata = { + [NetworkType.mainnet]: { + EIPS: {}, + status: 'available', }, }; const store = configureMockStore(middleware)(state); diff --git a/ui/pages/swaps/view-quote/view-quote.test.js b/ui/pages/swaps/view-quote/view-quote.test.js index c1aa42849..4cf0d55ee 100644 --- a/ui/pages/swaps/view-quote/view-quote.test.js +++ b/ui/pages/swaps/view-quote/view-quote.test.js @@ -2,6 +2,8 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { renderWithProvider, createSwapsMockStore, @@ -72,9 +74,11 @@ describe('ViewQuote', () => { it('renders the component with EIP-1559 enabled', () => { const state = createSwapsMockStore(); - state.metamask.networkDetails = { - EIPS: { - 1559: true, + state.metamask.selectedNetworkClientId = NetworkType.mainnet; + state.metamask.networksMetadata = { + [NetworkType.mainnet]: { + EIPS: { 1559: true }, + status: NetworkStatus.Available, }, }; const store = configureMockStore(middleware)(state); diff --git a/ui/pages/token-allowance/token-allowance.test.js b/ui/pages/token-allowance/token-allowance.test.js index f51303476..094203598 100644 --- a/ui/pages/token-allowance/token-allowance.test.js +++ b/ui/pages/token-allowance/token-allowance.test.js @@ -2,6 +2,8 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import { act, fireEvent } from '@testing-library/react'; import thunk from 'redux-thunk'; +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { renderWithProvider } from '../../../test/lib/render-helpers'; import { KeyringType } from '../../../shared/constants/keyring'; import TokenAllowance from './token-allowance'; @@ -44,9 +46,11 @@ const state = { type: 'mainnet', nickname: '', }, - networkDetails: { - EIPS: { - 1559: true, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: { 1559: true }, + status: NetworkStatus.Available, }, }, preferences: { diff --git a/ui/selectors/custom-gas.test.js b/ui/selectors/custom-gas.test.js index 4a1e71a11..30ed14d98 100644 --- a/ui/selectors/custom-gas.test.js +++ b/ui/selectors/custom-gas.test.js @@ -1,3 +1,5 @@ +import { NetworkType } from '@metamask/controller-utils'; +import { NetworkStatus } from '@metamask/network-controller'; import { GasEstimateTypes } from '../../shared/constants/gas'; import { getInitialSendStateWithExistingTxState } from '../../test/jest/mocks'; import { @@ -24,8 +26,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { low: '1', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -41,8 +47,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { low: '1', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -58,8 +68,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { low: '1', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -75,8 +89,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { low: undefined, }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -95,8 +113,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '150', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -112,8 +134,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: undefined, }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -129,8 +155,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -146,8 +176,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -163,8 +197,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -180,8 +218,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, gas: { @@ -197,8 +239,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, send: getInitialSendStateWithExistingTxState({ @@ -219,8 +265,12 @@ describe('custom-gas selectors', () => { gasFeeEstimates: { high: '139', }, - networkDetails: { - EIPS: {}, + selectedNetworkClientId: NetworkType.mainnet, + networksMetadata: { + [NetworkType.mainnet]: { + EIPS: {}, + status: NetworkStatus.Available, + }, }, }, send: getInitialSendStateWithExistingTxState({ diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 97dc5a612..8485c5d9f 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -105,7 +105,15 @@ import { getPermissionSubjects } from './permissions'; * @param {object} state - Redux state object. */ export function isNetworkLoading(state) { - return state.metamask.networkStatus !== NetworkStatus.Available; + const selectedNetworkClientId = getSelectedNetworkClientId(state); + return ( + state.metamask.networksMetadata[selectedNetworkClientId].status !== + NetworkStatus.Available + ); +} + +export function getSelectedNetworkClientId(state) { + return state.metamask.selectedNetworkClientId; } export function getNetworkIdentifier(state) { diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index 307cbde92..58b34ce3e 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -1,4 +1,4 @@ -import { ApprovalType } from '@metamask/controller-utils'; +import { ApprovalType, NetworkType } from '@metamask/controller-utils'; import mockState from '../../test/data/mock-state.json'; import { KeyringType } from '../../shared/constants/keyring'; import { @@ -493,8 +493,10 @@ describe('Selectors', () => { ...mockState, metamask: { ...mockState.metamask, - networkDetails: { - EIPS: { 1559: false }, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: { 1559: false }, + }, }, }, }); @@ -503,8 +505,10 @@ describe('Selectors', () => { ...mockState, metamask: { ...mockState.metamask, - networkDetails: { - EIPS: { 1559: false }, + networksMetadata: { + [NetworkType.goerli]: { + EIPS: { 1559: false }, + }, }, }, }); diff --git a/ui/store/store.ts b/ui/store/store.ts index 8f8e46847..73b387574 100644 --- a/ui/store/store.ts +++ b/ui/store/store.ts @@ -69,7 +69,13 @@ interface TemporaryBackgroundState { unapprovedPersonalMsgs: MessagesIndexedById; unapprovedTypedMessages: MessagesIndexedById; networkId: string | null; - networkStatus: NetworkStatus; + networksMetadata: { + [NetworkClientId: string]: { + EIPS: { [eip: string]: boolean }; + status: NetworkStatus; + }; + }; + selectedNetworkClientId: string; pendingApprovals: ApprovalControllerState['pendingApprovals']; approvalFlows: ApprovalControllerState['approvalFlows']; knownMethodData?: { diff --git a/yarn.lock b/yarn.lock index a52ac8daa..23b862842 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3924,19 +3924,19 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0, @metamask/controller-utils@npm:^4.2.0, @metamask/controller-utils@npm:^4.3.0": - version: 4.3.0 - resolution: "@metamask/controller-utils@npm:4.3.0" +"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0, @metamask/controller-utils@npm:^4.2.0, @metamask/controller-utils@npm:^4.3.0, @metamask/controller-utils@npm:^4.3.1": + version: 4.3.1 + resolution: "@metamask/controller-utils@npm:4.3.1" dependencies: + "@metamask/eth-query": "npm:^3.0.1" "@metamask/utils": "npm:^6.2.0" "@spruceid/siwe-parser": "npm:1.1.3" eth-ens-namehash: "npm:^2.0.8" - eth-query: "npm:^2.1.2" eth-rpc-errors: "npm:^4.0.2" ethereumjs-util: "npm:^7.0.10" ethjs-unit: "npm:^0.1.6" fast-deep-equal: "npm:^3.1.3" - checksum: 56059054da727625330f16e1a939ba116069382fcf1803b39038bc30807b5ca24e4173e1e7d5049247055c7df2f3c7451dae9196063f78135fa05972d54ec9df + checksum: 7e8f4d95d6138da27e601bed1927b50f4628718ca1760d175144d5530febde870fd3c390e4aa9d408e7322c14032a87d7ab449f6cd39ae0e06be0e3c7e1495ae languageName: node linkType: hard @@ -4117,6 +4117,16 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-query@npm:^3.0.1": + version: 3.0.1 + resolution: "@metamask/eth-query@npm:3.0.1" + dependencies: + json-rpc-random-id: "npm:^1.0.0" + xtend: "npm:^4.0.1" + checksum: d463aff018ae3f1229331177e9efa0eb62958c6fcc30039c22d151ee64da17d55153ef4861060aecec674f764aa9074341bef53fdf86c2258d3cb2682976e835 + languageName: node + linkType: hard + "@metamask/eth-sig-util@npm:5.0.2": version: 5.0.2 resolution: "@metamask/eth-sig-util@npm:5.0.2" @@ -4400,25 +4410,25 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^11.0.0": - version: 11.0.0 - resolution: "@metamask/network-controller@npm:11.0.0" +"@metamask/network-controller@npm:^12.0.0": + version: 12.0.0 + resolution: "@metamask/network-controller@npm:12.0.0" dependencies: "@metamask/base-controller": "npm:^3.2.0" - "@metamask/controller-utils": "npm:^4.3.0" + "@metamask/controller-utils": "npm:^4.3.1" "@metamask/eth-json-rpc-infura": "npm:^8.1.1" "@metamask/eth-json-rpc-middleware": "npm:^11.0.0" "@metamask/eth-json-rpc-provider": "npm:^1.0.0" + "@metamask/eth-query": "npm:^3.0.1" "@metamask/swappable-obj-proxy": "npm:^2.1.0" "@metamask/utils": "npm:^6.2.0" async-mutex: "npm:^0.2.6" eth-block-tracker: "npm:^7.0.1" - eth-query: "npm:^2.1.2" eth-rpc-errors: "npm:^4.0.2" immer: "npm:^9.0.6" json-rpc-engine: "npm:^6.1.0" uuid: "npm:^8.3.2" - checksum: de89ed99001eedce04309285276837080f038859a1a9fee231f89fdb851a037766396f36dc75b2d2feff6941171bb6bde6970d60c11f2885f44e33534e644dc1 + checksum: ea7c8010f1ca80c448050c7cf618598a1dabe82969fe1ff4a4952b85b3e4db677adab88d99a146cb11461d899628d3914f71e1b22d4249ccc5787a0281839afd languageName: node linkType: hard @@ -24259,7 +24269,7 @@ __metadata: "@metamask/logo": "npm:^3.1.1" "@metamask/message-manager": "npm:^7.0.2" "@metamask/metamask-eth-abis": "npm:^3.0.0" - "@metamask/network-controller": "npm:^11.0.0" + "@metamask/network-controller": "npm:^12.0.0" "@metamask/notification-controller": "npm:^3.0.0" "@metamask/obs-store": "npm:^8.1.0" "@metamask/permission-controller": "npm:^4.0.0"