Skip to content

feat: add @metamask/network-connection-banner-controller#9041

Open
cryptodev-2s wants to merge 50 commits into
mainfrom
wpc-1014-network-connection-banner-controller
Open

feat: add @metamask/network-connection-banner-controller#9041
cryptodev-2s wants to merge 50 commits into
mainfrom
wpc-1014-network-connection-banner-controller

Conversation

@cryptodev-2s

@cryptodev-2s cryptodev-2s commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Explanation

The RPC connection banner ("Still connecting" / "Unable to connect") is currently rendered by both metamask-extension and metamask-mobile based on duplicated logic in each repo:

  • The 5s / 30s timer state machine.
  • The show/hide rule (custom-RPC override, ≥2 distinct registrable domains failing, or all-enabled-failed escape hatch).
  • eTLD+1 grouping via psl so a single provider's wide outage doesn't pop the banner.
  • Infura URL detection.
  • The { chainId, networkName, rpcUrl, isInfuraEndpoint, infuraNetworkClientId } payload shape.

This PR introduces @metamask/network-connection-banner-controller so there's a single source of truth. The controller:

  • Subscribes to NetworkController:stateChanged, NetworkEnablementController:stateChanged, and ConnectivityController:stateChanged via the messenger.
  • Runs the 5s/30s escalation timers internally.
  • Exposes a flat state { status: 'available' | 'degraded' | 'unavailable', network: FailedNetwork | null } that clients subscribe to.
  • Exposes two messenger actions: dismissBanner() and switchToDefaultInfuraRpc({ chainId }) — the latter looks up the chain's first Infura endpoint and calls NetworkController:updateNetwork with replacementSelectedRpcEndpointIndex.
  • Stays analytics-free; clients diff state-change events into their own analytics translation.

psl 1.15 ships its types field outside its exports map so TypeScript's node16 module resolution can't find it; a small ambient src/psl.d.ts shim mirrors the workaround already in use in extension and mobile. ip-regex is pinned to ^4.3.0 (last CJS release) because the monorepo's Jest config doesn't transform ESM-only deps.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
switchToDefaultInfuraRpcEndpoint mutates default RPC via NetworkController; banner logic is intricate but isolated in a new package with broad test coverage.

Overview
Adds @metamask/network-connection-banner-controller, a new core package that centralizes the RPC connection banner logic previously duplicated in extension and mobile.

NetworkConnectionBannerController watches enabled EVM networks via NetworkController, NetworkEnablementController, and ConnectivityController, applies the shared show/hide rules (custom-RPC override, multi-domain failures, all-enabled-down escape hatch, single-provider Infura suppression via eTLD+1), and drives 5s → degraded and 30s → unavailable escalation timers. UI calls start() / stop() so timers do not run while the wallet surface is inactive; dismissBanner() and switchToDefaultInfuraRpcEndpoint(chainId) (via NetworkController:updateNetwork) handle user actions.

Monorepo wiring includes README/CODEOWNERS/teams/tsconfig, a root types/psl.d.ts shim for psl typing, and package deps psl / ip-regex.

Reviewed by Cursor Bugbot for commit cadd612. Bugbot is set up for automated code reviews on this repo. Configure here.

@socket-security

socket-security Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​metamask/​snaps-utils@​12.2.0 ⏵ 12.2.198 +110076 +195100
Updated@​metamask/​snaps-sdk@​11.1.0 ⏵ 11.1.1991007892100
Addedip-regex@​4.3.01001009580100
Updatedpsl@​1.9.0 ⏵ 1.15.010010010080100

View full report

