From 43a6bfbe0fa6113531eb61263dd830c56448253a Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Mon, 17 Aug 2026 11:36:47 +0200 Subject: [PATCH 1/5] fix(network-connection-banner-controller): subscribe to ClientController:stateChange The controller subscribed to ClientController:stateChanged using a locally defined event type, but @metamask/client-controller only declares and exports ClientController:stateChange. Clients that delegate the exported event (mobile) never deliver UI open state, so the controller never starts and the banner never shows. --- .../README.md | 2 +- .../NetworkConnectionBannerController.test.ts | 5 +++-- .../src/NetworkConnectionBannerController.ts | 17 ++++------------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/network-connection-banner-controller/README.md b/packages/network-connection-banner-controller/README.md index 7a0372d3391..c17ce310bd5 100644 --- a/packages/network-connection-banner-controller/README.md +++ b/packages/network-connection-banner-controller/README.md @@ -13,7 +13,7 @@ from the same failure start and must be greater than the degraded one. The controller stays dormant after construction so the 5s / 30s escalation timers do not run before a user is actually looking at the wallet (e.g. while the app is still on the lock screen). It manages its own lifecycle by -subscribing to `ClientController:stateChanged` and +subscribing to `ClientController:stateChange` and `KeyringController:unlock` / `KeyringController:lock`: evaluation runs only while the client UI is open on an unlocked wallet. When either condition stops holding, pending timers are cancelled and the banner state resets to diff --git a/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.test.ts b/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.test.ts index efc25f75282..847118212e0 100644 --- a/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.test.ts +++ b/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.test.ts @@ -1843,7 +1843,8 @@ async function withController( 'NetworkEnablementController:stateChange', // eslint-disable-next-line no-restricted-syntax -- awaiting upstream :stateChanged migration 'ConnectivityController:stateChange', - 'ClientController:stateChanged', + // eslint-disable-next-line no-restricted-syntax -- awaiting upstream :stateChanged migration + 'ClientController:stateChange', 'KeyringController:unlock', 'KeyringController:lock', ], @@ -1857,7 +1858,7 @@ async function withController( }); const setUiOpen = (isUiOpen: boolean): void => { - rootMessenger.publish('ClientController:stateChanged', { isUiOpen }, []); + rootMessenger.publish('ClientController:stateChange', { isUiOpen }, []); }; const setKeyringUnlocked = (isUnlocked: boolean): void => { rootMessenger.publish( diff --git a/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.ts b/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.ts index f3cc67e8079..a3bbdd023e9 100644 --- a/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.ts +++ b/packages/network-connection-banner-controller/src/NetworkConnectionBannerController.ts @@ -5,7 +5,7 @@ import type { } from '@metamask/base-controller'; import { BaseController } from '@metamask/base-controller'; import { clientControllerSelectors } from '@metamask/client-controller'; -import type { ClientControllerState } from '@metamask/client-controller'; +import type { ClientControllerStateChangeEvent } from '@metamask/client-controller'; import { CONNECTIVITY_STATUSES, connectivityControllerSelectors, @@ -264,16 +264,6 @@ export type NetworkConnectionBannerControllerStateChangedEvent = export type NetworkConnectionBannerControllerEvents = NetworkConnectionBannerControllerStateChangedEvent; -/** - * Published when the state of `ClientController` changes. Defined here - * because the `client-controller` package still exports the legacy - * `:stateChange` event type. - */ -type ClientControllerStateChangedEvent = ControllerStateChangedEvent< - 'ClientController', - ClientControllerState ->; - /** * Events from other messengers that * {@link NetworkConnectionBannerControllerMessenger} subscribes to. @@ -282,7 +272,7 @@ type AllowedEvents = | NetworkControllerStateChangeEvent | NetworkEnablementControllerStateChangeEvent | ConnectivityControllerStateChangeEvent - | ClientControllerStateChangedEvent + | ClientControllerStateChangeEvent | KeyringControllerUnlockEvent | KeyringControllerLockEvent; @@ -474,7 +464,8 @@ export class NetworkConnectionBannerController extends BaseController< // Lifecycle: evaluate RPC health (and run the banner escalation timers) // only while the client UI is open on an unlocked wallet. this.messenger.subscribe( - 'ClientController:stateChanged', + // eslint-disable-next-line no-restricted-syntax -- awaiting upstream :stateChanged migration + 'ClientController:stateChange', (isUiOpen) => { this.#isUiOpen = isUiOpen; this.#updateLifecycle(); From fae7256e4bebfd7bd263e19990cc3b6f953d6718 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Mon, 17 Aug 2026 11:37:42 +0200 Subject: [PATCH 2/5] docs: add changelog entry --- packages/network-connection-banner-controller/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/network-connection-banner-controller/CHANGELOG.md b/packages/network-connection-banner-controller/CHANGELOG.md index 231346f7838..84e5d9688de 100644 --- a/packages/network-connection-banner-controller/CHANGELOG.md +++ b/packages/network-connection-banner-controller/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** `NetworkConnectionBannerControllerMessenger` now requires the `ClientController:stateChange` event to be delegated instead of `ClientController:stateChanged` ([#9893](https://github.com/MetaMask/core/pull/9893)) + - Clients delegating `ClientController:stateChanged` must switch to `ClientController:stateChange`. + - Fixes the controller never starting (and the banner never showing) for clients that delegate the `ClientController:stateChange` event exported by `@metamask/client-controller`. - Bump `@metamask/network-controller` from `^35.0.0` to `^35.0.1` ([#9758](https://github.com/MetaMask/core/pull/9758)) - Bump `@metamask/network-enablement-controller` from `^6.0.1` to `^6.0.3` ([#9740](https://github.com/MetaMask/core/pull/9740), [#9791](https://github.com/MetaMask/core/pull/9791)) - Bump `@metamask/keyring-controller` from `^27.1.0` to `^27.1.1` ([#9791](https://github.com/MetaMask/core/pull/9791)) From c9c49e0d6897ce240c391034f0a8505b8e0bbcd9 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Mon, 17 Aug 2026 11:41:23 +0200 Subject: [PATCH 3/5] docs: correct changelog wording on the ClientController event change Both clients delegate ClientController:stateChanged today and BaseController publishes both names, so the banner does work at runtime. The defect is the undeclared event type, not a dead subscription. --- packages/network-connection-banner-controller/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/network-connection-banner-controller/CHANGELOG.md b/packages/network-connection-banner-controller/CHANGELOG.md index 84e5d9688de..c9b88314ad5 100644 --- a/packages/network-connection-banner-controller/CHANGELOG.md +++ b/packages/network-connection-banner-controller/CHANGELOG.md @@ -10,8 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **BREAKING:** `NetworkConnectionBannerControllerMessenger` now requires the `ClientController:stateChange` event to be delegated instead of `ClientController:stateChanged` ([#9893](https://github.com/MetaMask/core/pull/9893)) - - Clients delegating `ClientController:stateChanged` must switch to `ClientController:stateChange`. - - Fixes the controller never starting (and the banner never showing) for clients that delegate the `ClientController:stateChange` event exported by `@metamask/client-controller`. + - `ClientController:stateChanged` is not declared by `@metamask/client-controller`, so clients had to suppress a type error to delegate it. + - Clients delegating `ClientController:stateChanged` must switch to `ClientController:stateChange`, otherwise the controller no longer receives UI open state and the banner never shows. - Bump `@metamask/network-controller` from `^35.0.0` to `^35.0.1` ([#9758](https://github.com/MetaMask/core/pull/9758)) - Bump `@metamask/network-enablement-controller` from `^6.0.1` to `^6.0.3` ([#9740](https://github.com/MetaMask/core/pull/9740), [#9791](https://github.com/MetaMask/core/pull/9791)) - Bump `@metamask/keyring-controller` from `^27.1.0` to `^27.1.1` ([#9791](https://github.com/MetaMask/core/pull/9791)) From 965cac8b05eb4e18ac1e39aa370b9765bf1364e0 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Mon, 17 Aug 2026 11:44:18 +0200 Subject: [PATCH 4/5] docs: drop the type suppression note from the changelog entry --- packages/network-connection-banner-controller/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/network-connection-banner-controller/CHANGELOG.md b/packages/network-connection-banner-controller/CHANGELOG.md index c9b88314ad5..d6d855e6ceb 100644 --- a/packages/network-connection-banner-controller/CHANGELOG.md +++ b/packages/network-connection-banner-controller/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **BREAKING:** `NetworkConnectionBannerControllerMessenger` now requires the `ClientController:stateChange` event to be delegated instead of `ClientController:stateChanged` ([#9893](https://github.com/MetaMask/core/pull/9893)) - - `ClientController:stateChanged` is not declared by `@metamask/client-controller`, so clients had to suppress a type error to delegate it. - Clients delegating `ClientController:stateChanged` must switch to `ClientController:stateChange`, otherwise the controller no longer receives UI open state and the banner never shows. - Bump `@metamask/network-controller` from `^35.0.0` to `^35.0.1` ([#9758](https://github.com/MetaMask/core/pull/9758)) - Bump `@metamask/network-enablement-controller` from `^6.0.1` to `^6.0.3` ([#9740](https://github.com/MetaMask/core/pull/9740), [#9791](https://github.com/MetaMask/core/pull/9791)) From ec8b9d7d301e82bafb66b23a463bf63497ecf360 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Mon, 17 Aug 2026 11:46:11 +0200 Subject: [PATCH 5/5] docs: tighten the changelog entry --- packages/network-connection-banner-controller/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/network-connection-banner-controller/CHANGELOG.md b/packages/network-connection-banner-controller/CHANGELOG.md index d6d855e6ceb..998b96182d3 100644 --- a/packages/network-connection-banner-controller/CHANGELOG.md +++ b/packages/network-connection-banner-controller/CHANGELOG.md @@ -9,8 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** `NetworkConnectionBannerControllerMessenger` now requires the `ClientController:stateChange` event to be delegated instead of `ClientController:stateChanged` ([#9893](https://github.com/MetaMask/core/pull/9893)) - - Clients delegating `ClientController:stateChanged` must switch to `ClientController:stateChange`, otherwise the controller no longer receives UI open state and the banner never shows. +- **BREAKING:** `NetworkConnectionBannerControllerMessenger` now requires `ClientController:stateChange` to be delegated instead of `ClientController:stateChanged` ([#9893](https://github.com/MetaMask/core/pull/9893)) - Bump `@metamask/network-controller` from `^35.0.0` to `^35.0.1` ([#9758](https://github.com/MetaMask/core/pull/9758)) - Bump `@metamask/network-enablement-controller` from `^6.0.1` to `^6.0.3` ([#9740](https://github.com/MetaMask/core/pull/9740), [#9791](https://github.com/MetaMask/core/pull/9791)) - Bump `@metamask/keyring-controller` from `^27.1.0` to `^27.1.1` ([#9791](https://github.com/MetaMask/core/pull/9791))