@metamask-previews/network-connection-banner-controller 0.1.0-preview-bd4161b27 → 0.1.0-preview-6fc64deac
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -19
- package/dist/NetworkConnectionBannerController-method-action-types.cjs.map +1 -1
- package/dist/NetworkConnectionBannerController-method-action-types.d.cts +4 -26
- package/dist/NetworkConnectionBannerController-method-action-types.d.cts.map +1 -1
- package/dist/NetworkConnectionBannerController-method-action-types.d.mts +4 -26
- package/dist/NetworkConnectionBannerController-method-action-types.d.mts.map +1 -1
- package/dist/NetworkConnectionBannerController-method-action-types.mjs.map +1 -1
- package/dist/NetworkConnectionBannerController.cjs +108 -86
- package/dist/NetworkConnectionBannerController.cjs.map +1 -1
- package/dist/NetworkConnectionBannerController.d.cts +26 -39
- package/dist/NetworkConnectionBannerController.d.cts.map +1 -1
- package/dist/NetworkConnectionBannerController.d.mts +26 -39
- package/dist/NetworkConnectionBannerController.d.mts.map +1 -1
- package/dist/NetworkConnectionBannerController.mjs +109 -87
- package/dist/NetworkConnectionBannerController.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/url-utils.cjs +1 -52
- package/dist/url-utils.cjs.map +1 -1
- package/dist/url-utils.d.cts +0 -23
- package/dist/url-utils.d.cts.map +1 -1
- package/dist/url-utils.d.mts +0 -23
- package/dist/url-utils.d.mts.map +1 -1
- package/dist/url-utils.mjs +0 -53
- package/dist/url-utils.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
# `@metamask/network-connection-banner-controller`
|
|
2
2
|
|
|
3
3
|
NetworkConnectionBannerController decides when and how to surface the network
|
|
4
|
-
connection banner based on RPC endpoint health. It encapsulates the rule
|
|
5
|
-
5s/30s timer state machine
|
|
6
|
-
wider provider outage is in play.
|
|
4
|
+
connection banner based on RPC endpoint health. It encapsulates the rule and
|
|
5
|
+
the 5s/30s timer state machine.
|
|
7
6
|
|
|
8
7
|
## Lifecycle
|
|
9
8
|
|
|
10
9
|
The controller stays dormant after construction so the 5s / 30s escalation
|
|
11
10
|
timers do not run before a user is actually looking at the wallet (e.g. while
|
|
12
|
-
the app is still on the lock screen).
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
networkConnectionBannerController.stop();
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Both methods are idempotent. `start` runs the initial evaluation immediately
|
|
25
|
-
and enables reactions to upstream state changes. `stop` cancels any pending
|
|
26
|
-
timers and resets the banner state to `available`. Upstream state changes are
|
|
27
|
-
ignored while stopped.
|
|
11
|
+
the app is still on the lock screen). It manages its own lifecycle by
|
|
12
|
+
subscribing to `ClientController:stateChanged` and
|
|
13
|
+
`KeyringController:unlock` / `KeyringController:lock`: evaluation runs only
|
|
14
|
+
while the client UI is open on an unlocked wallet. When either condition
|
|
15
|
+
stops holding, pending timers are cancelled and the banner state resets to
|
|
16
|
+
`available`; upstream state changes are ignored until both hold again.
|
|
17
|
+
|
|
18
|
+
Clients need no lifecycle wiring beyond keeping `ClientController`'s
|
|
19
|
+
`isUiOpen` up to date (via `ClientController:setUiOpen`).
|
|
28
20
|
|
|
29
21
|
## Installation
|
|
30
22
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.cjs","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { NetworkConnectionBannerController } from './NetworkConnectionBannerController';\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.cjs","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { NetworkConnectionBannerController } from './NetworkConnectionBannerController';\n\n/**\n * Clears the banner state such that the banner will be hidden.\n */\nexport type NetworkConnectionBannerControllerDismissBannerAction = {\n type: `NetworkConnectionBannerController:dismissBanner`;\n handler: NetworkConnectionBannerController['dismissBanner'];\n};\n\n/**\n * Switches the chain's default RPC endpoint to its Infura endpoint and\n * makes it the active network, causing the banner to clear once the\n * network becomes available again.\n *\n * @param chainId - The chain whose default RPC endpoint should be switched.\n * @throws If the chain configuration cannot be found, or if it has no\n * Infura endpoint to switch to, or if the default is already Infura.\n */\nexport type NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction =\n {\n type: `NetworkConnectionBannerController:switchToDefaultInfuraRpcEndpoint`;\n handler: NetworkConnectionBannerController['switchToDefaultInfuraRpcEndpoint'];\n };\n\n/**\n * Union of all NetworkConnectionBannerController action types.\n */\nexport type NetworkConnectionBannerControllerMethodActions =\n | NetworkConnectionBannerControllerDismissBannerAction\n | NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction;\n"]}
|
|
@@ -3,29 +3,6 @@
|
|
|
3
3
|
* Do not edit manually.
|
|
4
4
|
*/
|
|
5
5
|
import type { NetworkConnectionBannerController } from "./NetworkConnectionBannerController.cjs";
|
|
6
|
-
/**
|
|
7
|
-
* Look for a failed network, if any, and populate the initial state of the
|
|
8
|
-
* banner. Reacts to upstream state changes from this point on.
|
|
9
|
-
*
|
|
10
|
-
* Call this when the wallet UI that consumes the banner becomes active
|
|
11
|
-
* (typically when the wallet is unlocked and the home surface mounts) so
|
|
12
|
-
* timers do not run while the user is not looking at the wallet. Should
|
|
13
|
-
* be called after `NetworkController`, `NetworkEnablementController`, and
|
|
14
|
-
* `ConnectivityController` have been initialized. Idempotent.
|
|
15
|
-
*/
|
|
16
|
-
export type NetworkConnectionBannerControllerStartAction = {
|
|
17
|
-
type: `NetworkConnectionBannerController:start`;
|
|
18
|
-
handler: NetworkConnectionBannerController['start'];
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Stops evaluating network connection state. Clears any pending banner
|
|
22
|
-
* timers and resets state to `available`. Call this when the UI
|
|
23
|
-
* consuming the banner is no longer active. Idempotent.
|
|
24
|
-
*/
|
|
25
|
-
export type NetworkConnectionBannerControllerStopAction = {
|
|
26
|
-
type: `NetworkConnectionBannerController:stop`;
|
|
27
|
-
handler: NetworkConnectionBannerController['stop'];
|
|
28
|
-
};
|
|
29
6
|
/**
|
|
30
7
|
* Clears the banner state such that the banner will be hidden.
|
|
31
8
|
*/
|
|
@@ -34,8 +11,9 @@ export type NetworkConnectionBannerControllerDismissBannerAction = {
|
|
|
34
11
|
handler: NetworkConnectionBannerController['dismissBanner'];
|
|
35
12
|
};
|
|
36
13
|
/**
|
|
37
|
-
* Switches the chain's default RPC endpoint to its Infura endpoint
|
|
38
|
-
* causing the banner to clear once the
|
|
14
|
+
* Switches the chain's default RPC endpoint to its Infura endpoint and
|
|
15
|
+
* makes it the active network, causing the banner to clear once the
|
|
16
|
+
* network becomes available again.
|
|
39
17
|
*
|
|
40
18
|
* @param chainId - The chain whose default RPC endpoint should be switched.
|
|
41
19
|
* @throws If the chain configuration cannot be found, or if it has no
|
|
@@ -48,5 +26,5 @@ export type NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAct
|
|
|
48
26
|
/**
|
|
49
27
|
* Union of all NetworkConnectionBannerController action types.
|
|
50
28
|
*/
|
|
51
|
-
export type NetworkConnectionBannerControllerMethodActions =
|
|
29
|
+
export type NetworkConnectionBannerControllerMethodActions = NetworkConnectionBannerControllerDismissBannerAction | NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction;
|
|
52
30
|
//# sourceMappingURL=NetworkConnectionBannerController-method-action-types.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.d.cts","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iCAAiC,EAAE,gDAA4C;AAE7F
|
|
1
|
+
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.d.cts","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iCAAiC,EAAE,gDAA4C;AAE7F;;GAEG;AACH,MAAM,MAAM,oDAAoD,GAAG;IACjE,IAAI,EAAE,iDAAiD,CAAC;IACxD,OAAO,EAAE,iCAAiC,CAAC,eAAe,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,uEAAuE,GACjF;IACE,IAAI,EAAE,oEAAoE,CAAC;IAC3E,OAAO,EAAE,iCAAiC,CAAC,kCAAkC,CAAC,CAAC;CAChF,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8CAA8C,GACtD,oDAAoD,GACpD,uEAAuE,CAAC"}
|
|
@@ -3,29 +3,6 @@
|
|
|
3
3
|
* Do not edit manually.
|
|
4
4
|
*/
|
|
5
5
|
import type { NetworkConnectionBannerController } from "./NetworkConnectionBannerController.mjs";
|
|
6
|
-
/**
|
|
7
|
-
* Look for a failed network, if any, and populate the initial state of the
|
|
8
|
-
* banner. Reacts to upstream state changes from this point on.
|
|
9
|
-
*
|
|
10
|
-
* Call this when the wallet UI that consumes the banner becomes active
|
|
11
|
-
* (typically when the wallet is unlocked and the home surface mounts) so
|
|
12
|
-
* timers do not run while the user is not looking at the wallet. Should
|
|
13
|
-
* be called after `NetworkController`, `NetworkEnablementController`, and
|
|
14
|
-
* `ConnectivityController` have been initialized. Idempotent.
|
|
15
|
-
*/
|
|
16
|
-
export type NetworkConnectionBannerControllerStartAction = {
|
|
17
|
-
type: `NetworkConnectionBannerController:start`;
|
|
18
|
-
handler: NetworkConnectionBannerController['start'];
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Stops evaluating network connection state. Clears any pending banner
|
|
22
|
-
* timers and resets state to `available`. Call this when the UI
|
|
23
|
-
* consuming the banner is no longer active. Idempotent.
|
|
24
|
-
*/
|
|
25
|
-
export type NetworkConnectionBannerControllerStopAction = {
|
|
26
|
-
type: `NetworkConnectionBannerController:stop`;
|
|
27
|
-
handler: NetworkConnectionBannerController['stop'];
|
|
28
|
-
};
|
|
29
6
|
/**
|
|
30
7
|
* Clears the banner state such that the banner will be hidden.
|
|
31
8
|
*/
|
|
@@ -34,8 +11,9 @@ export type NetworkConnectionBannerControllerDismissBannerAction = {
|
|
|
34
11
|
handler: NetworkConnectionBannerController['dismissBanner'];
|
|
35
12
|
};
|
|
36
13
|
/**
|
|
37
|
-
* Switches the chain's default RPC endpoint to its Infura endpoint
|
|
38
|
-
* causing the banner to clear once the
|
|
14
|
+
* Switches the chain's default RPC endpoint to its Infura endpoint and
|
|
15
|
+
* makes it the active network, causing the banner to clear once the
|
|
16
|
+
* network becomes available again.
|
|
39
17
|
*
|
|
40
18
|
* @param chainId - The chain whose default RPC endpoint should be switched.
|
|
41
19
|
* @throws If the chain configuration cannot be found, or if it has no
|
|
@@ -48,5 +26,5 @@ export type NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAct
|
|
|
48
26
|
/**
|
|
49
27
|
* Union of all NetworkConnectionBannerController action types.
|
|
50
28
|
*/
|
|
51
|
-
export type NetworkConnectionBannerControllerMethodActions =
|
|
29
|
+
export type NetworkConnectionBannerControllerMethodActions = NetworkConnectionBannerControllerDismissBannerAction | NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction;
|
|
52
30
|
//# sourceMappingURL=NetworkConnectionBannerController-method-action-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.d.mts","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iCAAiC,EAAE,gDAA4C;AAE7F
|
|
1
|
+
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.d.mts","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iCAAiC,EAAE,gDAA4C;AAE7F;;GAEG;AACH,MAAM,MAAM,oDAAoD,GAAG;IACjE,IAAI,EAAE,iDAAiD,CAAC;IACxD,OAAO,EAAE,iCAAiC,CAAC,eAAe,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,uEAAuE,GACjF;IACE,IAAI,EAAE,oEAAoE,CAAC;IAC3E,OAAO,EAAE,iCAAiC,CAAC,kCAAkC,CAAC,CAAC;CAChF,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8CAA8C,GACtD,oDAAoD,GACpD,uEAAuE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.mjs","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { NetworkConnectionBannerController } from './NetworkConnectionBannerController';\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"NetworkConnectionBannerController-method-action-types.mjs","sourceRoot":"","sources":["../src/NetworkConnectionBannerController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { NetworkConnectionBannerController } from './NetworkConnectionBannerController';\n\n/**\n * Clears the banner state such that the banner will be hidden.\n */\nexport type NetworkConnectionBannerControllerDismissBannerAction = {\n type: `NetworkConnectionBannerController:dismissBanner`;\n handler: NetworkConnectionBannerController['dismissBanner'];\n};\n\n/**\n * Switches the chain's default RPC endpoint to its Infura endpoint and\n * makes it the active network, causing the banner to clear once the\n * network becomes available again.\n *\n * @param chainId - The chain whose default RPC endpoint should be switched.\n * @throws If the chain configuration cannot be found, or if it has no\n * Infura endpoint to switch to, or if the default is already Infura.\n */\nexport type NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction =\n {\n type: `NetworkConnectionBannerController:switchToDefaultInfuraRpcEndpoint`;\n handler: NetworkConnectionBannerController['switchToDefaultInfuraRpcEndpoint'];\n };\n\n/**\n * Union of all NetworkConnectionBannerController action types.\n */\nexport type NetworkConnectionBannerControllerMethodActions =\n | NetworkConnectionBannerControllerDismissBannerAction\n | NetworkConnectionBannerControllerSwitchToDefaultInfuraRpcEndpointAction;\n"]}
|
|
@@ -10,10 +10,11 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
12
|
};
|
|
13
|
-
var _NetworkConnectionBannerController_instances, _NetworkConnectionBannerController_degradedTimer, _NetworkConnectionBannerController_unavailableTimer, _NetworkConnectionBannerController_pendingNetworkClientId, _NetworkConnectionBannerController_isStarted, _NetworkConnectionBannerController_refreshState, _NetworkConnectionBannerController_resetBanner, _NetworkConnectionBannerController_clearTimers, _NetworkConnectionBannerController_findFailedNetwork, _NetworkConnectionBannerController_getEnabledEvmChainIds,
|
|
13
|
+
var _NetworkConnectionBannerController_instances, _NetworkConnectionBannerController_degradedTimer, _NetworkConnectionBannerController_unavailableTimer, _NetworkConnectionBannerController_pendingNetworkClientId, _NetworkConnectionBannerController_isStarted, _NetworkConnectionBannerController_isUiOpen, _NetworkConnectionBannerController_isUnlocked, _NetworkConnectionBannerController_updateLifecycle, _NetworkConnectionBannerController_start, _NetworkConnectionBannerController_stop, _NetworkConnectionBannerController_refreshState, _NetworkConnectionBannerController_resetBanner, _NetworkConnectionBannerController_clearTimers, _NetworkConnectionBannerController_findFailedNetwork, _NetworkConnectionBannerController_getEnabledEvmChainIds, _NetworkConnectionBannerController_collectEnabledNetworks, _NetworkConnectionBannerController_buildFailedNetwork, _NetworkConnectionBannerController_pickFailedNetworkToDisplay;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.NetworkConnectionBannerController = exports.getDefaultNetworkConnectionBannerControllerState = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
17
|
+
const client_controller_1 = require("@metamask/client-controller");
|
|
17
18
|
const connectivity_controller_1 = require("@metamask/connectivity-controller");
|
|
18
19
|
const network_controller_1 = require("@metamask/network-controller");
|
|
19
20
|
const network_enablement_controller_1 = require("@metamask/network-enablement-controller");
|
|
@@ -107,31 +108,29 @@ const DEGRADED_BANNER_TIMEOUT = 5000;
|
|
|
107
108
|
*/
|
|
108
109
|
const UNAVAILABLE_BANNER_TIMEOUT = 30000;
|
|
109
110
|
const MESSENGER_EXPOSED_METHODS = [
|
|
110
|
-
'start',
|
|
111
|
-
'stop',
|
|
112
111
|
'dismissBanner',
|
|
113
112
|
'switchToDefaultInfuraRpcEndpoint',
|
|
114
113
|
];
|
|
115
114
|
/**
|
|
116
115
|
* NetworkConnectionBannerController decides whether the network connection
|
|
117
116
|
* banner should be shown for the user, and which failing network it should
|
|
118
|
-
* describe. It encapsulates the rule
|
|
119
|
-
* eTLD+1 grouping used to decide when a wider provider outage is in play.
|
|
117
|
+
* describe. It encapsulates the rule and the 5s / 30s timer escalation.
|
|
120
118
|
*
|
|
121
119
|
* The banner shows when:
|
|
122
120
|
*
|
|
123
|
-
* -
|
|
124
|
-
*
|
|
125
|
-
* -
|
|
126
|
-
*
|
|
127
|
-
* (escape hatch for single-network setups so they still get a signal).
|
|
121
|
+
* - A failing network's default RPC is a custom (non-Infura) endpoint —
|
|
122
|
+
* users always want to be informed about errors with RPCs they've chosen.
|
|
123
|
+
* - Every enabled EVM network is reporting a failed connectivity status
|
|
124
|
+
* (escape hatch so Infura-only setups still get a signal).
|
|
128
125
|
*
|
|
129
|
-
* A
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* can act on.
|
|
126
|
+
* A partial Infura outage alongside healthy peers is suppressed since it
|
|
127
|
+
* usually resolves on its own and the user cannot act on it. When a custom
|
|
128
|
+
* failure is present, it's surfaced first so the "Switch to MetaMask default
|
|
129
|
+
* RPC" CTA targets the network the user can act on.
|
|
134
130
|
*
|
|
131
|
+
* The controller manages its own lifecycle: it evaluates RPC health (and
|
|
132
|
+
* runs the escalation timers) only while the client UI is open
|
|
133
|
+
* (`ClientController`) and the wallet is unlocked (`KeyringController`).
|
|
135
134
|
* Clients only need to render the banner from the controller's state and wire
|
|
136
135
|
* click handlers to {@link dismissBanner} or {@link switchToDefaultInfuraRpcEndpoint}.
|
|
137
136
|
*/
|
|
@@ -154,44 +153,45 @@ class NetworkConnectionBannerController extends base_controller_1.BaseController
|
|
|
154
153
|
_NetworkConnectionBannerController_unavailableTimer.set(this, void 0);
|
|
155
154
|
_NetworkConnectionBannerController_pendingNetworkClientId.set(this, void 0);
|
|
156
155
|
_NetworkConnectionBannerController_isStarted.set(this, false);
|
|
156
|
+
/** Whether the client UI is open. Combined with {@link #isUnlocked}. */
|
|
157
|
+
_NetworkConnectionBannerController_isUiOpen.set(this, false);
|
|
158
|
+
/** Whether the keyring is unlocked. Combined with {@link #isUiOpen}. */
|
|
159
|
+
_NetworkConnectionBannerController_isUnlocked.set(this, false);
|
|
157
160
|
// Upstream controllers still expose :stateChange; switch to :stateChanged
|
|
158
161
|
// once those packages migrate their event types.
|
|
159
162
|
/* eslint-disable no-restricted-syntax -- awaiting upstream :stateChanged migration */
|
|
160
|
-
this.messenger.subscribe('NetworkController:stateChange', (networkControllerState) => __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this, {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
+
this.messenger.subscribe('NetworkController:stateChange', (networkControllerState) => __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this, {
|
|
164
|
+
networkControllerState,
|
|
165
|
+
networkEnablementControllerState: this.messenger.call('NetworkEnablementController:getState'),
|
|
166
|
+
connectivityControllerState: this.messenger.call('ConnectivityController:getState'),
|
|
167
|
+
}), selectNetworkControllerFields);
|
|
168
|
+
this.messenger.subscribe('NetworkEnablementController:stateChange', (networkEnablementControllerState) => __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this, {
|
|
169
|
+
networkControllerState: this.messenger.call('NetworkController:getState'),
|
|
170
|
+
networkEnablementControllerState,
|
|
171
|
+
connectivityControllerState: this.messenger.call('ConnectivityController:getState'),
|
|
172
|
+
}), selectNetworkEnablementControllerFields);
|
|
173
|
+
this.messenger.subscribe('ConnectivityController:stateChange', (connectivityControllerState) => __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this, {
|
|
174
|
+
networkControllerState: this.messenger.call('NetworkController:getState'),
|
|
175
|
+
networkEnablementControllerState: this.messenger.call('NetworkEnablementController:getState'),
|
|
176
|
+
connectivityControllerState,
|
|
177
|
+
}), selectConnectivityControllerFields);
|
|
163
178
|
/* eslint-enable no-restricted-syntax */
|
|
179
|
+
// Lifecycle: evaluate RPC health (and run the banner escalation timers)
|
|
180
|
+
// only while the client UI is open on an unlocked wallet.
|
|
181
|
+
this.messenger.subscribe('ClientController:stateChanged', (isUiOpen) => {
|
|
182
|
+
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isUiOpen, isUiOpen, "f");
|
|
183
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_updateLifecycle).call(this);
|
|
184
|
+
}, client_controller_1.clientControllerSelectors.selectIsUiOpen);
|
|
185
|
+
this.messenger.subscribe('KeyringController:unlock', () => {
|
|
186
|
+
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isUnlocked, true, "f");
|
|
187
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_updateLifecycle).call(this);
|
|
188
|
+
});
|
|
189
|
+
this.messenger.subscribe('KeyringController:lock', () => {
|
|
190
|
+
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isUnlocked, false, "f");
|
|
191
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_updateLifecycle).call(this);
|
|
192
|
+
});
|
|
164
193
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
165
194
|
}
|
|
166
|
-
/**
|
|
167
|
-
* Look for a failed network, if any, and populate the initial state of the
|
|
168
|
-
* banner. Reacts to upstream state changes from this point on.
|
|
169
|
-
*
|
|
170
|
-
* Call this when the wallet UI that consumes the banner becomes active
|
|
171
|
-
* (typically when the wallet is unlocked and the home surface mounts) so
|
|
172
|
-
* timers do not run while the user is not looking at the wallet. Should
|
|
173
|
-
* be called after `NetworkController`, `NetworkEnablementController`, and
|
|
174
|
-
* `ConnectivityController` have been initialized. Idempotent.
|
|
175
|
-
*/
|
|
176
|
-
start() {
|
|
177
|
-
if (__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isStarted, true, "f");
|
|
181
|
-
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Stops evaluating network connection state. Clears any pending banner
|
|
185
|
-
* timers and resets state to `available`. Call this when the UI
|
|
186
|
-
* consuming the banner is no longer active. Idempotent.
|
|
187
|
-
*/
|
|
188
|
-
stop() {
|
|
189
|
-
if (!__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isStarted, false, "f");
|
|
193
|
-
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_resetBanner).call(this);
|
|
194
|
-
}
|
|
195
195
|
/**
|
|
196
196
|
* Clears the banner state such that the banner will be hidden.
|
|
197
197
|
*/
|
|
@@ -199,8 +199,9 @@ class NetworkConnectionBannerController extends base_controller_1.BaseController
|
|
|
199
199
|
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_resetBanner).call(this);
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
|
-
* Switches the chain's default RPC endpoint to its Infura endpoint
|
|
203
|
-
* causing the banner to clear once the
|
|
202
|
+
* Switches the chain's default RPC endpoint to its Infura endpoint and
|
|
203
|
+
* makes it the active network, causing the banner to clear once the
|
|
204
|
+
* network becomes available again.
|
|
204
205
|
*
|
|
205
206
|
* @param chainId - The chain whose default RPC endpoint should be switched.
|
|
206
207
|
* @throws If the chain configuration cannot be found, or if it has no
|
|
@@ -222,25 +223,50 @@ class NetworkConnectionBannerController extends base_controller_1.BaseController
|
|
|
222
223
|
await this.messenger.call('NetworkController:updateNetwork', chainId, {
|
|
223
224
|
...networkConfiguration,
|
|
224
225
|
defaultRpcEndpointIndex: infuraEndpointIndex,
|
|
225
|
-
}
|
|
226
|
+
});
|
|
227
|
+
// Move the active connection onto the Infura endpoint too, so the user
|
|
228
|
+
// is no longer connected to the failing endpoint.
|
|
229
|
+
const infuraNetworkClientId = networkConfiguration.rpcEndpoints[infuraEndpointIndex].networkClientId;
|
|
230
|
+
const { selectedNetworkClientId } = this.messenger.call('NetworkController:getState');
|
|
231
|
+
if (infuraNetworkClientId !== selectedNetworkClientId) {
|
|
232
|
+
await this.messenger.call('NetworkController:setActiveNetwork', infuraNetworkClientId);
|
|
233
|
+
}
|
|
226
234
|
}
|
|
227
235
|
}
|
|
228
236
|
exports.NetworkConnectionBannerController = NetworkConnectionBannerController;
|
|
229
|
-
_NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnectionBannerController_unavailableTimer = new WeakMap(), _NetworkConnectionBannerController_pendingNetworkClientId = new WeakMap(), _NetworkConnectionBannerController_isStarted = new WeakMap(),
|
|
237
|
+
_NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnectionBannerController_unavailableTimer = new WeakMap(), _NetworkConnectionBannerController_pendingNetworkClientId = new WeakMap(), _NetworkConnectionBannerController_isStarted = new WeakMap(), _NetworkConnectionBannerController_isUiOpen = new WeakMap(), _NetworkConnectionBannerController_isUnlocked = new WeakMap(), _NetworkConnectionBannerController_instances = new WeakSet(), _NetworkConnectionBannerController_updateLifecycle = function _NetworkConnectionBannerController_updateLifecycle() {
|
|
238
|
+
if (__classPrivateFieldGet(this, _NetworkConnectionBannerController_isUiOpen, "f") && __classPrivateFieldGet(this, _NetworkConnectionBannerController_isUnlocked, "f")) {
|
|
239
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_start).call(this);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_stop).call(this);
|
|
243
|
+
}
|
|
244
|
+
}, _NetworkConnectionBannerController_start = function _NetworkConnectionBannerController_start() {
|
|
245
|
+
if (__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isStarted, true, "f");
|
|
249
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_refreshState).call(this, {
|
|
250
|
+
networkControllerState: this.messenger.call('NetworkController:getState'),
|
|
251
|
+
networkEnablementControllerState: this.messenger.call('NetworkEnablementController:getState'),
|
|
252
|
+
connectivityControllerState: this.messenger.call('ConnectivityController:getState'),
|
|
253
|
+
});
|
|
254
|
+
}, _NetworkConnectionBannerController_stop = function _NetworkConnectionBannerController_stop() {
|
|
255
|
+
if (!__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
__classPrivateFieldSet(this, _NetworkConnectionBannerController_isStarted, false, "f");
|
|
259
|
+
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_resetBanner).call(this);
|
|
260
|
+
}, _NetworkConnectionBannerController_refreshState = function _NetworkConnectionBannerController_refreshState({ networkControllerState, networkEnablementControllerState, connectivityControllerState, }) {
|
|
230
261
|
if (!__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
231
262
|
return;
|
|
232
263
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (connectivityStatus === connectivity_controller_1.CONNECTIVITY_STATUSES.Offline) {
|
|
264
|
+
if (connectivityControllerState.connectivityStatus ===
|
|
265
|
+
connectivity_controller_1.CONNECTIVITY_STATUSES.Offline) {
|
|
236
266
|
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_resetBanner).call(this);
|
|
237
267
|
return;
|
|
238
268
|
}
|
|
239
|
-
const
|
|
240
|
-
this.messenger.call('NetworkController:getState');
|
|
241
|
-
const enablementState = networkEnablementControllerState ??
|
|
242
|
-
this.messenger.call('NetworkEnablementController:getState');
|
|
243
|
-
const failedNetwork = __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_findFailedNetwork).call(this, networkState, enablementState);
|
|
269
|
+
const failedNetwork = __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_findFailedNetwork).call(this, networkControllerState, networkEnablementControllerState);
|
|
244
270
|
if (!failedNetwork) {
|
|
245
271
|
__classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_resetBanner).call(this);
|
|
246
272
|
return;
|
|
@@ -249,10 +275,16 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
249
275
|
this.state.networkConnectionBannerNetwork?.networkClientId ===
|
|
250
276
|
failedNetwork.networkClientId) {
|
|
251
277
|
this.update((state) => {
|
|
278
|
+
// Even if the network client ID has not changed, save the current
|
|
279
|
+
// version of the failed network to state in case the user has updated
|
|
280
|
+
// its RPC URL.
|
|
252
281
|
state.networkConnectionBannerNetwork = failedNetwork;
|
|
253
282
|
});
|
|
254
283
|
return;
|
|
255
284
|
}
|
|
285
|
+
// A degraded timer is already counting down for this same network.
|
|
286
|
+
// Repeated `stateChange` events must not clear and restart it, or a
|
|
287
|
+
// steady stream of updates could postpone the banner indefinitely.
|
|
256
288
|
if (__classPrivateFieldGet(this, _NetworkConnectionBannerController_pendingNetworkClientId, "f") === failedNetwork.networkClientId) {
|
|
257
289
|
return;
|
|
258
290
|
}
|
|
@@ -261,15 +293,15 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
261
293
|
state.networkConnectionBannerStatus = 'available';
|
|
262
294
|
state.networkConnectionBannerNetwork = null;
|
|
263
295
|
});
|
|
264
|
-
//
|
|
265
|
-
// called `stop()` re-entrantly. Bail before scheduling anything.
|
|
296
|
+
// If `stop` is called before scheduling timers, bail early.
|
|
266
297
|
if (!__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
267
298
|
return;
|
|
268
299
|
}
|
|
269
|
-
//
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
300
|
+
// Remember which network the pending timer is for (see the guard above)
|
|
301
|
+
// and capture the failing network at schedule time. If the failure
|
|
302
|
+
// resolves or a different network becomes the banner target while we
|
|
303
|
+
// wait, the subscription handlers re-enter this method and cancel or
|
|
304
|
+
// replace the timer before it fires.
|
|
273
305
|
__classPrivateFieldSet(this, _NetworkConnectionBannerController_pendingNetworkClientId, failedNetwork.networkClientId, "f");
|
|
274
306
|
__classPrivateFieldSet(this, _NetworkConnectionBannerController_degradedTimer, setTimeout(() => {
|
|
275
307
|
__classPrivateFieldSet(this, _NetworkConnectionBannerController_degradedTimer, undefined, "f");
|
|
@@ -278,8 +310,7 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
278
310
|
state.networkConnectionBannerStatus = 'degraded';
|
|
279
311
|
state.networkConnectionBannerNetwork = failedNetwork;
|
|
280
312
|
});
|
|
281
|
-
//
|
|
282
|
-
// called `stop()` re-entrantly. Bail before scheduling the escalation.
|
|
313
|
+
// If `stop` is called before scheduling timers, bail early.
|
|
283
314
|
if (!__classPrivateFieldGet(this, _NetworkConnectionBannerController_isStarted, "f")) {
|
|
284
315
|
return;
|
|
285
316
|
}
|
|
@@ -311,16 +342,17 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
311
342
|
__classPrivateFieldSet(this, _NetworkConnectionBannerController_unavailableTimer, undefined, "f");
|
|
312
343
|
}
|
|
313
344
|
}, _NetworkConnectionBannerController_findFailedNetwork = function _NetworkConnectionBannerController_findFailedNetwork(networkState, enablementState) {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
345
|
+
const enabledNetworks = __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_collectEnabledNetworks).call(this, networkState, enablementState);
|
|
346
|
+
// Networks whose connectivity has not been looked up yet are not failed.
|
|
347
|
+
const failedNetworks = enabledNetworks
|
|
348
|
+
.filter(({ metadata }) => metadata !== undefined && metadata.status !== network_controller_1.NetworkStatus.Available)
|
|
317
349
|
.map((network) => __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_buildFailedNetwork).call(this, network));
|
|
318
|
-
return __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m",
|
|
350
|
+
return __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_pickFailedNetworkToDisplay).call(this, failedNetworks, enabledNetworks.length);
|
|
319
351
|
}, _NetworkConnectionBannerController_getEnabledEvmChainIds = function _NetworkConnectionBannerController_getEnabledEvmChainIds(enabledNetworkMap) {
|
|
320
352
|
return Object.entries(enabledNetworkMap[utils_1.KnownCaipNamespace.Eip155] ?? {})
|
|
321
353
|
.filter(([, enabled]) => enabled)
|
|
322
354
|
.map(([chainId]) => chainId);
|
|
323
|
-
},
|
|
355
|
+
}, _NetworkConnectionBannerController_collectEnabledNetworks = function _NetworkConnectionBannerController_collectEnabledNetworks({ networkConfigurationsByChainId, networksMetadata, }, { enabledNetworkMap, }) {
|
|
324
356
|
return __classPrivateFieldGet(this, _NetworkConnectionBannerController_instances, "m", _NetworkConnectionBannerController_getEnabledEvmChainIds).call(this, enabledNetworkMap).flatMap((chainId) => {
|
|
325
357
|
const networkConfiguration = networkConfigurationsByChainId[chainId];
|
|
326
358
|
if (!networkConfiguration) {
|
|
@@ -331,10 +363,6 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
331
363
|
if (!defaultRpcEndpoint) {
|
|
332
364
|
return [];
|
|
333
365
|
}
|
|
334
|
-
const metadata = networksMetadata[defaultRpcEndpoint.networkClientId];
|
|
335
|
-
if (!metadata) {
|
|
336
|
-
return [];
|
|
337
|
-
}
|
|
338
366
|
return [
|
|
339
367
|
{
|
|
340
368
|
chainId,
|
|
@@ -342,7 +370,7 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
342
370
|
rpcEndpoints,
|
|
343
371
|
defaultRpcEndpointIndex,
|
|
344
372
|
defaultRpcEndpoint,
|
|
345
|
-
metadata,
|
|
373
|
+
metadata: networksMetadata[defaultRpcEndpoint.networkClientId],
|
|
346
374
|
},
|
|
347
375
|
];
|
|
348
376
|
});
|
|
@@ -363,20 +391,14 @@ _NetworkConnectionBannerController_degradedTimer = new WeakMap(), _NetworkConnec
|
|
|
363
391
|
rpcUrl: defaultRpcEndpoint.url,
|
|
364
392
|
isInfuraEndpoint,
|
|
365
393
|
switchableInfuraNetworkClientId,
|
|
366
|
-
domain: (0, url_utils_1.getDomain)(defaultRpcEndpoint.url),
|
|
367
394
|
};
|
|
368
|
-
},
|
|
395
|
+
}, _NetworkConnectionBannerController_pickFailedNetworkToDisplay = function _NetworkConnectionBannerController_pickFailedNetworkToDisplay(failedNetworks, totalEnabledNetworks) {
|
|
369
396
|
if (failedNetworks.length === 0) {
|
|
370
397
|
return null;
|
|
371
398
|
}
|
|
372
399
|
const firstCustomFailed = failedNetworks.find((entry) => !entry.isInfuraEndpoint);
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
.filter((domain) => domain !== null)).size;
|
|
376
|
-
const areAllKnownNetworksFailed = failedNetworks.length === totalNetworksWithMetadata;
|
|
377
|
-
if (!firstCustomFailed &&
|
|
378
|
-
distinctDomains <= 1 &&
|
|
379
|
-
!areAllKnownNetworksFailed) {
|
|
400
|
+
const areAllEnabledNetworksFailed = failedNetworks.length === totalEnabledNetworks;
|
|
401
|
+
if (!firstCustomFailed && !areAllEnabledNetworksFailed) {
|
|
380
402
|
return null;
|
|
381
403
|
}
|
|
382
404
|
return firstCustomFailed ?? failedNetworks[0];
|