Skip to content

fix(assets): memoize selectAllTokensFlat for referential stability - #33753

Merged
Prithpal-Sooriya merged 4 commits into
mainfrom
cursor/jira-issue-changes-b522
Jul 24, 2026
Merged

fix(assets): memoize selectAllTokensFlat for referential stability#33753
Prithpal-Sooriya merged 4 commits into
mainfrom
cursor/jira-issue-changes-b522

Conversation

@cursor

@cursor cursor Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Description

Memoizes selectAllTokensFlat so consumers do not re-render when the flattened token list content is unchanged.

selectAllTokensFlat previously used createSelector and returned a fresh [] for the empty case. Because the result function always builds a new array via reduce/concat, any recomputation produced a new reference even when token contents were identical.

This change:

  1. Switches selectAllTokensFlat to createDeepEqualSelector (already used by sibling token selectors)
  2. Returns a module-level frozen empty array (EMPTY_TOKENS) for the empty case
  3. Adds referential-stability unit tests (same state + equal-content states)

Caller note (out of scope): the only production consumer found is app/util/sentry/tags/index.ts, which reads .length and does not immediately .map/.filter the result.

Changelog

CHANGELOG entry: null

Related issues

Fixes: #31345
Fixes: ASSETS-3721

Manual testing steps

Feature: token list selector stability

  Scenario: wallet token list does not churn on unrelated store updates
    Given a wallet with tokens across one or more networks

    When an unrelated Redux update occurs that does not change token contents
    Then token list components subscribed via selectAllTokensFlat should keep a stable selector result reference

Unit coverage: yarn jest app/selectors/tokensController (23 passed), including referential-stability assertions.

Screenshots/Recordings

N/A — selector-only performance fix; no UI changes.

Before

N/A

After

N/A

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

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.
Open in Web View Automation 

Note

Low Risk
Selector-only memoization with no auth, data, or API behavior changes; production use is limited to Sentry tag .length.

Overview
selectAllTokensFlat no longer returns a new array reference on every recompute when the flattened token list is unchanged, which cuts unnecessary re-renders for Redux subscribers.

The selector is switched from createSelector to createDeepEqualSelector (aligned with other token selectors), and the empty case returns a shared frozen EMPTY_TOKENS instead of a fresh []. Unit tests assert stable references for repeated calls, equal-content state, and empty token maps.

Reviewed by Cursor Bugbot for commit 9d0d7e4. Bugbot is set up for automated code reviews on this repo. Configure here.

cursoragent and others added 2 commits July 24, 2026 08:03
Switch selectAllTokensFlat to createDeepEqualSelector and return a
shared frozen empty array so consumers do not re-render when token
map content is unchanged.

Co-authored-by: prithpal.sooriya <prithpal.sooriya@consensys.net>
…tests

Isolate referential-stability assertions from prior selector cache state.

Co-authored-by: prithpal.sooriya <prithpal.sooriya@consensys.net>
@Prithpal-Sooriya Prithpal-Sooriya added agent-assets area-performance Issues relating to slowness of app, cpu usage, and/or blank screens. No QA Needed Apply this label when your PR does not need any QA effort. no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed team-assets labels Jul 24, 2026 — with Cursor
Cast the frozen empty array as Token[] before Object.freeze so lint:tsc
accepts the shared empty reference.
@github-actions github-actions Bot added the risk:low AI analysis: low risk label Jul 24, 2026
@Prithpal-Sooriya
Prithpal-Sooriya added this pull request to the merge queue Jul 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 24, 2026
@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.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: None (no tests recommended)
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 92%
click to see 🤖 AI reasoning details

E2E Test Selection:
The PR makes two changes:

  1. tokensController.ts: Upgrades selectAllTokensFlat from createSelector to createDeepEqualSelector and introduces a frozen EMPTY_TOKENS constant for stable empty array references. This is a pure memoization/performance optimization — the functional output (token data) is identical, just with better reference stability to prevent unnecessary re-renders.

  2. tokensController.test.ts: Adds unit tests to verify the stable reference behavior of the updated selector.

Impact analysis:

  • selectAllTokensFlat is only consumed by app/util/sentry/tags/index.ts for tracking wallet.token_count in Sentry error tags — no React UI components use it directly (confirmed by grep showing zero .tsx importers).
  • The change is a memoization improvement, not a behavioral change. The selector still returns the same token data.
  • No user-facing flows are affected.
  • No E2E smoke tests cover Sentry tag reporting.

Conclusion: No E2E smoke tags are needed. The change is a low-risk internal optimization with unit test coverage. No performance test tags are warranted either, as this is a selector-level memoization fix that doesn't affect any measured performance scenarios (onboarding, login, launch, swaps, asset loading, etc.).

Performance Test Selection:
The change optimizes memoization of the selectAllTokensFlat selector, which is only used for Sentry tag reporting (wallet.token_count). While better memoization could theoretically reduce unnecessary re-renders, this selector is not used in any UI component and doesn't affect any of the measured performance scenarios (launch, login, onboarding, swaps, asset loading, account list, perps, predictions). No performance test tags are warranted.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@Prithpal-Sooriya
Prithpal-Sooriya added this pull request to the merge queue Jul 24, 2026
Merged via the queue into main with commit b08bff8 Jul 24, 2026
139 of 141 checks passed
@Prithpal-Sooriya
Prithpal-Sooriya deleted the cursor/jira-issue-changes-b522 branch July 24, 2026 16:53
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 24, 2026
@metamask-ci metamask-ci Bot added the release-8.6.0 Issue or pull request that will be included in release 8.6.0 label Jul 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

agent-assets area-performance Issues relating to slowness of app, cpu usage, and/or blank screens. No QA Needed Apply this label when your PR does not need any QA effort. no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed release-8.6.0 Issue or pull request that will be included in release 8.6.0 risk:low AI analysis: low risk size-S team-assets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memoize selectAllTokensFlat array result

2 participants