@cryptodev-2s cryptodev-2s force-pushed the wpc-1014-network-connection-banner-controller branch 2 times, most recently from 9111156 to d1fa945 Compare June 8, 2026 16:31
@cryptodev-2s

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.1-preview-7507a11
@metamask-previews/accounts-controller@39.0.0-preview-7507a11
@metamask-previews/address-book-controller@7.1.2-preview-7507a11
@metamask-previews/ai-controllers@0.7.0-preview-7507a11
@metamask-previews/analytics-controller@1.1.1-preview-7507a11
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-7507a11
@metamask-previews/announcement-controller@8.1.0-preview-7507a11
@metamask-previews/app-metadata-controller@2.0.1-preview-7507a11
@metamask-previews/approval-controller@9.0.1-preview-7507a11
@metamask-previews/assets-controller@8.3.2-preview-7507a11
@metamask-previews/assets-controllers@108.5.0-preview-7507a11
@metamask-previews/authenticated-user-storage@2.0.0-preview-7507a11
@metamask-previews/base-controller@9.1.0-preview-7507a11
@metamask-previews/base-data-service@0.1.3-preview-7507a11
@metamask-previews/bridge-controller@73.2.1-preview-7507a11
@metamask-previews/bridge-status-controller@72.0.2-preview-7507a11
@metamask-previews/build-utils@3.0.4-preview-7507a11
@metamask-previews/chain-agnostic-permission@1.6.1-preview-7507a11
@metamask-previews/chomp-api-service@3.1.0-preview-7507a11
@metamask-previews/claims-controller@0.5.2-preview-7507a11
@metamask-previews/client-controller@1.0.1-preview-7507a11
@metamask-previews/compliance-controller@2.1.0-preview-7507a11
@metamask-previews/composable-controller@12.0.1-preview-7507a11
@metamask-previews/config-registry-controller@0.4.0-preview-7507a11
@metamask-previews/connectivity-controller@0.2.0-preview-7507a11
@metamask-previews/controller-utils@12.1.0-preview-7507a11
@metamask-previews/core-backend@6.3.2-preview-7507a11
@metamask-previews/delegation-controller@3.0.1-preview-7507a11
@metamask-previews/earn-controller@12.2.0-preview-7507a11
@metamask-previews/eip-5792-middleware@3.0.4-preview-7507a11
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-7507a11
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-7507a11
@metamask-previews/ens-controller@19.1.3-preview-7507a11
@metamask-previews/eth-block-tracker@15.0.1-preview-7507a11
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-7507a11
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-7507a11
@metamask-previews/foundryup@1.0.1-preview-7507a11
@metamask-previews/gas-fee-controller@26.2.2-preview-7507a11
@metamask-previews/gator-permissions-controller@4.2.0-preview-7507a11
@metamask-previews/geolocation-controller@0.1.3-preview-7507a11
@metamask-previews/json-rpc-engine@10.5.0-preview-7507a11
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-7507a11
@metamask-previews/keyring-controller@26.0.0-preview-7507a11
@metamask-previews/logging-controller@8.0.2-preview-7507a11
@metamask-previews/message-manager@14.1.2-preview-7507a11
@metamask-previews/messenger@1.2.0-preview-7507a11
@metamask-previews/messenger-cli@0.2.0-preview-7507a11
@metamask-previews/money-account-balance-service@1.0.2-preview-7507a11
@metamask-previews/money-account-controller@0.3.2-preview-7507a11
@metamask-previews/money-account-upgrade-controller@2.0.3-preview-7507a11
@metamask-previews/multichain-account-service@10.0.2-preview-7507a11
@metamask-previews/multichain-api-middleware@3.1.3-preview-7507a11
@metamask-previews/multichain-network-controller@3.1.3-preview-7507a11
@metamask-previews/multichain-transactions-controller@7.1.1-preview-7507a11
@metamask-previews/name-controller@9.1.2-preview-7507a11
@metamask-previews/network-connection-banner-controller@0.1.0-preview-7507a11
@metamask-previews/network-controller@32.0.0-preview-7507a11
@metamask-previews/network-enablement-controller@5.3.0-preview-7507a11
@metamask-previews/notification-services-controller@24.1.2-preview-7507a11
@metamask-previews/passkey-controller@2.0.1-preview-7507a11
@metamask-previews/permission-controller@13.1.1-preview-7507a11
@metamask-previews/permission-log-controller@5.1.0-preview-7507a11
@metamask-previews/perps-controller@8.0.0-preview-7507a11
@metamask-previews/phishing-controller@17.2.0-preview-7507a11
@metamask-previews/polling-controller@16.0.6-preview-7507a11
@metamask-previews/preferences-controller@23.1.0-preview-7507a11
@metamask-previews/profile-metrics-controller@3.1.6-preview-7507a11
@metamask-previews/profile-sync-controller@28.1.1-preview-7507a11
@metamask-previews/ramps-controller@14.1.1-preview-7507a11
@metamask-previews/rate-limit-controller@7.0.1-preview-7507a11
@metamask-previews/react-data-query@0.2.1-preview-7507a11
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-7507a11
@metamask-previews/sample-controllers@5.0.1-preview-7507a11
@metamask-previews/seedless-onboarding-controller@10.0.1-preview-7507a11
@metamask-previews/selected-network-controller@26.1.3-preview-7507a11
@metamask-previews/shield-controller@5.1.2-preview-7507a11
@metamask-previews/signature-controller@39.2.4-preview-7507a11
@metamask-previews/snap-account-service@0.3.0-preview-7507a11
@metamask-previews/social-controllers@2.2.1-preview-7507a11
@metamask-previews/storage-service@1.0.1-preview-7507a11
@metamask-previews/subscription-controller@6.1.3-preview-7507a11
@metamask-previews/transaction-controller@67.0.0-preview-7507a11
@metamask-previews/transaction-pay-controller@23.3.0-preview-7507a11
@metamask-previews/user-operation-controller@41.2.3-preview-7507a11
@metamask-previews/wallet@2.0.0-preview-7507a11

@cryptodev-2s

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@cryptodev-2s cryptodev-2s marked this pull request as ready for review June 10, 2026 21:29
@cryptodev-2s cryptodev-2s requested a review from a team as a code owner June 10, 2026 21:29
@cryptodev-2s cryptodev-2s self-assigned this Jun 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.2-preview-69c25f142
@metamask-previews/accounts-controller@39.0.1-preview-69c25f142
@metamask-previews/address-book-controller@7.1.2-preview-69c25f142
@metamask-previews/ai-controllers@0.7.0-preview-69c25f142
@metamask-previews/analytics-controller@1.1.1-preview-69c25f142
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-69c25f142
@metamask-previews/announcement-controller@8.1.0-preview-69c25f142
@metamask-previews/app-metadata-controller@2.0.1-preview-69c25f142
@metamask-previews/approval-controller@9.0.2-preview-69c25f142
@metamask-previews/assets-controller@9.0.1-preview-69c25f142
@metamask-previews/assets-controllers@109.0.0-preview-69c25f142
@metamask-previews/authenticated-user-storage@2.0.0-preview-69c25f142
@metamask-previews/base-controller@9.1.0-preview-69c25f142
@metamask-previews/base-data-service@0.1.3-preview-69c25f142
@metamask-previews/bridge-controller@75.1.1-preview-69c25f142
@metamask-previews/bridge-status-controller@72.1.0-preview-69c25f142
@metamask-previews/build-utils@3.0.4-preview-69c25f142
@metamask-previews/chain-agnostic-permission@1.6.1-preview-69c25f142
@metamask-previews/chomp-api-service@3.1.0-preview-69c25f142
@metamask-previews/claims-controller@0.5.3-preview-69c25f142
@metamask-previews/client-controller@1.0.1-preview-69c25f142
@metamask-previews/compliance-controller@2.1.0-preview-69c25f142
@metamask-previews/composable-controller@12.0.1-preview-69c25f142
@metamask-previews/config-registry-controller@0.4.1-preview-69c25f142
@metamask-previews/connectivity-controller@0.2.0-preview-69c25f142
@metamask-previews/controller-utils@12.2.0-preview-69c25f142
@metamask-previews/core-backend@6.3.3-preview-69c25f142
@metamask-previews/delegation-controller@3.0.2-preview-69c25f142
@metamask-previews/earn-controller@12.2.0-preview-69c25f142
@metamask-previews/eip-5792-middleware@3.0.4-preview-69c25f142
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-69c25f142
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-69c25f142
@metamask-previews/ens-controller@19.1.3-preview-69c25f142
@metamask-previews/eth-block-tracker@15.0.1-preview-69c25f142
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-69c25f142
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-69c25f142
@metamask-previews/foundryup@1.0.1-preview-69c25f142
@metamask-previews/gas-fee-controller@26.2.2-preview-69c25f142
@metamask-previews/gator-permissions-controller@4.2.0-preview-69c25f142
@metamask-previews/geolocation-controller@0.1.3-preview-69c25f142
@metamask-previews/json-rpc-engine@10.5.0-preview-69c25f142
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-69c25f142
@metamask-previews/keyring-controller@27.0.0-preview-69c25f142
@metamask-previews/logging-controller@8.0.2-preview-69c25f142
@metamask-previews/message-manager@14.1.2-preview-69c25f142
@metamask-previews/messenger@1.2.0-preview-69c25f142
@metamask-previews/messenger-cli@0.2.0-preview-69c25f142
@metamask-previews/money-account-balance-service@1.0.2-preview-69c25f142
@metamask-previews/money-account-controller@0.3.3-preview-69c25f142
@metamask-previews/money-account-upgrade-controller@2.0.4-preview-69c25f142
@metamask-previews/multichain-account-service@10.0.3-preview-69c25f142
@metamask-previews/multichain-api-middleware@3.1.3-preview-69c25f142
@metamask-previews/multichain-network-controller@3.1.3-preview-69c25f142
@metamask-previews/multichain-transactions-controller@7.1.1-preview-69c25f142
@metamask-previews/name-controller@9.1.2-preview-69c25f142
@metamask-previews/network-connection-banner-controller@0.1.0-preview-69c25f142
@metamask-previews/network-controller@32.0.0-preview-69c25f142
@metamask-previews/network-enablement-controller@5.3.0-preview-69c25f142
@metamask-previews/notification-services-controller@24.1.3-preview-69c25f142
@metamask-previews/passkey-controller@2.0.1-preview-69c25f142
@metamask-previews/permission-controller@13.1.1-preview-69c25f142
@metamask-previews/permission-log-controller@5.1.0-preview-69c25f142
@metamask-previews/perps-controller@8.0.0-preview-69c25f142
@metamask-previews/phishing-controller@17.2.0-preview-69c25f142
@metamask-previews/polling-controller@16.0.6-preview-69c25f142
@metamask-previews/preferences-controller@23.1.0-preview-69c25f142
@metamask-previews/profile-metrics-controller@3.2.0-preview-69c25f142
@metamask-previews/profile-sync-controller@28.1.1-preview-69c25f142
@metamask-previews/ramps-controller@14.1.1-preview-69c25f142
@metamask-previews/rate-limit-controller@7.0.1-preview-69c25f142
@metamask-previews/react-data-query@0.2.1-preview-69c25f142
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-69c25f142
@metamask-previews/sample-controllers@5.0.1-preview-69c25f142
@metamask-previews/seedless-onboarding-controller@10.0.2-preview-69c25f142
@metamask-previews/selected-network-controller@26.1.3-preview-69c25f142
@metamask-previews/shield-controller@5.1.2-preview-69c25f142
@metamask-previews/signature-controller@39.2.5-preview-69c25f142
@metamask-previews/snap-account-service@0.3.1-preview-69c25f142
@metamask-previews/social-controllers@2.2.1-preview-69c25f142
@metamask-previews/storage-service@1.0.2-preview-69c25f142
@metamask-previews/subscription-controller@6.1.3-preview-69c25f142
@metamask-previews/transaction-controller@67.1.0-preview-69c25f142
@metamask-previews/transaction-pay-controller@23.5.1-preview-69c25f142
@metamask-previews/user-operation-controller@41.2.4-preview-69c25f142
@metamask-previews/wallet@3.0.0-preview-69c25f142

@cryptodev-2s

This comment was marked as outdated.

@cryptodev-2s cryptodev-2s force-pushed the wpc-1014-network-connection-banner-controller branch from 6d2ab14 to 2fc626b Compare June 10, 2026 22:43
@cryptodev-2s

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@cryptodev-2s

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.2-preview-fe651cdb3
@metamask-previews/accounts-controller@39.0.1-preview-fe651cdb3
@metamask-previews/address-book-controller@7.1.2-preview-fe651cdb3
@metamask-previews/ai-controllers@0.7.0-preview-fe651cdb3
@metamask-previews/analytics-controller@1.1.1-preview-fe651cdb3
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-fe651cdb3
@metamask-previews/announcement-controller@8.1.0-preview-fe651cdb3
@metamask-previews/app-metadata-controller@2.0.1-preview-fe651cdb3
@metamask-previews/approval-controller@9.0.2-preview-fe651cdb3
@metamask-previews/assets-controller@9.0.1-preview-fe651cdb3
@metamask-previews/assets-controllers@109.0.0-preview-fe651cdb3
@metamask-previews/authenticated-user-storage@2.0.0-preview-fe651cdb3
@metamask-previews/base-controller@9.1.0-preview-fe651cdb3
@metamask-previews/base-data-service@0.1.3-preview-fe651cdb3
@metamask-previews/bridge-controller@75.1.1-preview-fe651cdb3
@metamask-previews/bridge-status-controller@72.1.0-preview-fe651cdb3
@metamask-previews/build-utils@3.0.4-preview-fe651cdb3
@metamask-previews/chain-agnostic-permission@1.6.1-preview-fe651cdb3
@metamask-previews/chomp-api-service@3.1.0-preview-fe651cdb3
@metamask-previews/claims-controller@0.5.3-preview-fe651cdb3
@metamask-previews/client-controller@1.0.1-preview-fe651cdb3
@metamask-previews/compliance-controller@2.1.0-preview-fe651cdb3
@metamask-previews/composable-controller@12.0.1-preview-fe651cdb3
@metamask-previews/config-registry-controller@0.4.1-preview-fe651cdb3
@metamask-previews/connectivity-controller@0.2.0-preview-fe651cdb3
@metamask-previews/controller-utils@12.2.0-preview-fe651cdb3
@metamask-previews/core-backend@6.3.3-preview-fe651cdb3
@metamask-previews/delegation-controller@3.0.2-preview-fe651cdb3
@metamask-previews/earn-controller@12.2.0-preview-fe651cdb3
@metamask-previews/eip-5792-middleware@3.0.4-preview-fe651cdb3
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-fe651cdb3
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-fe651cdb3
@metamask-previews/ens-controller@19.1.3-preview-fe651cdb3
@metamask-previews/eth-block-tracker@15.0.1-preview-fe651cdb3
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-fe651cdb3
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-fe651cdb3
@metamask-previews/foundryup@1.0.1-preview-fe651cdb3
@metamask-previews/gas-fee-controller@26.2.2-preview-fe651cdb3
@metamask-previews/gator-permissions-controller@4.2.0-preview-fe651cdb3
@metamask-previews/geolocation-controller@0.1.3-preview-fe651cdb3
@metamask-previews/json-rpc-engine@10.5.0-preview-fe651cdb3
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-fe651cdb3
@metamask-previews/keyring-controller@27.0.0-preview-fe651cdb3
@metamask-previews/logging-controller@8.0.2-preview-fe651cdb3
@metamask-previews/message-manager@14.1.2-preview-fe651cdb3
@metamask-previews/messenger@1.2.0-preview-fe651cdb3
@metamask-previews/messenger-cli@0.2.0-preview-fe651cdb3
@metamask-previews/money-account-balance-service@1.0.2-preview-fe651cdb3
@metamask-previews/money-account-controller@0.3.3-preview-fe651cdb3
@metamask-previews/money-account-upgrade-controller@2.0.5-preview-fe651cdb3
@metamask-previews/multichain-account-service@10.0.3-preview-fe651cdb3
@metamask-previews/multichain-api-middleware@3.1.3-preview-fe651cdb3
@metamask-previews/multichain-network-controller@3.1.3-preview-fe651cdb3
@metamask-previews/multichain-transactions-controller@7.1.1-preview-fe651cdb3
@metamask-previews/name-controller@9.1.2-preview-fe651cdb3
@metamask-previews/network-connection-banner-controller@0.1.0-preview-fe651cdb3
@metamask-previews/network-controller@32.0.0-preview-fe651cdb3
@metamask-previews/network-enablement-controller@5.3.0-preview-fe651cdb3
@metamask-previews/notification-services-controller@24.1.3-preview-fe651cdb3
@metamask-previews/passkey-controller@2.0.1-preview-fe651cdb3
@metamask-previews/permission-controller@13.1.1-preview-fe651cdb3
@metamask-previews/permission-log-controller@5.1.0-preview-fe651cdb3
@metamask-previews/perps-controller@8.1.0-preview-fe651cdb3
@metamask-previews/phishing-controller@17.2.0-preview-fe651cdb3
@metamask-previews/polling-controller@16.0.6-preview-fe651cdb3
@metamask-previews/preferences-controller@23.1.0-preview-fe651cdb3
@metamask-previews/profile-metrics-controller@3.2.0-preview-fe651cdb3
@metamask-previews/profile-sync-controller@28.1.1-preview-fe651cdb3
@metamask-previews/ramps-controller@14.1.1-preview-fe651cdb3
@metamask-previews/rate-limit-controller@7.0.1-preview-fe651cdb3
@metamask-previews/react-data-query@0.2.1-preview-fe651cdb3
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-fe651cdb3
@metamask-previews/sample-controllers@5.0.1-preview-fe651cdb3
@metamask-previews/seedless-onboarding-controller@10.0.2-preview-fe651cdb3
@metamask-previews/selected-network-controller@26.1.3-preview-fe651cdb3
@metamask-previews/shield-controller@5.1.2-preview-fe651cdb3
@metamask-previews/signature-controller@39.2.5-preview-fe651cdb3
@metamask-previews/snap-account-service@0.3.1-preview-fe651cdb3
@metamask-previews/social-controllers@2.2.1-preview-fe651cdb3
@metamask-previews/storage-service@1.0.2-preview-fe651cdb3
@metamask-previews/subscription-controller@6.1.3-preview-fe651cdb3
@metamask-previews/transaction-controller@68.0.0-preview-fe651cdb3
@metamask-previews/transaction-pay-controller@23.5.1-preview-fe651cdb3
@metamask-previews/user-operation-controller@41.2.4-preview-fe651cdb3
@metamask-previews/wallet@3.0.0-preview-fe651cdb3

First pass collects enabled networks that have a default rpc endpoint
and metadata; second pass filters failing ones and enriches into
FailedNetwork. Drops the manual `totalNetworksWithMetadata` counter in
favor of `networksWithMetadata.length`.
Extracted:
- `#getEnabledEvmChainIds` — reads enabled EIP-155 chain ids
- `#collectNetworksWithMetadata` — first pass, joins config and metadata
- `#buildFailedNetwork` — enrichment for a single failing network
- `#pickBannerNetwork` — applies the rule to pick which one to surface

Also introduces a `NetworkWithMetadata` intermediate type.
Follows the controller guidelines: instead of reacting to every
`stateChange` on the three upstream controllers, subscribe with narrow
selectors so we only re-evaluate when a field we care about
(`networksMetadata`, `networkConfigurationsByChainId`,
`enabledNetworkMap`, `connectivityStatus`) actually changes.

Each subscription needs its own handler reference since the messenger
keys subscribers by handler identity — inline arrows wrap
`#onUpstreamChange` to keep them distinct.
Reverts the type based check from the prior commit. Match on the
`{infuraProjectId}` placeholder that lives on stored network
configurations (the placeholder is substituted with the real project
id at request time). URLs that already carry a substituted key are
treated as custom since we do not have the project id in this package.
Follows the pattern in docs/code-guidelines/controller-guidelines.md:
one subscribe per peer with a composed selector.

- NetworkController: `createSelector` over `networksMetadata` and
  `networkConfigurationsByChainId`, memoized so the projected object is
  reference stable while unrelated fields change.
- NetworkEnablementController: peer exposed `selectEnabledNetworkMap`.
- ConnectivityController: peer exposed
  `connectivityControllerSelectors.selectConnectivityStatus`.
The degraded and unavailable timer callbacks no longer re run
`#findFailedNetwork`. Instead they use the `FailedNetwork` captured at
schedule time: our upstream selector subscriptions cancel or replace
the pending timer whenever peer state changes in a way that matters,
so at fire time the captured failure is still the right one.

Removes the two silent recovery tests and the `setNetworkStateSilently`
helper, which simulated a scenario the messenger contract disallows.
@socket-security

socket-security Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Warn Low
Potential code anomaly (AI signal): npm launch-editor is 68.0% likely to have a medium risk anomaly

Notes: The code functions as a heuristic editor-detection utility. It actively reads environment variables and executes system commands to detect running editors across platforms. While this involves system introspection, there is no evidence of malicious behavior (no data exfiltration, no backdoors, no dynamic code execution beyond returning command tokens). Primary risks stem from reliance on external inputs and potential environment spoofing, which could mislead downstream behavior. Overall security risk is moderate with low malware likelihood.

Confidence: 0.68

Severity: 0.50

From: ?npm/@docusaurus/core@3.10.1npm/launch-editor@2.13.2

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/launch-editor@2.13.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

`RpcEndpoint` is defined inside `@metamask/network-controller` but not
re-exported from its barrel. Use `NetworkConfiguration['rpcEndpoints'][number]`
so we don't rely on a symbol that isn't part of the peer's public API.
Sync JSDoc for `dismissBanner` after the earlier trim.
The inline arrow selectors triggered `jsdoc/require-param`,
`jsdoc/require-returns`, and `@typescript-eslint/explicit-function-return-type`.
Extracting them as named consts with proper JSDoc and explicit return types
fixes all six errors and matches the pattern in connectivity-controller.
@cryptodev-2s

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@mcmire mcmire left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another round 😅

Comment thread .github/CODEOWNERS Outdated
/packages/wallet @MetaMask/core-platform
/packages/wallet-cli @MetaMask/core-platform @MetaMask/ocap-kernel
/packages/wallet-framework-docs @MetaMask/core-platform
/packages/network-connection-banner-controller @MetaMask/core-platform

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this list alphabetized and place this after multichain-api-middleware?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alphabetized in 699b24f5f.

* the controller's actions and events and to namespace the controller's state
* data when composed with other controllers.
*/
const controllerName = 'NetworkConnectionBannerController';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use CONTROLLER_NAME instead of controllerName? I recently updated the guidelines and sample controllers so that the name of this variable uses the same format as other constants.

Suggested change
const controllerName = 'NetworkConnectionBannerController';
const CONTROLLER_NAME = 'NetworkConnectionBannerController';

Also what do you think about defining this constant before selectNetworkControllerFields?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to CONTROLLER_NAME and moved above the module scope selectors in eff0473be.

* Details of a failing network the banner describes.
*/
export type FailedNetwork = {
chainId: Hex;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go ahead and define JSDoc for all of these properties too while we are at it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in eff0473be.

Comment on lines +271 to +273
// Scoped selectors per controller guideline so unrelated upstream
// `stateChange` events (e.g. a `NetworkController` selected client id
// update) do not trigger a re-evaluation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this comment?

Suggested change
// Scoped selectors per controller guideline so unrelated upstream
// `stateChange` events (e.g. a `NetworkController` selected client id
// update) do not trigger a re-evaluation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in eff0473be.

Comment on lines +301 to +304
* Starts evaluating network connection state.
*
* This method should be called after the upstream network, network
* enablement, and connectivity controllers have been initialized.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically true but doesn't talk about what happens after the network connection is evaluated.

What about:

Suggested change
* Starts evaluating network connection state.
*
* This method should be called after the upstream network, network
* enablement, and connectivity controllers have been initialized.
* Look for a failed network, if any, and populate the initial state of the
* banner.
*
* This method should be called after NetworkController,
* NetworkEnablementController, and ConnectivityController have been
* initialized.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewritten in eff0473be to describe what start() does (populate initial state, react from there) alongside when to call it.

Comment on lines +289 to +290
() => this.#onUpstreamChange(),
connectivityControllerSelectors.selectConnectivityStatus,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar as above, except that the selector should return an object:

Suggested change
() => this.#onUpstreamChange(),
connectivityControllerSelectors.selectConnectivityStatus,
this.#refreshState.bind(this),
({ connectivityStatus }: ConnectivityControllerState) => ({
connectivityController: {
connectivityStatus,
},
}),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added selectConnectivityControllerFields in 7dcb3d974.

Comment on lines +279 to +280
() => this.#onUpstreamChange(),
selectNetworkControllerFields,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have the network configurations and network metadata can we pass them along to #refreshState? Maybe #refreshState can take options for each of the pieces of data it needs, only calling <controller>:getState if it's missing a piece of data.

Suggested change
() => this.#onUpstreamChange(),
selectNetworkControllerFields,
this.#refreshState.bind(this),
(state: NetworkState) => ({
networkControllerState: {
networkConfigurationsByChainId: state.networkConfigurationsByChainId,
networksMetadata: state.networksMetadata,
},
}),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectNetworkControllerFields already returns { networksMetadata, networkConfigurationsByChainId }; subscription handlers now pass the projection straight into #refreshState as networkControllerState in 7dcb3d974.

Comment on lines +518 to +523
const otherInfura = rpcEndpoints.find(
(endpoint, index) =>
index !== defaultRpcEndpointIndex &&
getIsInfuraEndpoint(endpoint.url),
);
switchableInfuraNetworkClientId = otherInfura?.networkClientId ?? null;

@mcmire mcmire Jul 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should only be one Infura network (this name is misleading):

Suggested change
const otherInfura = rpcEndpoints.find(
(endpoint, index) =>
index !== defaultRpcEndpointIndex &&
getIsInfuraEndpoint(endpoint.url),
);
switchableInfuraNetworkClientId = otherInfura?.networkClientId ?? null;
const infuraEndpoint = rpcEndpoints.find(
(endpoint, index) =>
index !== defaultRpcEndpointIndex &&
getIsInfuraEndpoint(endpoint.url),
);
switchableInfuraNetworkClientId = infuraEndpoint?.networkClientId ?? null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed in eff0473be.

}
}

type NetworkWithMetadata = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about putting this type at the top of the file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved in eff0473be.

