Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions packages/network-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The default `retryTimeout` for the block tracker is now `20` seconds.
- Add `failoverUrls` constructor argument ([#9140](https://github.com/MetaMask/core/pull/9140))
- These will override `failoverUrls` from state during network client creation.
- Add forced RPC failover for Infura endpoints, driven by the `core-platform-rpc-failover-force-enabled` remote feature flag ([#9175](https://github.com/MetaMask/core/pull/9175))
- When enabled, Infura endpoints configured with failover URLs route all traffic to those failover URLs, bypassing Infura entirely. Infura endpoints without failover URLs continue to use Infura, and custom RPC endpoints are unaffected.
- Adds the `NetworkController.enableRpcFailoverForced` and `NetworkController.disableRpcFailoverForced` methods, along with the `NetworkControllerEnableRpcFailoverForcedAction` and `NetworkControllerDisableRpcFailoverForcedAction` messenger actions.

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ export type NetworkControllerDisableRpcFailoverAction = {
handler: NetworkController['disableRpcFailover'];
};

/**
* Forces RPC failover for Infura endpoints. When enabled, any Infura endpoint
* configured with failover URLs will route all traffic to those failover URLs,
* bypassing Infura entirely. Infura endpoints without failover URLs continue to
* use Infura. Custom endpoints are unaffected.
*/
export type NetworkControllerEnableRpcFailoverForcedAction = {
type: `NetworkController:enableRpcFailoverForced`;
handler: NetworkController['enableRpcFailoverForced'];
};

/**
* Stops forcing RPC failover for Infura endpoints, restoring the normal
* automatic-failover behavior governed by {@link enableRpcFailover}.
*/
export type NetworkControllerDisableRpcFailoverForcedAction = {
type: `NetworkController:disableRpcFailoverForced`;
handler: NetworkController['disableRpcFailoverForced'];
};

/**
* Accesses the provider and block tracker for the currently selected network.
*
Expand Down Expand Up @@ -311,6 +331,8 @@ export type NetworkControllerMethodActions =
| NetworkControllerGetEthQueryAction
| NetworkControllerEnableRpcFailoverAction
| NetworkControllerDisableRpcFailoverAction
| NetworkControllerEnableRpcFailoverForcedAction
| NetworkControllerDisableRpcFailoverForcedAction
| NetworkControllerGetProviderAndBlockTrackerAction
| NetworkControllerGetSelectedNetworkClientAction
| NetworkControllerGetSelectedChainIdAction
Expand Down
81 changes: 78 additions & 3 deletions packages/network-controller/src/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ 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 { getIsRpcFailoverEnabled, getIsRpcFailoverForced } from './selectors';
import { NetworkClientType } from './types';
import type {
BlockTracker,
Expand Down Expand Up @@ -669,7 +669,9 @@ type AllowedEvents = RemoteFeatureFlagControllerStateChangeEvent;
const MESSENGER_EXPOSED_METHODS = [
'addNetwork',
'disableRpcFailover',
'disableRpcFailoverForced',
'enableRpcFailover',
'enableRpcFailoverForced',
'findNetworkClientIdByChainId',
'get1559CompatibilityWithNetworkClientId',
'getEIP1559Compatibility',
Expand Down Expand Up @@ -1275,6 +1277,8 @@ export class NetworkController extends BaseController<

#isRpcFailoverEnabled = false;

#isRpcFailoverForced = false;

/**
* Constructs a NetworkController.
*
Expand Down Expand Up @@ -1378,6 +1382,15 @@ export class NetworkController extends BaseController<
},
getIsRpcFailoverEnabled,
);

this.messenger.subscribe(
// eslint-disable-next-line no-restricted-syntax
'RemoteFeatureFlagController:stateChange',
(isRpcFailoverForced) => {
this.#updateRpcFailoverForced(isRpcFailoverForced);
},
getIsRpcFailoverForced,
);
}

/**
Expand Down Expand Up @@ -1408,6 +1421,24 @@ export class NetworkController extends BaseController<
this.#updateRpcFailoverEnabled(false);
}

/**
* Forces RPC failover for Infura endpoints. When enabled, any Infura endpoint
* configured with failover URLs will route all traffic to those failover URLs,
* bypassing Infura entirely. Infura endpoints without failover URLs continue to
* use Infura. Custom endpoints are unaffected.
*/
enableRpcFailoverForced(): void {
this.#updateRpcFailoverForced(true);
}

/**
* Stops forcing RPC failover for Infura endpoints, restoring the normal
* automatic-failover behavior governed by {@link enableRpcFailover}.
*/
disableRpcFailoverForced(): void {
this.#updateRpcFailoverForced(false);
}

/**
* Enables or disables the RPC failover functionality, depending on the
* boolean given. This is done by reconstructing all network clients that were
Expand Down Expand Up @@ -1449,6 +1480,44 @@ export class NetworkController extends BaseController<
this.#isRpcFailoverEnabled = newIsRpcFailoverEnabled;
}

/**
* Enables or disables forced RPC failover, depending on the boolean given.
* This reconstructs all network clients that were configured with failover
* URLs so the new value takes effect. Network client IDs are preserved.
*
* @param newIsRpcFailoverForced - Whether or not to force RPC failover.
*/
#updateRpcFailoverForced(newIsRpcFailoverForced: boolean): void {
if (this.#isRpcFailoverForced === newIsRpcFailoverForced) {
return;
}

const autoManagedNetworkClientRegistry =
this.#ensureAutoManagedNetworkClientRegistryPopulated();

for (const networkClientsById of Object.values(
autoManagedNetworkClientRegistry,
)) {
for (const networkClientId of Object.keys(networkClientsById)) {
// Type assertion: We can assume that `networkClientId` is valid here.
const networkClient =
networkClientsById[
networkClientId as keyof typeof networkClientsById
];
if (
networkClient.configuration.failoverRpcUrls &&
networkClient.configuration.failoverRpcUrls.length > 0
) {
newIsRpcFailoverForced
? networkClient.enableRpcFailoverForced()
: networkClient.disableRpcFailoverForced();
}
}
}

this.#isRpcFailoverForced = newIsRpcFailoverForced;
}

/**
* Accesses the provider and block tracker for the currently selected network.
*
Expand Down Expand Up @@ -1610,12 +1679,14 @@ 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.#updateRpcFailoverForced(getIsRpcFailoverForced(state));

this.#applyNetworkSelection(this.state.selectedNetworkClientId);
}
Expand Down Expand Up @@ -2860,6 +2931,7 @@ export class NetworkController extends BaseController<
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverForced: this.#isRpcFailoverForced,
logger: this.#log,
});
} else {
Expand All @@ -2879,6 +2951,7 @@ export class NetworkController extends BaseController<
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverForced: this.#isRpcFailoverForced,
logger: this.#log,
});
}
Expand Down Expand Up @@ -3045,6 +3118,7 @@ export class NetworkController extends BaseController<
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverForced: this.#isRpcFailoverForced,
logger: this.#log,
}),
] as const;
Expand All @@ -3064,6 +3138,7 @@ export class NetworkController extends BaseController<
getBlockTrackerOptions: this.#getBlockTrackerOptions,
messenger: this.messenger,
isRpcFailoverEnabled: this.#isRpcFailoverEnabled,
isRpcFailoverForced: this.#isRpcFailoverForced,
logger: this.#log,
}),
] as const;
Expand Down
Loading
Loading