diff --git a/packages/network-controller/src/NetworkController.ts b/packages/network-controller/src/NetworkController.ts index 277a0b7915d..26560884dd9 100644 --- a/packages/network-controller/src/NetworkController.ts +++ b/packages/network-controller/src/NetworkController.ts @@ -1688,7 +1688,7 @@ export class NetworkController extends BaseController< async #lookupGivenNetwork(networkClientId: NetworkClientId) { const { networkStatus, isEIP1559Compatible } = await this.#determineNetworkMetadata(networkClientId); - this.#updateMetadataForNetwork( + this.#updateNetworkMetadata( networkClientId, networkStatus, isEIP1559Compatible, @@ -1713,80 +1713,20 @@ export class NetworkController extends BaseController< return; } - let networkChanged = false; - const listener = () => { - networkChanged = true; - try { - this.messagingSystem.unsubscribe( - 'NetworkController:networkDidChange', - listener, - ); - } catch (error) { - // In theory, this `catch` should not be necessary given that this error - // would occur "inside" of the call to `#determineEIP1559Compatibility` - // below and so it should be caught by the `try`/`catch` below (it is - // impossible to reproduce in tests for that reason). However, somehow - // it occurs within Mobile and so we have to add our own `try`/`catch` - // here. - /* istanbul ignore next */ - if ( - !(error instanceof Error) || - error.message !== - 'Subscription not found for event: NetworkController:networkDidChange' - ) { - // Again, this error should not happen and is impossible to reproduce - // in tests. - /* istanbul ignore next */ - throw error; - } - } - }; - this.messagingSystem.subscribe( - 'NetworkController:networkDidChange', - listener, - ); + // Capture up front in case the network is switched while awaiting the + // network request + const { selectedNetworkClientId } = this.state; const { isInfura, networkStatus, isEIP1559Compatible } = - await this.#determineNetworkMetadata(this.state.selectedNetworkClientId); - - if (networkChanged) { - // If the network has changed, then `lookupNetwork` either has been or is - // in the process of being called, so we don't need to go further. - return; - } + await this.#determineNetworkMetadata(selectedNetworkClientId); - try { - this.messagingSystem.unsubscribe( - 'NetworkController:networkDidChange', - listener, + if (selectedNetworkClientId === this.state.selectedNetworkClientId) { + this.#updateNetworkMetadata( + selectedNetworkClientId, + networkStatus, + isEIP1559Compatible, ); - } catch (error) { - if ( - !(error instanceof Error) || - error.message !== - 'Subscription not found for event: NetworkController:networkDidChange' - ) { - throw error; - } - } - - this.#updateMetadataForNetwork( - this.state.selectedNetworkClientId, - networkStatus, - isEIP1559Compatible, - ); - - if (isInfura) { - if (networkStatus === NetworkStatus.Available) { - this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); - } else if (networkStatus === NetworkStatus.Blocked) { - this.messagingSystem.publish('NetworkController:infuraIsBlocked'); - } - } else { - // Always publish infuraIsUnblocked regardless of network status to - // prevent consumers from being stuck in a blocked state if they were - // previously connected to an Infura network that was blocked - this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + this.#publishInfuraBlockedStatusEvents(isInfura, networkStatus); } } @@ -1798,7 +1738,7 @@ export class NetworkController extends BaseController< * @param isEIP1559Compatible - The EIP-1559 compatibility status to * store in state. */ - #updateMetadataForNetwork( + #updateNetworkMetadata( networkClientId: NetworkClientId, networkStatus: NetworkStatus, isEIP1559Compatible: boolean | undefined, @@ -1820,6 +1760,31 @@ export class NetworkController extends BaseController< }); } + /** + * Publishes events that advise users about whether the recently updated + * network is geo-blocked by Infura. + * + * @param isInfura - Whether the network points to an Infura URL. + * @param networkStatus - The status of the network. + */ + #publishInfuraBlockedStatusEvents( + isInfura: boolean, + networkStatus: NetworkStatus, + ) { + if (isInfura) { + if (networkStatus === NetworkStatus.Available) { + this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + } else if (networkStatus === NetworkStatus.Blocked) { + this.messagingSystem.publish('NetworkController:infuraIsBlocked'); + } + } else { + // Always publish infuraIsUnblocked regardless of network status to + // prevent consumers from being stuck in a blocked state if they were + // previously connected to an Infura network that was blocked + this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + } + } + /** * Convenience method to update provider network type settings. * diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index 1d54513d0fd..e9cbb6d248f 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -2225,55 +2225,6 @@ describe('NetworkController', () => { }); }); - describe('if removing the networkDidChange subscription fails for an unknown reason', () => { - it('re-throws the error', async () => { - const infuraProjectId = 'some-infura-project-id'; - - await withController( - { - state: { - selectedNetworkClientId: infuraNetworkType, - }, - infuraProjectId, - }, - async ({ controller, messenger }) => { - const fakeProvider = buildFakeProvider([ - // Called during provider initialization - { - request: { - method: 'eth_getBlockByNumber', - }, - response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE, - }, - // Called via `lookupNetwork` directly - { - request: { - method: 'eth_getBlockByNumber', - }, - response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE, - }, - ]); - const fakeNetworkClient = buildFakeClient(fakeProvider); - createNetworkClientMock.mockReturnValue(fakeNetworkClient); - await controller.initializeProvider(); - - const lookupNetworkPromise = controller.lookupNetwork(); - const error = new Error('oops'); - jest - .spyOn(messenger, 'unsubscribe') - .mockImplementation((eventType) => { - // This is okay. - // eslint-disable-next-line jest/no-conditional-in-test - if (eventType === 'NetworkController:networkDidChange') { - throw error; - } - }); - await expect(lookupNetworkPromise).rejects.toThrow(error); - }, - ); - }); - }); - lookupNetworkTests({ expectedNetworkClientType: NetworkClientType.Infura, expectedNetworkClientId: infuraNetworkType, @@ -2726,65 +2677,6 @@ describe('NetworkController', () => { }); }); - describe('if removing the networkDidChange subscription fails for an unknown reason', () => { - it('re-throws the error', async () => { - const infuraProjectId = 'some-infura-project-id'; - - await withController( - { - state: { - selectedNetworkClientId: 'AAAA-AAAA-AAAA-AAAA', - networkConfigurationsByChainId: { - '0x1337': buildCustomNetworkConfiguration({ - chainId: '0x1337', - rpcEndpoints: [ - buildCustomRpcEndpoint({ - networkClientId: 'AAAA-AAAA-AAAA-AAAA', - }), - ], - }), - }, - }, - infuraProjectId, - }, - async ({ controller, messenger }) => { - const fakeProvider = buildFakeProvider([ - // Called during provider initialization - { - request: { - method: 'eth_getBlockByNumber', - }, - response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE, - }, - // Called via `lookupNetwork` directly - { - request: { - method: 'eth_getBlockByNumber', - }, - response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE, - }, - ]); - const fakeNetworkClient = buildFakeClient(fakeProvider); - createNetworkClientMock.mockReturnValue(fakeNetworkClient); - await controller.initializeProvider(); - - const lookupNetworkPromise = controller.lookupNetwork(); - const error = new Error('oops'); - jest - .spyOn(messenger, 'unsubscribe') - .mockImplementation((eventType) => { - // This is okay. - // eslint-disable-next-line jest/no-conditional-in-test - if (eventType === 'NetworkController:networkDidChange') { - throw error; - } - }); - await expect(lookupNetworkPromise).rejects.toThrow(error); - }, - ); - }); - }); - lookupNetworkTests({ expectedNetworkClientType: NetworkClientType.Custom, expectedNetworkClientId: 'AAAA-AAAA-AAAA-AAAA',