[pull] main from MetaMask:main#635
Merged
pull[bot] merged 61 commits intoReality2byte:mainfrom Mar 27, 2026
Merged
Conversation
…alance layout (#27714) ## **Description** Cherry pick swaps a/b test that barely missed RC cutoff. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR adds an A/B test for the bridge token selector balance layout. Control keeps the current presentation by showing fiat balance on the top row and keeping the ticker in the token balance text. Treatment moves the token balance to the top row, removes the duplicate ticker from the token balance text, and keeps the top and bottom rows aligned with the intended size and color hierarchy. The PR also passes the active experiment through the bridge page-view and submit analytics paths using `active_ab_tests` so the treatment can be evaluated against downstream conversion metrics. ## **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: Added an experiment for the bridge token selector balance layout. ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Bridge token selector balance layout experiment Scenario: User sees the control layout in the bridge token selector Given the token selector balance layout experiment is in the control variant And the user opens the Bridge flow When the token selector list is shown Then the fiat balance is shown on the top row And the token balance is shown on the bottom row with the ticker included Scenario: User sees the treatment layout in the bridge token selector Given the token selector balance layout experiment is in the treatment variant And the user opens the Bridge flow When the token selector list is shown Then the token balance is shown on the top row without the duplicate ticker And the fiat balance is shown on the bottom row Scenario: Analytics include the active experiment Given the token selector balance layout experiment is active When the user opens the Bridge flow And submits a bridge quote Then the relevant page-view and submit analytics payloads include active_ab_tests for the active experiment ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** Control variant: <img width="322" height="683" alt="Screenshot 2026-03-18 at 19 11 16" src="https://github.com/user-attachments/assets/572bffbe-8ab3-446c-8da8-564cd0ded31d" /> ### **After** Treatment variant: <img width="317" height="690" alt="Screenshot 2026-03-19 at 18 24 35" src="https://github.com/user-attachments/assets/46b6241d-dd00-4ee1-8de6-7097a7533d14" /> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes bridge token list balance rendering and threads new `activeAbTests` metadata through bridge submission/page-view analytics, which could affect UI correctness and controller call signatures if mismatched. > > **Overview** > Adds a new A/B experiment (`swapsSWAPS4242AbtestTokenSelectorBalanceLayout`) that toggles the bridge token selector’s balance layout: *control* keeps fiat-on-top with token balance including ticker, while *treatment* shows token balance first and can omit the ticker. > > Updates bridge analytics and submission paths to include an `active_ab_tests`/`activeAbTests` array when experiments are active (now aggregating both the existing numpad quick actions test and the new token selector test), with new/updated unit tests covering the variant-driven UI ordering and the forwarded experiment metadata. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fb21046. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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. ## **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.
…ck cp-7.71.0 (#27763) - chore: Exempt `metamaskbotv2` from CLA check cp-7.71.0 (#27758) ## **Description** The CLABot workflow has been updated to exempt `metamaskv2` (i.e. commits created by Patroll tokens) from the CLA check. We saw the CLA check fail recently on a release branch due to some commits appearing for the first time from Patroll (see #27708 (comment)). This change will fix that CI failure. ## **Changelog** CHANGELOG entry: null ## **Related issues** N/A ## **Manual testing steps** N/A ## **Screenshots/Recordings** 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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk workflow change limited to expanding the CLA bot allowlist; main impact is potentially skipping CLA enforcement for this additional bot account. > > **Overview** > Updates the `CLA Signature Bot` GitHub Actions workflow to add `metamaskbotv2[bot]` to the CLA exemption allowlist, preventing CLA check failures on PRs/merge groups created by that bot. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f1f4342. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [0f0a400](0f0a400) Co-authored-by: Mark Stacey <markjstacey@gmail.com>
…re flag to single selector cp-7.71.0 (#27762) - refactor: simplify rampsUnifiedBuyV2 feature flag to single selector cp-7.71.0 (#27760) ## **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? --> The `rampsUnifiedBuyV2` feature flag previously used three chained selectors (`selectRampsUnifiedBuyV2Config` → `selectRampsUnifiedBuyV2ActiveFlag` / `selectRampsUnifiedBuyV2MinimumVersionFlag`) and a custom 2-arg `hasMinimumRequiredVersion` utility. This was inconsistent with how other feature flags (e.g. homepage redesign) are handled in the codebase. This PR consolidates the three selectors into a single `selectRampsUnifiedBuyV2Enabled` selector that uses the shared `validatedVersionGatedFeatureFlag` utility from `app/util/remoteFeatureFlag`. The remote flag shape is updated from `{ active, minimumVersion }` to `{ enabled, minimumVersion }` to match the standard `VersionGatedFeatureFlag` type. **Key changes:** - **Selector file** (`rampsUnifiedBuyV2.ts`): Replaced 3 selectors + `RampsUnifiedBuyV2Config` interface with a single `selectRampsUnifiedBuyV2Enabled` selector - **Hook** (`useRampsUnifiedV2Enabled.ts`): Simplified from two `useSelector` calls + `hasMinimumRequiredVersion` to a single `useSelector` - **Utility** (`isRampsUnifiedV2Enabled.ts`): Simplified to delegate directly to the selector - **Controller init** (`ramps-controller-init.ts`): Replaced local interface + `hasMinimumRequiredVersion` with `validatedVersionGatedFeatureFlag`; imports shared flag key constant - **Flag key constant**: Exported `RAMPS_UNIFIED_BUY_V2_FLAG_KEY` from the selector file as single source of truth - **E2E mocks/fixtures**: Updated flag shape from `active` to `enabled` in `FixtureBuilder`, `feature-flags-mocks`, and `feature-flag-registry` ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** N/A — this is a pure refactor of internal selector structure. Behavior is unchanged. All unit tests have been updated and pass. ## **Screenshots/Recordings** ### **Before** N/A ### **After** https://github.com/user-attachments/assets/13ab83a0-f3b1-4862-95cc-ec02fc5b89b5 ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches feature-flag gating that controls whether the ramps V2 flow and controller initialization run, and changes the expected remote flag shape from `active` to `enabled`. Main risk is misconfigured/older flag payloads causing the feature to be incorrectly disabled. > > **Overview** > Simplifies `rampsUnifiedBuyV2` enablement checks by replacing the chained config/active/min-version selectors and custom gating logic with a single `selectRampsUnifiedBuyV2Enabled` that delegates to `validatedVersionGatedFeatureFlag`. > > Updates the Ramp hook/utility and `ramps-controller-init` to consume this unified version-gated flag (keeping the build-flag override), and standardizes the remote flag payload from `{ active, minimumVersion }` to `{ enabled, minimumVersion }` across unit tests, E2E mocks/fixtures, and the feature-flag registry defaults. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 3edd562. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [73198ff](73198ff) Co-authored-by: Pedro Pablo Aste Kompen <wachunei@gmail.com> Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
…uring Transak navigation reset -> cp-7.71.0 (#27772) - fix(ramps): Preserve user-entered amount during Transak navigation reset -> cp-7.71.0 (#27742) ## **Description** Fixes the Buy flow amount reverting from the user-entered value back to the default $100 during the Transak native provider loading transition. When a user enters a custom amount (e.g. $30) and taps Continue, the Transak routing callbacks use `navigation.reset()` to rebuild the navigation stack with a fresh `BuildQuote` screen as the base route. This fresh instance initialized with `DEFAULT_AMOUNT = 100`, causing a visible flash of $100 during the transition to the checkout/KYC screen. The fix passes the current `quote.fiatAmount` as a route param (`amount`) to the `AMOUNT_INPUT` base route in every `navigation.reset()` call. `BuildQuote` now reads `params?.amount` as the initial state, preserving the user-entered amount through stack resets. ## **Changelog** CHANGELOG entry: Fixed Buy flow amount input reverting to $100 during Transak native provider checkout transition. ## **Related issues** Fixes: [TRAM-3348](https://consensyssoftware.atlassian.net/browse/TRAM-3348) ## **Manual testing steps** ```gherkin Feature: Amount persists through Transak native provider checkout transition Scenario: Custom amount does not revert to default during Continue loading Given the user is on the Buy screen with Transak Native provider And the default amount is $100 When the user changes the amount to $30 And the user taps Continue Then the displayed amount remains $30 during the loading transition And the amount does not flash back to $100 Scenario: Default amount is preserved when no custom amount is entered Given the user is on the Buy screen with Transak Native provider And the default amount is $100 When the user taps Continue without changing the amount Then the displayed amount remains $100 throughout the flow Scenario: Amount persists when navigating back from KYC/checkout screens Given the user entered $50 and proceeded through Continue When the user navigates back to the Buy screen Then the amount input shows $50 (not $100) ``` ## **Screenshots/Recordings** ### **Before** <!-- Screenshot/video showing amount reverting from $30 to $100 during loading --> https://github.com/user-attachments/assets/ba7fb42b-c43a-43f8-b438-0484090d7895 ### **After** <!-- Screenshot/video showing amount staying at $30 during loading transition --> https://github.com/user-attachments/assets/6d60c1ae-f0eb-448b-b7f3-297efbce85df https://github.com/user-attachments/assets/099ebf69-face-4bb0-8568-80357f59b35e <img width="523" height="877" alt="Screenshot 2026-03-20 175035" src="https://github.com/user-attachments/assets/6bebcd4a-c04d-40c6-90d4-7e50ed683824" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Updates Transak native-provider navigation/reset logic and initial screen state; mistakes could regress Buy/KYC routing or amount display during transitions, but changes are localized and covered by tests. > > **Overview** > Fixes the Transak native Buy flow so the user-entered fiat amount is preserved when the app uses `navigation.reset()` during KYC/checkout transitions. > > `BuildQuote` now supports an `amount` route param to initialize the amount state (and to prevent region defaults from overriding it), and `useTransakRouting` propagates this amount through all reset-based navigation paths (KYC approved → checkout, KYC forms, additional verification, verify identity, and KYC webview). Tests are updated/added to assert the amount is passed through routing callbacks and used as the initial displayed value. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a8bdee0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [8a03f66](8a03f66) Co-authored-by: Yu-Gi-Oh! <54774811+imyugioh@users.noreply.github.com> Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
….0 (#27801) - fix(ramp): fixes order details bug cp-7.71.0 (#27755) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Fixes an order details UI bug where the title for bank transfer details was displaying for non bank-transfer orders. [TRAM 3359](https://consensyssoftware.atlassian.net/browse/TRAM-3359) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fixes an order details UI bug ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### * <img width="458" height="974" alt="Screenshot 2026-03-20 at 10 03 02 AM" src="https://github.com/user-attachments/assets/4d94ca14-1e17-401d-945b-5f38acf28e4a" /> *Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> <img width="451" height="976" alt="Screenshot 2026-03-20 at 11 39 11 AM" src="https://github.com/user-attachments/assets/19595c85-e138-4fdc-bb52-a57271593ff8" /> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI-only change that gates rendering of the bank details section; main risk is unintentionally hiding bank details if upstream field names/structure change. > > **Overview** > Fixes an order details UI bug where the bank-transfer section header could render for non-bank-transfer orders. > > `OrderContent` now returns `null` for `bankDetailFields` unless at least one expected bank detail field (e.g., amount, routing/account, IBAN/BIC) is present, and tests add coverage for absent/empty/non-matching `paymentDetails` vs. bank-transfer/SEPA scenarios. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 65f6cfc. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [7e9748e](7e9748e) Co-authored-by: George Weiler <georgejweiler@gmail.com>
Resolved conflicts between stable (7.70.0) and release/7.71.0: Build/version: take release/7.71.0 (7.71.0, build 4148) - android/app/build.gradle, ios project, bitrise.yml Dependencies: take release/7.71.0 versions - package.json, yarn.lock Source: take release/7.71.0 (newer release work) - MarketInsightsView, testIds, mUSD events, MusdAggregatedRow tests, mp4Mock CHANGELOG, AndroidManifest, remote flag defaults, and selector updates from stable. Merge with "Create a merge commit" — do NOT squash. Made-with: Cursor
…re flags hydrate cp-7.71.0 (#27807) - fix: start Ramps V2 init when remote feature flags hydrate cp-7.71.0 (#27778) ## **Description** On a fresh install, `RemoteFeatureFlagController` loads flags asynchronously while Engine builds controllers. `rampsControllerInit` previously read the unified buy V2 flag only once; if flags were not in state yet, `RampsController.init()` never ran, so buy token lists stayed empty until a full app restart. This change subscribes to `RemoteFeatureFlagController:stateChange` (already delegated on `RampsControllerInitMessenger`) and re-runs the same V2 startup path when remote flag state updates. Order-status subscriptions are registered at most once. `RampsController.init()` remains idempotent for repeated calls. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-3350 ## **Manual testing steps** ```gherkin Feature: Unified buy V2 after fresh install Scenario: Buy token list loads without restarting the app Given a dev build with unified buy V2 enabled via remote flags And the app is installed fresh (or remote flag cache cleared) When the user completes onboarding and opens Buy / token selection Then tokens and providers load without requiring an app restart ``` ## **Screenshots/Recordings** <div> <a href="https://www.loom.com/share/e80a3794612d4030aa963834e5a8d7bf"> <p>Fix Ramps controller not initializing on fresh install - Watch Video</p> </a> <a href="https://www.loom.com/share/e80a3794612d4030aa963834e5a8d7bf"> <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/e80a3794612d4030aa963834e5a8d7bf-13202ae1a2494608-full-play.gif#t=0.1"> </a> </div> ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds a new subscription-driven initialization path triggered by `RemoteFeatureFlagController:stateChange`, which can change startup behavior and potentially cause repeated init/polling if underlying idempotency assumptions are wrong. > > **Overview** > Ensures Unified Buy V2 startup runs even when remote feature flags hydrate *after* Engine/controller initialization by subscribing to `RemoteFeatureFlagController:stateChange` and re-checking the V2 flag. > > Refactors V2 startup into a helper that conditionally calls `RampsController.init()`/`startOrderPolling()` and registers order-status subscriptions only once. Updates tests to cover the “flag off at startup then enabled on stateChange” scenario and to include `subscribe` in the thrown-state mock. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 78ff800. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [c6d96b6](c6d96b6) Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com>
…rder data is not yet available cp-7.71.0 (#27812) - fix(ramps): fixes 0 ETH ramps issue when order data is not yet available cp-7.71.0 (#27756) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** "0 ETH" was displayed on some order pages when the order info was not yet available. This bug fixes by adding "..." placeholder until the info arrives. [TRAM-3360](https://consensyssoftware.atlassian.net/browse/TRAM-3360) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixes small UI issue with ramps orders ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> <img width="544" height="319" alt="Screenshot 2026-03-20 at 11 51 50 AM" src="https://github.com/user-attachments/assets/cc2fd384-2c79-49c0-93fa-66b07192ffa6" /> <img width="436" height="933" alt="Screenshot 2026-03-20 at 11 53 40 AM" src="https://github.com/user-attachments/assets/1d350708-6bfe-4fae-af10-80868d26914c" /> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adjusts order-details loading/terminal-state logic and amount formatting, which could change what users see for certain pending/failed orders; impact is limited to UI display and snapshots. > > **Overview** > Prevents ramps order UIs from showing `0 ETH`/`0` amounts when data hasn’t arrived by treating `0`/missing `cryptoAmount` (and related fiat fields) as **unknown** and rendering an `...` placeholder in both the orders list (`displayOrder`) and order details (`OrderContent`). > > Order details now distinguishes *loading* vs *terminal* statuses (e.g., `Failed`, `Cancelled`) so terminal orders without amounts render placeholders instead of skeleton loaders, and fiat `fees`/`total` formatting is switched to `formatWithThreshold` currency formatting (snapshot updates included). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a9bc072. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> [174afa0](174afa0) Co-authored-by: George Weiler <georgejweiler@gmail.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
## Description Sync `stable` into `release/7.71.0` so the release branch includes everything merged to stable through **7.70.0** (e.g. hotfixes and changelog), matching the pattern from [#27468](#27468). ## Changelog CHANGELOG entry: null --- Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it alters Android permission declarations (Bluetooth/location) and changes feature-flag override precedence in certain build environments, which could affect runtime behavior or Play Store compliance if misconfigured. > > **Overview** > Updates `CHANGELOG.md` with release notes for `7.70.0`, adds `7.69.1`/`7.68.3`, and updates the compare links for the new tags. > > Adjusts Android Bluetooth-related permissions in `AndroidManifest.xml` by removing the API 30 maxSdk constraint on `ACCESS_FINE_LOCATION` and dropping the `neverForLocation` flag from `BLUETOOTH_SCAN`. > > Changes feature-flag selectors so that when `BUILDS_ENABLED_WITH_GH_ACTIONS_TEMPORARY=true` (and not `E2E`), **remote flags take precedence** and local env overrides are ignored for `extensionUxPna25` and `additionalNetworksBlacklist`, plus adds a small `buildTimeDefaultsConfig` helper for this gating. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 63cee1a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…etaMask/core#8251 -> cp-7.71.0 (#27823) - chore(deps): ramps-controller preview for MetaMask/core#8251 -> cp-7.71.0 (#27709) ## **Description** Integration PR to validate **MetaMask/core** changes in mobile CI/E2E by resolving `@metamask/ramps-controller` from a **preview** npm package (`previewBuilds` in `package.json` + updated `yarn.lock`). No application code changes. **Core PR:** MetaMask/core#8251 After core merges and a **released** version is published, this PR should be updated to remove `previewBuilds` and bump `dependencies` to the real version before merge. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A (validation / dependency preview only) ## **Manual testing steps** ```gherkin Feature: ramps-controller preview validation Scenario: app resolves preview package Given a clean install from this branch When the app bundles and runs Then @metamask/ramps-controller resolves to the preview version from previewBuilds Scenario: ramps flows still work Given the app is built from this branch When user exercises on-ramp flows that use ramps-controller Then no regressions vs main (same UX; underlying package is preview) ``` ## **Screenshots/Recordings** N/A — dependency-only change. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [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. --- <!-- Optional: paste below into GitHub if you use Cursor Bugbot summary --> > [!NOTE] > **Low Risk** > Low risk because this is a dependency source/version switch for `@metamask/ramps-controller` with no application code changes; main risk is behavior changes introduced by the preview package at runtime. > > **Overview** > Switches `@metamask/ramps-controller` to a **preview build** via `previewBuilds` in `package.json` and `yarn.lock` (e.g. `@metamask-previews/ramps-controller@12.0.0-preview-434bd0c`). Update the preview version string if the bot publishes a newer build for core#8251. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk patch-level dependency update; main risk is any runtime behavior changes in `@metamask/ramps-controller` affecting ramp flows, plus potential test fixture mismatches if state shape changes again. > > **Overview** > Updates `@metamask/ramps-controller` from `12.0.0` to `12.0.1` (including lockfile resolution changes). > > Aligns the default E2E/unit fixture (`default-fixture.json`) with the newer `RampsController` state shape by adding persisted sub-state for countries, providers/payment methods/tokens, native provider (Transak) auth/kyc/user details, requests, and orders. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0b2fc2f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [4a4f0ae](4a4f0ae) Co-authored-by: Yu-Gi-Oh! <54774811+imyugioh@users.noreply.github.com>
…s view entry point cp-7.71.0 (#27821) - chore: adds market insights metric to Perps view entry point cp-7.71.0 (#27814) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds two missing metric events to the Perps Market Details view to bring it to parity with the token details flow. `MARKET_INSIGHTS_OPENED` now fires whenever a user taps the Market Insights entry card, and `PERPS_SCREEN_VIEWED` now includes a `market_insights_displayed` boolean property that reflects whether a report was actually shown, with the event held until the insights fetch resolves so the value is fully accurate. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: changes are limited to analytics instrumentation and event timing gated on Market Insights loading, with added unit tests to validate tracking and navigation behavior. > > **Overview** > Adds missing Market Insights instrumentation to the Perps market details screen. > > `PerpsMarketDetailsView` now fires `MetaMetricsEvents.MARKET_INSIGHTS_OPENED` (with `perps_market`) when the Market Insights entry card is tapped, and delays `MetaMetricsEvents.PERPS_SCREEN_VIEWED` until insights loading completes so it can include an accurate `market_insights_displayed` boolean. > > Updates/extends `PerpsMarketDetailsView.test.tsx` with mocks for `useMarketInsights`/feature flags and new tests covering the new tracking payloads and navigation to `Routes.MARKET_INSIGHTS.VIEW` with `isPerps: true`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit dc97116. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [6e0f698](6e0f698) Co-authored-by: António Regadas <antonio.regadas@consensys.net>
…ack redirection cp-7.71.0 (#27829) - fix(ramps): improve external-browser callback redirection cp-7.71.0 (#27804) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **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? --> Fixes the external-browser return flow for unified ramps by moving callback resolution out of Build Quote and into Order Details. The bug was that external-browser returns were resolved too early in BuildQuote. If callback parsing or order lookup failed there, users could get bounced around or end up on a broken Order Details screen. This change fixes that by moving callback resolution into Order Details itself. BuildQuote now only hands off the callback context, and Order Details fetches the real order itself. That makes the flow more reliable: bailed callbacks return to Build Quote, and real fetch failures show a retryable error instead of a broken redirect. **What changed** - **Build Quote -> Order Details callback handoff** After a successful external-browser return, Build Quote now navigates to Order Details with the full `callbackUrl`, `providerCode`, and `walletAddress` instead of trying to resolve the order immediately. - **Order Details callback bootstrap** Order Details now supports loading from callback params, fetching the real order on first render, and updating route params once the order has been resolved. - **Bailed / invalid callback handling** If the callback resolves to a bailed order state or no usable order, the user is sent back to Build Quote instead of landing on a blank or broken Order Details screen. - **Retryable callback error state** If fetching the order from the callback URL fails, Order Details now shows a retryable error screen rather than silently resetting away. This makes transient backend/network failures recoverable. - **Navigation tests updated** Tests were updated to reflect the callback-based route shape and the new Order Details retry behavior. **What stays untouched** This PR does not change Order Content amount rendering, list display formatting, or duplicate placeholder cleanup. It is scoped only to fixing the external-browser redirection and callback-resolution path. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> Paypal Order going to build quote page first: Uploading Screen Recording 2026-03-23 at 1.00.39 PM.mov… ### **After** <!-- [screenshots/recordings] --> Native Transak Redirection https://github.com/user-attachments/assets/32d1a7f9-23c7-4df1-aba8-f639338d7a6f Bailed Paypal order (return to build quote page): https://github.com/user-attachments/assets/8ed07fa3-e7df-4b69-b2f0-9318799c8249 Paypal order going to order details page: https://github.com/user-attachments/assets/5a2e8489-a4b0-488d-8aca-7982df63c45c ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the unified ramps external-browser return flow and navigation params, which can impact users reaching the correct order state after checkout; failures may surface as new retry/error behaviors. > > **Overview** > Fixes unified ramps external-browser return handling by **moving callback URL resolution out of `BuildQuote` and into `OrderDetails`**. > > `BuildQuote` no longer calls `getOrderFromCallback`/`addOrder` on InAppBrowser success; it now resets navigation to `OrderDetails` with `callbackUrl`, `providerCode`, and `walletAddress`. `OrderDetails` bootstraps from these callback params, fetches the real order (bailing back to `BuildQuote` for invalid/bailed statuses), updates route params to the resolved `orderId`, and shows a retryable error state if the callback fetch fails. > > Updates `rampsNavigation` to support an `OrderDetails` route shaped around callback params (and makes `orderId` optional), and adjusts/adds tests to cover the new handoff and retry behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0eabfd6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [4efb704](4efb704) Co-authored-by: George Weiler <georgejweiler@gmail.com>
) - fix: support webcredentials cp-7.71.0 (#27741) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This pr patch the expo-web-browser to support https redirect schema Taking reference from expo-web-browser sdk 55 https://github.com/expo/expo/blob/308031a6665f885811760aff7aebb68aea4a846a/packages/expo-web-browser/ios/WebAuthSession.swift#L36 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: expo-web-browser support https redirect scheme CHANGELOG entry: use webcredential for ios google login ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes iOS `ASWebAuthenticationSession` callback configuration and entitlements, which can affect login/redirect flows and associated-domain behavior. > > **Overview** > Enables **HTTPS redirect-based auth callbacks** on iOS by patching `expo-web-browser`’s `WebAuthSession` to use iOS 17.4+/macOS 14.4+ `.https(host:path)` callbacks when the `redirectUrl` is `https`, falling back to the legacy `callbackURLScheme` behavior otherwise. > > Updates iOS entitlements (`MetaMask.entitlements` and `MetaMaskDebug.entitlements`) to include `webcredentials:link.metamask.io`, and wires the patch into the build via a Yarn `resolutions` entry plus corresponding `yarn.lock` changes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7730be3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [a2f8164](a2f8164) Co-authored-by: ieow <4881057+ieow@users.noreply.github.com>
…27868) - feat: add metrics opt In event (#27846) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** * Add Metrics Opt In event in Onboarding, Optinmetrics and MetaMetricsAndDataCollectionSection screen <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: METRICS_OPT_IN analytics on user opt-in Scenario: User opts in from onboarding MetaMetrics screen Given the user is on the onboarding MetaMetrics / data collection screen with basic usage enabled by default When the user continues without turning off basic usage Then the app completes onboarding as before and analytics pipelines receive a "Metrics Opt In" event with onboarding location and expected properties in addition to "Analytics Preference Selected" Scenario: User enables MetaMetrics from Settings Given the user is logged in and MetaMetrics is currently off When the user opens Settings > Security & privacy and turns the MetaMetrics switch on Then the app opts in successfully and emits "Metrics Opt In" with settings location and updated_after_onboarding before the preference-selected event Scenario: User enables marketing which requires MetaMetrics Given MetaMetrics is off and marketing data collection is off When the user turns marketing data collection on (which enables MetaMetrics) Then MetaMetrics turns on and "Metrics Opt In" is recorded before the subsequent preference events ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="702" height="94" alt="Screenshot 2026-03-24 at 3 35 19 PM" src="https://github.com/user-attachments/assets/e5177be9-8c93-413b-ae76-8e10c3e50352" /> <img width="703" height="50" alt="Screenshot 2026-03-24 at 3 36 30 PM" src="https://github.com/user-attachments/assets/6da0d4cb-f660-49b9-818e-bb45fe1e413e" /> <img width="695" height="91" alt="Screenshot 2026-03-24 at 3 40 10 PM" src="https://github.com/user-attachments/assets/229e4a2d-80c3-469e-b1a9-639df7068c17" /> <!-- [screenshots/recordings] --> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk analytics-only change that adds an additional tracking call when users enable metrics (onboarding, social login, and settings). Main risk is event ordering/duplication affecting downstream dashboards rather than app behavior. > > **Overview** > Adds a new `MetaMetricsEvents.METRICS_OPT_IN` event and emits it whenever users enable metrics, including the onboarding opt-in screen (`location: onboarding_metametrics`), social login onboarding flow (`location: onboarding_social_login`), and the settings MetaMetrics toggle (`location: settings` / `onboarding_default_settings`). > > Updates tests to assert the new opt-in event is sent (and in settings/onboarding cases is sent *before* `ANALYTICS_PREFERENCE_SELECTED`), including verifying `updated_after_onboarding` and optional `account_type` properties. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9968f73. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [79b1aa8](79b1aa8) Co-authored-by: Gaurav Goel <grvgoel19@gmail.com>
… details for selected account -> cp-7.71.0 (#27865) - fix(ramps): filter activity tab's transfer details for selected account -> cp-7.71.0 (#27830) ## **Description** ### Activity — on-ramp orders scoped to the selected account The Activity **Orders** tab merges legacy fiat orders with V2 `RampsController` orders. Legacy rows were already limited to the **selected account group** via `getOrders`. V2 orders were not filtered, so purchase history from other wallets could appear. This change adds `selectRampsOrdersForSelectedAccountGroup`, which keeps only orders whose `walletAddress` matches any formatted address in the selected account group (same semantics as legacy, using `areAddressesEqual` for EVM vs non-EVM). Hook and modal consumers that should reflect “current wallet context” now use this selector instead of the raw controller list. ### Transak — preserve user-entered fiat amount on Build Quote (in-app) After **additional verification**, opening the KYC/payment webview called `navigateToKycWebview` with **`quote.fiatAmount`**, and the stack reset rewrote **RampAmountInput** params with that value. The quote total can differ from what the user typed (e.g. fees), so Build Quote could show **27.37** after the user entered **25**, and that value persisted after closing the sheet or going back. **Change:** `routeAfterAuthentication(..., amount)` already carried the typed fiat; `navigateToAdditionalVerificationCallback` now puts the same `amount` on **both** `RampAmountInput` and `RampAdditionalVerification` route params. **V2 Additional Verification** reads that param and passes **only** it into `navigateToKycWebview` (no `quote.fiatAmount` for this purpose). **Out of scope:** Order detail screens and stored order payloads are unchanged. The **Transak payment webview** URL is unchanged (no `fiatAmount` override in widget params); only in-app Build Quote / stack state matches the user’s input. ## **Changelog** CHANGELOG entry: Fixed Activity on-ramp (Orders) list showing V2 purchases from wallets other than the selected account group; fixed Transak unified buy flow so the fiat amount on Build Quote after additional verification matches the user-entered amount on the amount screen (in-app stack), without changing Transak’s payment widget totals. ### Tests - `selectRampsOrdersForSelectedAccountGroup` and ramp hook consumers (selector + hook unit tests). - `useTransakRouting`: IDPROOF / additional verification navigation with user `amount` set and omitted. - V2 `AdditionalVerification`: continue passes route `amount` into `navigateToKycWebview`. ## **Related issues** Refs: [TRAM-3361](https://consensyssoftware.atlassian.net/browse/TRAM-3361) ## **Manual testing steps** ```gherkin Feature: Activity on-ramp orders and Transak amount (TRAM-3361) Scenario: Orders tab shows only selected account group’s V2 on-ramp orders Given the user has two wallets (or account groups) with separate on-ramp purchase history And unified ramps V2 orders exist for more than one wallet address When the user selects account group A and opens Activity → Orders Then only on-ramp orders whose destination wallet belongs to account group A are listed When the user switches to account group B Then the Orders tab lists only orders for account group B Scenario: Custom fiat amount survives Transak additional verification on Build Quote Given the user is in unified Buy with Transak (native) as provider And the user enters a custom fiat amount (e.g. 25) on the amount screen When the user continues through flows that require additional verification And the user taps Continue on the additional verification screen Then Build Quote under the KYC/payment sheet still shows the entered amount (e.g. 25), not only the quote total When the user closes the webview or goes back from the flow Then the amount screen still shows the same entered amount (e.g. 25) ``` ## **Screenshots/Recordings** ### **Before** <!-- Add video: Activity Orders showing other wallet’s purchases / wrong fiat amount after verification or in widget --> https://github.com/user-attachments/assets/b26bb3cb-8219-48a3-8128-7c79026fdd18 ### **After** <!-- Add video: Activity Orders scoped to selected account / correct custom amount through verification and widget --> https://github.com/user-attachments/assets/3e1929e3-7e1a-42c9-98bd-ea8f7bc9b1eb https://github.com/user-attachments/assets/ef6d14ed-6533-4e04-a5a4-8cbd44477170 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate UX/data-scoping change: filters which on-ramp orders appear based on multichain account selection and adjusts Transak navigation params, which could hide expected history or affect flow state if account/address resolution is off. > > **Overview** > Fixes unified ramp UI to **scope V2 `RampsController` orders to the selected account group**, preventing purchases from other wallets from showing up in Activity-derived surfaces. This introduces `selectRampsOrdersForSelectedAccountGroup` (address-matched via `areAddressesEqual`) and switches key consumers (`useRampsOrders`, `useRampsProviders`, `useRampsButtonClickData`, `ProviderSelectionModal`) from the unfiltered selector. > > Updates the Transak additional-verification flow to **preserve the user-entered fiat amount** through stack resets: `useTransakRouting` now carries `amount` into `RampAdditionalVerification` params, and `AdditionalVerification` uses that param (not `quote.fiatAmount`) when opening the KYC webview. Selector and routing behavior are covered with expanded unit tests. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 39d5861. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [4661cdb](4661cdb) --------- Co-authored-by: Yu-Gi-Oh! <54774811+imyugioh@users.noreply.github.com>
…27876) - feat: legacy-ios-feature-flag cp-7.71.0 (#27848) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Support webcredential for ios google login Part 2/4 - Add feature flag This pr add feature flag for the ios google login PR list Part 1/ 4 - #27741 Part 2/ 4 - #27848 Part 3/ 4 - #27850 Part 4/ 4 - TBA <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: added legacyIosGoogleConfigEnabled feature flag ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: adds a new remote feature flag and selector with env override, without changing authentication flow yet; main risk is misconfiguration since the selector defaults to enabled. > > **Overview** > Adds a new remote feature flag, `legacyIosGoogleConfigEnabled`, including registry metadata and a dedicated selector `selectLegacyIosGoogleConfigEnabled` (defaulting to `true`) that can be force-overridden via `MM_LEGACY_IOS_GOOGLE_CONFIG_ENABLED`. > > Includes unit tests covering default/remote/env override behavior, and updates `babel.config.tests.js` to avoid inlining env vars for the new selector and its tests. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ca7e813. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [6ae4c95](6ae4c95) Co-authored-by: ieow <4881057+ieow@users.noreply.github.com>
…7892) - fix: hardware wallet eip 7702 issue (cp-7.71.0) (#27615) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR will provide a fix for hardware wallet to gas free network like Monad and Sei. Due to currently Hardware wallet is not supported for EIP 7702 gas sponsorship, and Swap feature is not working for hardware wallet user. This fix will fall back the Gasless transaction to User pay gas previous model so that user can still do the swap and sign transaction like bfore. This is temporately fix for current version of extensions, and we will do a proper support in the future. Similar to extension PR: MetaMask/metamask-extension#40915 Ticket: https://consensyssoftware.atlassian.net/jira/software/c/projects/NEB/boards/3738/backlog?selectedIssue=NEB-767 ## **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: Hardware wallet user will fall back to use `User pay gas` for those Gasless network due to hardware wallet not supported in Gasless network like Sei and Monad. ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Gas sponsorship disabled for hardware wallet accounts Scenario: Hardware wallet user does not use gas sponsorship on sponsored network Given the user has added a hardware wallet account (Ledger or QR-based) And the hardware wallet account is selected as the active account And the user has added a gas-sponsored network (e.g. Monad) When the user attempts to perform a swap a dapp interaction or send a transaction on the sponsored network Then the transaction should not use gas sponsorship And the UI should not display any gas sponsorship labels (e.g. "No network fee", "Paid by MetaMask") And the user should see the normal network gas fee And the transaction should follow the standard user-pays-gas flow ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> > With HW account: Network list: <img width="392" height="800" alt="Screenshot 2026-03-18 at 16 05 48" src="https://github.com/user-attachments/assets/601c30cc-fd78-456e-87b5-cc70e7ce3433" /> Tx flow: <img width="392" height="800" alt="Screenshot 2026-03-18 at 15 53 04" src="https://github.com/user-attachments/assets/7c7b60cf-3f79-4701-a1e5-1fbba2bfe84e" /> <img width="392" height="800" alt="Screenshot 2026-03-18 at 15 55 20" src="https://github.com/user-attachments/assets/a3258815-f1d2-4abf-8b22-209b73a0fbba" /> <img width="392" height="800" alt="Screenshot 2026-03-18 at 15 55 47" src="https://github.com/user-attachments/assets/9275c82c-e56a-47ad-a203-a34f67ed6ed9" /> ### **After** > With HW account: Network list: <img width="392" height="800" alt="Screenshot 2026-03-18 at 16 06 19" src="https://github.com/user-attachments/assets/03a296be-17fe-4387-baa0-23bae3ba00eb" /> Tx flow: <img width="392" height="800" alt="Screenshot 2026-03-18 at 15 49 55" src="https://github.com/user-attachments/assets/b39bc1b0-4b28-4e06-ae06-a381458ba7f6" /> <img width="392" height="800" alt="Screenshot 2026-03-18 at 15 50 29" src="https://github.com/user-attachments/assets/76a31213-9ecd-4290-b407-58ffb8d82f48" /> <!-- [screenshots/recordings] --> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches gasless sponsorship and transaction publishing paths (including 7702 delegation), which can affect whether transactions are sponsored vs user-paid and could change behavior on supported chains. Changes are scoped to hardware-wallet detection gates with added tests, reducing regression risk. > > **Overview** > Hardware wallet accounts now **opt out of gasless / EIP-7702 sponsorship**, forcing swaps/bridge and confirmations to use the normal *user-pays-gas* path. > > This adds an `accountSupports7702` gate to `TransactionControllerInit` so `Delegation7702PublishHook` and `isEIP7702GasFeeTokensEnabled` only activate for keyrings that support 7702, and updates `useIsGaslessSupported`/`useIsGasIncluded7702Supported` (via new `useIsHardwareWalletForBridge`) to report unsupported for hardware signers. > > Network selection UI (`NetworkSelector`, `NetworkMultiSelectorList`, `CustomNetwork`) now hides the “No network fee” sponsored label for hardware wallets, and a patched `@metamask/bridge-status-controller` waits for approval tx confirmation when required. Tests were added/updated to cover the new hardware-wallet gating behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 83f66fc. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Julien Fontanel <julien.fontanel@consensys.net> Co-authored-by: Frederic HENG <frederic.heng@consensys.net> Co-authored-by: Arafet (CN - Hong Kong) <52028926+arafetbenmakhlouf@users.noreply.github.com> Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com> [c4b93de](c4b93de) --------- Co-authored-by: khanti42 <florin.dzeladini@consensys.net> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Julien Fontanel <julien.fontanel@consensys.net> Co-authored-by: Frederic HENG <frederic.heng@consensys.net> Co-authored-by: Arafet (CN - Hong Kong) <52028926+arafetbenmakhlouf@users.noreply.github.com> Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com>
…ure from dual-cache desync cp-7.70.1 (#27912) - fix(perps): fix HIP-3 asset ID lookup failure from dual-cache desync cp-7.70.1 (#27854) ## **Description** Fix HIP-3 asset ID lookup failure (`"Asset ID not found for xyz:BRENTOIL"`) that blocked trading on HIP-3 markets when navigating via the old Perps tab layout. **Root cause**: Dual-cache desync between `#cachedValidatedDexs` (string DEX names) and `#cachedAllPerpDexs` (raw API objects for `perpDexIndex` computation). The standalone preload path (`#getStandaloneValidatedDexs`) populated one cache but not the other. When `#buildAssetMapping` later ran, it found "xyz" in `dexsToMap` but couldn't compute its `perpDexIndex` because `#cachedAllPerpDexs` was null. **Why old Perps tab vs new Homepage Sections**: Both layouts sit inside `Wallet/index.tsx`, which calls `startMarketDataPreload()` on mount. This fires standalone HTTP calls that populate `#cachedValidatedDexs` but not `#cachedAllPerpDexs`. - **New homepage sections**: `PerpsSectionWithProvider` mounts immediately. Stream hooks fire `ensureReady()` before or concurrently with the standalone preload. Since `#cachedValidatedDexs` is often still null, `fetchValidatedDexsInternal` runs fresh and sets **both** caches correctly. - **Old tab layout**: The Perps tab doesn't mount until the user taps it. By that time, `startMarketDataPreload()` has already completed → `#cachedValidatedDexs` is populated by standalone. When the tab mounts → `getValidatedDexs()` → **cache hit** → `fetchValidatedDexsInternal` is never called → `#cachedAllPerpDexs` stays null → `buildAssetMapping` can't find "xyz". **Changes (1 file, 3 sites)**: 1. **Root cause fix**: `#getStandaloneValidatedDexs` now sets `this.#cachedAllPerpDexs = allDexs` after a successful `perpDexs()` call, keeping both caches in sync. 2. **Cache poisoning fix**: Removed `this.#cachedAllPerpDexs = this.#cachedAllPerpDexs ?? [null]` from the catch block in `#buildAssetMapping`. 3. **Cache poisoning fix**: Replaced persistent `if (!cache) { cache = [null] }` with local `const allPerpDexs = cache ?? [null]` — consumers read the cache, only the owner writes it. ## **Changelog** CHANGELOG entry: Fixed a bug where closing positions on HIP-3 markets (e.g., xyz:BRENTOIL) failed with "Asset ID not found" when navigating via the Perps tab ## **Related issues** Fixes: HIP-3 asset ID lookup failure on old Perps tab layout ## **Manual testing steps** ```gherkin Feature: HIP-3 position management via Perps tab Scenario: user closes a HIP-3 position from the old Perps tab Given user has an open position on a HIP-3 market (e.g., xyz:BRENTOIL) And user is using the old tab layout (homepage redesign v1 disabled) When user navigates to the Perps tab And user taps close on the xyz:BRENTOIL position Then the position closes successfully without "Asset ID not found" error Scenario: user opens a HIP-3 position from the old Perps tab Given user is on the Perps tab (old layout) When user navigates to xyz:BRENTOIL market and places a market order Then the order executes successfully with correct asset ID routing ``` ## **Screenshots/Recordings** ### **Before** Metro logs show the desync: ``` getValidatedDexs CACHE HIT {"cachedAllNull": true, "dexs": [null, "xyz"]} buildAssetMapping state {"allPerpDexsLen": 1, "cachedAllNull": true} Could not find perpDexIndex for DEX xyz Asset ID not found for xyz:BRENTOIL ``` ### **After** Metro logs show both caches in sync: ``` buildAssetMapping state {"allPerpDexsLen": 8, "cachedAllNull": false, "dexsToMap": [null, "xyz"]} Asset map state at order time {"assetExistsInMap": true, "hip3AssetsCount": 54, "totalAssetsInMap": 283} Resolved DEX-specific asset ID {"assetId": 110049, "coin": "xyz:BRENTOIL"} usePerpsClosePosition: Close result {"success": true, "orderId": "359617825254"} ``` ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches HIP-3 market routing/asset-ID mapping in `HyperLiquidProvider`, so a mistake could break trading on some perps markets; scope is small and localized to cache population/fallback behavior. > > **Overview** > Fixes a HIP-3 asset mapping failure where `#cachedValidatedDexs` could be populated via the standalone preload path while `#cachedAllPerpDexs` stayed `null`, leading to missing `perpDexIndex` during `#buildAssetMapping`. > > `#getStandaloneValidatedDexs()` now also populates `#cachedAllPerpDexs` after a successful `perpDexs()` call, and `#buildAssetMapping()` no longer “poisons” the shared cache with a persistent `[null]` fallback (it uses a local fallback instead). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c925609. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [2898ec8](2898ec8) Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
## Description Sync `stable` into `release/7.71.0` so the release branch includes everything merged to stable through **7.70.1** (hotfixes and changelog from [#27824](#27824)) ## Changelog CHANGELOG entry: null --- Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: only updates release metadata (CHANGELOG links/entries and `OTA_VERSION`) with no functional code changes beyond versioning. > > **Overview** > Adds a `7.70.1` section to `CHANGELOG.md` (including two perps-related fixes) and updates the compare links so *Unreleased* starts from `v7.70.1`. > > Bumps `OTA_VERSION` in `app/constants/ota.ts` from `v7.65.1` to `v7.70.1` to match the hotfix release. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b8fba18. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com> Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com> Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
…Action cp-7.71.0 (#27934) - chore: New Crowdin translations by Github Action cp-7.71.0 (#27496) Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> [0b1f7be](0b1f7be) Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…n behind remote flag cp-7.71.0 (#27959) - feat(earn): gate Tron unstaked claim button behind remote flag (#27908) ## **Description** Adds the remote boolean flag **`tronClaimUnstakedTrxButtonEnabled`** so we can hide the **claim** action on the Tron unstaked banner if something goes wrong in production, without removing the banner copy. **Why:** We need a safe kill switch for the claim CTA only. **How:** - Register the flag in `FeatureFlagNames` with default `false` (missing/undefined → button hidden; opt-in). - **`selectTronClaimUnstakedTrxButtonEnabled`** in `app/selectors/featureFlagController/tronClaimUnstakedTrxButtonEnabled/` reads merged remote flags (same pattern as other boolean flags). - `TronUnstakedBanner` uses `useSelector(selectTronClaimUnstakedTrxButtonEnabled)` and renders the primary claim button only when the flag is `true`; title and description stay visible when the button is hidden. - Register the flag in **`tests/feature-flags/feature-flag-registry.ts`** (`inProd: true`, `productionDefault: false`) so CI/E2E mocks match production client-config. **Ops:** Ensure **`tronClaimUnstakedTrxButtonEnabled`** exists in LaunchDarkly / client-config; set to **`true`** where the claim button should appear. ## **Changelog** CHANGELOG entry: Added a remote feature flag to control visibility of the Tron unstaked TRX claim button on the token details banner. ## **Related issues** Fixes: NEB-838 ## **Manual testing steps** ```gherkin Feature: Tron unstaked banner claim button behind remote flag Scenario: user views TRX token details with claimable unstaked balance and flag enabled Given a Tron account with TRX ready for withdrawal and remote flag `tronClaimUnstakedTrxButtonEnabled` is true (or overridden in dev tools) When user opens native TRX token details and the unstaked banner is shown Then the banner shows title, description, and the claim button, and tapping claim still triggers the existing flow Scenario: user views TRX token details when flag is off or unset Given the same balance state but `tronClaimUnstakedTrxButtonEnabled` is false, missing, or undefined in remote flags When user opens native TRX token details and the unstaked banner is shown Then the banner shows title and description but does not show the claim button ``` ## **Screenshots/Recordings** ### **Before** See prior screenshots on this PR (token details with banner). ### **After** Feature flag disabled / enabled — screenshots attached in thread (banner with and without claim CTA). ## **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. ## **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. [ef5e684](ef5e684) Co-authored-by: Ulisses Ferreira <ulisses@hey.com>
… cp-7.71.0 (#27941) - feat: show legacy ios login warning prompt cp-7.71.0 (#27875) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Add warning prompt for ios <17.4 for google login Supports the fix for: https://github.com/MetaMask/MetaMask-planning/issues/7148 Part 1/ 4 - #27741 Part 2/ 4 - #27848 Part 3/ 4 - #27850 (deferred to 7.72.0) Part 4/ 4 - #27875 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Add warning prompt for ios <17.4 for google login ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> For < iOS 17.4 https://github.com/user-attachments/assets/f6f3a031-82cc-486d-af5f-e6e1bbc7ed10 For >= iOS 17.4 https://github.com/user-attachments/assets/2cdc0bf3-d59b-4858-be81-baae5e0a4dd2 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Modifies the onboarding social login path by inserting a conditional pre-login warning and new navigation helper, which could affect Google login flow timing/navigation on iOS devices. Changes are localized but touch user authentication entrypoints and analytics tracking. > > **Overview** > Adds an **iOS < 17.4 warning gate** before starting Google OAuth during onboarding (both create and import flows), showing a non-interactable `SuccessErrorSheet` that must be acknowledged before proceeding. > > Introduces `Device.comparePlatformVersionTo()` (using `compare-versions`) and a reusable `navigateToSuccessErrorSheetPromise()` helper to await sheet dismissal, plus a new MetaMetrics event (`WALLET_GOOGLE_IOS_WARNING_VIEWED`) and localized warning copy. > > Updates onboarding tests to mock the new device helper/navigation and to assert the warning sheet + tracking fire before continuing with Google login. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 3b43b83. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [002d91a](002d91a) Co-authored-by: ieow <4881057+ieow@users.noreply.github.com>
…en user has a position cp-7.71.0 (#27924) - fix: hides perps buttons in ai insights when user has a position cp-7.71.0 (#27919) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR is a bug fix for #27916 where: - In the AI Market Insights in Perps, the action buttons are wrong when user has an open position: the action buttons should be the same in AI market insight page and market page, ie. “modify” and “Close” when user has an open position Fix: - When the user has an existing perps position, the MarketInsights footer action buttons (Long/Short) are hidden since the relevant actions (modify/close) live on the Perps market details page - The "AI summary for information only" disclaimer is moved inline below the feedback section when the footer is hidden, so it remains visible - Position state is passed via route params (hasPerpsPosition) from the caller rather than fetched async inside MarketInsightsView, preventing a flash where buttons briefly appear then disappear while the position loads <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed a bug that was causing incorrect Perps action buttons to be displayed ## **Related issues** Fixes: #27916 ## **Manual testing steps** ```gherkin - Open MarketInsights from token details → Swap/Buy buttons visible with disclaimer in footer - Open MarketInsights from perps with no position → Long/Short buttons visible with disclaimer in footer - Open MarketInsights from perps with an existing position → no footer buttons, disclaimer shown below "Was this helpful?" - Verify no flash/layout shift on the perps + position flow ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/0373c1bb-d433-4c9a-8768-117a40d98f9e ### **After** <!-- [screenshots/recordings] --> <img width="3699" height="3090" alt="SCR-20260325-nzfa" src="https://github.com/user-attachments/assets/4b058c59-6df0-4d16-acf7-8d6bb839183f" /> ## **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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI/navigation tweak that changes which CTAs are shown based on a new route param; main risk is incorrect param wiring causing missing actions or disclaimer placement in the Perps insights flow. > > **Overview** > Fixes Perps AI Market Insights showing inappropriate `Long`/`Short` CTAs when the user already has an open position. > > Adds a `hasPerpsPosition` route param (set by `PerpsMarketDetailsView`) and uses it in `MarketInsightsView` to **hide the footer action buttons** for Perps-with-position while **keeping the informational disclaimer visible** by moving it inline under the feedback section for that case. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 833593b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [8a7bced](8a7bced) Co-authored-by: João Santos <joaosantos15@users.noreply.github.com>
This PR updates the change log for 7.71.0. (Hotfix - no test plan generated.) --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: chloeYue <chloe.gao@consensys.net>
…27708) Made-with: Cursor
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1546 ## **Manual testing steps** no manual testing steps ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [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. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches the hardware wallet connection flow and bottom-sheet callbacks to emit new analytics, so incorrect state resets or callback wiring could affect connection UX/cleanup. No auth or funds-handling logic changes, and coverage is added with extensive unit tests. > > **Overview** > Adds a new hardware-wallet analytics module that classifies **flow context** (Connection/Send/Swaps/Transaction/Message) and normalizes **error types/details**, then emits three new MetaMetrics events for recovery: `HARDWARE_WALLET_RECOVERY_MODAL_VIEWED`, `..._CTA_CLICKED`, and `..._SUCCESS_MODAL_VIEWED`. > > Wires this into the hardware wallet UI/flow by deriving the analytics flow from the first pending approval at the start of each `ensureDeviceReady` run, tracking CTA taps from error screens via a new `onCTAClicked` prop on `HardwareWalletBottomSheet`, and resetting analytics state when the sheet is closed. Includes comprehensive unit tests for helper mappings, Redux-derived flow detection, and event firing/counting behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9bec1b0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…27708) (#28016) ## Description Merges `stable` into `release/7.71.0` and resolves `CHANGELOG.md` conflicts so [PR #27708](#27708) (`release/7.71.0` → `stable`) can merge cleanly. ### CHANGELOG resolution (per local release changelog guidelines) - Kept **`## [7.71.0]`** (cleaned release notes) **above** **`## [7.70.1]`** / **`## [7.70.0]`** from stable. - **Compare links:** `[Unreleased]` → `v7.71.0...HEAD`; `[7.71.0]` → `v7.70.1...v7.71.0`; left `[7.70.1]` / `[7.70.0]` lines unchanged below. ### After this PR 1. Merge this PR into `release/7.71.0` using **Create a merge commit** (not squash), per release process. 2. Re-try / update [PR #27708](#27708). ## Changelog CHANGELOG entry: null --- Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: merge-conflict resolution focused on `CHANGELOG.md` ordering/compare links with no runtime code changes. > > **Overview** > Merges `stable` into `release/7.71.0` and resolves the `CHANGELOG.md` conflict by keeping the cleaned `7.71.0` notes above `7.70.1`/`7.70.0` and updating the compare links (`[Unreleased]` → `v7.71.0...HEAD`, `[7.71.0]` → `v7.70.1...v7.71.0`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 424324a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
# 🚀 v7.71.0 Testing & Release Quality Process Hi Team, As part of our new **MetaMask Release Quality Process**, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment. --- ## 📋 Key Processes ### Testing Strategy - **Developer Teams:** Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows. - **QA Team:** Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing. - **Customer Success Team:** Validate new functionalities and provide feedback to support release monitoring. ### GitHub Signoff - Each team must **sign off on the Release Candidate (RC)** via GitHub by the end of the validation timeline (**Tuesday EOD PT**). - Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed. ### Issue Resolution - **Resolve all Release Blockers** (Sev0 and Sev1) by **Tuesday EOD PT**. - For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines. ### Cherry-Picking Criteria - Only **critical fixes** meeting outlined criteria will be cherry-picked. - Developers must ensure these fixes are thoroughly reviewed, tested, and merged by **Tuesday EOD PT**. --- ## 🗓️ Timeline and Milestones 1. **Today (Friday):** Begin Release Candidate validation. 2. **Tuesday EOD PT:** Finalize RC with all fixes and cherry-picks. 3. **Wednesday:** Buffer day for final checks. 4. **Thursday:** Submit release to app stores and begin rollout to 1% of users. 5. **Monday:** Scale deployment to 10%. 6. **Tuesday:** Full rollout to 100%. --- ## ✅ Signoff Checklist Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion: # Team sign-off checklist - [x] Accounts Framework - [x] Assets - [x] Bots Team - [x] Card - [x] Confirmations - [x] Core Platform - [x] Design System - [x] Earn - [x] Mobile Platform - [x] Mobile UX - [ ] Money Movement - [x] Networks - [x] Onboarding - [x] Perps - [x] Predict - [x] Rewards - [x] Social & AI - [x] Swaps and Bridge - [x] team-hardware-wallets - [ ] team-ramp - [x] Transactions - [x] Wallet Integrations This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀 Feel free to reach out if you have questions or need clarification. Many thanks in advance # Reference - Testing plan sheet - https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372
This PR syncs the stable branch to main for version 7.73.0. *Synchronization Process:* - Fetches the latest changes from the remote repository - Resets the branch to match the stable branch - Attempts to merge changes from main into the branch - Handles merge conflicts if they occur *File Preservation:* Preserves specific files from the stable branch: - CHANGELOG.md - bitrise.yml - android/app/build.gradle - ios/MetaMask.xcodeproj/project.pbxproj - package.json Indicates the next version candidate of main to 7.73.0
…#27844) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Users with open Perpetuals or Predict positions could not see aggregate unrealized P&L on the wallet homepage next to those sections, and the Perps tab “Your positions” subtitle duplicated similar layout logic. This PR: - **Wallet homepage — Perps:** Shows a sub-row under “Perpetuals” with aggregate unrealized P&L (and ROE %) when the user has **filled** open positions; hides it for privacy mode, while loading account data, or when there are no positions (including **orders-only** — no row). Colors follow profit (green) / loss (red) / flat (default text). - **Wallet homepage — Predict:** Shows the same style of row under “Predictions” using the existing unrealized P&L API (`useUnrealizedPnL`); pull-to-refresh also invalidates that query. Respects privacy mode. - **Perps home (tab):** Keeps the positions subtitle visible whenever there are open positions (including flat P&L), uses design-system text colors, and reuses the shared **`HomepageSectionUnrealizedPnlRow`** for the value + “Unrealized P&L” line so layout matches the homepage spec (4px under title, 8px between value and label). - **Shared UI:** New `HomepageSectionUnrealizedPnlRow` under homepage components (used by homepage sections + `PerpsHomeSection`). - **Predict:** `formatPredictUnrealizedPnLStringParts` in `format.ts` centralizes i18n interpolation for unrealized P&L strings; `PredictPositionsHeader` and `PredictionsSection` both use it. ## **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: Added unrealized P&L summary on the wallet homepage for Perpetuals and Predictions, and aligned the Perps home “Your positions” subtitle with the same layout. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-584 ## **Manual testing steps** ```gherkin Feature: Unrealized P&L on homepage Perps and Predict Scenario: Perps section shows aggregate unrealized P&L with open positions Given the user has at least one open Perpetuals position and privacy mode is off When the user views the wallet homepage Then the Perpetuals section shows a line with signed dollar P&L, percentage, and an unrealized P&L label below the section title And positive P&L is green and negative P&L is red Scenario: Perps section hides P&L without open positions Given the user has no open Perpetuals positions (only limit orders or none) When the user views the wallet homepage Then no unrealized P&L sub-row appears under Perpetuals and spacing below the title is unchanged Scenario: Predict section shows unrealized P&L with open positions Given the user has open Predict positions and privacy mode is off When the user views the wallet homepage Then the Predictions section shows the unrealized P&L sub-row consistent with design Scenario: Privacy mode hides homepage P&L values Given privacy mode is enabled When the user views the wallet homepage with Perps and/or Predict positions Then unrealized P&L sub-rows for those sections are not shown Scenario: Perps tab positions subtitle matches homepage styling Given the user has open Perps positions When the user opens the Perps home screen Then “Your positions” shows the unrealized P&L value and label with the same visual treatment as the homepage row ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk: adds new homepage UI rows driven by live Perps account state and Predict react-query data (including query invalidation on refresh), which could affect loading/visibility states and performance but does not touch auth or funds movement. > > **Overview** > Adds a shared `HomepageSectionUnrealizedPnlRow` component and uses it to display **aggregate unrealized P&L** under the Wallet homepage **Perpetuals** and **Predictions** section titles when the user has open positions (and not in privacy mode), including loading placeholders and tone-based coloring. > > Refactors Perps tab `PerpsHomeSection`/`PerpsHomeView` to reuse the same value+label row, switch to design-system `TextColor` tokens, and keep the positions subtitle visible whenever positions exist (including flat P&L). Predict’s positions header and homepage section now share a centralized `formatPredictUnrealizedPnLStringParts` formatter, and Predictions pull-to-refresh also invalidates the unrealized P&L query; tests were updated/added accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 50ae867. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Replace the default `QueryClient` with a custom `QueryClient` from `createUIQueryClient`. This establishes the query client required for using the `BaseDataService` pattern from the core repo, which handles cache syncing. Existing UI-only queries should work as they did previously. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** https://consensyssoftware.atlassian.net/browse/WPC-445 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes how the global React Query `QueryClient` is constructed and introduces messenger-backed call/subscribe plumbing that could affect caching and network behavior across the app. > > **Overview** > Switches `ReactQueryService` to build its `queryClient` via `@metamask/react-data-query`’s `createUIQueryClient`, passing an Engine messenger adapter to support data services and cache syncing while keeping the existing default query options. > > Adds a `DATA_SERVICES` registry (currently empty) for wiring in available data services, updates unit tests to validate the new client defaults and cache clearing behavior, and adds the new `@metamask/react-data-query` dependency (plus lockfile updates). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 088a264. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…#28011) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** > Updates Predict Market Details tab testIDs to be **stable and semantic** by switching from index-based IDs to typed tab-key IDs (`'positions' | 'outcomes' | 'about'`), and updates `PredictMarketDetailsTabBar` plus its unit tests to use the new `getPredictMarketDetailsSelector.tabBarTab(tabKey)` API. > > Adds explicit testIDs to the confirmations `NetworkFilter` tabs by introducing `network-filter.testIds.ts` and passing a required `testID` prop into `NetworkFilterTab` for the “All networks” option and each per-chain tab. > ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: changes are limited to test ID generation and wiring for UI elements, with no business logic or data flow modifications. > > **Overview** > Updates Predict Market Details tab testIDs to be **stable and semantic** by switching from index-based IDs to typed tab-key IDs (`'positions' | 'outcomes' | 'about'`), and updates `PredictMarketDetailsTabBar` plus its unit tests to use the new `getPredictMarketDetailsSelector.tabBarTab(tabKey)` API. > > Adds explicit testIDs to the confirmations `NetworkFilter` tabs by introducing `network-filter.testIds.ts` and passing a required `testID` prop into `NetworkFilterTab` for the “All networks” option and each per-chain tab. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bea4356. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
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 : )