Skip to content

[pull] main from MetaMask:main#735

Merged
pull[bot] merged 27 commits intoReality2byte:mainfrom
MetaMask:main
May 6, 2026
Merged

[pull] main from MetaMask:main#735
pull[bot] merged 27 commits intoReality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 6, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

jpuri and others added 27 commits May 6, 2026 11:57
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

Metrics functionality fixes for money account transactions

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1341

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**
NA

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I've included tests if applicable
- [X] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Updates transaction-type classification for metrics and activity
filtering, which could affect analytics attribution and visibility of
transactions in activity feeds if mis-tagged. Changes are mostly
additive and covered by new unit tests, but touch shared transaction
metrics utilities.
> 
> **Overview**
> Adds *money account* support to the transaction metrics pipeline by
introducing `MonetizedPrimitive.MoneyAccount`, mapping
`moneyAccountDeposit`/`moneyAccountWithdraw` in `getMonetizedPrimitive`,
and ensuring base `transaction_type` string derivation returns
`money_account_deposit|withdraw` (including when nested).
> 
> Updates MM Pay metrics to treat money account deposit/withdraw as PAY
types and derive `mm_pay_use_case` accordingly, and adjusts the
confirmation UI metrics hook to include
`simulation_sending_assets_total_value` for money account **deposits**
(but not withdraws). Also expands staged A/B test attribution and
activity `PAY_TYPES` filtering to include money account transactions,
with accompanying test coverage.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bac530a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR fixes inconsistencies in Predict position values across the home
screen, market details, and card/list surfaces.

It moves active-position live updates into `usePredictPositions` via
`usePredictLivePositions`, syncs websocket-derived values back into the
shared React Query positions cache, removes duplicate component-level
live subscriptions, scopes live subscriptions to focused screens only,
and fixes market websocket unsubscribe behavior so overlapping token
subscriptions do not break updates on other active screens. It also
updates the positions header to read claimable positions from
`usePredictPositions` instead of Redux/controller state so it stays
aligned with the shared query source.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixed live prediction position values so they stay
updated across the home screen and market details views.

## **Related issues**

Refs: https://consensyssoftware.atlassian.net/browse/PRED-820

## **Manual testing steps**

```gherkin
Feature: live predict positions stay synchronized across screens

  Scenario: home positions continue updating after visiting market details
    Given the user has at least one active Predict position
    And the user is on the Wallet home screen with the Predictions positions section visible
    When the user waits for live position values to update
    And opens one of the active positions into market details
    And waits for live position values to update on market details
    And navigates back to the Wallet home screen
    Then the same home position continues receiving live value updates

  Scenario: only the focused screen keeps market subscriptions active
    Given the user has active Predict positions on the Wallet home screen
    When the user opens a single position in market details
    Then market details only shows live updates for the focused position tokens
    And no unrelated position updates continue streaming from the hidden home screen

  Scenario: claimable positions still render correctly
    Given the user has claimable Predict positions
    When the user opens surfaces that show claimable positions
    Then claimable amounts still render correctly
    And the positions header claim button amount matches the claimable positions list
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because it changes how live price updates propagate
through shared React Query caches and alters WebSocket
subscription/unsubscribe behavior, which could affect update frequency
and data correctness across multiple screens.
> 
> **Overview**
> Ensures Predict **active position** values stay consistent across
home, market details, and card surfaces by adding an opt-in
`livePriceUpdates` flag to `usePredictPositions` that enables
`usePredictLivePositions` to *sync websocket-derived PnL/value updates
back into the shared positions query cache*.
> 
> Removes component-level live position mapping (`PredictPicks`,
`PredictPicksForCard`) in favor of consuming already-updated
`usePredictPositions` data, and scopes live subscriptions to focused
screens while skipping claimable positions.
> 
> Fixes Polymarket market-price WebSocket unsubscribe logic to avoid
unsubscribing token IDs still required by other active subscriptions,
and updates `PredictPositionsHeader` to derive won/claimable positions
from `usePredictPositions` instead of Redux state; tests were
updated/added to cover the new live-update and unsubscribe semantics.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8eda7a8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Updates Card feature user-facing terminology from "cashback" to "mUSD
back" to align with product language.

**Why:** The term "cashback" was used inconsistently and doesn't reflect
the actual reward mechanism (mUSD tokens).

**What changed:** 11 locale strings in the English translation file were
updated. Internal code (variable names, function names, routes, types)
remains unchanged to maintain flexibility if the reward token changes in
the future.

## **Changelog**

CHANGELOG entry: Updated Card feature to display "mUSD back" instead of
"cashback" in all user-facing text

## **Related issues**

Fixes: 

## **Manual testing steps**

```gherkin
Feature: Card mUSD Back terminology

  Scenario: User views MetaMask Card promotional content
    Given user is on a screen showing MetaMask Card benefits

    When user views the card benefits
    Then user sees "mUSD back" terminology instead of "cashback"
    And user sees percentages displayed as "X% mUSD back"

  Scenario: User views Card Home manage options
    Given user has a MetaMask Card linked
    And user is on the Card Home screen

    When user views the manage card options
    Then user sees "mUSD Back" as the rewards option title
    And user sees "Earn X% mUSD back on all spending" as the description

  Scenario: User views mUSD Back withdrawal screen
    Given user has available mUSD back rewards
    And user navigates to the mUSD Back screen

    When user views the screen
    Then user sees "mUSD Back" as the screen title
    And user sees "Available mUSD back" label
    And user sees "No mUSD back available" when balance is zero
```

## **Screenshots/Recordings**

### **Before**

N/A - Text-only changes in locale file. Strings previously displayed
"cashback", "Cashback", "cash back" variants.

### **After**

<img width="350" height="800" alt="image"
src="https://github.com/user-attachments/assets/e8b80600-4eca-4a09-868c-0696276606a9"
/>
<img width="350" height="800" alt="Simulator Screenshot - iPhone 17 Pro
- 2026-05-04 at 15 31 05"
src="https://github.com/user-attachments/assets/ed821df3-5393-4d97-9eef-a14aa4f021bb"
/>
<img width="350" height="800" alt="Simulator Screenshot - iPhone 17 Pro
- 2026-05-04 at 15 31 16"
src="https://github.com/user-attachments/assets/a759d7f2-d73f-46ac-ad0b-b7f1d6881894"
/>


**Updated strings:**
| Location | New Text |
|----------|----------|
| Card promo | "{{percentage}}% mUSD back" |
| Card link bullet | "Up to 3% mUSD back" |
| Benefits section | "1-3% mUSD back" |
| Manage options title | "mUSD Back" |
| Manage options desc | "Earn 1% mUSD back on all spending" |
| Manage options desc (metal) | "Earn 3% mUSD back on all spending" |
| Rewards screen title | "mUSD Back" |
| Available balance label | "Available mUSD back" |
| Empty state | "No mUSD back available" |
| Loading error | "Failed to load mUSD back. Please try again." |
| Funding required | "...before redeeming mUSD back." |

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - N/A - locale string changes only, no runtime impact
- [ ] I've tested with a power user scenario
  - N/A - locale string changes only
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
  - N/A - no new operations added

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk copy-only change: updates English locale strings and a couple
of UI tests to reflect new wording, with no logic, API, or data-flow
changes.
> 
> **Overview**
> Updates MetaMask Card user-facing copy to use **“mUSD back”**
terminology instead of **“cashback”** across card marketing, benefits,
manage options, and the rewards/withdrawal screen via
`locales/languages/en.json`.
> 
> Adjusts related UI tests (`Cashback.test.tsx`,
`MoneyWhatYouGet.test.tsx`) to assert the new strings (e.g., “Available
mUSD”, “1-3% mUSD back”).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
663913a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…29598)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

migrate the wallet **AccountSelector** screen
(`app/components/Views/AccountSelector`) to
`@metamask/design-system-react-native` (BottomSheet, Button, Text).

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1685

## **Manual testing steps**

- Open the "Account List" and check that there aren't any UI regressions

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/460303fc-20e0-4eb6-83be-d32c698ec6ef

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because this refactors a user-facing modal/sheet UI,
removes the existing reanimated slide/backdrop behavior, and changes
safe-area/keyboard offset handling, which could introduce visual
regressions or layout issues.
> 
> **Overview**
> Migrates `AccountSelector` UI from custom `StyleSheet`/legacy
component-library `Button`+`Text` and reanimated backdrop/slide-in
animation to design-system `Box`/`Button`/`Text` with Tailwind classes,
deleting `AccountSelector.styles.ts`.
> 
> Simplifies close behavior to a direct `navigation.goBack()` and
adjusts `KeyboardAvoidingView` positioning using
`useSafeAreaFrame`/insets; also changes Sentry tracing to start in
`useLayoutEffect` and end after paint instead of tying trace completion
to the removed animation callback.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4b27c58. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description**


Adds Sentry performance traces for token-overview advanced chart
visibility (time from series change until skeleton clears), with
separate trace types for dashboards to distinguish initial load / asset
or currency changes from time-range-only updates.
Also fixes a bug in metrics consent detection during early Sentry
initialization.

## Changes

### Advanced Chart Performance Tracing
**AdvancedChart component:**
- Added optional `onSkeletonHidden` callback that fires once when
loading/layout settles and the chart is ready
- Guarded by refs to reset when series key or HTML content changes
**PriceAdvanced component:**
- Starts `trace()` when `ohlcvSeriesKey` changes
- Ends trace via `endTrace()` when:
  - Skeleton hides (chart ready)
  - Chart error occurs
  - Trace is superseded by a newer series
  - Falls back to legacy chart
- `getAdvancedChartVisibilityTraceRequest()` selects appropriate
`TraceName` and `TraceOperation` based on what changed:
- Same asset + currency with only range change →
`TokenOverviewAdvancedChartTimeRangeVisible` trace
  - Otherwise → `TokenOverviewAdvancedChartInitialVisible` trace
**trace.ts:**
- Added new `TraceName` values:
- `TokenOverviewAdvancedChartInitialVisible` - for initial load or
asset/currency changes
- `TokenOverviewAdvancedChartTimeRangeVisible` - for time range selector
changes only
- Added new `TraceOperation` values:
- `token_overview.advanced_chart` - initial load or asset/currency
change
  - `token_overview.advanced_chart_time_range` - time range change only


### Metrics Consent Fix

**Problem:**
The original implementation attempted to read from
`analytics.isEnabled()` during Sentry initialization in `index.js:45`.
However, this occurs before Engine and Redux are initialized, causing
`analytics.isEnabled()` to incorrectly return `false` even for opted-in
users (it checks in-memory state that doesn't exist yet).
**Solution:**
`hasMetricsConsent()` now reads directly from AnalyticsController's
persisted state in FilesystemStorage (`persist:AnalyticsController`)
before falling back to the legacy `METRICS_OPT_IN` storage key. This
approach:
- Works before Engine/Redux initialization (FilesystemStorage is always
available)
- Reads the actual persisted opt-in value from disk (`{"optedIn":
true/false}`)
- Follows the same pattern as `ControllerStorage.getAllPersistedState()`
in `persistConfig/index.ts`
- Avoids dependency on deprecated `METRICS_OPT_IN` as the primary source
**MetaMetricsAndDataCollectionSection:**
- Calls `updateCachedConsent()` when user toggles analytics
participation
- Ensures in-memory consent cache stays synchronized with
AnalyticsController state


## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Adds tracing for advanced charts

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3129

## **Manual testing steps**

```gherkin
Feature: Advanced Chart Performance Tracing

  Scenario: user opens token details and chart loads successfully
    Given the user is on the home screen

    When user taps on a token to open token details
    Then a single "Starting sampled root span" log appears for "Token Overview Advanced Chart Initial Visible"
    And a single "Finishing" log appears for the same span ID
    And no duplicate "Token Overview" traces appear

  Scenario: user navigates back before chart finishes loading
    Given the user is on token details with the chart still loading (skeleton visible)

    When user quickly navigates back to the home screen
    Then a "Finishing" log appears for the "Token Overview Advanced Chart Initial Visible" span
    And the finish log appears after the navigation back (after "[UserInteraction]" log)

  Scenario: user navigates back after chart has loaded
    Given the user is on token details and the chart has fully loaded

    When user navigates back to the home screen
    Then no "Token Overview" trace logs appear during navigation back

  Scenario: user changes time range on the chart
    Given the user is on token details with the chart loaded on 1D range

    When user taps on the 1W time range selector
    Then a "Finishing" log appears for the previous "Token Overview Advanced Chart Initial Visible" span
    And a new "Starting sampled root span" log appears for "Token Overview Advanced Chart Time Range Visible"
    And a "Finishing" log appears for the new span when the chart reloads
```

```
How to verify locally:
1. Enable Sentry trace logging by filtering console output for "Tracing"
2. Navigate to a token's details screen
3. Confirm you see exactly ONE "Starting sampled root span" for
   "Token Overview Advanced Chart Initial Visible" followed by ONE
   "Finishing" log for the same span ID
4. Navigate back — confirm no additional trace start/finish for that span
5. Re-enter the token, change time range — confirm the old trace ends
   with superseded and a new "Time Range Visible" trace starts and finishes
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new Sentry tracing lifecycle hooks around the token overview
advanced chart and changes how metrics consent is determined during
early app startup, which could affect whether performance data is
captured or suppressed.
> 
> **Overview**
> Adds Sentry performance traces for token overview *advanced chart
visibility*, starting a trace on `ohlcvSeriesKey` changes and ending it
when the chart skeleton disappears, errors, is superseded by a newer
request, falls back to the legacy chart, or unmounts (including
`assetId` and truncated error details).
> 
> Extends `AdvancedChart` with an `onSkeletonHidden` callback that fires
once when the native skeleton overlay is removed (resetting on
series/HTML reload), and adds new `TraceName`/`TraceOperation` constants
to distinguish *initial/asset changes* vs *time-range-only* updates.
> 
> Fixes early Sentry init consent detection by updating
`hasMetricsConsent()` to read `persist:AnalyticsController` from
`redux-persist-filesystem-storage` (fallback to legacy
`METRICS_OPT_IN`), and keeps the in-memory consent cache in sync via
`updateCachedConsent()` from settings; tests were updated/added for
these behaviors.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7ec6bbd. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…gn system (#29697)

## **Description**

Migrates the `RevealSRP` and `EditMultichainAccountName` multichain
account sheets from component-library primitives to
`@metamask/design-system-react-native`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs:
[MUL-1687](https://consensyssoftware.atlassian.net/browse/MUL-1687)

## **Manual testing steps**

```gherkin
Feature: Multichain account sheets (design system)

  Scenario: Reveal SRP intro screen
    Given the user opens the Reveal SRP flow for a multichain account
    When they view the intro sheet
    Then the header, description, primary "Get started", and secondary "Learn more" actions render and match prior behavior
    When they tap the back control
    Then navigation returns to the previous screen

  Scenario: Edit multichain account group name
    Given the user opens Edit multichain account name for an account group
    When they change the name and tap Save
    Then the name is persisted and the screen closes
    When they tap the back control without saving
    Then navigation returns to the previous screen
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/a4faecee-8e04-4e5a-a3b8-194933d74fa2

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

## **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.

<!-- Generated with the help of the pr-description AI skill -->


[MUL-1687]:
https://consensyssoftware.atlassian.net/browse/MUL-1687?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily a UI refactor, but it touches the SRP reveal entry flow and
navigation controls, so regressions could impact a security-sensitive
user journey (layout/safe-area/back/save behaviors across iOS/Android).
> 
> **Overview**
> Migrates the `RevealSRP` and `EditMultichainAccountName` sheets from
component-library primitives and custom `StyleSheet` files to
`@metamask/design-system-react-native` components with Tailwind-based
styling, including Android-specific status bar inset handling.
> 
> Adds a dedicated back-button test id
(`EditAccountNameIds.BACK_BUTTON`) and updates/expands tests to assert
navigation via that control, cover a missing-`accountGroup` fallback
header, and exercise Android rendering paths (status bar height
present/absent).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e74bb6c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
This PR migrates the WC performance test to the new framework.
`skip-e2e` has been applied since all changes are related to Appium.

### Framework changes:
- Allows for lazy fetch on `getElementByNameiOS`

iOS Run:
https://app-automate.browserstack.com/dashboard/v2/builds/8c27168975bc74376449c6f9fa82158c549c8f41/sessions/195066d41131f7143a0b1989f5e0b710d39999f4
(Quality-Gates failed)
Android Run:
https://app-automate.browserstack.com/dashboard/v2/builds/91d934900ddd178f4d255db708e8a14ac3153aed/sessions/05e33619e97368cfd712ec14a41c19033b01ce45

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1725

## **Manual testing steps**
N/A

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
N/A
<!-- [screenshots/recordings] -->

### **After**
N/A
<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because it rewires a cross-context (native/web)
performance test and adds new iOS/Android selectors and retry logic,
which can introduce flaky behavior if locators or timing differ across
devices.
> 
> **Overview**
> Migrates the Uniswap WalletConnect performance interaction test from
the legacy JS/WebdriverIO setup to the new Playwright-based fixture
(`uniswap-interaction.spec.js` replaced with
`uniswap-interaction.spec.ts`), updating flows to use
`loginToAppPlaywright`, `native-browser.flow`, and
`PlaywrightContextHelpers`.
> 
> Adds a new `UniswapDapp` page object to encapsulate Uniswap connect +
WalletConnect + MetaMask deep link interactions and “Uniswap displayed”
checks with platform-specific selectors and retry/wait helpers.
> 
> Extends test/framework selectors by adding an optional `lazy` mode to
`PlaywrightMatchers.getElementByNameiOS`, and updates
`DappConnectionModal` selectors/behavior for iOS (edit accounts) plus a
small tap/refactor in network selection.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cdc8842. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Wires the QR scan errors from PR 1 into pairing and signing flows. QR
scan failures now surface through the hardware wallet bottom sheet with
retry support, signing confirmations can reopen the scanner from the
error CTA, and replacement transaction gas params are normalized through
the shared helper.

This is PR 2 of 3 and is stacked on #29388.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Improved retry behavior when QR hardware wallet signing
scans fail

## **Related issues**

Refs: MUL-1665

## **Manual testing steps**

```gherkin
Feature: QR hardware signing retry

  Scenario: user retries a failed QR signing scan
    Given the user is signing with a QR-based hardware wallet
    When the user scans an invalid QR code
    Then the hardware wallet bottom sheet displays the QR scan error
    When the user taps Try again
    Then the QR scanner reopens for another signing scan
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because it changes the hardware-wallet bottom-sheet
recovery flow and retry behavior for QR signing, which could affect
signing UX/state transitions. Adds new analytics properties for QR scan
failures; incorrect classification could skew metrics but not funds.
> 
> **Overview**
> **Improves QR hardware wallet scan-failure recovery during
pairing/signing.** QR scan errors now route through the hardware wallet
bottom sheet with a dedicated retry path that can reopen the QR scanner
for signing retries, plus a provider-level
`setQrScanRetryHandler`/`onRetryQrScan` mechanism to coordinate retries
outside provider-managed flows.
> 
> **Adds QR scan error-specific UI + analytics.** `ErrorContent` treats
QR scan errors specially (custom title, *Try again* + *Learn more*, no
generic icon) and supports `OPEN_SETTINGS` recovery;
`useHardwareWalletAnalytics` now attaches QR scan metadata
(`error_category`, `is_ur_format`, optional `received_ur_type`) to
recovery viewed/CTA/success events.
> 
> Includes supporting refactors and tests (QR adapter no longer emits
`AppOpened` on `ensureDeviceReady`, new `isQRHardwareScanError`,
`useQrScanErrorForwarding`, `useIsConfirmationFromQrAccount`, and
`useQrConfirm`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
31443d4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ecessary cp-7.76.0 (#29787)

## **Description**

### Bug
When navigating from the Swap/Bridge "Select token" screen to Token
Details via the (i) icon, security info (badge, SecurityTrustEntryCard,
warning banners) is missing.

### Root Cause
The Bridge `/getTokens/popular` API returns security data in a different
shape `({ type: "Verified" })` than what Token Details expects `({
resultType: "Verified", features: [...], ... })`. When navigating, the
entire token object — including this wrong-shaped securityData — is
spread into route params. `useTokenSecurityData` sees it as `truthy`
prefetched data, skips its own API call, and the UI reads resultType /
features → undefined → nothing renders.

### Fix
Added a runtime type guard in `useTokenSecurityData` that validates
`prefetchedData` has the required `resultType` (string) and features
(array) before trusting it. If the shape is invalid, the hook falls
through to `fetchTokenAssets()` and gets the full, correctly-shaped
data.



## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixed security badges and trust info now display
correctly on Token Details when navigating from the Swap token selector.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/1dbc3bbd-293d-4b90-a473-8ce505b8c718


### **After**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/61466686-09a6-45db-8961-7fd5d4690ff8


## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: adds a small runtime type guard and a focused test to ensure
`useTokenSecurityData` falls back to fetching when prefetched security
data is malformed.
> 
> **Overview**
> Fixes Token Details security UI missing when navigating from
Swap/Bridge by **validating `prefetchedData` at runtime** in
`useTokenSecurityData` (requires `resultType` string and `features`
array) and treating invalid shapes as absent so the hook fetches via
`fetchTokenAssets`.
> 
> Adds a regression test covering the Bridge-style wrong-shaped data to
ensure the hook ignores it and fetches correct security data instead.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2e9c4c8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…9745)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
e2e docu updated to include exceptions for release branches
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only change that clarifies CI behavior for
release-branch PRs; no runtime or build logic is modified.
> 
> **Overview**
> Updates `E2E_DECISION_TREE.md` to rename **AI test selection** to
**Smart AI E2E test selection** and document *release-branch*
exceptions.
> 
> Specifies that release-branch PRs do not get the
`pr-not-ready-for-e2e` label and skip smart selection in favor of
running all required E2E suites when changes are non-ignorable.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
063f4a1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Migrate "Backup & sync" UI components to
`@metamask/design-system-react-native`, specifically `Text`, `Icon`, and
`BottomSheet`.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1684

## **Manual testing steps**

- Onboarding
  - Go through the onboarding flow
  - Before finishing, disable "Backup & Sync"
  - Check that there aren't any UI regressions
- Settings
  - Disable "Backup & Sync" and enable it back
  - Check that there aren't any UI regressions

## **Screenshots/Recordings**

### Onboarding

<img width="300" alt="Screenshot 2026-05-04 at 2 08 04 PM"
src="https://github.com/user-attachments/assets/e6d5dd7c-7d96-4cd9-867d-c677cf314fe5"
/> <img width="300" alt="Screenshot 2026-05-04 at 2 08 13 PM"
src="https://github.com/user-attachments/assets/0a56a630-f1db-4d08-96ab-a0459026aebc"
/>

### Settings

<img width="300" alt="Screenshot 2026-05-04 at 2 21 33 PM"
src="https://github.com/user-attachments/assets/a9faa395-8309-4ece-a73a-96cf3d737257"
/> <img width="300" alt="Screenshot 2026-05-04 at 2 21 40 PM"
src="https://github.com/user-attachments/assets/f8e33356-9402-464d-9262-f3809db383f4"
/>

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily a UI refactor, but it changes shared component imports/enums
and adds a global Jest mock for the design-system `BottomSheet`, which
could affect rendering/tests across the suite.
> 
> **Overview**
> Migrates the Backup & Sync settings/onboarding UI to
`@metamask/design-system-react-native` primitives (`Text`, `Icon`,
`BottomSheet`), updating variant/color enum values (e.g., `HeadingSm`,
`TextAlternative`, `SuccessDefault`).
> 
> Updates the shared notification modal (`Notification/Modal`) to use
design-system `Text`/`Icon` and adjusts typography variants accordingly.
> 
> Improves test stability by adding a global Jest mock for the
design-system `BottomSheet` in `testSetup.js` (synchronous open/close
callbacks) and stubbing `QuickBuyBottomSheet` in `TraderPositionView`
tests to avoid unintended mounts/selector dependencies.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ad2f26b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

Renders the existing `WhatsHappeningSection` at the top of the Explore
page's Now tab (V2 layout), gated behind the FF.

<img height="800" alt="Simulator Screenshot - iPhone 17 Pro - 2026-05-06
at 12 09 27"
src="https://github.com/user-attachments/assets/328bdffa-59d5-4111-a5d4-923449171c00"
/>


## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: adds a feature-flagged UI section to the top of Explore’s
Now tab plus a small ref-based refresh hook; no auth, persistence, or
critical transaction logic changes.
> 
> **Overview**
> Renders `WhatsHappeningSection` at the top of
`TrendingView/tabs/NowTab`, gated by `selectWhatsHappeningEnabled`, and
forwards a `SectionRefreshHandle` ref so the section can be refreshed
when the tab’s `refresh.trigger` changes.
> 
> Adds a focused unit test (`NowTab.test.tsx`) that verifies **flag-on
renders**, **flag-off does not mount**, and that a **ref is passed** to
support pull-to-refresh without pulling in the section’s heavy
dependencies.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d3b9432. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Joao Santos <jrmsantos15@gmail.com>
Co-authored-by: João Santos <joaosantos15@users.noreply.github.com>
## **Description**

Money Home's `MoneyMetaMaskCard` upsell currently shows two card rows
(Virtual at 1% cashback, Metal at 3% cashback) to every user. The Metal
card is only available to US users today, so this PR adds geolocation
gating: the Metal card row is only rendered when the Ramps-detected
geolocation positively resolves to `US`. Loading, unknown (`undefined`),
and non-US country codes all fail closed and render only the Virtual
card row.

While here, both "Get now" buttons now route through the canonical
`metamask://card-onboarding` deeplink (via `handleDeeplink`) instead of
`navigation.navigate(Routes.CARD.ROOT)`, matching the upsell entry point
used elsewhere (e.g. `EarnRewardsPreview`).

`MoneyMetaMaskCard` accepts a new `showMetalCard` prop (default `false`)
so the view layer keeps ownership of the geolocation read; the component
stays a dumb presentational primitive. `MoneyHomeView` reads
`getDetectedGeolocation` from `app/reducers/fiatOrders` and normalizes
it the same way `useMusdConversionEligibility` does
(`?.toUpperCase().split('-')[0] === 'US'`).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MUSD-739

## **Manual testing steps**

```gherkin
Feature: Metal card geolocation gating in Money Home

  Scenario: US user sees both Virtual and Metal card rows
    Given the user's Ramps geolocation has resolved to "US"
    When the user opens the Money home screen and scrolls to the MetaMask Card section in upsell mode
    Then the Virtual card row (1% cashback) is visible
    And the Metal card row (3% cashback) is visible

  Scenario: Non-US user sees only the Virtual card row
    Given the user's Ramps geolocation has resolved to "GB" (or any non-US code)
    When the user opens the Money home screen and scrolls to the MetaMask Card section in upsell mode
    Then the Virtual card row (1% cashback) is visible
    And the Metal card row is not rendered

  Scenario: Unknown / loading geolocation hides the Metal card row
    Given the Ramps geolocation has not yet resolved (undefined)
    When the user opens the Money home screen and scrolls to the MetaMask Card section in upsell mode
    Then only the Virtual card row is visible

  Scenario: Get now button opens the card-onboarding deeplink
    Given the MetaMask Card upsell section is visible
    When the user taps the "Get now" button on either the Virtual or Metal card row
    Then the metamask://card-onboarding deeplink is dispatched
```

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI change that conditionally hides the Metal card upsell row
based on the existing ramps geolocation selector; main risk is incorrect
geolocation normalization causing the Metal row to appear/disappear
unexpectedly.
> 
> **Overview**
> Money Home now **hides the Metal card upsell row outside the US** by
reading `getDetectedGeolocation` and passing a new `showMetalCard` flag
into `MoneyMetaMaskCard` (US and US sub-regions like `US-CA` only;
`undefined`/non-US fail closed).
> 
> `MoneyMetaMaskCard` is updated to accept `showMetalCard` (default
`false`) and only render the Metal row when enabled, with tests expanded
to cover the new gating and MoneyHomeView integration.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
616aab6. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…29502)

## **Description**

Keep the `MoneyKeyring` builder registered in the `KeyringController` so
that if the feature flag gets enabled dynamically, the controller and
keyring will get created dynamically too!

- The money keyring state is never removed/cleared
- When the flag goes from ON -> OFF and there was a Money account, it
gets cleared
- When the flag goes from OFF -> ON and there was no Money account, it
gets created automatically

## **Changelog**

CHANGELOG entry: N/A

## **Related issues**

Fixes: TODO

## **Manual testing steps**

Make sure to enable this in your `.js.env`:
```env
DEBUG=metamask:money-account-controller
```

Here's a patch to get some logs:
```diff
diff --git a/app/core/Engine/controllers/money-account-controller-init.ts b/app/core/Engine/controllers/money-account-controller-init.ts
index c493253..b5d5f4b761 100644
--- a/app/core/Engine/controllers/money-account-controller-init.ts
+++ b/app/core/Engine/controllers/money-account-controller-init.ts
@@ -39,12 +39,14 @@ export const moneyAccountControllerInit: MessengerClientInitFunction<
           const { isUnlocked } = initMessenger.call(
             'KeyringController:getState',
           );
+            console.log('testing: Initializing money account due to FF on');
           // Check for the `KeyringController` to be unlocked, otherwise we won't be able
           // to create the Money keyring if it doesn't exist yet!
           if (isUnlocked) {
             // This call is idempotent, so it is safe to call even if the
             // controller is already initialized.
             await controller.init();
+          console.log('testing: Clearing money account state due to FF off');
           }
         } else if (!isEnabled && hasMoneyAccount) {
           // Clear state if we had a previous Money account and FF is off.
diff --git a/app/core/Engine/controllers/remote-feature-flag-controller-init.ts b/app/core/Engine/controllers/remote-feature-flag-controller-init.ts
index 2ab54cc..2ac6fb26d9 100644
--- a/app/core/Engine/controllers/remote-feature-flag-controller-init.ts
+++ b/app/core/Engine/controllers/remote-feature-flag-controller-init.ts
@@ -45,9 +45,7 @@ export const remoteFeatureFlagControllerInit: MessengerClientInitFunction<
         distribution: getFeatureFlagAppDistribution(),
       },
     }),
-    fetchInterval: __DEV__
-      ? 1000
-      : AppConstants.FEATURE_FLAGS_API.DEFAULT_FETCH_INTERVAL,
+    fetchInterval: 1000,
   });

   if (disabled) {
@@ -61,6 +59,15 @@ export const remoteFeatureFlagControllerInit: MessengerClientInitFunction<
         Logger.log('Feature flags updated');
       })
       .catch((error) => Logger.log('Feature flags update failed: ', error));
+    setInterval(() =>
+      controller
+        .updateRemoteFeatureFlags()
+        .then(() => {
+          Logger.log('Feature flags updated (interval)');
+        })
+        .catch((error) => Logger.log('Feature flags update failed: ', error))
+      , 10 * 1000
+    );
   }

   return {
diff --git a/app/lib/Money/feature-flags.ts b/app/lib/Money/feature-flags.ts
index 736ed10..464497e8dc 100644
--- a/app/lib/Money/feature-flags.ts
+++ b/app/lib/Money/feature-flags.ts
@@ -16,6 +16,7 @@ export function isMoneyAccountEnabled(
   const localFlag = process.env.MM_MONEY_ENABLE_MONEY_ACCOUNT === 'true';
   const remoteFlag =
     remoteFeatureFlags?.moneyEnableMoneyAccount as VersionGatedFeatureFlag;
+  console.log('testing: Remote Flag is:', remoteFlag, 'Local Flag is:', localFlag);

   return validatedVersionGatedFeatureFlag(remoteFlag) ?? localFlag;
 }
```

```gherkin
Feature: Money account feature flag handling (ON)

  Scenario: flag is ON
    Given the flag was OFF

    When the flag gets updated
    Then the Money account gets created automatically
    
Feature: Money account feature flag handling (OFF)

  Scenario: flag is OFF
    Given the flag was ON

    When the flag gets updated
    Then the Money account gets cleared automatically
```

If you enabled those extra logs (with the patch above), toggling ON/OFF
should give you something like this:

```log
$ yarn watch |& grep -E "metamask:money-account-controller|testing:"
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KQFS1XQNH0399NJM7EZEFWP7 - primary) account is: 0xad9d9f06da37139dd54fd48fda02cae244a590cb (b3961609-ef94-42ea-90fc-93149e185d56) +0ms
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": false, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Clearing money account state due to FF off
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Initializing money account due to FF on
 (NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KQFS1XQNH0399NJM7EZEFWP7) account created: 0xad9d9f06da37139dd54fd48fda02cae244a590cb (b3961609-ef94-42ea-90fc-93149e185d56) +26s
 (NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KQFS1XQNH0399NJM7EZEFWP7 - primary) account is: 0xad9d9f06da37139dd54fd48fda02cae244a590cb (b3961609-ef94-42ea-90fc-93149e185d56) +0ms
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": false, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Clearing money account state due to FF off
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": false, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": false, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Initializing money account due to FF on
 (NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KQFS1XQNH0399NJM7EZEFWP7) account created: 0xad9d9f06da37139dd54fd48fda02cae244a590cb (b3961609-ef94-42ea-90fc-93149e185d56) +1m
 (NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KQFS1XQNH0399NJM7EZEFWP7 - primary) account is: 0xad9d9f06da37139dd54fd48fda02cae244a590cb (b3961609-ef94-42ea-90fc-93149e185d56) +0ms
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
 (NOBRIDGE) LOG  testing: Remote Flag is: {"enabled": true, "minimumVersion": "0.0.0"} Local Flag is: false
```

- We only re-init if there was no Money account AND the flag is ON
- We only clear if there was a Money account AND the flag is OFF
- We only do those steps once (not clearing twice, not calling `init`
twice)

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches account/keyring initialization and wallet reset flows, so
mistakes could create or wipe Money account state unexpectedly when
feature flags change. Changes are scoped and covered by targeted unit
tests, but still impact core account plumbing.
> 
> **Overview**
> **Money accounts are now managed dynamically based on remote
feature-flag updates.** `MoneyAccountController` subscribes to
`RemoteFeatureFlagController:stateChange` during init and will `init()`
when the flag turns on (only if the keyring is unlocked and no money
accounts exist), or `clearState()` when the flag turns off (only if
money accounts exist), with error logging on failures.
> 
> **Keyring handling is made resilient to flag timing.** The
`MoneyKeyring` builder is now always registered in
`keyringControllerInit` so vault deserialization can recognize the type
even if the Money feature flag is disabled at that moment.
> 
> **State clearing responsibilities are centralized.**
`Engine.resetState` now clears `MoneyAccountController` state, while
`AccountTreeInitService.clearState` no longer clears money accounts.
Tests were updated/added to assert these behaviors and the new init
messenger wiring (`getMoneyAccountControllerInitMessenger`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9d427ea. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Two small polish items in the MetaMask Card section on Money Home.

- **MUSD-746** wraps the "1% cashback" / "3% cashback" labels on the
Virtual and Metal card rows in the MMDS `Tag` (severity = success) so
they read as pills. This matches the APY tag pattern in the Money Home
header and gives the labels stronger emphasis.
- **MUSD-740** rebalances the `link` variant of `MoneyMetaMaskCard`. The
card image is enlarged from `104×66` to `152×96` (a new `linkCardImage`
style), and the row gains `BoxAlignItems.Center` so the checklist sits
vertically centred next to the larger image. The upsell variant rows are
unchanged.

No copy, analytics, or routing changes.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
- https://consensyssoftware.atlassian.net/browse/MUSD-740
- https://consensyssoftware.atlassian.net/browse/MUSD-746

## **Manual testing steps**

```gherkin
Feature: MetaMask Card section polish

  Scenario: user views the MetaMask Card section in upsell mode
    Given the Money Account feature flag is enabled and the user has no card
    When the user scrolls to the "MetaMask Card" section on Money Home
    Then "1% cashback" and "3% cashback" render as green pill tags
    And both pills sit immediately below the card name
    And the existing "Get now" buttons are unchanged

  Scenario: user views the MetaMask Card section in link mode
    Given the user is in the link-card flow
    When the "Link MetaMask Card" card is rendered
    Then the card image is visibly larger than before
    And the two checklist bullets ("Up to 3% cash back", "Up to N% APY") are vertically centred next to the image
    And the "Link card" button position is unchanged
```

## **Screenshots/Recordings**

<img width="1206" height="2622" alt="image"
src="https://github.com/user-attachments/assets/0f954d2e-5b0c-4417-9ac0-5bcef3d452c3"
/>


## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only changes: swaps cashback labels to MMDS `Tag` pills
and tweaks link-mode layout/image sizing without touching navigation,
analytics, or data logic.
> 
> **Overview**
> Updates the Money Home `MoneyMetaMaskCard` UI polish.
> 
> Cashback labels in the upsell rows are now rendered as MMDS `Tag`
pills (success severity) instead of plain green text. Link mode layout
is adjusted by enlarging the card image via a new `linkCardImage` style
and vertically centering the image/bullet row.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8b2297f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
https://consensyssoftware.atlassian.net/browse/RWDS-1264
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-05-06 at 11 15 48"
src="https://github.com/user-attachments/assets/8ed005e3-a515-4a41-872d-05bf1d489a0d"
/>


## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI formatting change limited to `OndoActivityRow` display
logic, with added test coverage; no business logic, persistence, or
security-sensitive code impacted.
> 
> **Overview**
> Updates Ondo campaign activity rows so **`REBALANCE` entries display
USD amounts without the leading `+` sign**, while
deposits/withdrawals/outflows continue to use signed USD formatting.
> 
> Adds a small helper (`formatActivityUsd`) to special-case rebalance
values (returning `—` for `null`/non-numeric inputs) and extends the
unit test suite to assert the new rebalance formatting behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0ea01cd. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Two adjustments to the Money Home Earnings section.

- **MUSD-737** replaces the `Lifetime earnings` and `Projected earnings`
metrics on the Earnings card with forward-looking `Est. monthly
earnings` and `Est. yearly earnings`. Values are computed from the
user's Money Account balance and the current vault APY using the
existing `calculateProjectedEarnings` utility (years = 1/12 and 1
respectively). The previous `+green` color treatment on the lifetime
value is dropped — projections aren't past gains.
- **MUSD-738** drops the `condensed` collapse path on
`MoneyPotentialEarnings` so up to five convertible-token rows always
render when the user has eligible tokens, regardless of Money Account
transaction count. The `Earn on your crypto` single-CTA card no longer
appears mid-state. `MoneyMusdTokenRow` and `MoneyActivityList` are
unchanged.

Locale strings: the `money.earnings.lifetime` /
`money.earnings.projected` keys are renamed to
`money.earnings.estimated_monthly` / `money.earnings.estimated_yearly`
across all language files. The `money.earnings_tooltip.lifetime_*` /
`projected_*` keys are renamed to `monthly_*` / `yearly_*` so the
info-sheet copy mirrors the new section framing.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
- https://consensyssoftware.atlassian.net/browse/MUSD-737
- https://consensyssoftware.atlassian.net/browse/MUSD-738

## **Manual testing steps**

```gherkin
Feature: Money Home Earnings section refresh

  Scenario: user with a non-zero Money Account balance opens Money Home
    Given the Money Account feature flag is enabled
    And the user has a Money Account balance greater than $0
    When the user navigates to Money Home
    Then the Earnings card shows "Est. monthly earnings" and "Est. yearly earnings"
    And both values reflect balance × APY scaled to the relevant period
    And no "Lifetime earnings" or "Projected earnings" labels are visible

  Scenario: user with at least one Money Account transaction sees convertible tokens
    Given the user has Money Account transaction count greater than 0
    And the user has at least one convertible token with a positive fiat balance
    When the user scrolls to the Earnings area on Money Home
    Then up to five convertible-token rows are rendered
    And no "Earn on your crypto" / "View potential earnings" collapsed card is shown

  Scenario: user opens the Earnings info sheet
    Given Money Home is open
    When the user taps the info icon next to the Earnings section title
    Then the info sheet shows "Est. monthly earnings" and "Est. yearly earnings" headings
    And the body copy describes monthly and yearly projections
```

## **Screenshots/Recordings**

### **Before**

<!-- to be added -->

### **After**

<!-- to be added -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI/UX change that adjusts earnings calculations/labels and
removes a display mode; main risk is incorrect projections or
regressions in Money Home navigation/press handlers.
> 
> **Overview**
> Updates Money Home’s Earnings card to show **estimated monthly** and
**annual** earnings instead of lifetime/projected values, computing both
from current balance and APY (with additional guards for invalid/zero
inputs).
> 
> Removes `MoneyPotentialEarnings` “condensed” mode so up to five
convertible token rows always render when eligible tokens exist, and
simplifies the earnings info sheet copy/strings to a single “estimated
earnings” message. Tests were updated/expanded to cover the new metrics
and key navigation/press behaviors (conversion, token row press,
learn-more, and error logging).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
175f4cd. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…way to leave (#29763)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
Fixes a regression introduced in
#29454 where Earn
redirects to the activity view for successful pooled-staking or lending
deposits would leave users stranded without a way to exit.

This comes as part of a larger change to replace activity with Money in
the main navbar.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixes a regression where Earn redirects to the activity
view for successful pooled-staking or lending deposits would leave users
stranded without a way to exit.

## **Related issues**

Fixes: [MUSD-772: Fix deposit redirects for Earn flows leaving users
stranded on Activity
page](https://consensyssoftware.atlassian.net/browse/MUSD-772)

## **Manual testing steps**

```gherkin
Feature: Activity screen navigation when Money Home is enabled

  Scenario: user accesses activity list from Money Home
    Given the Money Home feature flag is enabled
    And user is on the pooled-staking or lending deposit confirmation screen

    When confirms their transaction
    Then user is redirected to the activty with
    And a back button is displayed in the Activity screen header
    And user can navigate back to Wallet Home without being stranded
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/85bb5c72-978e-4e63-86b4-e35bb35e83da

### **After**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/5752d2aa-7f8b-4b32-bec8-b58b5eb2351b

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes back-navigation behavior (including Android hardware back
handling) for `ActivityView` when the Money Home feature flag is
enabled, which could affect user navigation flows if routing assumptions
are wrong. Scope is limited and covered by new unit tests around back
button and hardware back handling.
> 
> **Overview**
> Fixes a regression where users redirected into `ActivityView` (e.g.,
after successful Earn deposits) could get stuck without a reliable way
to exit when the Money Home experience is enabled.
> 
> When `selectMoneyHomeScreenEnabledFlag` is on, `ActivityView` now
always shows a back button and routes both header back and Android
`hardwareBackPress` to `Routes.HOME_TABS` (instead of returning to the
prior stack/confirmation screen). The wallet’s Activity entrypoint no
longer passes `showBackButton` params, and `Routes` adds a new
`HOME_TABS` route constant.
> 
> Adds/updates `ActivityView` tests to cover Money-flag behavior for
header back, hardware back interception, and header variant selection.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e5a0c60. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: 

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-05-06 at 11 48 33"
src="https://github.com/user-attachments/assets/bfdba79e-6614-403c-a1f0-6d228d8465a1"
/>

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: swaps a hardcoded month-name formatter for cached
`Intl.DateTimeFormat` using the app locale, plus a small Jest mock
adjustment; behavior changes are limited to date label rendering.
> 
> **Overview**
> Campaign tile date labels are now **localized** by formatting
month/day via `getIntlDateTimeFormatter` using `I18n.locale`, replacing
the prior hardcoded English month list.
> 
> Tests were updated to mock the `i18n` module’s default export
(`locale`) so the new locale-aware formatter can run under Jest.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
38c82e4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
This PR moves the default fixture change detection spec from
`regression` into `smoke`

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes: 

## **Manual testing steps**
N/A

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
N/A
<!-- [screenshots/recordings] -->

### **After**
N/A
<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x]  I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this only updates CI/workflow and a helper script to
reference the relocated fixture validation test path, with no production
code changes.
> 
> **Overview**
> The fixture update workflow and local `update-e2e-fixture.sh` script
now run `tests/smoke/fixtures/fixture-validation.spec.ts` instead of the
prior `tests/regression/...` location, aligning automation with the
test’s new suite placement.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6358611. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

Added metrics for the new explore page v2 to be tracked for the next RC

Segment changes: Consensys/segment-schema#551

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: add explore v2 metrics

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2957

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily adds optional analytics callbacks and tracking calls without
changing core navigation flows; risk is low aside from potential
duplicate/missing events due to new hook/prop wiring across many UI
components.
> 
> **Overview**
> Adds new MetaMetrics event `EXPLORE_INTERACTED` and a
`trackExploreInteracted` helper with typed properties for Explore V2
interactions.
> 
> Instruments Explore V2 UI to emit interaction events for **tab
switches**, **section “See all” taps**, **item taps** (tokens, perps,
predictions, sites), and **prediction buy/vote taps**. This is
implemented by threading optional `onCardPress`/`onBuyButtonPress`
callbacks through Predict/Trending/perps/site row components and
introducing a shared `PerpsToggleBlock` used by Macro/RWAs to
standardize pill-toggled perps tracking.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ac1becb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The `prepare` job in `build.yml` runs `yarn install --immutable` without
a yarn global cache on every pipeline run. Over 21 runs in the past
week, this step averaged **2m 18s** (median 2m 19s, sd=2s -- extremely
consistent).

The `setup-node-modules.yml` workflow already uses `cache: 'yarn'` in
the same `actions/setup-node@v4` action and completes yarn install in
~50s-1m.

This PR adds `cache: 'yarn'` to the `prepare` job's
`actions/setup-node@v4` step, matching the existing pattern. On cache
hit, yarn resolves packages from the local global cache instead of
downloading from the registry.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MCWP-574

## **Manual testing steps**

```gherkin
Feature: Yarn cache in prepare job

  Scenario: First run populates the cache (cache miss)
    Given a production build is triggered via workflow_dispatch
    And no prior yarn cache exists for the current yarn.lock

    When the "Setup Node.js" step runs in the prepare job
    Then the step log shows no cache restored
    And "yarn install --immutable" completes at baseline timing (~2m 18s)
    And the "Post Setup Node.js" step shows "Cache saved"

  Scenario: Subsequent run restores the cache (cache hit)
    Given a production build is triggered via workflow_dispatch
    And a yarn cache exists from a previous run

    When the "Setup Node.js" step runs in the prepare job
    Then the step log shows "Cache restored"
    And "yarn install --immutable" completes in ~50s-1m (cache hit)
    And the build completes successfully with all artifacts produced
```

## **Screenshots/Recordings**

N/A - CI workflow change only, no UI impact.

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**
This PR makes the following changes to the MMConnect runs:
- Only run on Samsung Devices -> reduces consumption on browserstack and
keeps tests stable
- Only run on `rc` environment

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1797

## **Manual testing steps**
N/A

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
N/A
<!-- [screenshots/recordings] -->

### **After**
N/A
<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes CI workflow conditions and device selection for MM-Connect
runs, which could unintentionally reduce test coverage or skip runs if
the matrix/filter is wrong. No production app code changes, but it
affects release-signal reliability.
> 
> **Overview**
> Updates the performance E2E GitHub workflow to **scope Android
MM-Connect runs more narrowly**.
> 
> MM-Connect now uses a dedicated `android_mm_connect_matrix` filtered
to Samsung devices, and both the MM-Connect job and the RN Playground
APK upload step are gated to run only when `build_variant` is `rc`
(skipping these steps for experimental builds).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1fb6325. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR closes **Phase 7** of the incremental **Unified Buy (v2)
headless buy** plan (`app/components/UI/Ramp/headless/PLAN.md`):
headless consumers now receive structured `HeadlessBuyError` data for
hard failures instead of depending on Ramp UI surfaces like banners,
ErrorViews, or order toasts.

**Reason**

- Phase 6
([#29340](#29340)) fired
`onOrderCreated` and bypassed the order-details redirect on success, but
several failure paths were still UI-coupled. Limit failures could be
wrapped into generic display errors, Checkout/WebView failures rendered
local UI, and one Transak success path could still show a toast before a
headless consumer regained control.

**What changed**

- **`HeadlessBuyErrorCode` + `failSession`** — centralizes error
normalization in `sessionRegistry`, preserving explicit error
codes/details and closing the session with failed terminal semantics
after `onError` fires.
- **`HeadlessHost`** — uses `failSession` for auth errors, malformed
asset ids, and `continueWithQuote` rejections so the consumer receives
one structured `onError` callback and one terminal close.
- **`useTransakRouting`** — preserves `LimitExceededError` as
`LIMIT_EXCEEDED`, forwards checkout-processing failures through
`onError`, and suppresses the manual-bank-transfer toast path when a
live headless session owns the flow.
- **`Checkout`** — routes callback-processing failures and primary
WebView HTTP errors through `onError` for headless sessions, then
unwinds the ramp stack instead of rendering the checkout ErrorView.
- **`BuildQuote`** — keeps legacy headless params from falling back to
banner-only error handling if they are encountered.
- **`PLAN.md`** — marks Phase 7 complete.

**References**

- **Stacked on Phase 6**:
[#29340](#29340)
(`poc/headless-buy-phase-6`). **This PR's base is
`poc/headless-buy-phase-6`** so the diff is Phase 7-only.
- Continues from **Phase 5**:
[#29338](#29338)
(Headless Host + quote-first start).

**Tests**

- `yarn eslint app/components/UI/Ramp/headless/types.ts
app/components/UI/Ramp/headless/sessionRegistry.ts
app/components/UI/Ramp/headless/sessionRegistry.test.ts
app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.tsx
app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.test.tsx
app/components/UI/Ramp/hooks/useTransakRouting.ts
app/components/UI/Ramp/hooks/useTransakRouting.test.ts
app/components/UI/Ramp/Views/Checkout/Checkout.tsx
app/components/UI/Ramp/Views/Checkout/Checkout.test.tsx
app/components/UI/Ramp/Views/BuildQuote/BuildQuote.tsx`
- `yarn jest --watchman=false
app/components/UI/Ramp/headless/sessionRegistry.test.ts
app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.test.tsx
app/components/UI/Ramp/hooks/useTransakRouting.test.ts
app/components/UI/Ramp/Views/Checkout/Checkout.test.tsx
app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx`
- `yarn lint:tsc` was attempted, but the local run is blocked by
unrelated existing type errors in SocialLeaderboard tests and controller
messenger types.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: _No GitHub issue — incremental POC on branch
`saustrie-consensys/headless-buy-phase-7`._

Continuity:
[#29340](#29340) (Phase
6 — headless order success callback + stack unwind).
[#29338](#29338) (Phase
5 — Headless Host + quote-first start).

## **Manual testing steps**

```gherkin
Feature: Headless Buy Phase 7 (structured errors)

  Scenario: Native Transak limit failure surfaces as data
    Given the app is an internal build and I am signed in
    And I open Settings → Fiat on-ramp → Headless Buy playground
    When I start a headless native quote that exceeds the user's Transak limit
    Then the playground event log should show `onError({ code: "LIMIT_EXCEEDED" })`
    And the session should close without showing a Ramp-only toast or order-details redirect

  Scenario: Aggregator Checkout failure surfaces as data
    Given I start a headless aggregator quote from the playground
    When the Checkout callback or primary WebView request fails
    Then the consumer should receive `onError({ code: "UNKNOWN", message })`
    And the app should unwind out of the Ramp stack instead of rendering the Checkout ErrorView

  Scenario: Non-headless Buy flow is unchanged
    Given I open Wallet → Buy through the regular flow
    When a quote, checkout, or limit error occurs
    Then the existing Ramp UI surfaces should render as before
```

## **Screenshots/Recordings**

### **Before**

N/A — Phase 7 changes error/callback plumbing only.

### **After**

N/A — no user-facing UI changes, but here's a video anyways.


https://github.com/user-attachments/assets/2ce3a5a7-7205-4490-9174-8be7672ae464



## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes error handling and navigation unwinding for headless Unified
Buy flows across `HeadlessHost`, `Checkout`, and `useTransakRouting`,
which could affect session lifecycle and user recovery paths if
misrouted. Scope is contained to headless-mode branches with added test
coverage, but touches core buy/checkout flow control.
> 
> **Overview**
> **Headless buy errors are now surfaced as structured data instead of
Ramp UI.** A new `failSession` helper in `headless/sessionRegistry`
normalizes thrown/native errors into `HeadlessBuyError` (including
`LIMIT_EXCEEDED` mapping and optional `details`), fires `onError`, and
closes the session with failed terminal semantics.
> 
> Headless flows now consistently use this failure path: `HeadlessHost`
forwards auth/asset/continue failures via `failSession`, `Checkout`
sends callback-processing and primary WebView HTTP errors through
`onError` and pops the ramp stack instead of rendering an ErrorView, and
`useTransakRouting` preserves `LimitExceededError` details, suppresses
toasts when a live headless session is present, and routes post-checkout
processing failures through `failSession` + stack unwind. Tests are
updated/added to cover these headless-specific error paths and
regression guards.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7bdaa03. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: saustrie-consensys <270766059+saustrie-consensys@users.noreply.github.com>
#29736)

## **Description**

Implements MUSD-747: peek-and-hide behaviour for the Money Home "Add
money" footer button so it doesn't visually clash with the onboarding
stepper card's primary CTA while the stepper is in the viewport.

- The footer is always mounted as an absolutely-positioned overlay;
visibility is driven by a Reanimated `translateY` shared value
(`FOOTER_HIDDEN_OFFSET` off-screen by default).
- When the user scrolls past the onboarding stepper's bottom edge, the
footer slides in (`withTiming(0, 300ms)`, `Easing.out(cubic)`).
- When the user scrolls back so the stepper re-enters the viewport, the
footer slides out (`withTiming(FOOTER_HIDDEN_OFFSET, 300ms)`,
`Easing.in(cubic)`).
- The stepper itself is rendered unconditionally — its render condition
is upstream and this PR does not change it.
- ScrollView bottom padding is driven by the measured footer height so
the footer never visually covers reachable content.
- Visibility is tracked in a ref (`isStepperVisibleRef`); scroll events
do not trigger React re-renders, only crossing the threshold flips the
ref and runs the animation.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MUSD-747

## **Manual testing steps**

```gherkin
Feature: Add money footer peek-and-hide

  Scenario: stepper is fully in the viewport
    Given the user is on the Money Home view
    And the onboarding stepper card is in the viewport
    Then the "Add money" footer is hidden (translated off-screen)

  Scenario: user scrolls past the stepper
    Given the user is on the Money Home view
    When the user scrolls so the stepper card's bottom edge is above the viewport
    Then the "Add money" footer slides up into view

  Scenario: user scrolls the stepper back into view
    Given the "Add money" footer is visible after scrolling past the stepper
    When the user scrolls back up so the stepper re-enters the viewport
    Then the "Add money" footer slides out

  Scenario: stepper layout has not yet measured (initial paint)
    Given the user opens the Money Home view for the first time
    When the stepper's onLayout has not yet reported a non-zero height
    Then the "Add money" footer remains hidden, avoiding a flash of "Add money"
```

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate UI/UX change to `MoneyHomeView` scroll/layout behavior using
Reanimated and layout measurements; risk is mainly regressions in footer
visibility/overlap across devices and safe-area/scroll edge cases.
> 
> **Overview**
> **Adds a peek-and-hide animated "Add money" footer on
`MoneyHomeView`.** The footer is now an absolutely-positioned overlay
that slides in/out via Reanimated `translateY` based on whether the
onboarding stepper is considered visible.
> 
> Introduces `computeStepperVisibility` to decide when the user has
scrolled past the stepper bottom, tracks scroll/measurements via refs
(to avoid per-frame re-renders), and dynamically pads the `ScrollView`
bottom using the measured footer height so content isn’t covered.
Updates/extends tests to cover the new navigation cases and the footer
visibility/measurement/scroll handlers, and adds unit tests for the
visibility computation.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6f62266. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Implements the treatment UI for the
`coreMCU589AbtestHubPageDiscoveryTabs` A/B test

When the treatment variant is active, the homepage replaces the standard
scrollable layout with a top-tab navigation bar exposing three
verticals:

- **Portfolio:** existing homepage sections with balance header and
pull-to-refresh
- **Perpetuals:** `PerpsHomeView` wrapped in connection + stream
providers
- **Predictions:** `PredictFeed` wrapped in preview sheet provider

When the control variant is active (or the flag is absent), the existing
homepage layout is fully preserved.

Key implementation details:
- `HomepageDiscoveryTabs`: new component that owns tab layout, per-tab
gradient crossfade, and wallet header hide/show coordination across all
three tabs
- `TabsList` — design-system tab primitive with `keepMounted` support.
Perpetuals and Predictions both use `keepMounted={false}`:
- **Performance**: both screens have a heavy hydration cost on first
mount; keeping them alive while invisible wastes resources on tabs the
user may never visit
- **Open connections**: `PerpsHomeView` establishes WebSocket channels
for live market data via its stream providers on mount; leaving these
running in the background wastes bandwidth and server-side connection
slots
- **Memory**: `PredictFeed` and its preview sheet provider hold feed
state that can safely be discarded between visits
- Portfolio uses `keepMounted={true}` (the default) since it is the
landing tab and its scroll position and section state should survive
switching away and back

- Wallet header animates up/down on scroll via Reanimated shared values;
icon collapse and gradient opacity are synced via
`TabIconAnimationContext`
- Scroll event forwarding keeps existing `HOME_VIEWED` section analytics
working in the Portfolio tab
- A/B gating is handled by `useABTest(HUB_PAGE_DISCOVERY_TABS_AB_KEY)`

[Figma
Design](https://www.figma.com/design/z0panHXrMSMUSof2SaPkd4/Home-2026?m=auto&node-id=4280-62214&t=AAKr2hzmyPx57F4Y-1)
for reference. Only difference between this UI and the Figma is that the
tabs take up the entire space

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-591

## **Manual testing steps**

```gherkin
Feature: Hub Page Discovery Tabs

  Scenario: treatment variant shows top tabs
    Given the coreMCU589AbtestHubPageDiscoveryTabs flag is set to "treatment"

    When user opens the app to the Wallet screen
    Then three tabs are visible: Portfolio, Perpetuals, Predictions
    And switching between tabs is smooth with no layout shift
    And the wallet header hides on scroll and restores on tab switch
    And pull-to-refresh works on the Portfolio tab

  Scenario: control variant preserves existing layout
    Given the coreMCU589AbtestHubPageDiscoveryTabs flag is set to "control"

    When user opens the app to the Wallet screen
    Then the existing homepage layout is shown with no tabs
```

## **Screenshots/Recordings**

### iOS

Dark Mode


https://github.com/user-attachments/assets/7df6a46d-b3b3-44cc-a697-b796581dd759

Light Mode (No Gradient)


https://github.com/user-attachments/assets/97b1f901-6092-42f9-926c-e8e6785c6f4e

### Android

Dark Mode


https://github.com/user-attachments/assets/4232f3fc-a47c-4516-93c2-104e4a3fb5cb

Light Mode (No Gradient)


https://github.com/user-attachments/assets/3f11dd8f-696f-438e-9867-1b08dc69200d

### **Before**

`~`

### **After**

`~`

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces a new A/B-test-gated navigation structure and shared header
animation/scroll handling on the Wallet home screen, which could affect
core navigation and scroll/refresh behavior. Risk is mitigated by
control-path preservation and added unit coverage, but Reanimated
worklet interactions and tab switching edge cases remain sensitive.
> 
> **Overview**
> When the Hub Page Discovery Tabs A/B test is in *treatment* (and
homepage sections are enabled), Wallet home now renders a new top-level
`HomepageDiscoveryTabs` experience with three tabs: Portfolio,
Perpetuals (`PerpsHomeView`), and Predictions (`PredictFeed`). The
control path preserves the existing scroll layout.
> 
> Adds `useDiscoveryScrollManager`, a Reanimated-backed hook that
hides/shows the shared Wallet header based on scroll threshold, restores
per-tab header state on tab entry, forwards scroll events back to JS
(for analytics), and emits `onHeaderHiddenChange` to sync sibling
animations.
> 
> Updates `Wallet` to measure/animate the header via shared values, pass
refresh/portfolio header/scroll callbacks into the new tabs view, and
crossfade a dark-mode gradient overlay per active tab. `PerpsHomeView`
and `PredictFeed` gain `hideHeader` and header-sync props, and
`useFeedScrollManager` can now notify header hidden/show changes; tests
are added/updated across these components and the new hook.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
38e679d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This is part of the effort to reduce the amount of GH repo secrets.
Remove redundant social auth related keys and unused qa build configs.
```
MAIN_IOS_GOOGLE_CLIENT_ID_UAT
MAIN_IOS_GOOGLE_REDIRECT_URI_UAT
MAIN_ANDROID_GOOGLE_CLIENT_ID_UAT
MAIN_ANDROID_GOOGLE_SERVER_CLIENT_ID_UAT
MAIN_ANDROID_APPLE_CLIENT_ID_UAT
```

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk because this only removes unused/legacy QA build entries and
redundant OAuth-related secret wiring in CI/build scripts; main/flask
build paths and canonical secret names remain unchanged. Risk is limited
to any external/legacy pipeline still depending on the deleted QA build
names or old secret aliases.
> 
> **Overview**
> **Removes legacy QA build support** by deleting the `qa-prod`/`qa-dev`
entries from `builds.yml` and dropping them from the `build.yml`
dispatch options.
> 
> **Simplifies CI secret wiring** by removing the unused `MAIN_*_UAT`
and `FLASK_*_PROD` OAuth/social env vars from E2E build/test workflows
(`build-android-e2e.yml`, `build-ios-e2e.yml`, `run-e2e-workflow.yml`,
`run-e2e-api-specs.yml`, `update-e2e-fixtures.yml`) and deleting the
corresponding remap logic from `scripts/build.sh`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f238c9a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators May 6, 2026
@pull pull Bot added the ⤵️ pull label May 6, 2026
@pull pull Bot merged commit f0c0bf8 into Reality2byte:main May 6, 2026
4 of 16 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.