* `{infuraProjectId}` placeholder form that lives on stored network
* configurations before the wallet substitutes the real project id at
* request time. URLs that already carry a substituted key are treated as
* custom (we do not have the project id in this package).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this controller take an Infura project ID so that we can match the custom endpoints as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkConfiguration.rpcEndpoints[i].url is always stored with the {infuraProjectId} placeholder in MetaMask (substitution happens at request time in the network client). The placeholder match already covers every real case, so threading a project id through the constructor would add state the controller does not otherwise care about. Happy to revisit if a client ever starts persisting substituted URLs.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-3c0e8a808
@metamask-previews/accounts-controller@39.0.4-preview-3c0e8a808
@metamask-previews/address-book-controller@7.1.2-preview-3c0e8a808
@metamask-previews/ai-controllers@0.7.0-preview-3c0e8a808
@metamask-previews/analytics-controller@1.2.1-preview-3c0e8a808
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-3c0e8a808
@metamask-previews/announcement-controller@8.1.0-preview-3c0e8a808
@metamask-previews/app-metadata-controller@2.0.1-preview-3c0e8a808
@metamask-previews/approval-controller@9.0.2-preview-3c0e8a808
@metamask-previews/assets-controller@10.0.1-preview-3c0e8a808
@metamask-previews/assets-controllers@109.3.0-preview-3c0e8a808
@metamask-previews/authenticated-user-storage@3.0.0-preview-3c0e8a808
@metamask-previews/base-controller@9.1.0-preview-3c0e8a808
@metamask-previews/base-data-service@0.1.3-preview-3c0e8a808
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-3c0e8a808
@metamask-previews/bridge-controller@77.3.2-preview-3c0e8a808
@metamask-previews/bridge-status-controller@74.0.2-preview-3c0e8a808
@metamask-previews/build-utils@3.0.4-preview-3c0e8a808
@metamask-previews/chain-agnostic-permission@1.6.2-preview-3c0e8a808
@metamask-previews/chomp-api-service@3.1.0-preview-3c0e8a808
@metamask-previews/claims-controller@0.5.3-preview-3c0e8a808
@metamask-previews/client-controller@1.0.1-preview-3c0e8a808
@metamask-previews/client-utils@0.0.0-preview-3c0e8a808
@metamask-previews/compliance-controller@2.1.0-preview-3c0e8a808
@metamask-previews/composable-controller@12.0.1-preview-3c0e8a808
@metamask-previews/config-registry-controller@0.4.1-preview-3c0e8a808
@metamask-previews/connectivity-controller@0.2.0-preview-3c0e8a808
@metamask-previews/controller-utils@12.3.0-preview-3c0e8a808
@metamask-previews/core-backend@6.5.0-preview-3c0e8a808
@metamask-previews/delegation-controller@3.0.2-preview-3c0e8a808
@metamask-previews/earn-controller@12.2.2-preview-3c0e8a808
@metamask-previews/eip-5792-middleware@3.0.4-preview-3c0e8a808
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-3c0e8a808
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-3c0e8a808
@metamask-previews/ens-controller@19.1.5-preview-3c0e8a808
@metamask-previews/eth-block-tracker@15.0.1-preview-3c0e8a808
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-3c0e8a808
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-3c0e8a808
@metamask-previews/foundryup@1.0.1-preview-3c0e8a808
@metamask-previews/gas-fee-controller@26.2.4-preview-3c0e8a808
@metamask-previews/gator-permissions-controller@4.2.2-preview-3c0e8a808
@metamask-previews/geolocation-controller@0.1.3-preview-3c0e8a808
@metamask-previews/java-tron-up@1.0.0-preview-3c0e8a808
@metamask-previews/json-rpc-engine@10.5.0-preview-3c0e8a808
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-3c0e8a808
@metamask-previews/keyring-controller@27.1.0-preview-3c0e8a808
@metamask-previews/local-node-utils@1.0.0-preview-3c0e8a808
@metamask-previews/logging-controller@8.0.2-preview-3c0e8a808
@metamask-previews/message-manager@14.1.2-preview-3c0e8a808
@metamask-previews/messenger@1.2.0-preview-3c0e8a808
@metamask-previews/messenger-cli@0.2.0-preview-3c0e8a808
@metamask-previews/money-account-balance-service@2.1.2-preview-3c0e8a808
@metamask-previews/money-account-controller@0.3.3-preview-3c0e8a808
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-3c0e8a808
@metamask-previews/multichain-account-service@11.1.0-preview-3c0e8a808
@metamask-previews/multichain-api-middleware@4.0.0-preview-3c0e8a808
@metamask-previews/multichain-network-controller@3.2.1-preview-3c0e8a808
@metamask-previews/multichain-transactions-controller@7.1.1-preview-3c0e8a808
@metamask-previews/name-controller@9.1.2-preview-3c0e8a808
@metamask-previews/network-connection-banner-controller@0.1.0-preview-3c0e8a808
@metamask-previews/network-controller@34.0.0-preview-3c0e8a808
@metamask-previews/network-enablement-controller@5.4.1-preview-3c0e8a808
@metamask-previews/notification-services-controller@24.3.0-preview-3c0e8a808
@metamask-previews/passkey-controller@2.0.1-preview-3c0e8a808
@metamask-previews/permission-controller@13.1.1-preview-3c0e8a808
@metamask-previews/permission-log-controller@5.1.0-preview-3c0e8a808
@metamask-previews/perps-controller@9.1.0-preview-3c0e8a808
@metamask-previews/phishing-controller@17.2.0-preview-3c0e8a808
@metamask-previews/platform-api-docs@0.0.0-preview-3c0e8a808
@metamask-previews/polling-controller@16.0.8-preview-3c0e8a808
@metamask-previews/preferences-controller@23.1.0-preview-3c0e8a808
@metamask-previews/profile-metrics-controller@4.0.1-preview-3c0e8a808
@metamask-previews/profile-sync-controller@28.2.0-preview-3c0e8a808
@metamask-previews/ramps-controller@15.0.0-preview-3c0e8a808
@metamask-previews/rate-limit-controller@7.0.1-preview-3c0e8a808
@metamask-previews/react-data-query@0.2.1-preview-3c0e8a808
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-3c0e8a808
@metamask-previews/sample-controllers@5.0.3-preview-3c0e8a808
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-3c0e8a808
@metamask-previews/selected-network-controller@26.1.5-preview-3c0e8a808
@metamask-previews/shield-controller@5.1.2-preview-3c0e8a808
@metamask-previews/signature-controller@39.2.7-preview-3c0e8a808
@metamask-previews/smart-transactions-controller@24.2.4-preview-3c0e8a808
@metamask-previews/snap-account-service@1.0.0-preview-3c0e8a808
@metamask-previews/social-controllers@2.3.1-preview-3c0e8a808
@metamask-previews/solana-test-validator-up@1.0.0-preview-3c0e8a808
@metamask-previews/stellar-quickstart-up@0.0.0-preview-3c0e8a808
@metamask-previews/storage-service@1.0.2-preview-3c0e8a808
@metamask-previews/subscription-controller@6.2.0-preview-3c0e8a808
@metamask-previews/transaction-controller@68.2.2-preview-3c0e8a808
@metamask-previews/transaction-pay-controller@23.17.4-preview-3c0e8a808
@metamask-previews/user-operation-controller@41.2.6-preview-3c0e8a808
@metamask-previews/wallet@6.0.0-preview-3c0e8a808
@metamask-previews/wallet-cli@0.0.0-preview-3c0e8a808

BREAKING CHANGE: `init()` is gone. Consumers of the banner controller
now drive its lifecycle via `start()` and `stop()`.

The old `init()` model ran the controller from the moment the wallet
Engine constructed it, which meant the 5s / 30s escalation timers could
complete while the user was still on the lock screen. A first look
after unlock could show `unavailable` even though nothing was actually
wrong.

`start()` and `stop()` tie the controller to the UI that renders the
banner. Both are idempotent. `start()` runs the initial evaluation and
enables reactions to upstream state changes. `stop()` cancels pending
timers, resets banner state to `available`, and ignores upstream
changes until the next `start()`.

- Rename messenger action `NetworkConnectionBannerController:init` to
  `NetworkConnectionBannerController:start` and add
  `NetworkConnectionBannerController:stop`.
- Rewrite the README lifecycle section.
- Reorganize tests into a dedicated `start / stop` block with coverage
  for stop cancelling a pending banner, ignoring upstream changes after
  stop, resuming on start after stop, and idempotence when never
  started.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 44d1ed7. Configure here.

A synchronous listener on `NetworkConnectionBannerController:stateChanged`
could call `stop()` from inside `#refreshState`, either during the pre
timer reset `update` or during the degraded timer's own `update`. The
enclosing `setTimeout` was still scheduled, so the banner could escalate
to `degraded` or `unavailable` after the UI had stopped the controller.

Two new guards check `#started` after each `update` before scheduling the
next timer. New regression tests exercise both re entry points.
- Rename `controllerName` to `CONTROLLER_NAME` per updated guidelines
  and move it above the module scope selectors.
- Move the `NetworkWithMetadata` intermediate type to the top of the
  file with the other type definitions.
- Add JSDoc to the previously undocumented properties of the
  `FailedNetwork` type.
- Drop the redundant scoped selectors comment above the subscribe
  block, and the extra blank line before the `failedNetwork` guard in
  `#refreshState`.
- Rewrite the `start` JSDoc to describe what it does, not just when it
  runs.
- Rename `switchToDefaultInfuraRpc` to
  `switchToDefaultInfuraRpcEndpoint` (RPC endpoints are the term we
  use) and take `chainId` as a positional argument since there is only
  one.
- Rename `otherInfura` to `infuraEndpoint` in `#buildFailedNetwork`
  since there is only one Infura endpoint per chain.
- `StubbedState` type becomes `ExternalState` with controller name keys
  (`NetworkController`, `NetworkEnablementController`,
  `ConnectivityController`) that match the messenger namespace.
- Rework `BuildExternalStateArgs` to reference peer state types directly
  and use property names that match `NetworkController` state
  (`networkConfigurationsByChainId`, `networksMetadata`,
  `enabledEvmChainIds` since we are strictly on the EIP 155 namespace).
- `buildEnablementState` becomes `buildNetworkEnablementControllerState`
  to match the actual controller name.
- `makeMetadata` becomes `buildNetworkMetadata`, and `buildConfiguration`
  becomes `buildNetworkConfiguration` for consistency with the other
  `build*` helpers.
- `buildNetworkState` becomes `buildExternalState`, `setNetworkState`
  becomes `publishNetworkStateChanges`, and the `initialState` argument
  of `withController` becomes `externalState`.
- Rename `describe` blocks to match the event they exercise:
  `on NetworkController:stateChange` and
  `on ConnectivityController:stateChange`.
Moves `network-connection-banner-controller` to its alphabetically
sorted position after `multichain-api-middleware`.
Adds `setNetworkControllerState` and `setNetworkEnablementControllerState`
so tests that specifically want to exercise one peer's `stateChange`
event can publish only that event, matching the code path they claim to
cover. `publishNetworkStateChanges` stays as a setup convenience for
tests that want to seed both at once.

The `start / stop` describe now uses `setNetworkControllerState`
directly, moving the enablement setup to the `externalState` argument of
`withController`.

Adds an `on NetworkEnablementController:stateChange` describe block with
coverage for enabling a failing chain and disabling one whose banner is
already showing.
`buildInfuraEndpoint` and `buildCustomEndpoint` now live with the other
test helpers at the bottom of the file and take options bags so the
network client id is called out by name at every call site.
Neither field influences the banner rule and no test asserts on them.
Falling back to the `buildNetworkConfiguration` defaults keeps the
Polygon test setups smaller without changing behavior.
`#refreshState` now takes optional `networkControllerState`,
`networkEnablementControllerState`, and `connectivityControllerState`
parameters (each `Pick`d down to the fields the rule uses), falling
back to the respective `<controller>:getState` call when omitted.

Subscription handlers pass their memoized projection straight in, so
event driven re evaluations reuse the value the selector already
computed instead of calling `getState` again. `#findFailedNetwork`,
`#collectNetworksWithMetadata`, and `#getEnabledEvmChainIds` take state
as arguments too.

The `#isStarted` gate lives at the top of `#refreshState` now, so the
old `#onUpstreamChange` shim goes away. Adds two composed selectors
(`selectNetworkEnablementControllerFields`,
`selectConnectivityControllerFields`) that return object projections
matching the `Pick` shape.
Options bag first, then test function. Matches the pattern in
`sample-petnames-controller.test.ts`. Existing shorthand
`withController(fn)` for the no options case keeps working via the
variadic overload.
@cryptodev-2s cryptodev-2s requested a review from mcmire July 2, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants