Skip to content

Stabilize selectEarnTokens and selectBridgeHistoryForAccount (allocating result functions on hot paths) #31496

Description

@MajorLift

Performance audit finding · Severity: Medium · Effort: Small-Medium · Fix risk: Simple · Test safety net: Partial
Owner: Earn / Bridge CODEOWNERS
Files: app/selectors/earnController/earn/index.ts:122, app/selectors/bridgeStatusController/index.ts:14

What is this about?

A per-selector triage of the ten highest-subscription components (51 selector definitions read; ruled-out verdicts in this issue's edit history and #31493) left two selectors standing — both allocate heavily on hot, always-visible paths:

  1. selectEarnTokens (app/selectors/earnController/earn/index.ts:122) — a createDeepEqualSelector that rebuilds a large nested structure (earn tokens × markets × chains via .reduce) on every recompute, and deep-compares its sizable inputs on every check. Consumed by both WalletActions and TradeWalletActions, which sit on the primary action surfaces.
  2. selectBridgeHistoryForAccount (app/selectors/bridgeStatusController/index.ts:14) — a plain createSelector whose result function allocates a fresh object via .reduce per recompute, handing consumers a new reference whenever the upstream recomputes even if the history is unchanged.

Why it matters

Both costs scale with power-user data (token count, bridge history length) and run at the batched-flush cadence for as long as their screens are mounted. These are the confirmed offenders out of 80+ candidate reads — the rest were verified stable/cheap and ruled out.

Scenario

N/A — see Technical Details.

Design

N/A — internal performance change; no UI/design impact.

Technical Details

For selectEarnTokens: narrow the inputs to the slices that actually change, split the mega-aggregation into composed memoized layers so a price tick doesn't rebuild the world, and verify whether the deep-equal input compare is still needed once inputs are narrow (see the reference-stability contract test in the mms-performance skill's mm-selector-cascade). For selectBridgeHistoryForAccount: stabilize the output with a resultEqualityCheck or narrow inputs so recomputes track actual history changes.

Threat Modeling Framework

N/A — performance-only change; behavior is preserved, no new data flow / trust boundary / attack surface.

Acceptance Criteria

  • Both selectors return the same reference across unrelated flushes with unchanged data (assert toBe across two equal-content states).
  • Profiler on a power-user profile: WalletActions/TradeWalletActions and bridge history consumers stop re-rendering on unrelated dispatches.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Sev2-normalAn issue that may lead to users misunderstanding some limited risks they are takingarea-performanceIssues relating to slowness of app, cpu usage, and/or blank screens.ta-needs-engineer-escalationTriage-Agent - Applied when confidence is below thresholdta-triagedteam-mobile-platformMobile Platform team

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    To be fixed

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions