[pull] main from MetaMask:main#496
Merged
Merged
Conversation
## **Description** This PR addresses multiple UI revision requests for the "Scan your hardware wallet to connect" screen in the Add wallet flow. Mirrored design with `ShareAddressQR` 1. Centered the reader 2. Added white transparent background 3. Moved hint text above the box 4. Updated copy 5. Fixed white clipping issue at the top and bottom of modal ## **Changelog** CHANGELOG entry: Fixed hardware wallet scan screen layout with centered reader, blurred edges, and improved text positioning ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MDP-680 ## **Manual testing steps** ```gherkin Feature: Scan hardware wallet screen Scenario: user views the scan hardware wallet screen Given the user is on the Add wallet flow When user navigates to the QR-based hardware wallet scan screen Then the scanning frame should be centered on the screen And the edges around the frame should have a blurred/gradient effect And the text "Scan your hardware wallet" should appear above the frame And the "Scanning..." text should appear below the frame ``` ## **Screenshots/Recordings** | before | after | | -------- | ------- | |  |  | ### **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** - [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** > Primarily UI/layout changes to the QR scanning modal, but it also refactors error analytics emission and adjusts modal/window positioning which could affect scanner usability on different devices. > > **Overview** > Refines the QR-based hardware wallet scanner modal to match the app’s other QR scanner UI: adds a full-screen overlay with centered frame, moves the hint text above the frame, and shows scanning progress below. > > Updates modal presentation (`coverScreen`, `statusBarTranslucent`), revises camera/no-permission layouts, and tweaks styles/positioning (absolute layout, overlay shading, close button placement). Also centralizes hardware-wallet error analytics into a reusable `sendErrorAnalytics` helper and updates English copy keys from `hint_text`/`purpose_*` to `hint_text_pair` and `hint_text_sign`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit dfff06f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…5545) <!-- 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** Moves the "Earn %" CTA for Ethereum and Tron to be next to the asset name. This fix is needed because large token balances are causing the "Earn %" CTA to clip into the percentage changed text. <!-- 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: moved the "Earn %" CTA for Ethereum and Tron to be next to the asset name ## **Related issues** Fixes: [MUSD-279: Move the Earn CTAs next to ETH and Tron contextually next to the asset name's](https://consensyssoftware.atlassian.net/browse/MUSD-279) ## **Manual testing steps** ```gherkin Feature: Earn call-to-action placement in token list Scenario: user sees stake call-to-action next to token name When user views ETH and the token in the token list When user has non-zero token balance Then a Stake call-to-action is displayed inline next to the token name ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> Earn CTA collides with the percentage changed text for large token balances. ### **After** <!-- [screenshots/recordings] --> <img width="454" height="81" alt="Screenshot 2026-02-02 at 3 50 50 PM" src="https://github.com/user-attachments/assets/21a1671f-2d66-4017-bc2b-1c78fcfd4e02" /> <img width="454" height="81" alt="Screenshot 2026-02-02 at 3 51 07 PM" src="https://github.com/user-attachments/assets/690691a3-ebf9-43ea-a8a8-5f298c66c3bd" /> ## **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-only layout change in `TokenListItem` that repositions the Earn/Stake CTA; main risk is minor alignment/regression across different token name lengths and badges. > > **Overview** > Moves the token list item Earn/Stake CTA (via `renderEarnCta()`) from the secondary balance row to sit inline next to the asset name/label, preventing it from colliding with large balance/percentage-change text. > > Adds an `assetNameContainer` row wrapper style to align the name/label and CTA horizontally. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9de9bcc. 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? --> This PR updates the `useAnalytics` hook type definitions to support the types for the `createEventBuilder` method. ## **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/MCWP-317 (additional change) ## **Manual testing steps** N/A ## **Screenshots/Recordings** N/A ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **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** > Type-only change that broadens `createEventBuilder`’s input union; low runtime risk but may affect TypeScript compile expectations where this hook is consumed. > > **Overview** > Updates `useAnalytics` hook typings so `createEventBuilder` accepts additional analytics event types (`IMetaMetricsEvent` and `ITrackingEvent`) alongside `string`/`AnalyticsTrackingEvent`, improving type compatibility for callers. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 73287df. 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**
This is a simple PR that updates the @metamask/storage-service to 1.0.0.
No breaking changes, we are just updating the version to 1 as it is
going to be used in prod.
CHANGELOG entry: null
<!--
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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk dependency bump with no code changes, but it could introduce
runtime regressions if `@metamask/storage-service` behavior changed
between 0.0.1 and 1.0.0.
>
> **Overview**
> Updates the `@metamask/storage-service` dependency from `^0.0.1` to
`^1.0.0` and refreshes `yarn.lock` to resolve the new package version
(including its updated transitive dependency on `@metamask/utils`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e9f26f6. 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? --> Several E2E tests are still using the `remoteFeatureMultichainAccountsAccountDetailsV2` util to mock the remote feature flag value. This PR removes the usage of this method with the value `true` since this is already the default behaviour covered by the default fixture. ## **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: null ## **Manual testing steps** Not applicable ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> Not applicable ## **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** > Test-only changes remove explicit enabling of `enableMultichainAccountsState2`; risk is low but could cause E2E flakes if the default feature-flag behavior changes in the test harness. > > **Overview** > Removes explicit mocking of the `remoteFeatureMultichainAccountsAccountDetailsV2(true)` remote feature flag across multiple multichain E2E/regression specs, relying on the default-enabled behavior instead. > > Cleans up related imports and `testSpecificMock` blocks (including the multichain provider snap test and multichain asset-list regression), simplifying fixture setup while preserving the existing test flows. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 63da2a2. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…25603) ## **Description** convert promise chains to async/await in AnimatedQRScanner ## **Changelog** CHANGELOG entry:null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MDP-680 ## **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** `~` ### **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** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk refactor limited to error-analytics plumbing; behavior should be equivalent but could affect when/if analytics fire if the async keyring lookup throws differently. > > **Overview** > Refactors `AnimatedQRScanner` error analytics to replace `.then/.catch` promise chaining with `async/await` and a `try/catch` around the QR keyring device-name lookup. > > Analytics events for `MetaMetricsEvents.HARDWARE_WALLET_ERROR` are still emitted with `device_model` set to the resolved keyring name, or `'Unknown'` if lookup fails, with no functional changes outside this error-reporting path. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8ed2614. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** This PR updates the Browser Tabs View to match the new design specifications. **Key changes:** 1. **Replaced bottom action bar with top navigation bar** - Removed the old bottom bar (Close All / + / Done buttons) and added a new top navigation bar with: - Back button (ArrowLeft icon) on the left - "Opened tabs" title centered - Add button (Add icon) on the right 2. **Updated back button behavior** - The back button now navigates to the Explore page (TrendingView) when: - No tabs exist, OR - The active tab was closed 3. **Updated "+" button behavior** - Creates a new empty tab (DiscoveryTab) and immediately dismisses the tabs view 4. **Converted tabs from list to 2-column grid layout** - Tabs are now displayed in a more compact grid format with smaller thumbnails 5. **Removed Close All functionality** - This feature has been removed from the UI ### Files Changed | File | Changes | |------|---------| | `app/components/UI/Tabs/index.js` | Removed bottom bar, added top nav bar, grid layout | | `app/components/UI/Tabs/TabThumbnail/TabThumbnail.styles.ts` | Updated dimensions for grid | | `app/components/Views/Browser/index.js` | Enhanced closeTabsView navigation logic | | `app/components/Views/BrowserTab/BrowserView.testIds.ts` | Added/deprecated test IDs | | `app/components/UI/Tabs/index.test.tsx` | Updated tests and snapshots | | `locales/languages/en.json` | Added new localization strings | ## **Changelog** CHANGELOG entry: Updated the Browser Tabs View with a new top navigation bar, 2-column grid layout, and improved navigation behavior ## **Related issues** Fixes: **Jira Ticket:** https://consensyssoftware.atlassian.net/browse/MCWP-266 ## **Manual testing steps** ```gherkin Feature: Browser Tabs View Scenario: User opens tabs view and sees new UI Given user has multiple browser tabs open When user taps the tabs button to open tabs view Then user sees a top bar with back button, "Opened tabs" title, and add button And tabs are displayed in a 2-column grid layout Scenario: User creates a new tab from tabs view Given user is in the tabs view When user taps the add (+) button Then a new empty tab is created And the tabs view is dismissed And user is switched to the new tab Scenario: User navigates back with active tab Given user has browser tabs open And user is in the tabs view When user taps the back button Then the tabs view is dismissed And user returns to the active tab Scenario: User navigates back with no tabs Given user has no browser tabs open And user is in the tabs view When user taps the back button Then user is navigated to the Explore page Scenario: User navigates back after closing active tab Given user has closed the active tab in tabs view When user taps the back button Then user is navigated to the Explore page ``` ## **Screenshots/Recordings** ### **Before** <!-- Add screenshot of old tabs view with bottom bar --> ### **After** <!-- Add screenshot of new tabs view with top bar and grid layout --> https://github.com/user-attachments/assets/100407f6-9b8b-4dfc-b53e-b70a0ce9d65e ## **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** > Medium risk because it changes core tab-management UX (new-tab creation return value, scroll positioning, and close-tabs navigation) and removes the `closeAllTabs` flow, which could regress navigation or tab state handling. > > **Overview** > Updates the Browser Tabs view UI to match new designs by replacing the bottom action bar (*Close all / + / Done*) with a top bar containing back/add icon buttons and an `Opened tabs` title. > > Switches the tabs list to a 2-column grid with new sizing constants (`Tabs.constants.ts`) and updated `TabThumbnail` dimensions/spacing, including updated scroll-to-active-tab positioning for the grid. > > Changes behavior so `newTab()` returns success/failure (used to keep the tabs view open when the max-tabs modal is shown) and so closing the tabs view navigates to Explore (`Routes.TRENDING_VIEW`) when there are no tabs or the active tab no longer exists; removes `closeAllTabs` plumbing across Browser/Tabs types and call sites. > > Refreshes snapshots, expands unit coverage (including a large `Browser.functions.test.tsx` suite), updates smoke tests, and adds new i18n strings and test IDs (with deprecated IDs retained for compatibility). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0276675. 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>
…eed (#25461) Add a new "Hot" tab category for prediction markets that can be dynamically configured via remote feature flags. The flag controls both visibility and custom query parameters for filtering markets, enabling backend-driven tab configuration without app updates. <!-- 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** Summary - Adds a new "Hot" tab to the Predict feed that is controlled by a remote feature flag - The Hot tab supports configurable query parameters passed directly to the Polymarket API - When enabled, the Hot tab appears as the first tab in the feed How It Works 1. **Remote Feature Flag**: The `predictHotTab` flag controls: - `enabled`: Whether the Hot tab is displayed - `queryParams`: Raw query string passed to Polymarket API (e.g., `"&tag_id=149&order=volume24hr"`) 2. **API Behavior**: When Hot tab is active with custom query params: - Only `limit`, `offset`, and `customQueryParams` are sent to the API - Default filters (active, archived, closed, liquidity_min, volume_min) are bypassed - This allows full control of the API query via the feature flag 3. **Default State**: Flag is disabled by default with fallback query params <!-- 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/PRED-539?atlOrigin=eyJpIjoiYTBiZTQ4MTY3NzlkNDE4YzgzMWRlZDJlN2EyMjNiNDAiLCJwIjoiaiJ9 ## **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** > Changes Predict feed navigation and market-fetching behavior by adding a new `hot` category with remotely supplied raw query params that can bypass default API filters, which could affect results and pagination if misconfigured. > > **Overview** > Adds a new **remote feature-flagged “Hot” tab** to `PredictFeed`, inserted as the first tab when `predictHotTab` is enabled (with version gating and a default fallback), and wires its `queryParams` through to market fetching. > > Extends `usePredictMarketData`/provider params with `customQueryParams` and updates the Polymarket API query builder to, for the `hot` category only, optionally construct the request using just `limit`/`offset` plus the provided raw query string (otherwise falling back to the existing default filters). Includes locale text for “Hot” and adds/updates unit tests covering selector validation, tab rendering/analytics session start, hook refetching, and Polymarket URL construction. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9f8c5cb. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
This PR adds a sticky Buy/Sell action bar to the Token Details page
(V2), allowing users to quickly swap into or out of the token they're
viewing.
To test this please make sure you have `isTokenDetailsRevampedEnabled`
return `true`
### Buy Button Logic
```
User taps Buy
├─ Has tokens on same chain? → Use highest USD value token → Open Swap
├─ Has tokens on any chain? → Use highest USD value token → Open Bridge/Swap
└─ No eligible tokens? → Route to On-Ramp (buy crypto with cash)
```
- **Destination**: Always the current token being viewed
- **Source**: Smartly selected based on user's portfolio
### Sell Button Logic
```
User taps Sell
├─ Destination = getDefaultDestToken(chainId)
│ ├─ Ethereum, Linea → mUSD
│ ├─ Optimism, Arbitrum, Base, Avalanche, Sei, Monad → USDC
│ └─ BSC, Polygon, zkSync → USDT
│
└─ If source === default dest (e.g., selling mUSD)?
└─ Fallback to native token (ETH, BNB, etc.)
```
- **Source**: Always the current token being viewed
- **Destination**: Set as defined and will be handled automatically by
swap UI
- **Visibility**: Sell button only appears if user has balance > 0
## **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 Buy/Sell sticky action bar to Token Details page
with smart token selection
## **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="376" height="773" alt="Screenshot 2026-02-02 at 10 56 02"
src="https://github.com/user-attachments/assets/d68a3f44-cd62-4f2d-9b88-87e343b043b7"
/>
<img width="385" height="772" alt="Screenshot 2026-02-02 at 10 56 37"
src="https://github.com/user-attachments/assets/e5301851-2320-4416-a515-175f18a3337e"
/>
## **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**
> Adds new Token Details action UI and new swap/on-ramp routing logic
based on the user’s asset map, which could affect navigation into
swaps/bridge flows. Although gated behind a temporary flag (default
`false`), the address normalization change may impact asset lookup
behavior broadly if assumptions differ.
>
> **Overview**
> **Token Details V2 now supports a feature-flagged sticky action
footer** (`BottomSheetFooter`) below the transactions view, padding for
safe-area insets. The footer always shows **Buy** and conditionally
shows **Sell** only when the viewed token has a positive balance.
>
> **Action handling is extended in `useTokenActions`** with
`handleBuyPress`/`handleSellPress`: Buy selects a swap/bridge source
token by choosing the highest-fiat-balance asset (preferring same-chain,
else any chain; allows cross-chain native-token zero-address matching),
and falls back to on-ramp when no eligible assets exist; Sell opens
swaps with the current token as the source and leaves destination
undefined for the swap UI.
>
> Separately, `useTokenBalance` now normalizes token addresses via
`toFormattedAddress` before `selectAsset` lookup, and new/updated tests
cover the footer visibility and the new action selection behavior.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b8cdb3e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ode cleanup (#25237) ## **Description** Replaces the static empty state with a featured markets experience and adds A/B testing capability to experiment with different presentation styles. ### **Core Changes** **A/B Test Implementation:** - Added `predictHomeFeaturedVariant` feature flag with version gating support - **Carousel variant** (default): Horizontal scrolling cards with market details and price charts - **List variant**: Vertical list using `PredictMarketRowItem` for a more compact view - `PredictHomeFeatured` component routes to the appropriate variant based on feature flag **New Component Architecture:** - `PredictHomePositions`: Orchestrator that fetches positions and decides what to render - `PredictHomeFeatured`: Router component for A/B test variants - `PredictHomeFeaturedCarousel`: Carousel variant (horizontal cards) - `PredictHomeFeaturedList`: List variant (vertical row items) - `PredictHomeFeaturedSkeleton`: Variant-aware loading skeleton - `PredictHomeSkeleton`: Row-style skeleton matching position list layout - `PredictHomeAccountState`: Balance/claim card wrapper - `PredictHomePositionList`: Active + claimable positions list **Variant-Specific Analytics Entry Points:** Each variant has its own entry point for measuring A/B test conversion rates: | Entry Point | Value | Used By | |-------------|-------|---------| | `HOMEPAGE_FEATURED_CAROUSEL` | `'homepage_featured_carousel'` | Carousel variant | | `HOMEPAGE_FEATURED_LIST` | `'homepage_featured_list'` | List variant | This enables filtering analytics by `entry_point` to compare: - Impressions per variant - Click-through rates - Trade conversion rates **UX Improvements:** - Balance card hidden when user has no positions (only shows with active positions) - Variant-specific loading skeletons match the actual content layout - Fixed UI flash on account switch via stale data detection in `usePredictPositions` ### **Dead Code Removal** Removed unused components superseded by the new `PredictHome` architecture: - `PredictPositions/` directory (replaced by `PredictHomePositions`) - `PredictPositionSkeleton/` directory (only used by `PredictPositions`) - `PredictPositionEmpty/` directory (replaced by `PredictHomeFeaturedCarousel`) **Total: ~1,500 lines of dead code removed** ## **Changelog** CHANGELOG entry: Added A/B test for homepage featured section (carousel vs list) with variant-specific analytics; replaced empty predictions state with featured markets; hide balance card when no positions exist; removed dead code ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/PRED-552 ## **Manual testing steps** ```gherkin Feature: Predictions empty state shows featured markets with A/B test Scenario: user views positions tab with no active predictions (carousel variant) Given user has no active prediction positions And predictHomeFeaturedVariant flag is set to "carousel" (or not set) When user views the Positions section Then user sees a "Trending" header with an arrow And user sees a horizontal carousel of market cards And user does NOT see the balance/account state card And analytics events use entry_point: 'homepage_featured_carousel' Scenario: user views positions tab with no active predictions (list variant) Given user has no active prediction positions And predictHomeFeaturedVariant flag is set to "list" When user views the Positions section Then user sees a "Trending" header with an arrow And user sees a vertical list of market row items And user does NOT see the balance/account state card And analytics events use entry_point: 'homepage_featured_list' Scenario: loading skeleton matches variant Given user has no active prediction positions When positions are being refreshed Then loading skeleton style matches the configured variant (carousel shows horizontal card skeletons, list shows row skeletons) Scenario: user views positions tab with active predictions Given user has active prediction positions When user views the Positions section Then user sees the balance/account state card And user sees their active positions list Scenario: switching accounts shows loading state correctly Given user A has positions and user B has no positions When user switches from account A to account B Then user sees a skeleton loading state (no UI flash) Then user sees the featured section (empty state) ``` ## **Feature Flag Configuration** ```typescript // Remote feature flag structure { predictHomeFeaturedVariant: { enabled: true, minimumVersion: "7.x.x", // Version gating variant: "carousel" | "list" } } ``` ## **Analytics Query Example** ```sql -- Compare A/B test variant performance SELECT entry_point, COUNT(*) as impressions, COUNT(CASE WHEN event = 'market_details_viewed' THEN 1 END) as market_views, COUNT(CASE WHEN event = 'predict_trade_initiated' THEN 1 END) as trades, ROUND(COUNT(CASE WHEN event = 'predict_trade_initiated' THEN 1 END) * 100.0 / NULLIF(COUNT(CASE WHEN event = 'market_details_viewed' THEN 1 END), 0), 2) as conversion_rate FROM predict_events WHERE entry_point IN ('homepage_featured_carousel', 'homepage_featured_list') GROUP BY entry_point ``` ## **Screenshots/Recordings** ### **Before** <!-- User will add screenshots --> ### **After** <!-- User will add screenshots --> https://www.loom.com/share/ab7bd7b9ac23480fb2f1a6b4ec461ce2 ## **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** > Moderate UI/UX refactor in the Predict tab that changes loading/empty-state behavior and navigation/analytics entry points; risk is mainly regressions in rendering, refresh, and tracking across account switches. > > **Overview** > Replaces the old `PredictPositions`/empty-state flow with a new `PredictHome`-based orchestration (`PredictHomePositions`) that decides between **featured markets** (when no positions), **account state + positions list** (when positions exist), and variant-aware **skeleton states** during initial load/refresh. > > Adds an A/B test for the featured section via a version-gated remote flag `predictHomeFeaturedVariant`, routing between a `Section`-backed carousel and a `usePredictMarketData`-backed list, and introduces new analytics `entryPoint`s (`homepage_featured_carousel`, `homepage_featured_list`). > > Introduces `PredictEntryPointContext` and updates multiple market card/row components to prefer a context-provided `entryPoint` over props/defaults (while preserving Trending overrides), and hardens `usePredictPositions` to avoid UI flashes on account switch by treating previously-loaded data as stale and initializing `isLoading` based on `loadOnMount`. > > Cleans up dead code by deleting `PredictPositions`, `PredictPositionEmpty`, and `PredictPositionSkeleton`, and updates `PredictTabView` and tests to use the new `PredictHomePositions` refresh/error surface. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 58f39b9. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** iOS source maps were not being uploaded to bitrise due to a bad path <img width="1599" height="830" alt="Screenshot 2026-02-03 at 5 13 13 PM" src="https://github.com/user-attachments/assets/44f82ea7-5ca8-4ff6-a43b-40fdf7de7981" /> `react-native-xcode.sh` cds into the the `PROJECT_ROOT` before creating the source maps, so it was creating the source maps OUTSIDE of the repo. Hence the odd file path we see in the screenshot. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Create a PR and check that the iOS source maps are uploaded to bitrise. ## **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** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk shell-script change that only affects where the iOS JS sourcemap is written; main risk is CI/build pipeline expectations around artifact paths. > > **Overview** > Fixes iOS sourcemap generation in CI by forcing React Native/Sentry bundling to write the sourcemap to a **stable, repo-root-relative** location. > > `scripts/ios/bundle-js-and-sentry-upload.sh` now creates `sourcemaps/ios/` and exports `SOURCEMAP_FILE` (default `sourcemaps/ios/index.js.map`) so Bitrise can reliably collect and deploy the artifact. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0c6f1db. 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 : )