-
-
Notifications
You must be signed in to change notification settings - Fork 288
feat: add @metamask/network-connection-banner-controller #9041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
cryptodev-2s
wants to merge
50
commits into
main
Choose a base branch
from
wpc-1014-network-connection-banner-controller
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+3,313
−241
Open
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 9b432be
fix: regenerate yarn.lock after constraints rewrote dep ranges
cryptodev-2s 49c1ce0
docs: reference PR in initial changelog entry
cryptodev-2s 04c1299
chore: align @metamask/utils version with monorepo + drop trailing pe…
cryptodev-2s 199ffcd
refactor: read controller state directly instead of via cross-package…
cryptodev-2s bd2f1f4
fix: dedupe deps
cryptodev-2s 4ef0113
chore: register network-connection-banner-controller in teams.json
cryptodev-2s e9d2c3b
style: apply oxfmt to controller and test files
cryptodev-2s bddf493
docs: add Unreleased link reference for changelog validation
cryptodev-2s e3c4194
refactor: extract repeated reset-banner block into a helper
cryptodev-2s ae79cbc
fix: align network banner state change events
cryptodev-2s 8f4af11
fix: preserve pending banner escalation timer
cryptodev-2s 3cb9037
feat(network-connection-banner-controller): add selectors
cryptodev-2s 5cab6c5
fix: lint:misc
cryptodev-2s f313374
fix: evaluate network banner state on startup
cryptodev-2s ce115cd
fix: constraints
cryptodev-2s ea01dbf
fix: ignore missing network status metadata
cryptodev-2s fbc5d24
fix: defer network banner evaluation until init
cryptodev-2s ba2e209
docs: consolidate network banner changelog
cryptodev-2s d4f5ab6
fix: clear recovered network banner on escalation
cryptodev-2s 2bef766
Merge branch 'main' into wpc-1014-network-connection-banner-controller
cryptodev-2s 14ccdd3
refactor: address review nits on banner controller
cryptodev-2s 3bdeda1
refactor!: simplify banner controller public API
cryptodev-2s e9d630c
refactor: stop exporting url helpers from package entry point
cryptodev-2s c0bf31a
refactor: move psl ambient shim to shared types dir
cryptodev-2s 9852e44
refactor: match Infura endpoints by type instead of URL suffix
cryptodev-2s b258d15
refactor: split #findFailedNetwork into two passes
cryptodev-2s fc5d981
refactor: decompose #findFailedNetwork into focused helpers
cryptodev-2s f846550
refactor: use selector-scoped subscriptions to upstream state
cryptodev-2s 4b79c86
refactor: match Infura endpoints by url placeholder
cryptodev-2s 23a1a46
refactor: align selector subscriptions with controller guidelines
cryptodev-2s 2d00549
refactor: trust the messenger in banner timer callbacks
cryptodev-2s e8a9eae
Merge remote-tracking branch 'origin/main' into wpc-1014-network-conn…
cryptodev-2s 285da04
fix: constraints
cryptodev-2s 75ac02b
fix: derive RpcEndpoint type instead of importing it
cryptodev-2s a86c7c0
chore: regenerate messenger action types
cryptodev-2s 3c0e8a8
fix: extract inner selectors so createSelector satisfies lint rules
cryptodev-2s 44d1ed7
feat!: replace init with start / stop lifecycle
cryptodev-2s 9b811eb
fix: guard timers against synchronous stop during refresh
cryptodev-2s eff0473
refactor: apply review nits on banner controller
cryptodev-2s 09c7ab3
refactor(test): rename test helpers per review
cryptodev-2s 699b24f
chore: alphabetize CODEOWNERS entry for banner controller
cryptodev-2s 5c2329f
test: split state setters per peer and cover NEC:stateChange
cryptodev-2s f96e665
test: move endpoint builders to bottom with options bag args
cryptodev-2s 772d8dc
refactor: rename #started to #isStarted for boolean convention
cryptodev-2s aa8e923
test: drop unused name and nativeCurrency test config overrides
cryptodev-2s 7dcb3d9
refactor: thread peer state through #refreshState
cryptodev-2s 6b0fd9a
test: switch withController to sample-controllers signature
cryptodev-2s c7a4d85
style: format long call to #findFailedNetwork
cryptodev-2s cadd612
style: disable naming-convention for ExternalState controller keys
cryptodev-2s File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
packages/network-connection-banner-controller/CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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
29
packages/network-connection-banner-controller/jest.config.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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
81
packages/network-connection-banner-controller/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" | ||
| } | ||
| } |
58 changes: 58 additions & 0 deletions
58
...connection-banner-controller/src/NetworkConnectionBannerController-method-action-types.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetized in
699b24f5f.