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

Make setActiveNetwork async (#18605)

The network controller method `setActiveNetwork` is now async, and the
asynchronous `_setProviderConfig` step is now awaited. The function
will not resolve until the network has finished switching.

This change affects the `eth_switchEthereumChain` and
`eth_addEthereumChain` middleware, and it affects any network switching
performed in our UI.

Relates to https://github.com/MetaMask/metamask-extension/issues/18587
This commit is contained in:
Mark Stacey 2023-04-18 13:25:05 -02:30 committed by GitHub
parent c6aa4f38c5
commit 1fe28ee15a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 117 deletions

View File

@ -1192,7 +1192,7 @@ describe('NetworkController', () => {
}); });
expect(oldChainIdResult).toBe('0x5'); expect(oldChainIdResult).toBe('0x5');
controller.setActiveNetwork('testNetworkConfigurationId'); await controller.setActiveNetwork('testNetworkConfigurationId');
const promisifiedSendAsync2 = promisify(provider.sendAsync).bind( const promisifiedSendAsync2 = promisify(provider.sendAsync).bind(
provider, provider,
); );
@ -2431,16 +2431,10 @@ describe('NetworkController', () => {
}, },
}, },
beforeCompleting: async () => { beforeCompleting: async () => {
await waitForStateChanges({ await controller.setActiveNetwork(
controller,
propertyPath: ['networkStatus'],
operation: () => {
controller.setActiveNetwork(
'testNetworkConfigurationId', 'testNetworkConfigurationId',
); );
}, },
});
},
}, },
], ],
}); });
@ -2506,16 +2500,10 @@ describe('NetworkController', () => {
network1.mockEssentialRpcCalls({ network1.mockEssentialRpcCalls({
eth_getBlockByNumber: { eth_getBlockByNumber: {
beforeCompleting: async () => { beforeCompleting: async () => {
await waitForStateChanges({ await controller.setActiveNetwork(
controller,
propertyPath: ['networkStatus'],
operation: () => {
controller.setActiveNetwork(
'testNetworkConfigurationId', 'testNetworkConfigurationId',
); );
}, },
});
},
}, },
net_version: { net_version: {
response: { response: {
@ -2578,16 +2566,10 @@ describe('NetworkController', () => {
latestBlock: POST_1559_BLOCK, latestBlock: POST_1559_BLOCK,
eth_getBlockByNumber: { eth_getBlockByNumber: {
beforeCompleting: async () => { beforeCompleting: async () => {
await waitForStateChanges({ await controller.setActiveNetwork(
controller,
propertyPath: ['networkStatus'],
operation: () => {
controller.setActiveNetwork(
'testNetworkConfigurationId', 'testNetworkConfigurationId',
); );
}, },
});
},
}, },
}); });
const network2 = new CustomNetworkCommunications({ const network2 = new CustomNetworkCommunications({
@ -4032,9 +4014,9 @@ describe('NetworkController', () => {
async ({ controller, network }) => { async ({ controller, network }) => {
network.mockEssentialRpcCalls(); network.mockEssentialRpcCalls();
expect(() => await expect(() =>
controller.setActiveNetwork('invalid-network-configuration-id'), controller.setActiveNetwork('invalid-network-configuration-id'),
).toThrow( ).rejects.toThrow(
new Error( new Error(
'networkConfigurationId invalid-network-configuration-id does not match a configured networkConfiguration', 'networkConfigurationId invalid-network-configuration-id does not match a configured networkConfiguration',
), ),
@ -4075,7 +4057,7 @@ describe('NetworkController', () => {
}); });
network.mockEssentialRpcCalls(); network.mockEssentialRpcCalls();
controller.setActiveNetwork('testNetworkConfigurationId1'); await controller.setActiveNetwork('testNetworkConfigurationId1');
expect(controller.store.getState().provider).toStrictEqual({ expect(controller.store.getState().provider).toStrictEqual({
type: 'rpc', type: 'rpc',
@ -4144,6 +4126,8 @@ describe('NetworkController', () => {
messenger: unrestrictedMessenger, messenger: unrestrictedMessenger,
eventType: NetworkControllerEventType.NetworkWillChange, eventType: NetworkControllerEventType.NetworkWillChange,
operation: () => { operation: () => {
// Intentionally not awaited because we're checking state
// partway through the operation
controller.setActiveNetwork('testNetworkConfigurationId2'); controller.setActiveNetwork('testNetworkConfigurationId2');
}, },
beforeResolving: () => { beforeResolving: () => {
@ -4208,6 +4192,8 @@ describe('NetworkController', () => {
// before networkDidChange // before networkDidChange
count: 1, count: 1,
operation: () => { operation: () => {
// Intentionally not awaited because we're checking state
// partway through the operation.
controller.setActiveNetwork('testNetworkConfigurationId1'); controller.setActiveNetwork('testNetworkConfigurationId1');
}, },
}); });
@ -4267,6 +4253,8 @@ describe('NetworkController', () => {
// before networkDidChange // before networkDidChange
count: 1, count: 1,
operation: () => { operation: () => {
// Intentionally not awaited because we're checking state
// partway through the operation
controller.setActiveNetwork('testNetworkConfigurationId2'); controller.setActiveNetwork('testNetworkConfigurationId2');
}, },
}); });
@ -4308,7 +4296,7 @@ describe('NetworkController', () => {
}, },
}); });
controller.setActiveNetwork('testNetworkConfigurationId'); await controller.setActiveNetwork('testNetworkConfigurationId');
const { provider } = controller.getProviderAndBlockTracker(); const { provider } = controller.getProviderAndBlockTracker();
assert(provider, 'Provider is somehow unset'); assert(provider, 'Provider is somehow unset');
@ -4356,7 +4344,7 @@ describe('NetworkController', () => {
const { provider: providerBefore } = const { provider: providerBefore } =
controller.getProviderAndBlockTracker(); controller.getProviderAndBlockTracker();
controller.setActiveNetwork('testNetworkConfigurationId'); await controller.setActiveNetwork('testNetworkConfigurationId');
const { provider: providerAfter } = const { provider: providerAfter } =
controller.getProviderAndBlockTracker(); controller.getProviderAndBlockTracker();
@ -4392,8 +4380,8 @@ describe('NetworkController', () => {
const networkDidChange = await waitForPublishedEvents({ const networkDidChange = await waitForPublishedEvents({
messenger: unrestrictedMessenger, messenger: unrestrictedMessenger,
eventType: NetworkControllerEventType.NetworkDidChange, eventType: NetworkControllerEventType.NetworkDidChange,
operation: () => { operation: async () => {
controller.setActiveNetwork('testNetworkConfigurationId'); await controller.setActiveNetwork('testNetworkConfigurationId');
}, },
}); });
@ -4429,8 +4417,8 @@ describe('NetworkController', () => {
const infuraIsUnblocked = await waitForPublishedEvents({ const infuraIsUnblocked = await waitForPublishedEvents({
messenger: unrestrictedMessenger, messenger: unrestrictedMessenger,
eventType: NetworkControllerEventType.InfuraIsUnblocked, eventType: NetworkControllerEventType.InfuraIsUnblocked,
operation: () => { operation: async () => {
controller.setActiveNetwork('testNetworkConfigurationId'); await controller.setActiveNetwork('testNetworkConfigurationId');
}, },
}); });
@ -4462,13 +4450,7 @@ describe('NetworkController', () => {
response: SUCCESSFUL_NET_VERSION_RESPONSE, response: SUCCESSFUL_NET_VERSION_RESPONSE,
}, },
}); });
await waitForStateChanges({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
propertyPath: ['networkStatus'],
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
expect(controller.store.getState().networkStatus).toBe('available'); expect(controller.store.getState().networkStatus).toBe('available');
}, },
@ -4501,16 +4483,7 @@ describe('NetworkController', () => {
latestBlock: POST_1559_BLOCK, latestBlock: POST_1559_BLOCK,
}); });
await waitForStateChanges({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
propertyPath: ['networkDetails'],
// setActiveNetwork clears networkDetails first, and then updates it
// to what we expect it to be
count: 2,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
expect(controller.store.getState().networkDetails).toStrictEqual({ expect(controller.store.getState().networkDetails).toStrictEqual({
EIPS: { EIPS: {
@ -5657,12 +5630,7 @@ describe('NetworkController', () => {
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId2');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId2');
},
});
expect(controller.store.getState().provider).toStrictEqual({ expect(controller.store.getState().provider).toStrictEqual({
type: 'rpc', type: 'rpc',
rpcUrl: 'https://mock-rpc-url-2', rpcUrl: 'https://mock-rpc-url-2',
@ -5730,12 +5698,7 @@ describe('NetworkController', () => {
}); });
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
await waitForLookupNetworkToComplete({ await waitForLookupNetworkToComplete({
controller, controller,
@ -5787,12 +5750,7 @@ describe('NetworkController', () => {
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
expect(controller.store.getState().networkStatus).toBe( expect(controller.store.getState().networkStatus).toBe(
'available', 'available',
); );
@ -5855,12 +5813,7 @@ describe('NetworkController', () => {
}); });
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
expect(controller.store.getState().networkDetails).toStrictEqual({ expect(controller.store.getState().networkDetails).toStrictEqual({
EIPS: { EIPS: {
1559: true, 1559: true,
@ -5926,12 +5879,7 @@ describe('NetworkController', () => {
}); });
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
await waitForLookupNetworkToComplete({ await waitForLookupNetworkToComplete({
controller, controller,
@ -5986,12 +5934,7 @@ describe('NetworkController', () => {
}); });
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
const { provider: providerBefore } = const { provider: providerBefore } =
controller.getProviderAndBlockTracker(); controller.getProviderAndBlockTracker();
@ -6045,12 +5988,7 @@ describe('NetworkController', () => {
currentNetwork.mockEssentialRpcCalls(); currentNetwork.mockEssentialRpcCalls();
previousNetwork.mockEssentialRpcCalls(); previousNetwork.mockEssentialRpcCalls();
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
await waitForLookupNetworkToComplete({ await waitForLookupNetworkToComplete({
controller, controller,
@ -6103,12 +6041,7 @@ describe('NetworkController', () => {
response: BLOCKED_INFURA_RESPONSE, response: BLOCKED_INFURA_RESPONSE,
}, },
}); });
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
const promiseForNoInfuraIsUnblockedEvents = const promiseForNoInfuraIsUnblockedEvents =
waitForPublishedEvents({ waitForPublishedEvents({
messenger: unrestrictedMessenger, messenger: unrestrictedMessenger,
@ -6173,13 +6106,7 @@ describe('NetworkController', () => {
}, },
}); });
await waitForStateChanges({ await controller.setActiveNetwork('currentNetworkConfiguration');
controller,
propertyPath: ['networkStatus'],
operation: () => {
controller.setActiveNetwork('currentNetworkConfiguration');
},
});
expect(controller.store.getState().networkStatus).toBe( expect(controller.store.getState().networkStatus).toBe(
'unavailable', 'unavailable',
); );
@ -6228,12 +6155,7 @@ describe('NetworkController', () => {
latestBlock: POST_1559_BLOCK, latestBlock: POST_1559_BLOCK,
}); });
await waitForLookupNetworkToComplete({ await controller.setActiveNetwork('testNetworkConfigurationId');
controller,
operation: () => {
controller.setActiveNetwork('testNetworkConfigurationId');
},
});
expect(controller.store.getState().networkDetails).toStrictEqual({ expect(controller.store.getState().networkDetails).toStrictEqual({
EIPS: { EIPS: {
1559: false, 1559: false,

View File

@ -704,7 +704,7 @@ export class NetworkController extends EventEmitter {
* @returns The URL of the RPC endpoint representing the newly switched * @returns The URL of the RPC endpoint representing the newly switched
* network. * network.
*/ */
setActiveNetwork(networkConfigurationId: NetworkConfigurationId): string { async setActiveNetwork(networkConfigurationId: NetworkConfigurationId) {
const targetNetwork = const targetNetwork =
this.store.getState().networkConfigurations[networkConfigurationId]; this.store.getState().networkConfigurations[networkConfigurationId];
@ -714,7 +714,7 @@ export class NetworkController extends EventEmitter {
); );
} }
this.#setProviderConfig({ await this.#setProviderConfig({
type: NETWORK_TYPES.RPC, type: NETWORK_TYPES.RPC,
...targetNetwork, ...targetNetwork,
}); });