Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c3ab29b
feat(network-controller): add getIsRpcFailoverForced selector
cryptodev-2s Jun 17, 2026
003b255
test(network-controller): clarify non-boolean selector test name
cryptodev-2s Jun 17, 2026
e51b625
feat(network-controller): force Infura traffic to failover when forced
cryptodev-2s Jun 17, 2026
4792d92
test(network-controller): cover disableRpcFailoverForced and document…
cryptodev-2s Jun 17, 2026
6a4e3c1
feat(network-controller): react to wallet-framework-rpc-failover-forc…
cryptodev-2s Jun 17, 2026
9beb97d
fix(network-controller): export forced failover action types
cryptodev-2s Jun 17, 2026
938e1bd
docs(network-controller): changelog for forced RPC failover
cryptodev-2s Jun 17, 2026
ba7ad24
docs(network-controller): point changelog at the real PR number
cryptodev-2s Jun 17, 2026
51ec735
docs(network-controller): note positional primary under forced failover
cryptodev-2s Jun 17, 2026
4bc51fe
fix: run lint:misc
cryptodev-2s Jun 17, 2026
18ef4dc
fix: messenger types
cryptodev-2s Jun 17, 2026
fe94fab
fix: remove no-restricted-syntax
cryptodev-2s Jun 17, 2026
0bd5566
refactor(network-controller): rename force-failover flag to core-plat…
cryptodev-2s Jun 17, 2026
8760483
Merge origin/main into feat/force-rpc-failover
cryptodev-2s Jun 18, 2026
eca6f20
Merge branch 'main' into feat/force-rpc-failover
cryptodev-2s Jun 19, 2026
89ac401
Merge remote-tracking branch 'origin/main' into feat/force-rpc-failover
cryptodev-2s Jun 22, 2026
bc8dce7
fix: changelog
cryptodev-2s Jun 22, 2026
2a256af
fix: lint:misc
cryptodev-2s Jun 22, 2026
1aec6fe
fix(network-controller): read forced failover flag as camelCase key
cryptodev-2s Jun 23, 2026
2b5ec37
Merge branch 'main' into feat/force-rpc-failover
cryptodev-2s Jun 23, 2026
3e8f194
Merge branch 'main' into feat/force-rpc-failover
cryptodev-2s Jun 24, 2026
4efa475
refactor(network-controller): remove unused forced failover public API
cryptodev-2s Jun 24, 2026
c9c9e75
refactor(network-controller): rename forced failover methods to enabl…
cryptodev-2s Jun 24, 2026
064fe2d
refactor(network-controller): extract endpoint selection into getAvai…
cryptodev-2s Jun 24, 2026
c7bcaa1
test(network-controller): drop selector non-boolean passthrough test
cryptodev-2s Jun 24, 2026
ceabdd3
refactor(network-controller): share failover client walk via helper
cryptodev-2s Jun 24, 2026
fec431a
fix: lint misc
cryptodev-2s Jun 24, 2026
f69f859
feat(network-controller)!: drive RPC failover from corePlatformRpcFai…
cryptodev-2s Jun 24, 2026
a23fb7f
fix: lint misc
cryptodev-2s Jun 24, 2026
5a4eb69
fix(network-controller): add return type to selector test helper
cryptodev-2s Jun 24, 2026
9503e0e
Merge branch 'main' into feat/force-rpc-failover
cryptodev-2s Jun 24, 2026
e690b24
refactor(network-controller): track failover as a single mode in the …
cryptodev-2s Jun 24, 2026
4b9faa2
refactor(network-controller)!: remove enableRpcFailover/disableRpcFai…
cryptodev-2s Jun 24, 2026
0f31429
fix: lint misc
cryptodev-2s Jun 24, 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
11 changes: 11 additions & 0 deletions packages/network-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- **BREAKING:** Drive RPC failover from the single `corePlatformRpcFailoverMode` remote feature flag ([#9175](https://github.com/MetaMask/core/pull/9175))
- The flag is a string with three values: `disabled` (failover off), `enabled` (divert to failover URLs when the primary endpoint is unavailable), and `forced` (Infura endpoints that have failover URLs route all traffic to those URLs, bypassing Infura entirely). Custom endpoints are unaffected, and the value defaults to `disabled` when the flag is absent or unrecognized.
- `NetworkController` no longer reads the `walletFrameworkRpcFailoverEnabled` flag; the `enabled` mode replaces it. Update your remote feature flag configuration to set `corePlatformRpcFailoverMode`.

### Removed

- **BREAKING:** Remove the `NetworkController.enableRpcFailover` and `NetworkController.disableRpcFailover` methods, their `NetworkController:enableRpcFailover` / `NetworkController:disableRpcFailover` messenger actions, and the `NetworkControllerEnableRpcFailoverAction` / `NetworkControllerDisableRpcFailoverAction` types ([#9175](https://github.com/MetaMask/core/pull/9175))
- RPC failover is now driven entirely by the `corePlatformRpcFailoverMode` remote feature flag, so there is no longer an imperative toggle.

## [33.0.0]

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,6 @@ export type NetworkControllerGetEthQueryAction = {
handler: NetworkController['getEthQuery'];
};

/**
* Enables the RPC failover functionality. That is, if any RPC endpoints are
* configured with failover URLs, then traffic will automatically be diverted
* to them if those RPC endpoints are unavailable.
*/
export type NetworkControllerEnableRpcFailoverAction = {
type: `NetworkController:enableRpcFailover`;
handler: NetworkController['enableRpcFailover'];
};

/**
* Disables the RPC failover functionality. That is, even if any RPC endpoints
* are configured with failover URLs, then traffic will not automatically be
* diverted to them if those RPC endpoints are unavailable.
*/
export type NetworkControllerDisableRpcFailoverAction = {
type: `NetworkController:disableRpcFailover`;
handler: NetworkController['disableRpcFailover'];
};

/**
* Accesses the provider and block tracker for the currently selected network.
*
Expand Down Expand Up @@ -309,8 +289,6 @@ export type NetworkControllerFindNetworkClientIdByChainIdAction = {
*/
export type NetworkControllerMethodActions =
| NetworkControllerGetEthQueryAction
| NetworkControllerEnableRpcFailoverAction
| NetworkControllerDisableRpcFailoverAction
| NetworkControllerGetProviderAndBlockTrackerAction
| NetworkControllerGetSelectedNetworkClientAction
| NetworkControllerGetSelectedChainIdAction
Expand Down
113 changes: 64 additions & 49 deletions packages/network-controller/src/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ import type { DegradedEventType, RetryReason } from './create-network-client';
import { projectLogger, createModuleLogger } from './logger';
import type { NetworkControllerMethodActions } from './NetworkController-method-action-types';
import type { RpcServiceOptionsWithDefaults } from './rpc-service/rpc-service';
import { getIsRpcFailoverEnabled } from './selectors';
import { getRpcFailoverMode } from './selectors';
import type { RpcFailoverMode } from './selectors';
import { NetworkClientType } from './types';
import type {
BlockTracker,
Expand Down Expand Up @@ -668,8 +669,6 @@ type AllowedEvents = RemoteFeatureFlagControllerStateChangeEvent;

const MESSENGER_EXPOSED_METHODS = [
'addNetwork',
'disableRpcFailover',
'enableRpcFailover',
'findNetworkClientIdByChainId',
'get1559CompatibilityWithNetworkClientId',
'getEIP1559Compatibility',
Expand Down Expand Up @@ -1273,7 +1272,7 @@ export class NetworkController extends BaseController<
NetworkConfiguration
>;

#isRpcFailoverEnabled = false;
#rpcFailoverMode: RpcFailoverMode = 'disabled';

/**
* Constructs a NetworkController.
Expand Down Expand Up @@ -1373,10 +1372,10 @@ export class NetworkController extends BaseController<
this.messenger.subscribe(
// eslint-disable-next-line no-restricted-syntax
'RemoteFeatureFlagController:stateChange',
(isRpcFailoverEnabled) => {
this.#updateRpcFailoverEnabled(isRpcFailoverEnabled);
(rpcFailoverMode) => {
this.#updateRpcFailover(rpcFailoverMode);
},
getIsRpcFailoverEnabled,
getRpcFailoverMode,
);
}

Expand All @@ -1391,38 +1390,19 @@ export class NetworkController extends BaseController<
}

/**
* Enables the RPC failover functionality. That is, if any RPC endpoints are
* configured with failover URLs, then traffic will automatically be diverted
* to them if those RPC endpoints are unavailable.
*/
enableRpcFailover(): void {
this.#updateRpcFailoverEnabled(true);
}

/**
* Disables the RPC failover functionality. That is, even if any RPC endpoints
* are configured with failover URLs, then traffic will not automatically be
* diverted to them if those RPC endpoints are unavailable.
*/
disableRpcFailover(): void {
this.#updateRpcFailoverEnabled(false);
}

/**
* Enables or disables the RPC failover functionality, depending on the
* boolean given. This is done by reconstructing all network clients that were
* originally configured with failover URLs so that those URLs are either
* honored or ignored. Network client IDs will be preserved so as not to
* invalidate state in other controllers.
* Invokes the given callback for each auto-managed network client that was
* configured with failover URLs. Used to reconstruct those clients when an
* RPC failover setting changes.
*
* @param newIsRpcFailoverEnabled - Whether or not to enable or disable the
* RPC failover functionality.
*/
#updateRpcFailoverEnabled(newIsRpcFailoverEnabled: boolean): void {
if (this.#isRpcFailoverEnabled === newIsRpcFailoverEnabled) {
return;
}

* @param callback - Called with each network client that has failover URLs.
*/
#forEachNetworkClientWithFailover(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this can be moved into updateRpcFailover instead of being a separate callback function now

callback: (
networkClient:
| AutoManagedNetworkClient<InfuraNetworkClientConfiguration>
| AutoManagedNetworkClient<CustomNetworkClientConfiguration>,
) => void,
): void {
const autoManagedNetworkClientRegistry =
this.#ensureAutoManagedNetworkClientRegistryPopulated();

Expand All @@ -1439,14 +1419,44 @@ export class NetworkController extends BaseController<
networkClient.configuration.failoverRpcUrls &&
networkClient.configuration.failoverRpcUrls.length > 0
) {
newIsRpcFailoverEnabled
? networkClient.enableRpcFailover()
: networkClient.disableRpcFailover();
callback(networkClient);
}
}
}
}

/**
* Applies the given RPC failover mode by reconstructing all network clients
* that were configured with failover URLs so that the new mode takes effect.
* Network client IDs are preserved so as not to invalidate state in other
* controllers.
*
* @param newMode - The RPC failover mode to apply.
*/
#updateRpcFailover(newMode: RpcFailoverMode): void {
if (this.#rpcFailoverMode === newMode) {
return;
}

const wasEnabled = this.#rpcFailoverMode === 'enabled';
const wasForced = this.#rpcFailoverMode === 'forced';
const isEnabled = newMode === 'enabled';
const isForced = newMode === 'forced';

this.#forEachNetworkClientWithFailover((networkClient) => {
if (isEnabled !== wasEnabled) {
isEnabled
? networkClient.enableRpcFailover()
: networkClient.disableRpcFailover();
}
if (isForced !== wasForced) {
isForced
? networkClient.enableForcedRpcFailover()
: networkClient.disableForcedRpcFailover();
}
});

this.#isRpcFailoverEnabled = newIsRpcFailoverEnabled;
this.#rpcFailoverMode = newMode;
}

/**
Expand Down Expand Up @@ -1610,12 +1620,13 @@ export class NetworkController extends BaseController<
}

/**
* Initialize the NetworkController, updating the RPC failover feature flag
* and applying the network selection.
* Initialize the NetworkController, updating the RPC failover feature flags
* (`isRpcFailoverEnabled` and `isRpcFailoverForced`) and applying the network
* selection.
*/
init(): void {
const state = this.messenger.call('RemoteFeatureFlagController:getState');
this.#updateRpcFailoverEnabled(getIsRpcFailoverEnabled(state));
this.#updateRpcFailover(getRpcFailoverMode(state));

this.#applyNetworkSelection(this.state.selectedNetworkClientId);
}
Expand Down Expand Up @@ -2859,7 +2870,8 @@ export class NetworkController extends BaseController<
getRpcServiceOptions: this.#getRpcServiceOptions,
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverEnabled: this.#rpcFailoverMode === 'enabled',
isRpcFailoverForced: this.#rpcFailoverMode === 'forced',
logger: this.#log,
});
} else {
Expand All @@ -2878,7 +2890,8 @@ export class NetworkController extends BaseController<
getRpcServiceOptions: this.#getRpcServiceOptions,
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverEnabled: this.#rpcFailoverMode === 'enabled',
isRpcFailoverForced: this.#rpcFailoverMode === 'forced',
logger: this.#log,
});
}
Expand Down Expand Up @@ -3044,7 +3057,8 @@ export class NetworkController extends BaseController<
getRpcServiceOptions: this.#getRpcServiceOptions,
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverEnabled: this.#rpcFailoverMode === 'enabled',
isRpcFailoverForced: this.#rpcFailoverMode === 'forced',
logger: this.#log,
}),
] as const;
Expand All @@ -3063,7 +3077,8 @@ export class NetworkController extends BaseController<
getRpcServiceOptions: this.#getRpcServiceOptions,
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverEnabled: this.#rpcFailoverMode === 'enabled',
isRpcFailoverForced: this.#rpcFailoverMode === 'forced',
logger: this.#log,
}),
] as const;
Expand Down
Loading
Loading