Skip to content

refactor: prevent token fetching being called multiple times#8113

Merged
Prithpal-Sooriya merged 18 commits intomainfrom
cursor/eip712domain-chainid-controller-0711
Mar 6, 2026
Merged

refactor: prevent token fetching being called multiple times#8113
Prithpal-Sooriya merged 18 commits intomainfrom
cursor/eip712domain-chainid-controller-0711

Conversation

@Prithpal-Sooriya
Copy link
Contributor

@Prithpal-Sooriya Prithpal-Sooriya commented Mar 4, 2026

Explanation

  • What is the current state of things and why does it need to change?
    The TokenListController could initiate polling for token lists before its initialize() method had completed, leading to redundant network requests (N+1 problem) on application startup. While a previous fix addressed this at the application's initialization layer, the core race condition existed within the controller itself.
  • What is the solution your changes offer and how does it work?
    This PR implements the race condition protection directly within the TokenListController. It introduces internal state (#initializePromise, #isInitialized) to track the initialization status. The _executePoll method now awaits #waitForInitialization() before fetching, ensuring that token list polling only proceeds after the controller has been fully initialized. The initialize() method is also made idempotent.
  • Are there any changes whose purpose might not obvious to those unfamiliar with the domain?
    The #waitForInitialization() method includes logic to handle cases where initialize() fails. If initialization fails, polling will still proceed (after logging an error) rather than being indefinitely blocked, preventing a complete halt of token list updates due to a transient initialization issue.
  • If your primary goal was to update one package but you found you had to update another one along the way, why did you do so?
    N/A
  • If you had to upgrade a dependency, why did you do so?
    N/A

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Open in Web Open in Cursor 

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
@cursor
Copy link

cursor bot commented Mar 4, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
@Prithpal-Sooriya Prithpal-Sooriya changed the title Eip712domain chainid controller refactor: prevent token fetching being called multiple times Mar 4, 2026
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Prithpal-Sooriya and others added 5 commits March 4, 2026 18:28
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
- Updated the `onNetworkStateChange` callback parameter for clarity.
- Introduced a `resolveMockWaitForInit` function to streamline test initialization.
- Removed the internal `#isInitialized` flag and adjusted initialization error handling to simplify the flow.
- Enhanced test cases to ensure proper polling behavior after initialization.

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
- Simplified the `getMessenger` function to directly return a typed `RootMessenger`.
- Updated action handlers for `StorageService` to use async functions and return appropriate types.
- Streamlined test cases by utilizing the `getMessenger` function for cleaner initialization.
- Removed redundant code and improved clarity in test assertions.

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
@Prithpal-Sooriya Prithpal-Sooriya marked this pull request as ready for review March 4, 2026 19:24
@Prithpal-Sooriya Prithpal-Sooriya requested review from a team as code owners March 4, 2026 19:24
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

/**
* Promise for the in-flight initialization sequence.
*/
#initializePromise?: Promise<void>;
Copy link
Contributor

Choose a reason for hiding this comment

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

oooh nice one

salimtb
salimtb previously approved these changes Mar 5, 2026
@Prithpal-Sooriya
Copy link
Contributor Author

@cursor READ AND FOLLOW THESE MEMORY FILES:

Can you get latest from main and resolve merge conflicts? Thx

@cursor
Copy link

cursor bot commented Mar 5, 2026

Here’s a response you can post on that PR thread:

Done — I pulled the latest from main, resolved the merge conflicts, and pushed the updated branch.
Conflict resolution was in packages/assets-controllers/CHANGELOG.md (kept both Changed and Fixed Unreleased entries, in Keep-a-Changelog order).
I also re-ran TokenListController tests to verify everything still passes after the sync.

Branch updated successfully: cursor/eip712domain-chainid-controller-0711
Latest pushed tip: 223243f3d

Reflection Statement: Existing memory guidance was sufficient; no memory update is required for this task.

Open in Web Open in Cursor 

salimtb and others added 6 commits March 5, 2026 17:55
…8117)

When `isHomepageSectionsV1Enabled` is true, `AccountTrackerController`
now uses all popular EVM networks (via
`NetworkEnablementController:listPopularEvmNetworks`) for balance
refresh on account change and keyring unlock, instead of only the
enabled networks from `NetworkEnablementController` state

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes which networks `AccountTrackerController` refreshes on account
switch/unlock, which can affect balance update coverage and increase
polling load when the flag is enabled. Behavior is gated by
`isHomepageSectionsV1Enabled`, but the non-flag path also now derives
networks from enablement state instead of all configured RPC endpoints.
>
> **Overview**
> **Updates balance refresh network selection in
`AccountTrackerController`.** A new `isHomepageSectionsV1Enabled`
constructor option controls `#getNetworkClientIds`: when enabled it
refreshes across the *popular* EVM chain IDs returned by
`NetworkEnablementController:listPopularEvmNetworks`; otherwise it
refreshes only across EVM networks marked enabled in
`NetworkEnablementController:getState` (using each chain’s default RPC
endpoint).
>
> Tests are extended to mock the new `NetworkEnablementController`
actions and to assert the correct refresh source on keyring unlock, and
the package changelog is updated to document the behavior change.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9e139f3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Add logging capabilities in the `AccountsController`.

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to adding static debug logs around
existing sync flows with no functional behavior changes. Main concern is
potential log noise/perf if enabled in consumers.
> 
> **Overview**
> Adds a new `logger.ts` that exposes a project-scoped logger for
`accounts-controller`.
> 
> In `AccountsController`, emits start/finish log messages around
`updateAccounts` and `KeyringController:stateChange`-driven
synchronization, and documents the addition in the package changelog.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
85da84b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation
Add an optional "refundTo" param for Relay calls.

## References

Fixes MetaMask/metamask-mobile#26990

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes Relay quote request payloads for post-quote flows by
optionally overriding the refund recipient address, which can affect
where funds return on failed Relay transactions. Scoped to an opt-in
field but touches transaction/quote plumbing and external API requests.
> 
> **Overview**
> Adds an optional `refundTo` address that can be set via
`TransactionPayController.setTransactionConfig` and persisted on
`TransactionData`, then propagated into post-quote `QuoteRequest`s.
> 
> Updates the Relay strategy so post-quote quote requests include
`refundTo` in the outbound Relay quote body when provided (otherwise
omitting it), and extends unit tests plus the `CHANGELOG` to cover the
new behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5c2e6b3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
## Explanation
Bumps @metamask/transaction-pay-controller to v ^16.3.0 (includes the
optional `refundTo` param).

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this PR only updates package version metadata and the
`@metamask/transaction-pay-controller` changelog/version, with no
runtime code changes.
> 
> **Overview**
> Updates release metadata by bumping the root `package.json` version to
`851.0.0`.
> 
> Bumps `@metamask/transaction-pay-controller` from `16.2.0` to `16.3.0`
and adds the `16.3.0` section/compare links to `CHANGELOG.md` (noting
the new optional `refundTo` types and dependency bumps included in that
release).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ffea1e4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…er` (#8115)

## Explanation

A similar effort was made in the extension client as it uses a local
version of the `PreferencesController`. These changes are required in
core to have a similar effect on the mobile client. Old methods and
state that were removed:

1. `identities` - Legacy state for accounts.
2. `lostIdentities` - Legacy state for accounts.
3. `selectedAddress` - Legacy state for `selectedAccount`.
4. Removed methods that operate on the above state and also removed
`setSmartAccountOptInForAccounts` as that is deprecated and not used in
either client.

## References

N/A

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Breaking API/state removal (including persisted fields and messenger
event wiring) can cause compile/runtime issues for any consumer still
referencing `identities`/`selectedAddress` or the removed methods.
Changes are otherwise mostly deletions with updated tests and
dependencies.
> 
> **Overview**
> **Breaking cleanup of `PreferencesController` legacy account
preferences.** The controller no longer stores `identities`,
`lostIdentities`, or `selectedAddress`, and removes all related
types/methods (including KeyringController-driven identity syncing and
`setSelectedAddress`).
> 
> Also removes the deprecated `setSmartAccountOptInForAccounts` API,
drops `@metamask/keyring-controller`/`@metamask/controller-utils` (and
`lodash` test usage), updates tests/snapshots accordingly, and records
the breaking change in the package changelog.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
39f043a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Currently when doing an account lookup by address we're doing an O(n)
operation in the clients, this has been improved to O(1) by adding an
address -> account id mapping in state. The `getAccountByAddress`
function now also takes advantage of this new piece of state to improve
its lookup time.

## References

N/A

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes the public controller state shape
(consumer migrations required) and alters address-lookup behavior with
new caching/fallback logic that could surface mismatches if callers use
non-normalized addresses.
> 
> **Overview**
> **Performance improvement:** `AccountsController` state now includes a
derived `accountIdByAddress` (address → account id) map, marked
*non-persisted* and excluded from state logs.
> 
> `getAccountByAddress` is rewritten to use this map (with a lowercase
fallback + debug logging on cache misses), and the map is
constructed/maintained across constructor initialization,
`updateAccounts`, `loadBackup`, and keyring add/remove patches.
> 
> Tests and typings are updated accordingly (including
`utils.constructAccountIdByAddress` tests and downstream state-shape
updates such as `ProfileMetricsController` tests).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
903ebe3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@cursor cursor bot requested review from a team as code owners March 5, 2026 17:56
@Prithpal-Sooriya
Copy link
Contributor Author

https://github.com/cursor READ AND FOLLOW THESE MEMORY FILES:

https://raw.githubusercontent.com/Prithpal-Sooriya/Cloud-Agent-Memory/refs/heads/main/Memory.md
Can you get latest from main and resolve merge conflicts? Thx

@cursor
Copy link

cursor bot commented Mar 6, 2026

Here’s a response you can post on that PR thread:

Done — I pulled the latest from main, resolved the merge conflicts, and pushed the updated branch.
Conflicts were in:

  • package.json (kept repo version from main)
  • packages/assets-controllers/CHANGELOG.md (kept both Changed and Fixed unreleased entries, in correct order)

I also re-ran:

  • yarn changelog:validate
  • yarn workspace @metamask/assets-controllers run jest --no-coverage src/TokenListController.test.ts

Latest pushed commit: 6c9cac3ed

Reflection Statement: Existing memory guidance was sufficient; no memory update is required for this task.

Open in Web Open in Cursor 

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
@Prithpal-Sooriya Prithpal-Sooriya added this pull request to the merge queue Mar 6, 2026
Merged via the queue into main with commit 24941d8 Mar 6, 2026
322 checks passed
@Prithpal-Sooriya Prithpal-Sooriya deleted the cursor/eip712domain-chainid-controller-0711 branch March 6, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Sentry] N+1 API Call

6 participants