Skip to content

fix: cp-7.57.0 Initialize feature flags from state#21168

Merged
mcmire merged 4 commits into
mainfrom
reenable-remote-feature-flag-controller-persistence
Oct 15, 2025
Merged

fix: cp-7.57.0 Initialize feature flags from state#21168
mcmire merged 4 commits into
mainfrom
reenable-remote-feature-flag-controller-persistence

Conversation

@mcmire

@mcmire mcmire commented Oct 14, 2025

Copy link
Copy Markdown
Contributor

Description

0ee7360 introduced a change such that when the app is cold-started and Engine is initialized, RemoteFeatureFlagController is no longer instructed to reuse feature flags from a previous start, but rather, it will fetch them all over again. This change was made so that by simply listening to RemoteFeatureFlagController:stateChange, the RPC failover mode in NetworkController could be easily enabled or disabled.

In hindsight, this changed increased the start time of the app, negatively impacting performance. This is particularly noticeable on low-end devices where the app is frequently killed and restarted automatically due to out-of-memory issues. Also, changing the behavior of RemoteFeatureFlagController:stateChange in the way described above is admittedly strange.

To address this, this PR once again initializes RemoteFeatureFlagController from persisted state. As for NetworkController, it now correctly asks for the RemoteFeatureFlagController state once it is initialized and uses it to switch the RPC failover mode.

Changelog

CHANGELOG entry: Don't re-fetch feature flags on app restart, but rely on persistence instead

Related issues

(N/A)

Manual testing steps

  1. Check out this branch.
  2. Add QUICKNODE_ environment variables to .js.env. Ask me for what they should be.
  3. Check out this branch, run yarn setup:expo, run yarn watch:clean.
  4. Open node_modules/@metamask/network-controller/dist/rpc-service/rpc-service.cjs, look for async function _RpcService_processRequest and make these changes:
    async function _RpcService_processRequest(fetchOptions) {
        let response;
        try {
            return await __classPrivateFieldGet(this, _RpcService_policy, "f").execute(async () => {
    +           console.log('[REQUEST]', this.endpointUrl.toString(), 'with', fetchOptions);
    +           if (
    +             this.endpointUrl.toString().includes("linea-mainnet.infura.io") ||
    +             this.endpointUrl.toString().includes("mainnet.era.zksync.io")
    +           ) {
    +               console.log('[RESPONSE]', this.endpointUrl.toString(), '=> 502');
    +               throw new controller_utils_1.HttpError(502);
    +           }
                response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, this.endpointUrl, fetchOptions);
    +           console.log('[RESPONSE]', this.endpointUrl.toString(), '=>', response.status);
                if (!response.ok) {
                    throw new controller_utils_1.HttpError(response.status);
                }
                return await response.json();
            });
        }
  5. Open app/core/Engine/controllers/network-controller-init.ts, look for new NetworkController, and make these changes:
            return {
              ...commonOptions,
              policyOptions: {
                maxRetries,
    -           maxConsecutiveFailures: (maxRetries + 1) * 7,
    +           maxConsecutiveFailures: (maxRetries + 1) * 4,
              },
            };
          },
          additionalDefaultNetworks,
        };
        const networkController = new NetworkController(networkControllerOptions);
  6. Open the app, go through onboarding if needed.
  7. Once on the home screen, switch to Linea.
  8. Monitor the messages appearing in your terminal. Pretty quickly, you should see a line that says [REQUEST] https://linea-mainnet.infura.io/v3/<api key>... with a line under this is [RESPONSE] https://linea-mainnet.infura.io/v3/<api key> => 502.
  9. Pull down on the token list a few times to refresh it.
  10. Eventually you should start to see lines in the terminal such as [REQUEST] https://<name>.linea-mainnet.quiknode.pro/<api-key>. This is an indicator that the RPC failover logic is still working.

Screenshots/Recordings

(N/A)

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Initialize RemoteFeatureFlagController from persisted state and toggle NetworkController RPC failover based on walletFrameworkRpcFailoverEnabled at init and on updates, with new tests.

  • Engine initialization:
    • Initialize RemoteFeatureFlagController with persisted state.
    • Add toggleRpcFailover helper and subscribe to RemoteFeatureFlagController:stateChange using selector state.remoteFeatureFlags.walletFrameworkRpcFailoverEnabled.
    • Immediately toggle RPC failover on init based on persisted walletFrameworkRpcFailoverEnabled.
  • Tests (app/core/Engine/Engine.test.ts):
    • Mock ClientConfigApiService and NetworkController methods.
    • Add tests to verify RPC failover is enabled/disabled on init per existing flag.
    • Add async tests to verify RPC failover toggles when the feature flag changes after fetch.

Written by Cursor Bugbot for commit df7f8ed. This will update automatically on new commits. Configure here.

0ee7360 introduced a change such that
when the app is cold-started and Engine is initialized,
RemoteFeatureFlagController is no longer instructed to reuse feature
flags from a previous start, but rather, it will fetch them all over
again. This change was made so that by simply listening to
`RemoteFeatureFlagController:stateChange`, the RPC failover mode in
NetworkController could be easily enabled or disabled.

In hindsign, this changed increased the start time of the app,
negatively impacting performance. This is particularly noticeable on
low-end devices where the app is frequently killed and restarted
automatically due to out-of-memory issues. Also,
changing the behavior of `RemoteFeatureFlagController:stateChange` in
the way described above is admittedly strange.

To address this, this PR once again initializes
RemoteFeatureFlagController from persisted state. As for
NetworkController, it now correctly asks for the
RemoteFeatureFlagController state once it is initialized and uses it to
switch the RPC failover mode.
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-core-platform Core Platform team label Oct 14, 2025
@Cal-L Cal-L changed the title fix: cp-13.5.0 Initialize feature flags from state fix: cp-7.57.0 Initialize feature flags from state Oct 14, 2025
NicolasMassart
NicolasMassart previously approved these changes Oct 15, 2025

@NicolasMassart NicolasMassart left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Happy to re-approve once changes made

Comment thread app/core/Engine/Engine.ts Outdated
Comment thread app/core/Engine/Engine.test.ts
Comment thread app/core/Engine/Engine.test.ts
Comment thread app/core/Engine/Engine.test.ts
Comment thread app/core/Engine/Engine.test.ts Outdated
Comment thread app/core/Engine/Engine.test.ts Outdated
@mcmire mcmire marked this pull request as ready for review October 15, 2025 16:29
@mcmire mcmire requested a review from a team as a code owner October 15, 2025 16:29
@sonarqubecloud

Copy link
Copy Markdown

Comment thread app/core/Engine/Engine.test.ts

@sethkfman sethkfman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM - providing sign-off for platform

@mcmire mcmire added this pull request to the merge queue Oct 15, 2025
Merged via the queue into main with commit 981f4e5 Oct 15, 2025
163 of 166 checks passed
@mcmire mcmire deleted the reenable-remote-feature-flag-controller-persistence branch October 15, 2025 19:12
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 15, 2025
@metamaskbot metamaskbot added the release-7.58.0 Issue or pull request that will be included in release 7.58.0 label Oct 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.58.0 Issue or pull request that will be included in release 7.58.0 size-M team-core-platform Core Platform team

Projects

None yet

4 participants