Skip to content
Open
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
66abd50
feat: add @metamask/network-connection-banner-controller
cryptodev-2s Jun 8, 2026
9b432be
fix: regenerate yarn.lock after constraints rewrote dep ranges
cryptodev-2s Jun 8, 2026
49c1ce0
docs: reference PR in initial changelog entry
cryptodev-2s Jun 8, 2026
04c1299
chore: align @metamask/utils version with monorepo + drop trailing pe…
cryptodev-2s Jun 8, 2026
199ffcd
refactor: read controller state directly instead of via cross-package…
cryptodev-2s Jun 8, 2026
bd2f1f4
fix: dedupe deps
cryptodev-2s Jun 8, 2026
4ef0113
chore: register network-connection-banner-controller in teams.json
cryptodev-2s Jun 8, 2026
e9d2c3b
style: apply oxfmt to controller and test files
cryptodev-2s Jun 8, 2026
bddf493
docs: add Unreleased link reference for changelog validation
cryptodev-2s Jun 8, 2026
e3c4194
refactor: extract repeated reset-banner block into a helper
cryptodev-2s Jun 8, 2026
ae79cbc
fix: align network banner state change events
cryptodev-2s Jun 10, 2026
8f4af11
fix: preserve pending banner escalation timer
cryptodev-2s Jun 10, 2026
3cb9037
feat(network-connection-banner-controller): add selectors
cryptodev-2s Jun 10, 2026
5cab6c5
fix: lint:misc
cryptodev-2s Jun 10, 2026
f313374
fix: evaluate network banner state on startup
cryptodev-2s Jun 11, 2026
ce115cd
fix: constraints
cryptodev-2s Jun 11, 2026
ea01dbf
fix: ignore missing network status metadata
cryptodev-2s Jun 11, 2026
fbc5d24
fix: defer network banner evaluation until init
cryptodev-2s Jun 12, 2026
ba2e209
docs: consolidate network banner changelog
cryptodev-2s Jun 12, 2026
d4f5ab6
fix: clear recovered network banner on escalation
cryptodev-2s Jun 12, 2026
2bef766
Merge branch 'main' into wpc-1014-network-connection-banner-controller
cryptodev-2s Jun 16, 2026
14ccdd3
refactor: address review nits on banner controller
cryptodev-2s Jul 2, 2026
3bdeda1
refactor!: simplify banner controller public API
cryptodev-2s Jul 2, 2026
e9d630c
refactor: stop exporting url helpers from package entry point
cryptodev-2s Jul 2, 2026
c0bf31a
refactor: move psl ambient shim to shared types dir
cryptodev-2s Jul 2, 2026
9852e44
refactor: match Infura endpoints by type instead of URL suffix
cryptodev-2s Jul 2, 2026
b258d15
refactor: split #findFailedNetwork into two passes
cryptodev-2s Jul 2, 2026
fc5d981
refactor: decompose #findFailedNetwork into focused helpers
cryptodev-2s Jul 2, 2026
f846550
refactor: use selector-scoped subscriptions to upstream state
cryptodev-2s Jul 2, 2026
4b79c86
refactor: match Infura endpoints by url placeholder
cryptodev-2s Jul 2, 2026
23a1a46
refactor: align selector subscriptions with controller guidelines
cryptodev-2s Jul 2, 2026
2d00549
refactor: trust the messenger in banner timer callbacks
cryptodev-2s Jul 2, 2026
e8a9eae
Merge remote-tracking branch 'origin/main' into wpc-1014-network-conn…
cryptodev-2s Jul 2, 2026
285da04
fix: constraints
cryptodev-2s Jul 2, 2026
75ac02b
fix: derive RpcEndpoint type instead of importing it
cryptodev-2s Jul 2, 2026
a86c7c0
chore: regenerate messenger action types
cryptodev-2s Jul 2, 2026
3c0e8a8
fix: extract inner selectors so createSelector satisfies lint rules
cryptodev-2s Jul 2, 2026
44d1ed7
feat!: replace init with start / stop lifecycle
cryptodev-2s Jul 2, 2026
9b811eb
fix: guard timers against synchronous stop during refresh
cryptodev-2s Jul 2, 2026
eff0473
refactor: apply review nits on banner controller
cryptodev-2s Jul 2, 2026
09c7ab3
refactor(test): rename test helpers per review
cryptodev-2s Jul 2, 2026
699b24f
chore: alphabetize CODEOWNERS entry for banner controller
cryptodev-2s Jul 2, 2026
5c2329f
test: split state setters per peer and cover NEC:stateChange
cryptodev-2s Jul 2, 2026
f96e665
test: move endpoint builders to bottom with options bag args
cryptodev-2s Jul 2, 2026
772d8dc
refactor: rename #started to #isStarted for boolean convention
cryptodev-2s Jul 2, 2026
aa8e923
test: drop unused name and nativeCurrency test config overrides
cryptodev-2s Jul 2, 2026
7dcb3d9
refactor: thread peer state through #refreshState
cryptodev-2s Jul 2, 2026
6b0fd9a
test: switch withController to sample-controllers signature
cryptodev-2s Jul 2, 2026
c7a4d85
style: format long call to #findFailedNetwork
cryptodev-2s Jul 2, 2026
cadd612
style: disable naming-convention for ExternalState controller keys
cryptodev-2s Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 30 additions & 29 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -81,35 +81,36 @@
/packages/geolocation-controller @MetaMask/mobile-platform

## Core Platform Team
/packages/base-controller @MetaMask/core-platform
/packages/base-data-service @MetaMask/core-platform
/packages/build-utils @MetaMask/core-platform
/packages/chain-agnostic-permission @MetaMask/core-platform
/packages/composable-controller @MetaMask/core-platform
/packages/connectivity-controller @MetaMask/core-platform
/packages/controller-utils @MetaMask/core-platform
/packages/eip-5792-middleware @MetaMask/core-platform
/packages/eip1193-permission-middleware @MetaMask/core-platform
/packages/eth-block-tracker @MetaMask/core-platform
/packages/eth-json-rpc-middleware @MetaMask/core-platform
/packages/eth-json-rpc-provider @MetaMask/core-platform
/packages/json-rpc-engine @MetaMask/core-platform
/packages/json-rpc-middleware-stream @MetaMask/core-platform
/packages/messenger @MetaMask/core-platform
/packages/messenger-cli @MetaMask/core-platform
/packages/multichain-api-middleware @MetaMask/core-platform
/packages/permission-controller @MetaMask/core-platform
/packages/permission-log-controller @MetaMask/core-platform
/packages/platform-api-docs @MetaMask/core-platform
/packages/polling-controller @MetaMask/core-platform
/packages/preferences-controller @MetaMask/core-platform
/packages/rate-limit-controller @MetaMask/core-platform
/packages/react-data-query @MetaMask/core-platform
/packages/sample-controllers @MetaMask/core-platform
/packages/selected-network-controller @MetaMask/core-platform
/packages/wallet @MetaMask/core-platform
/packages/wallet-cli @MetaMask/core-platform @MetaMask/ocap-kernel
/packages/wallet-framework-docs @MetaMask/core-platform
/packages/base-controller @MetaMask/core-platform
/packages/base-data-service @MetaMask/core-platform
/packages/build-utils @MetaMask/core-platform
/packages/chain-agnostic-permission @MetaMask/core-platform
/packages/composable-controller @MetaMask/core-platform
/packages/connectivity-controller @MetaMask/core-platform
/packages/controller-utils @MetaMask/core-platform
/packages/eip-5792-middleware @MetaMask/core-platform
/packages/eip1193-permission-middleware @MetaMask/core-platform
/packages/eth-block-tracker @MetaMask/core-platform
/packages/eth-json-rpc-middleware @MetaMask/core-platform
/packages/eth-json-rpc-provider @MetaMask/core-platform
/packages/json-rpc-engine @MetaMask/core-platform
/packages/json-rpc-middleware-stream @MetaMask/core-platform
/packages/messenger @MetaMask/core-platform
/packages/messenger-cli @MetaMask/core-platform
/packages/multichain-api-middleware @MetaMask/core-platform
/packages/permission-controller @MetaMask/core-platform
/packages/permission-log-controller @MetaMask/core-platform
/packages/platform-api-docs @MetaMask/core-platform
/packages/polling-controller @MetaMask/core-platform
/packages/preferences-controller @MetaMask/core-platform
/packages/rate-limit-controller @MetaMask/core-platform
/packages/react-data-query @MetaMask/core-platform
/packages/sample-controllers @MetaMask/core-platform
/packages/selected-network-controller @MetaMask/core-platform
/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.


## Web3Auth Team
/packages/seedless-onboarding-controller @MetaMask/web3auth
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ yarn skills --reset # clear saved local selection
- [`@metamask/multichain-network-controller`](packages/multichain-network-controller)
- [`@metamask/multichain-transactions-controller`](packages/multichain-transactions-controller)
- [`@metamask/name-controller`](packages/name-controller)
- [`@metamask/network-connection-banner-controller`](packages/network-connection-banner-controller)
- [`@metamask/network-controller`](packages/network-controller)
- [`@metamask/network-enablement-controller`](packages/network-enablement-controller)
- [`@metamask/notification-services-controller`](packages/notification-services-controller)
Expand Down Expand Up @@ -201,6 +202,7 @@ linkStyle default opacity:0.5
multichain_network_controller(["@metamask/multichain-network-controller"]);
multichain_transactions_controller(["@metamask/multichain-transactions-controller"]);
name_controller(["@metamask/name-controller"]);
network_connection_banner_controller(["@metamask/network-connection-banner-controller"]);
network_controller(["@metamask/network-controller"]);
network_enablement_controller(["@metamask/network-enablement-controller"]);
notification_services_controller(["@metamask/notification-services-controller"]);
Expand Down Expand Up @@ -454,6 +456,11 @@ linkStyle default opacity:0.5
name_controller --> base_controller;
name_controller --> controller_utils;
name_controller --> messenger;
network_connection_banner_controller --> base_controller;
network_connection_banner_controller --> connectivity_controller;
network_connection_banner_controller --> messenger;
network_connection_banner_controller --> network_controller;
network_connection_banner_controller --> network_enablement_controller;
network_controller --> base_controller;
network_controller --> connectivity_controller;
network_controller --> controller_utils;
Expand Down
17 changes: 17 additions & 0 deletions packages/network-connection-banner-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Add `NetworkConnectionBannerController`, which evaluates enabled network RPC
health after initialization and manages degraded and unavailable banner state,
dismissal, and switching custom RPC endpoints to an available Infura endpoint
([#9041](https://github.com/MetaMask/core/pull/9041))

[Unreleased]: https://github.com/MetaMask/core/
20 changes: 20 additions & 0 deletions packages/network-connection-banner-controller/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
MIT License

Copyright (c) 2026 MetaMask

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 changes: 39 additions & 0 deletions packages/network-connection-banner-controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# `@metamask/network-connection-banner-controller`

NetworkConnectionBannerController decides when and how to surface the network
connection banner based on RPC endpoint health. It encapsulates the shared
rule, the 5s/30s timer state machine, and the eTLD+1 grouping previously
duplicated across MetaMask clients.

## Lifecycle

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). The UI that renders the banner is
responsible for driving the lifecycle:

```typescript
// When the wallet UI that shows the banner becomes active
// (e.g. the home surface mounts after unlock):
networkConnectionBannerController.start();

// When it goes away:
networkConnectionBannerController.stop();
```

Both methods are idempotent. `start` runs the initial evaluation immediately
and enables reactions to upstream state changes. `stop` cancels any pending
timers and resets the banner state to `available`. Upstream state changes are
ignored while stopped.

## Installation

`yarn add @metamask/network-connection-banner-controller`

or

`npm install @metamask/network-connection-banner-controller`

## Contributing

This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).
29 changes: 29 additions & 0 deletions packages/network-connection-banner-controller/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/

const merge = require('deepmerge');
const path = require('path');

const baseConfig = require('../../jest.config.packages');

const displayName = path.basename(__dirname);

module.exports = merge(baseConfig, {
// The display name when running multiple projects
displayName,

// Skip the ambient psl.d.ts shim from coverage — it's a type-only file.
coveragePathIgnorePatterns: ['.*\\.d\\.ts$'],

// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 100,
functions: 100,
lines: 100,
statements: 100,
},
},
});
81 changes: 81 additions & 0 deletions packages/network-connection-banner-controller/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"name": "@metamask/network-connection-banner-controller",
"version": "0.1.0",
"description": "Decides when and how to surface the network connection banner based on RPC endpoint health",
"keywords": [
"Ethereum",
"MetaMask"
],
"homepage": "https://github.com/MetaMask/core/tree/main/packages/network-connection-banner-controller#readme",
"bugs": {
"url": "https://github.com/MetaMask/core/issues"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/MetaMask/core.git"
},
"files": [
"dist/"
],
"sideEffects": false,
"main": "./dist/index.cjs",
"types": "./dist/index.d.cts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
"build:docs": "typedoc",
"changelog:update": "../../scripts/update-changelog.sh @metamask/network-connection-banner-controller",
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/network-connection-banner-controller",
"messenger-action-types:check": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --check",
"messenger-action-types:generate": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --generate",
"since-latest-release": "../../scripts/since-latest-release.sh",
"test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
"test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^9.1.0",
"@metamask/connectivity-controller": "^0.2.0",
"@metamask/messenger": "^1.2.0",
"@metamask/network-controller": "^34.0.0",
"@metamask/network-enablement-controller": "^5.4.1",
"@metamask/utils": "^11.11.0",
"ip-regex": "^4.3.0",
"psl": "^1.15.0",
"reselect": "^5.1.1"
},
"devDependencies": {
"@metamask/auto-changelog": "^6.1.0",
"@ts-bridge/cli": "^0.6.4",
"@types/jest": "^29.5.14",
"deepmerge": "^4.2.2",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"tsx": "^4.20.5",
"typedoc": "^0.25.13",
"typedoc-plugin-missing-exports": "^2.0.0",
"typescript": "~5.3.3"
},
"engines": {
"node": "^18.18 || >=20"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* This file is auto generated.
* Do not edit manually.
*/

import type { NetworkConnectionBannerController } from './NetworkConnectionBannerController';

/**
* Starts evaluating network connection state. Call this when the wallet
* UI that consumes the banner becomes active (typically when the wallet
* is unlocked and the home surface mounts) so timers do not run while
* the user is not looking at the wallet. Idempotent.
*/
export type NetworkConnectionBannerControllerStartAction = {
type: `NetworkConnectionBannerController:start`;
handler: NetworkConnectionBannerController['start'];
};

/**
* Stops evaluating network connection state. Clears any pending banner
* timers and resets state to `available`. Call this when the UI
* consuming the banner is no longer active. Idempotent.
*/
export type NetworkConnectionBannerControllerStopAction = {
type: `NetworkConnectionBannerController:stop`;
handler: NetworkConnectionBannerController['stop'];
};

/**
* Clears the banner state such that the banner will be hidden.
*/
export type NetworkConnectionBannerControllerDismissBannerAction = {
type: `NetworkConnectionBannerController:dismissBanner`;
handler: NetworkConnectionBannerController['dismissBanner'];
};

/**
* Switches the chain's default RPC endpoint to its first Infura endpoint,
* causing the banner to clear once the network becomes available again.
*
* @param args - The arguments to this action.
* @param args.chainId - The chain whose default RPC should be switched.
* @throws If the chain configuration cannot be found, or if it has no
* Infura endpoint to switch to, or if the default is already Infura.
*/
export type NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcAction = {
type: `NetworkConnectionBannerController:switchToDefaultInfuraRpc`;
handler: NetworkConnectionBannerController['switchToDefaultInfuraRpc'];
};

/**
* Union of all NetworkConnectionBannerController action types.
*/
export type NetworkConnectionBannerControllerMethodActions =
| NetworkConnectionBannerControllerStartAction
| NetworkConnectionBannerControllerStopAction
| NetworkConnectionBannerControllerDismissBannerAction
| NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcAction;
Loading
Loading