Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 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
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
/packages/composable-controller @MetaMask/core-platform
/packages/connectivity-controller @MetaMask/core-platform
/packages/controller-utils @MetaMask/core-platform
/packages/network-connection-banner-controller @MetaMask/core-platform
/packages/eth-json-rpc-middleware @MetaMask/core-platform
/packages/messenger @MetaMask/core-platform
/packages/messenger-cli @MetaMask/core-platform
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,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 @@ -189,6 +190,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 @@ -436,6 +438,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
31 changes: 31 additions & 0 deletions packages/network-connection-banner-controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# `@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.

## Initialization

After constructing the controller, call `init()` only after the
`NetworkController`, `NetworkEnablementController`, and
`ConnectivityController` have initialized. Until then, upstream state changes
are ignored and no banner timers run.

```typescript
networkConnectionBannerController.init();
```

`init()` is idempotent and immediately evaluates the latest upstream state.

## 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": "^32.0.0",
"@metamask/network-enablement-controller": "^5.3.0",
"@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,49 @@
/**
* This file is auto generated.
* Do not edit manually.
*/

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

/**
* Starts evaluating network connection state.
*
* This method should be called after the upstream network, network
* enablement, and connectivity controllers have been initialized.
*/
export type NetworkConnectionBannerControllerInitAction = {
type: `NetworkConnectionBannerController:init`;
handler: NetworkConnectionBannerController['init'];
};

/**
* Clears the banner state regardless of the current rule outcome. The next
* subscription-driven evaluation will re-show the banner if the conditions
* still hold.
*/
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 =
| NetworkConnectionBannerControllerInitAction
| NetworkConnectionBannerControllerDismissBannerAction
| NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcAction;
Loading
Loading