[pull] main from MetaMask:main#843
Merged
Merged
Conversation
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
Added Money account first time deposit animation that is fired from new
globally mounted `useMoneyFirstTimeDepositTracker`. This animation only
fires if there are no other confirmed Money account deposits already.
Previously failed deposits don't block the animation.
Added `selectMoneyFirstTimeDepositAnimationEnabledFlag` which uses
`earnMoneyFirstTimeDepositAnimationEnabled` LD flag and
`MM_MONEY_FIRST_TIME_DEPOSIT_ANIMATION_ENABLED` env var to
enable/disable the first time deposit animation.
<!-- mms-check: type=text required=true -->
<!--
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**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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: added Money account first time deposit animation
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: [MUSD-997: First time deposit
animation](https://consensyssoftware.atlassian.net/browse/MUSD-997)
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: First-time Money account deposit animation
Scenario: user completes their first Money account deposit
Given the user has no prior confirmed Money account deposit transactions
And the first-time deposit animation feature flag is enabled
When user confirms a Money account deposit transaction
Then the first-time deposit animation screen is shown with parallax and celebratory animation
And the user can dismiss the screen to return home
Scenario: user completes a subsequent Money account deposit
Given the user already has a prior confirmed Money account deposit
And the first-time deposit animation feature flag is enabled
When user confirms another Money account deposit transaction
Then no animation screen is shown
And the user is not navigated away from the confirmation flow
Scenario: animation feature flag is disabled
Given the first-time deposit animation feature flag is disabled
When user confirms their first Money account deposit transaction
Then no animation screen is shown
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
N/A - Animation didn't exist
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/c230a093-f569-431d-bd61-a02190ef0478
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
Bump `@metamask/money-account-balance-service` to `v2.1.0`. This version
uses the `pending` block tag for balance fetching.
<!-- mms-check: type=text required=true -->
<!--
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**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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: bump @metamask/money-account-balance-service to v2.1.0
to use pending block tag in balance fetches
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: [MUSD-1016: Update @metamask/money-account-balance-service to
v2.1.0](https://consensyssoftware.atlassian.net/browse/MUSD-949)
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: Money account balance fetching
Scenario: user can load Money account balance
Given user have Money account
When user launches app
Then user sees Money account balance on Wallet home and Money home screens
Feature: Money account balance update sending to Perps/Predict
Scenario: user's Money account balance updates after sending to Perps/Predict
Given user have Money account with non-zero balance
When user sends funds from Money account to Perps/Predict
And the transaction confirms
Then user's Money account balance updates to reflect send
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
N/A - Balance wasn't updating after sending to Perps/Predict
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/75787005-e93b-41b1-a35f-2adee340b47a
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Fixes two QuickBuy UX issues on the trader position sheet:
- Rate tag flip: Pre-quote metadata showed 1 [dest] = X [source] while
the quote pill showed 1 [source] = X [dest], so the tag swapped sides
when a quote landed. Buy-mode pre-quote now uses the same source-first
orientation as the quote-derived rate.
- Amount loading state: Replaced the secondary-line spinner with a
skeleton + token symbol so the fiat headline and token context stay
visible during blocking quote loads. Buy/Sell button spinner behavior is
unchanged.
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 15 44 37"
src="https://github.com/user-attachments/assets/93e3af49-edaf-46f1-a0ca-a163b35738da"
/>
https://github.com/user-attachments/assets/9735648c-51b4-495c-9344-0563ad59b15e
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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**
<!-- mms-check: type=issue-link required=true -->
Fixes:
https://consensyssoftware.atlassian.net/browse/TSA-608
https://consensyssoftware.atlassian.net/browse/TSA-716
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```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**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
NA
### **After**
NA
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Design-polish batch across the Social Leaderboard / Top Traders surfaces
to match the latest Figma.
- Leaderboard rows: new RankMedal medallion badge (gold/silver/bronze
SVG) on the avatar for top-3, replacing the rank column + crown/ring;
subline shows only the signed full PnL.
- Home carousel: compact horizontal cards (155px, full-width small
Follow button).
- Trader profile view also updated to match figma spec
- Position chart: trade markers 10px / 2px stroke.
- Trades list: removed white title underline; rows show action now:
"Bought"/"Sold".
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 14 11 42"
src="https://github.com/user-attachments/assets/5a6e3593-8522-44a3-8699-56293ae15786"
/>
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 16 24 07"
src="https://github.com/user-attachments/assets/0254e371-55b2-49a8-b361-ff4f72a5bb7c"
/>
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 15 08 14"
src="https://github.com/user-attachments/assets/b4680457-83eb-44a9-bb81-ec75abd2c124"
/>
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 14 14 39"
src="https://github.com/user-attachments/assets/6d66d5aa-95ac-4d97-b403-52ee36f2fab5"
/>
<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-17
at 15 07 48"
src="https://github.com/user-attachments/assets/26588fbc-2375-49bc-b142-9662c5f335c5"
/>
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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**
<!-- mms-check: type=issue-link required=true -->
Fixes:
https://consensyssoftware.atlassian.net/browse/TSA-765
https://consensyssoftware.atlassian.net/browse/TSA-468
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```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**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
NA
### **After**
NA
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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
- [ ] 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.
---------
Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** This PR standardizes section spacing and structure across the Explore feed (TrendingView) so all tabs follow a consistent layout pattern. **Motivation:** Section spacing was previously handled with ad-hoc margins on individual components (`mb-7`, `mb-9`, `compactSectionTail`, etc.), which led to inconsistent gaps between sections across tabs and made it hard to maintain visual rhythm as sections were added or reordered. **Solution:** - Introduced a shared `sectionLayout` pattern on each Explore tab (Now, Crypto, Dapps, Macro, RWAs, Sports) that computes `showDivider` and `addSectionTailGap` from the set of visible sections. - Migrated Explore section headers to MMDS `SectionHeader` and added MMDS `SectionDivider` between sections. - Removed per-component bottom/top margin hacks from carousels, pill lists, card lists, and tile carousels; spacing is now owned by section wrappers. - Updated `WhatsHappeningSection` with `hideHeader`, `showDivider`, and `addSectionTailGap` props so it integrates cleanly into the Explore layout (including A/B variant ordering on the Now tab). - Aligned Explore search result section headers with the same MMDS components. - Added bottom padding to `ExploreScroll` and replaced `SafeAreaView` with `Box` in `TrendingView`. ## **Changelog** CHANGELOG entry: Aligned section spacing and dividers across Explore tabs for a more consistent layout ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-781 ## **Manual testing steps** ```gherkin Feature: Explore section spacing alignment Scenario: Now tab sections use consistent dividers and spacing Given the user is on the Wallet tab with Explore visible And Perps, Predict, and What's Happening feature flags are enabled When the user opens the Explore "Now" tab Then sections are separated by dividers (except the first visible section) And horizontal sections (carousels, pill lists) have consistent tail spacing before the next section And vertical list sections (e.g. Stocks) do not have extra tail gap below the list Scenario: Crypto tab section layout Given the user opens the Explore "Crypto" tab When Trending Tokens, Crypto Perps, and Predictions sections are visible Then each section after the first shows a SectionDivider And spacing between carousel sections is consistent Scenario: Dapps tab section layout Given the user opens the Explore "Sites" tab When Recents, Favorites, Ecosystems, and Popular sections are visible Then dividers appear between sections in the correct order And the Ecosystems subtitle still renders under its section header Scenario: Explore search results headers Given the user opens Explore search and enters a query with results When search results render grouped by section Then section headers use MMDS SectionHeader styling And dividers appear between search result sections (not before the first) Scenario: What's Happening on Explore (non-homepage) Given What's Happening is enabled on the Now tab When the What's Happening carousel renders in Explore Then it uses the Explore SectionHeader (not the homepage temp header) And divider/spacing props match adjacent sections ``` ## **Screenshots/Recordings** ### **Before** https://github.com/user-attachments/assets/e8494120-87c6-4e4c-b7e0-3577e510b426 ### **After** https://github.com/user-attachments/assets/eb00f187-9330-4e4e-ae7e-dfd31f0525bc ## **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 *(no new tests in this commit — visual/layout refactor only)* - [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 ## **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** > UI-only layout and styling across Explore tabs and search; no auth, data, or navigation logic changes beyond visual structure. > > **Overview** > Standardizes **Explore (TrendingView)** section rhythm by moving spacing and separators out of individual carousels/lists and into tab-level section wrappers. > > Each Explore tab now builds a **visible-section list** and uses a shared `sectionLayout` helper to derive **`showDivider`** (MMDS `SectionDivider` between sections, not before the first) and **`addSectionTailGap`** (`pb-3` after horizontal sections only; vertical `CardList` sections skip extra tail gap). **Per-section margin hacks** (`mb-7`, `mb-9`, `compactSectionTail`, default `PillScrollList` wrapper margins, `CardList` bottom margin) are removed from shared components. > > **Section headers** on Explore switch to MMDS `SectionHeader` via `TrendingView/components/SectionHeader`; **Explore search** headers follow the same pattern with `isFirstHeader` to control dividers. **`WhatsHappeningSection`** gains `hideHeader`, `showDivider`, and `addSectionTailGap` so the Now tab can render the Explore header/divider layout while keeping the homepage temp header elsewhere. **`ExploreScroll`** adds bottom padding; **`TrendingView`** drops `SafeAreaView` for `Box`. Perps tabs hoist **`PerpsSectionProvider`** to the tab root after splitting content components. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5a408e5. 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>
…ll (#31931) ## **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? --> On Money Home, every Card-related entry point was navigating to `Routes.CARD.ROOT` with `animation: 'slide_from_bottom'`, so Card Home opened with a bottom-to-top modal transition even for cardholders and linked users. That animation should be reserved for the CardWelcome educational screen shown to brand-new users in upsell mode. This change hoists the existing `metamaskCardMode` derivation and reuses it in `navigateToCardHome`: only when `metamaskCardMode === 'upsell'` do we pass `animation: 'slide_from_bottom'`. All other modes (`manage`, `link`, `verifying`) omit the animation param and fall back to the MainNavigator default (`slide_from_right`). Unit tests cover manage-mode navigation and guard against regressions to the modal animation. ## **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 Card navigation from Money Home to use a push animation except when opening the CardWelcome educational screen ## **Related issues** Fixes: CARD-450 ## **Manual testing steps** ```gherkin Feature: Card navigation animation from Money Home Background: Given I am logged into MetaMask Mobile And I am on the Money Home screen Scenario: brand-new user opens Card from upsell Get now Given I am not a cardholder And the MetaMask Card section is in upsell mode When user taps "Get now" on the MetaMask Card section Then the CardWelcome screen should slide in from the bottom Scenario: linked cardholder opens Card from Manage Given I am a cardholder with my card linked to my Money account And the MetaMask Card section is in manage mode When user taps "Manage" on the MetaMask Card section Then Card Home should push in from the right Scenario: cardholder opens Card from the action row Given I am a cardholder with my card linked to my Money account When user taps the Card button in the Money Home action row Then Card Home should push in from the right And the screen should not slide in from the bottom ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A — animation change; screen recordings recommended to compare bottom-to-top vs right-to-left transitions. ### **After** N/A — screen recordings recommended showing upsell (bottom-to-top) vs manage/action-row (right-to-left) flows. ## **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 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 --> 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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Adds the TMCU-926 homepage discovery pills A/B/C experiment on the
legacy scroll wallet homepage. Users in `grayIcons` or `colorIcons`
variants see a horizontal pill rail below the growth banner with
Perpetuals, Predictions, Stocks, and Crypto shortcuts. Control users see
no pills.
Implementation includes LaunchDarkly flag wiring
(`homeTMCU926AbtestDiscoveryPills`), `HomepageDiscoveryPills` UI (gray
design-system icons vs color PNG assets), wallet integration (legacy
homepage only; excludes MCU-589 discovery-tabs treatment), navigation to
perps / predict / explore destinations, and Segment instrumentation
(`pill_tapped` Home Viewed plus destination attribution).
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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**
<!-- mms-check: type=issue-link required=true -->
Fixes:
Refs: https://consensyssoftware.atlassian.net/browse/TMCU-926
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: Homepage discovery pills A/B test (TMCU-926)
Background:
Given I am logged into MetaMask Mobile on the legacy scroll wallet homepage
And LaunchDarkly flag homeTMCU926AbtestDiscoveryPills is configured
Scenario: control variant shows no discovery pills
Given I am assigned to the control variant
When I view the wallet home screen below the growth banner
Then I should not see discovery pills
Scenario: grayIcons variant shows pills and navigates
Given I am assigned to the grayIcons variant
When I tap the Perpetuals pill
Then I should navigate to the perps home screen
When I return and tap the Predictions pill
Then I should navigate to the predict market list
When I return and tap the Crypto pill
Then I should navigate to Explore on the Crypto tab
When I return and tap the Stocks pill
Then I should navigate to Explore on the RWAs tab
Scenario: colorIcons variant shows color pill assets
Given I am assigned to the colorIcons variant
When I view the discovery pills below the growth banner
Then each pill should display its color icon asset
Scenario: discovery pills hidden for discovery-tabs treatment
Given I am in the MCU-589 hub page discovery tabs treatment
When I view the wallet home screen
Then I should not see discovery pills on the legacy homepage layout
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/6a66727f-47fa-4e47-b535-01b4a4a2e8b6
<img width="300"
src="https://github.com/user-attachments/assets/192369be-ac39-4460-87fe-5a0f4b5f027a"
/>
<img width="300"
src="https://github.com/user-attachments/assets/434f6522-6e84-4161-b88d-6be139831157"
/><img width="300"
src="https://github.com/user-attachments/assets/ee305bc6-5dc6-4d32-846b-cd287b7c0c54"
/>
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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 -->
…31888) ## **Description** This PR fixes the hardware wallet (Ledger/QR) confirmation flow, which was broken for sends and signature requests originating from a hardware wallet account. ## **Changelog** CHANGELOG entry: Fixed a bug that prevented hardware wallet users from completing sends and signatures ## **Related issues** Fixes: #31845 ## **Manual testing steps** Feature: Hardware wallet confirmation flow Scenario: Ledger account completes a send Given the active account is a Ledger hardware wallet account And the Ledger device is connected And the user is on the send screen with a valid recipient and amount When user taps confirm to submit the transaction Then the Ledger device prompts to sign for the correct account And the transaction is submitted from the selected account Scenario: Ledger account signs a message from a dApp Given the active account is a Ledger hardware wallet account And a dApp has requested a signature When user confirms the signature request Then the Ledger device prompts to sign for the correct account And the signature is completed successfully Scenario: Confirmation is rejected when no signing address is available Given a confirmation request with no resolvable `from` address When user attempts to confirm Then the confirmation is rejected And no hardware wallet operation is attempted ## **Screenshots/Recordings** <!-- TODO: attach before/after recordings of the Ledger send/sign flow. Recording the "After" path showing the device signing with the correct account is the key evidence. --> ### **Before** ### **After** https://github.com/user-attachments/assets/6bb222b6-a662-4f56-aadd-24ecc60a3df9 ## **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 - [ ] 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. Notes on my choices: - Checklists: I checked only the items I could verify (coding standards followed, template completed, tests included in the diff, JSDoc on getDeviceIdForAddress). Left performance/labels unchecked honestly — those need your confirmation. - CHANGELOG: rewrote to past-tense user-facing prose per the template's examples. - Tests: the commit added/updated useConfirmActions.test.ts, useLedgerConfirm.test.ts, and useQrConfirm.test.ts, so "tests included" is legitimately checkable.
…live pricing cp-7.81.2 (#31852) ## **Description** Extended sports game-details tabs (moneyline, spreads, totals, and future market types) were not grouping or pricing outcomes reliably compared to Polymarket. This PR: 1. **Adds `enabledSportsMarketTypes`** to the `predictExtendedSportsMarkets` remote flag so outcome grouping respects an allowlist of supported market types (defaults to moneyline, spreads, and totals when the field is omitted on an enabled flag). 2. **Fixes spread line ordering** to match Polymarket’s ascending/descending display based on the first spread’s displayed sign. 3. **Polls REST ask prices** (`entry.sell`) for non-moneyline grouped outcomes while keeping moneyline on live WebSocket best-ask prices; polling pauses while the buy sheet is open. 4. **Refactors game-details outcome UI** into `outcomeGrouping.ts`, `PredictGameOutcomeCards.tsx`, `usePricedOutcomeGroup.ts`, and `utils.ts`, with unit tests colocated by module. **Why:** PRED-957 — corners, team totals, and first-half team totals (and related extended markets) were not showing up or behaving correctly in game details. **How:** Filter groupable outcomes at parse time, sort line markets consistently, price cards through the correct source per market type, and slim `PredictGameOutcomesTab` to routing + composition only. ## **Changelog** CHANGELOG entry: Fixed extended sports game-details outcome tabs to group enabled market types correctly, order spread lines like Polymarket, and show current buy prices for non-moneyline markets. ## **Related issues** Fixes: - PRED-957 - PRED-958 ## **Manual testing steps** ```gherkin Feature: Extended sports game details outcomes Scenario: User views grouped game lines with live prices Given extended sports markets are enabled for the game league And enabledSportsMarketTypes includes moneyline, spreads, and totals When the user opens a live or upcoming game details screen And selects the Game Lines chip Then moneyline, spreads, and totals subgroups render And spread lines appear in the same order as on Polymarket And non-moneyline buy button prices reflect REST ask prices And moneyline buy button prices reflect live WebSocket best ask Scenario: Price polling pauses while buy sheet is open Given the user is on a game details spreads or totals card When the user opens the buy preview sheet Then REST price polling stops until the sheet is dismissed Scenario: Enabled market types flag limits grouped tabs Given enabledSportsMarketTypes is set to ["moneyline"] only When the user opens game details for an extended-league game Then only moneyline appears in outcome groups And the full outcomes list remains available on the market object ``` **Automated tests run locally:** ```bash npx jest --runTestsByPath \ app/components/UI/Predict/components/PredictGameDetailsContent/utils.test.ts \ app/components/UI/Predict/components/PredictGameDetailsContent/usePricedOutcomeGroup.test.tsx \ app/components/UI/Predict/components/PredictGameDetailsContent/PredictGameOutcomesTab.test.tsx \ app/components/UI/Predict/providers/polymarket/outcomeGrouping.test.ts \ app/components/UI/Predict/providers/polymarket/utils.test.ts \ app/components/UI/Predict/utils/resolvePredictFeatureFlags.test.ts \ --coverage=false ``` ## **Screenshots/Recordings** N/A — manual QA pending on device/simulator. Will attach before/after recordings of game-details Game Lines (spreads order + buy prices) before marking Ready for review. ### **Before** <!-- Add recording: spread lines out of order / stale buy prices --> ### **After** <!-- Add recording: spread lines match Polymarket / REST prices on spreads & totals --> ## **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 ## **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.
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Removing old ways of calling `keyring_createAccount` via the Snap
keyring.
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
CHANGELOG entry: null
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: N/A
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
N/A
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
N/A
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
---------
Co-authored-by: Hassan Malik <hbmalik88@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as a warning in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Updates the VIP invite and referee splash experiences to use the **Gold
Fox Collective** branding, consolidates duplicated splash UI/copy, and
updates the VIP referee dashboard stats.
**Splash screens**
- Rebranded `splash_title` from "Gold Fox VIP" to "Welcome to Gold Fox
Collective" across all locales
- Removed duplicate `referee_splash_*` translation keys that mirrored
shared `splash_*` strings (kept `referee_splash_continue` since it
differs from `splash_accept_invite`)
- Extracted shared `VipSplashGradientTitle` and `VipSplashScreenLayout`
components
- Removed thin `VipSplashScreen` / `VipRefereeSplashScreen` wrappers;
views now render the shared layout directly
**VIP referee dashboard**
- Replaced the generic **Points** stat with **Points to
{referredByCode}** using `dashboard.points`
- Kept **Swaps volume** and **Perps volume** as separate stat cells (not
combined)
- Updated loading skeleton to match the three-cell layout
- Added `referee_points_to_label` and restored
`referee_swaps_volume_label` / `referee_perps_volume_label` in all
supported locales
**Tests**
- Added unit tests for `VipSplashGradientTitle` and
`VipSplashScreenLayout`
- Extended `RewardsVipRefereeView` coverage for separate volume cells,
points-to label, and missing referral code
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
CHANGELOG entry: Updated VIP splash screens to say "Welcome to Gold Fox
Collective" and updated the VIP referee dashboard to show swaps volume,
perps volume, and points to referrer.
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/RWDS-1402
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: VIP splash and referee dashboard updates
Scenario: VIP invite splash shows Gold Fox Collective branding
Given a user with VIP program enabled and an unaccepted VIP invite
When the user opens the VIP splash screen
Then the title reads "Welcome to Gold Fox Collective"
And the primary CTA reads "Accept invite"
Scenario: VIP referee splash shows Gold Fox Collective branding
Given a user flagged as a VIP referee who has not accepted the referee splash
When the user opens the VIP referee splash screen
Then the title reads "Welcome to Gold Fox Collective"
And the primary CTA reads "Continue"
And the referred-by code is shown when available
Scenario: VIP referee dashboard shows updated stats
Given a VIP referee user with dashboard data loaded
When the user opens the VIP referee dashboard
Then the stats section shows "Swaps volume" and "Perps volume" separately
And the stats section shows "Points to {referredByCode}" with dashboard points
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
Edit: Screenshots look good, removed.
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
…ar lists (#30997) ## **Description** ### What `useNetworkEnablement` is consumed in ~22 files (network selectors, polling setup, token lists, `useCurrentNetworkInfo`, etc.). It returned a **brand-new object literal on every render**, and its `popularEvmNetworks` / `popularMultichainNetworks` / `popularNetworks` members were **fresh arrays each render** (computed inline with a `?? []` fresh fallback). Any consumer that feeds those into a `useMemo`/`useEffect`/`useCallback` dependency array re-ran every render — which is exactly what polling and token-list code does (several consumers even work around it today with `popularNetworks.join(',')`). ### Changes - Memoize the three popular-network lists in a single `useMemo` (returning a tuple), keyed on the controller instance **and** `selectNetworkConfigurations`, with a stable module-level empty-array fallback. - Wrap the returned object in `useMemo` so consumers get a stable identity. ### Why key on `selectNetworkConfigurations` (not just the controller) The controller's `listPopularEvmNetworks()` / `listPopularMultichainNetworks()` / `listPopularNetworks()` filter the static `POPULAR_NETWORKS` list by **mutable** NetworkController / MultichainNetworkController config state (`networkConfigurationsByChainId` / `multichainNetworkConfigurationsByChainId`). The controller instance reference never changes, so memoizing on it alone would serve a **stale** list when the user adds/removes a network. `selectNetworkConfigurations` is a `createDeepEqualSelector` that merges both EVM and non-EVM configs, so it changes only when the configs actually change — keeping the lists fresh on config changes while stable between them. (An `eslint-disable react-hooks/exhaustive-deps` is used with a comment because the dependency is read internally by the controller methods and isn't syntactically visible to the linter.) **Behavior is unchanged** (same values; lists still reflect current configs). ### Risk Low — memoization + a more-correct dependency key; no output changes. From the internal performance audit (`unstable-hook`, `fix_risk: Simple`, `test_safety_net: Covered`). Note: review flagged (and this PR fixes) that the naive "memoize on the controller instance" approach would have introduced stale data — hence the config-selector key. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #31381 ## **Manual testing steps** > **Validation status:** behavior-preserving refactor validated by the unit test(s) below; not yet manually profiled on Android / a power-user device, and no new Sentry traces added — the underlying audit finding is still `status: UNVALIDATED`. The Performance-checks boxes are intentionally left **unchecked** until that profiling is done. ## **Screenshots/Recordings** N/A — internal performance refactor; no user-facing UI change. ### **Before** N/A ### **After** N/A ## **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 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. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Performance-only memoization with unchanged outputs; config selector dependency avoids stale popular-network lists. > > **Overview** > **`useNetworkEnablement`** now returns a **stable object** and stable **`popularEvmNetworks` / `popularMultichainNetworks` / `popularNetworks`** references across re-renders when inputs are unchanged, instead of new literals and `?? []` arrays every time. > > Popular lists are built in one **`useMemo`**, keyed on the enablement controller and **`selectNetworkConfigurations`** (deep-equal), so lists stay correct when networks are added or removed—not only when the controller reference changes. Empty lists share a module-level **`EMPTY_ARRAY`** fallback for constant identity. > > Tests add **referential stability** coverage (`===` on the hook result and `popularNetworks` after `rerender`). This should reduce unnecessary **`useMemo`/`useEffect`** churn in many consumers (polling, token lists, balance UI) that today depend on those values or work around unstable arrays. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4c7c7fc. 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: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Vince Howard <vincenguyenhoward@gmail.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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
<!--
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?
-->
Remove more dead code around Snap keyring clients this time.
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
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**
<!-- mms-check: type=issue-link required=true -->
Fixes: N/A
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```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**
<!-- mms-check: type=screenshot required=true -->
<!-- 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**
<!-- mms-check: type=checklist required=true -->
<!--
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.
…31942) ## **Description** The bridge Redux slice had a local copy of `hasMinimumRequiredVersion` that duplicated the canonical implementation in `app/util/remoteFeatureFlag`. This PR removes the bridge-specific helper and updates the slice to import the shared utility instead. **Reason for change:** Avoid maintaining two equivalent version-check implementations that can drift over time. **Improvement:** Bridge feature-flag version gating now uses the same helper as the rest of the app (feature flag selectors, rewards, etc.), with existing coverage retained in `app/util/remoteFeatureFlag/index.test.ts`. Bridge-related test mocks were updated to target the shared module path. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [MCWP-665](https://consensyssoftware.atlassian.net/browse/MCWP-665) ## **Manual testing steps** N/A — internal refactor with no user-facing behavior change. Verified via unit tests: - `yarn jest app/util/remoteFeatureFlag/index.test.ts` - `yarn jest app/core/redux/slices/bridge/selectNoFeeAssets.test.ts` ## **Screenshots/Recordings** N/A — no UI changes. ### **Before** N/A ### **After** N/A ## **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 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. Made with [Cursor](https://cursor.com) [MCWP-665]: https://consensyssoftware.atlassian.net/browse/MCWP-665?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: Cursor <cursoragent@cursor.com>
…ive markets cp-7.81.2 (#31922) ## **Description** This PR updates Predict sport game market cards so Moneyline odds can update from live WebSocket market prices. The main sport market card now subscribes to live prices for the visible Moneyline tokens and displays live `bestAsk` values when available, falling back to static token prices when live data is missing or disabled. The featured carousel sport card uses the same live-price fallback for payout rows and buy button odds. The live sport-card price behavior is controlled by a default-on remote feature flag, `predictSportCardLivePrices`, so the WebSocket subscriptions can be disabled remotely while preserving the existing static price display. Diagnostic console logs were also added around live market price subscribe/unsubscribe events to make subscription behavior visible during validation. ## **Changelog** CHANGELOG entry: Updated Predict sport game market cards to show live Moneyline prices. ## **Related issues** Fixes: PRED-958 / PRED-1028 ## **Manual testing steps** ```gherkin Feature: Predict sport game card live prices Scenario: sport game cards show live Moneyline odds Given Predict sport game markets are visible on the feed or featured carousel And the predictSportCardLivePrices remote feature flag is enabled or missing When live market price WebSocket updates are received for the visible Moneyline tokens Then the sport game card odds update from the live best ask price And the card falls back to the static token price when live prices are unavailable Scenario: live sport card prices are disabled remotely Given the predictSportCardLivePrices remote feature flag is disabled When Predict sport game cards render Then the cards do not enable live market price subscriptions And the cards continue showing static token prices ``` Focused automated tests run: ```bash npx jest --runTestsByPath app/components/UI/Predict/utils/resolvePredictFeatureFlags.test.ts --coverage=false npx jest --runTestsByPath app/components/UI/Predict/selectors/featureFlags/index.test.ts --coverage=false npx jest --runTestsByPath app/components/UI/Predict/components/PredictMarketSportCard/PredictMarketSportCard.test.tsx --coverage=false npx jest --runTestsByPath app/components/UI/Predict/components/FeaturedCarousel/FeaturedCarouselSportCard.test.tsx --coverage=false ``` ## **Screenshots/Recordings** N/A - this change updates live odds data plumbing and feature flag behavior. Visual output is covered by component tests for the rendered odds text. ### **Before** N/A ### **After** N/A ## **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] N/A - targeted Predict card price display and feature flag gating change; Android-specific performance validation was not required. - [x] N/A - no expected impact on power-user account/token scenarios. - [x] N/A - no new production performance trace was needed for this UI price-display change. 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. ## **Description** Extended sports game-details tabs (moneyline, spreads, totals, and future market types) were not grouping or pricing outcomes reliably compared to Polymarket. This PR: 1. **Adds `enabledSportsMarketTypes`** to the `predictExtendedSportsMarkets` remote flag so outcome grouping respects an allowlist of supported market types (defaults to moneyline, spreads, and totals when the field is omitted on an enabled flag). 2. **Fixes spread line ordering** to match Polymarket’s ascending/descending display based on the first spread’s displayed sign. 3. **Polls REST ask prices** (`entry.sell`) for non-moneyline grouped outcomes while keeping moneyline on live WebSocket best-ask prices; polling pauses while the buy sheet is open. 4. **Refactors game-details outcome UI** into `outcomeGrouping.ts`, `PredictGameOutcomeCards.tsx`, `usePricedOutcomeGroup.ts`, and `utils.ts`, with unit tests colocated by module. **Why:** PRED-957 — corners, team totals, and first-half team totals (and related extended markets) were not showing up or behaving correctly in game details. **How:** Filter groupable outcomes at parse time, sort line markets consistently, price cards through the correct source per market type, and slim `PredictGameOutcomesTab` to routing + composition only. ## **Changelog** CHANGELOG entry: Fixed extended sports game-details outcome tabs to group enabled market types correctly, order spread lines like Polymarket, and show current buy prices for non-moneyline markets. ## **Related issues** Fixes: PRED-957 ## **Manual testing steps** ```gherkin Feature: Extended sports game details outcomes Scenario: User views grouped game lines with live prices Given extended sports markets are enabled for the game league And enabledSportsMarketTypes includes moneyline, spreads, and totals When the user opens a live or upcoming game details screen And selects the Game Lines chip Then moneyline, spreads, and totals subgroups render And spread lines appear in the same order as on Polymarket And non-moneyline buy button prices reflect REST ask prices And moneyline buy button prices reflect live WebSocket best ask Scenario: Price polling pauses while buy sheet is open Given the user is on a game details spreads or totals card When the user opens the buy preview sheet Then REST price polling stops until the sheet is dismissed Scenario: Enabled market types flag limits grouped tabs Given enabledSportsMarketTypes is set to ["moneyline"] only When the user opens game details for an extended-league game Then only moneyline appears in outcome groups And the full outcomes list remains available on the market object ``` **Automated tests run locally:** ```bash npx jest --runTestsByPath \ app/components/UI/Predict/components/PredictGameDetailsContent/utils.test.ts \ app/components/UI/Predict/components/PredictGameDetailsContent/usePricedOutcomeGroup.test.tsx \ app/components/UI/Predict/components/PredictGameDetailsContent/PredictGameOutcomesTab.test.tsx \ app/components/UI/Predict/providers/polymarket/outcomeGrouping.test.ts \ app/components/UI/Predict/providers/polymarket/utils.test.ts \ app/components/UI/Predict/utils/resolvePredictFeatureFlags.test.ts \ --coverage=false ``` ## **Screenshots/Recordings** N/A — manual QA pending on device/simulator. Will attach before/after recordings of game-details Game Lines (spreads order + buy prices) before marking Ready for review. ### **Before** <!-- Add recording: spread lines out of order / stale buy prices --> ### **After** <!-- Add recording: spread lines match Polymarket / REST prices on spreads & totals --> ## **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 ## **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.
…ions (#31938) ## **Description** <!-- mms-check: type=text required=true --> <!-- 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? --> Cashback redemption is moving to Money Accounts as the primary destination for users outside restricted regions. Previously, every user without an approved Linea funding source was prompted to set up Linea USDC delegation — even when Money Account was the correct redemption path. This PR updates the Cashback screen to branch setup and withdrawal gating by region and feature flag: - **Supported regions** (Money Account FF enabled and user not residency-blocked): withdrawal requires a delegated Money Account. Users without one see a new Money Account warning and are redirected to the Money Account link flow via `startLinkFlow`, returning to Cashback after setup. - **UK / restricted regions or FF off**: both Linea and Money Account delegations are valid redemption destinations (backend resolves the landing wallet by spending priority). The gate accepts either funding source so UK users with only Monad/Money Account delegation are no longer shown a false Linea warning. The existing Linea USDC Spending Limit redirect is preserved when neither destination is configured. Also includes a small fix to `truncateAddress` so Solana base58 addresses are truncated directly instead of falling through the EVM checksum path. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- 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: Updated cashback redemption setup to redirect supported-region users to Money Account delegation instead of Linea USDC ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CARD-417 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Cashback redemption destination routing Background: Given I am a verified MetaMask Card holder with available mUSD back balance And I am on the Card Cashback screen Scenario: supported-region user without Money Account sees Money Account setup prompt Given the Money Account feature flag is enabled And my card residency is outside a blocked region (e.g. US) And I do not have a Money Account delegated for card spending When I open the Cashback screen Then I should see a "Set up Money Account" warning banner And the Withdraw button should be disabled When I tap "Set up Money Account" Then the Money Account link flow should open And after completing setup I should return to the Cashback screen Scenario: supported-region user with Money Account delegated can withdraw Given the Money Account feature flag is enabled And my card residency is outside a blocked region And I have a Money Account delegated for card spending When I open the Cashback screen Then I should not see a funding setup warning And the Withdraw button should be enabled Scenario: UK user with only Linea funding can withdraw Given my card residency is in the UK (blocked region) And I have approved Linea USDC funding And I do not have a Money Account delegated When I open the Cashback screen Then I should not see a funding setup warning And the Withdraw button should be enabled Scenario: UK user with only Money Account delegated can withdraw Given my card residency is in the UK (blocked region) And I do not have approved Linea funding And I have a Money Account delegated for card spending When I open the Cashback screen Then I should not see a Linea funding warning And the Withdraw button should be enabled Scenario: UK user with neither destination sees Linea setup prompt Given my card residency is in the UK (blocked region) And I do not have approved Linea funding And I do not have a Money Account delegated When I open the Cashback screen Then I should see a "Set up Linea funding" warning banner When I tap "Set up funding" Then I should be navigated to Spending Limit with Linea USDC pre-selected Scenario: Money Account FF off uses UK-style Linea or Monad gate Given the Money Account feature flag is disabled And I have a Money Account delegated but no Linea funding When I open the Cashback screen Then I should not see a funding setup warning And the Withdraw button should be enabled ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- 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** <!-- mms-check: type=checklist required=true --> <!-- 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 --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** Adds a scheduled GitHub Actions workflow that aggregates Playwright JSON artifacts from Appium smoke runs on `main` (`ci.yml`) and posts infra/flaky/watch test summaries to Slack via the `playwright-test-health-report` action ([github-tools](https://github.com/MetaMask/github-tools/tree/main/.github/actions/playwright-test-health-report), merged in [#262](MetaMask/github-tools#262)). Pinned to `MetaMask/github-tools@4a2ddd75`. Runs weekdays at 10:00 and 15:00 UTC, with `workflow_dispatch` and a configurable lookback window. Uses `SLACK_WEBHOOK_PLAYWRIGHT_HEALTH_REPORT`. ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: Appium CI health reporting follow-up to #31730 / #31756 ## **Manual testing steps** ```gherkin Feature: Playwright Appium test health report Scenario: PR trigger posts report to Slack Given SLACK_WEBHOOK_PLAYWRIGHT_HEALTH_REPORT_TEST was configured in repo secrets And this PR was open against main with a temporary pull_request trigger When the pull_request workflow ran on playwright-test-health-report.yml changes Then a Playwright Test Health Report (Mobile Appium) message appeared in Slack (see screenshot) Scenario: Scheduled report after merge to main Given the workflow exists on main with SLACK_WEBHOOK_PLAYWRIGHT_HEALTH_REPORT configured When the weekday schedule runs or an engineer triggers workflow_dispatch with lookback_days=1 Then the report is generated from main ci.yml Playwright JSON artifacts ``` ## **Screenshots/Recordings** ### **Before** N/A — new workflow only. ### **After** Slack report from PR test run (1-day lookback on `main` Appium smoke):  ## **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 ## **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. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **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? --> Adds a new memoized selector, `selectShouldShowMoneyEducation`, that gates the Money account education/warning screen. It returns `true` only when the user is in the US **and** is not authenticated with the card service **and** is not a cardholder. To support it, this PR also adds `selectIsUserInUS`, which derives US residency from the detected geolocation (`getDetectedGeolocation`). It handles both `US` and `US-CA` (country-region) formats, is case-insensitive, and defaults to `false` when geolocation is unknown or still loading — consistent with the existing `selectIsMoneyAccountGeoEligible` pattern in this file. The "authenticated" and "cardholder" signals reuse the existing `selectIsCardAuthenticated` and `selectIsCardholder` selectors from `app/selectors/cardController`. ## **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` --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: null ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> N/A — selector-only change covered by unit tests (`eligibility.test.ts`). The selector is not yet wired into a UI surface, so there is no user-facing flow to exercise manually. ## **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. --> - [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. --> - [ ] 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 --> --------- 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. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- 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? --> Users with access to the Money account tab no longer need a separate Card entry point in the wallet header. This PR removes that redundant discovery path when the Money account is both feature-flag enabled and geo-eligible, while keeping the Card button visible in regions where Money is unavailable so users can still discover MetaMask Card. Changes: - **Wallet header**: Hide the `CardButton` when `isMoneyAccountVisible` (Money account flag on and geo-eligible), matching the same inline pattern used by `MainNavigator` and the wallet `MoneyBalanceCard`. - **Money Home**: Gate `MoneyMetaMaskCard` upsell and verifying modes on Money account visibility via `deriveMoneyMetaMaskCardMode`; link/manage modes continue to use existing linkage requirements. - **Card ↔ Money linkage**: `useMoneyAccountCardLinkage` now requires Money account flag **and** geo eligibility before reporting base requirements / `canLink`. Card residency blocking reads `selectMoneyAccountGeoBlockedCountries` instead of the legacy Earn mUSD conversion geo list. Unit and component-view tests cover wallet header visibility, Money Home card section gating, linkage hook flag/geo behavior, and updated residency selector fixtures. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- 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: Removed the wallet header Card button for users who have the Money account tab available ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CARD-410 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Card entry point gating when Money account is visible Background: Given I am logged into MetaMask Mobile And I have a wallet with at least one account Scenario: wallet header Card button is hidden when Money account is available Given the Money account feature flag is enabled And my detected geolocation is eligible for Money account (e.g. US, not in blocked regions) When I open the Wallet home screen Then I should see the Money tab in the bottom navigation And I should not see the Card icon in the wallet header Scenario: wallet header Card button remains when Money account is geo-ineligible Given the Money account feature flag is enabled And my detected geolocation is in a blocked region (e.g. GB when GB is blocked) When I open the Wallet home screen Then I should not see the Money tab in the bottom navigation And I should see the Card icon in the wallet header Scenario: wallet header Card button remains when Money account flag is off Given the Money account feature flag is disabled When I open the Wallet home screen Then I should not see the Money tab in the bottom navigation And I should see the Card icon in the wallet header Scenario: Money Home hides card upsell when Money account is not visible Given the Money account feature flag is enabled And my detected geolocation is in a blocked region And I navigate to Money Home via deeplink or internal route When the Money Home screen loads Then I should not see the MetaMask Card upsell section Scenario: Money Home shows card upsell when Money account is visible Given the Money account feature flag is enabled And my detected geolocation is eligible And I am not a cardholder When I open the Money tab Then I should see the MetaMask Card upsell section on Money Home Scenario: Card Home link CTA respects Money account visibility Given the Money account feature flag is enabled And my detected geolocation is eligible And I have a MetaMask Card that is not linked to my Money account When I open Card Home Then I should see the link Money account CTA When the Money account feature flag is disabled or geolocation is blocked Then the link Money account CTA should not appear on Card Home ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- 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** <!-- mms-check: type=checklist required=true --> <!-- 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 --> --------- 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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Fixes Predict the Pitch campaign stats navigation and aligns the stats
page with the campaign details summary.
1. **Navigation fix:** Register `RewardsPredictThePitchCampaignStats` in
`RewardsNavigator` so tapping through from campaign details no longer
throws an unhandled `NAVIGATE` action.
2. **Stats page parity:** Add a **Markets traded** cell to
`PredictThePitchCampaignStatsView` on the same row as **Total volume**,
using the same display rules as `PredictThePitchStatsSummary` (`x/y`
below minimum, count only when met).
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not be labeled with
`no-changelog`,
write a short User-Facing description in the past tense.
-->
CHANGELOG entry: Fixed Predict the Pitch campaign stats navigation and
added markets traded to the stats performance section.
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Refs: Predict the Pitch campaign stats navigation error
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: Predict the Pitch campaign stats
Scenario: user opens campaign stats from details
Given the user is opted into an active Predict the Pitch campaign
And the user is on the campaign details screen
When the user navigates to campaign stats
Then the stats screen opens without a navigation error
And performance shows ROI, PnL, total volume, and markets traded on one row
Scenario: markets traded display below minimum
Given the user's leaderboard position has marketsTraded below minimumMarketsTraded
When the user views campaign stats
Then markets traded is shown as "x/y"
Scenario: markets traded display at or above minimum
Given the user's leaderboard position meets the minimum markets traded requirement
When the user views campaign stats
Then markets traded shows the count only
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
Navigation to stats failed with: `The action 'NAVIGATE' with payload
{"name":"RewardsPredictThePitchCampaignStats",...} was not handled by
any navigator.`
### **After**
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-06-17 at 17 04 08"
src="https://github.com/user-attachments/assets/41f6cdc0-bf34-4dda-97ce-b5440f33c24b"
/>
Stats screen loads successfully and shows markets traded beside total
volume.
N/A — screenshots not attached in this update.
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )