[pull] main from MetaMask:main#517
Merged
Merged
Conversation
style: center button content in LedgerConnect and LedgerSelectAccount… components Updated styles in `Scan.tsx` and `index.styles.ts` to center the button content by adding `justifyContent: 'center'` to the button styles, enhancing the UI consistency across the Ledger components. <!-- 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: fix #25693 styling issue in for ledger devices ## **Related issues** Fixes: #25693 ## **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** - [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** > Style-only changes limited to Ledger selector layout plus a snapshot update; no functional, security, or data-flow impact. > > **Overview** > Fixes a Ledger UI alignment issue by centering the contents of the device/path selector containers. > > Adds `justifyContent: 'center'` to the dropdown wrapper styles in `LedgerConnect/Scan.tsx` and `LedgerSelectAccount/index.styles.ts`, and updates the LedgerConnect Jest snapshot accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 70e5b96. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Long token names in the Send flow and MM Pay token picker were pushing the balance display off the screen. This fix adds proper flex constraints to allow the token name container to shrink while keeping the balance visible. 1. **Reason for change:** Tokens with long names (e.g., DAI on Linea, USDT on Base) push the balance completely off screen in the Send flow token picker and MM Pay deposit confirmation. 2. **Solution:** Add flex constraints (`flex-1`, `min-w-0`) to the token info container to allow proper shrinking, and change the balance container to `shrink-0` to prevent it from being pushed off screen. This matches the behavior of the home page token list. ## **Changelog** CHANGELOG entry: Fixed long token names pushing balance off screen in Send flow and MM Pay token picker ## **Related issues** Fixes: MetaMask/MetaMask-planning#6940 ## **Manual testing steps** ```gherkin Feature: Token picker displays long token names correctly Scenario: User views token with long name in Send flow Given user has a token with a long name (e.g., DAI on Linea, USDT on Base) When user starts a Send flow and opens the token picker Then the long token name is truncated with ellipsis And the balance is visible on the right side of the screen Scenario: User views token with long name in MM Pay deposit Given user has a token with a long name When user starts a Perps or Predict deposit and views the token picker Then the long token name is truncated with ellipsis And the balance is visible on the right side of the screen ``` ## **Screenshots/Recordings** ### **Before** Long token names push the balance off the screen (see issue for screenshots). ### **After** Long token names truncate with ellipsis while the balance remains visible. ## **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 - [x] 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.
## **Description**
`@metamask/perps-controller` is a local path alias (not an npm package)
resolved via `tsconfig.json` paths and `metro.config.js`. ESLint's
`import/no-extraneous-dependencies` rule doesn't understand path aliases
and flags every import as missing from `package.json`.
This adds `import/internal-regex` to `.eslintrc.js` settings so imports
matching `^@metamask/perps-controller` are classified as internal
modules, skipping the `package.json` check.
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: false positive ESLint errors on `@metamask/perps-controller`
imports.
## **Manual testing steps**
```gherkin
Feature: ESLint config for perps-controller path alias
Scenario: Lint a file importing @metamask/perps-controller
Given the developer has the current branch checked out
When running `npx eslint app/components/UI/Perps/Views/PerpsTabView/PerpsTabView.tsx`
Then no `import/no-extraneous-dependencies` error is reported for @metamask/perps-controller
```
## **Screenshots/Recordings**
N/A - config-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
- [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**
> Config-only ESLint change affecting lint classification of a single
import prefix; no runtime behavior changes.
>
> **Overview**
> Adjusts ESLint `import` settings to classify
`^@metamask/perps-controller` as an *internal* module via
`import/internal-regex`.
>
> This prevents `import/no-extraneous-dependencies` from flagging the
`@metamask/perps-controller` path alias as missing from `package.json`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
52e11c4. 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?
-->
## Summary
- Adds bidirectional communication between E2E tests and the app via the
existing CommandQueueServer
- Tests can now request a snapshot of the app's Redux +
Engine/Controller state and assert on it
- All app-side code is guarded by `isE2E` — zero production impact
## Changes
- **`tests/framework/types.ts`** — Added `exportState` to
`E2ECommandTypes` enum (renamed from `PerpsModifiersCommandTypes`)
- **`tests/framework/fixtures/CommandQueueServer.ts`** — Added `POST
/exported-state`, `GET /exported-state.json` routes,
`requestStateExport()` and `getExportedState()` methods
- **`app/util/test/e2eStateExport.ts`** — New: captures app state
(`store.getState()`) and POSTs it to the server
- **`app/util/test/e2eCommandPolling.ts`** — New: polls `/queue.json`
for generic commands like `export-state`
- **`app/store/index.ts`** — Bootstraps generic command polling on store
init when `isE2E`
- **`tests/regression/wallet/state-export.spec.ts`** — E2E test:
onboards a new wallet, exports state, verifies accounts
- **Unit tests** for `e2eCommandPolling` and `e2eStateExport` confirming
no-op in production
## **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**
- [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**
> Changes are gated behind `isE2E` and primarily affect the test
harness, with minimal production impact; the main risk is E2E flakiness
from the new store-init polling timer and command server interactions.
>
> **Overview**
> Enables **bidirectional E2E test ↔ app communication** by adding an
E2E-only command poller in the app that consumes `/queue.json` and
handles a new `export-state` command by serializing `store.getState()`
(Redux + engine background state) and POSTing it back to the
`CommandQueueServer`.
>
> Updates the test harness `CommandQueueServer` to persist exported
state and expose `POST /exported-state` + `GET /exported-state.json`,
adds helper APIs (`requestStateExport`, `getExportedState`), and
introduces a regression spec asserting onboarding produces accounts via
the exported snapshot. Perps command handling is consolidated under a
shared `E2ECommandTypes` enum and moved out of the Perps UI bridge by
deleting the old perps-specific HTTP polling logic, while keeping the
deep-link handler for perps commands.
>
> Separately, the `smart-e2e-selection` GitHub composite action now
checks the `skip-smart-e2e-selection` label up front and gates
subsequent setup steps on it, and fixture JSON imports are redirected to
`fixtures/json/*`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6230e51. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…balance (#25960) <!-- 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** 1. **What is the reason for the change?** The "Add funds to start trading perps" banner with "Add funds" CTA on the Perps market details screen was removed by product. Users should still be able to start a trade (Long/Short) even when their perps balance is zero; they can add funds in the order/deposit flow if needed. 2. **What is the improvement/solution?** - Removed the add-funds banner and "Add funds" button from the fixed actions footer on the Perps market details (asset) screen. - Action footer now shows Long/Short (or Modify/Close when there is a position) whenever position data is loaded, regardless of balance. Users with zero perps balance can tap Long or Short and proceed to the order flow. - Removed unused logic: `hasZeroBalance`, `hasAddFundsButton`, `handleAddFundsPress`, and hooks only used for that CTA (`useConfirmNavigation`, `usePerpsTrading`, `usePerpsNetworkManagement`, `usePerpsLiveAccount`). - Updated unit tests to assert Long/Short buttons are shown with zero balance and that the add-funds banner is no longer present. ## **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: Removed "Add funds to start trading perps" banner from Perps market details and allow opening trades (Long/Short) when perps balance is zero. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2530 ## **Manual testing steps** ```gherkin Feature: Perps market details – no add-funds banner, trade with zero balance Scenario: user opens a perps market with zero balance Given user is on a Perps market details screen and their perps balance is 0 When the screen has finished loading Then the "Add funds to start trading perps" banner and "Add funds" button are not shown And Long and Short buttons are shown in the footer And user can tap Long or Short and proceed to the order flow Scenario: user opens a perps market with non-zero balance Given user is on a Perps market details screen and their perps balance is > 0 When the screen has finished loading Then Long and Short (or Modify/Close if they have a position) are shown as before And no add-funds banner is shown ``` ## **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="1206" height="2622" alt="simulator_screenshot_27173437-1211-4E38-B9DD-D5CACE24AFD1" src="https://github.com/user-attachments/assets/4f5acacb-9c25-41b1-89d0-fa531a530df6" /> ## **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** > UI behavior change limited to the market details action footer and corresponding tests; no changes to order placement or on-chain flows, but it can affect user navigation expectations for zero-balance users. > > **Overview** > Removes the fixed-footer "Add funds to start trading perps" banner/CTA from `PerpsMarketDetailsView` and no longer gates the Long/Short actions on having a non-zero perps balance (buttons now render whenever position loading is complete). > > Deletes the associated deposit-navigation handler and related hooks/imports used only for that CTA, and updates tests to assert Long/Short buttons are visible at zero balance while the add-funds UI and its navigation/geo-block test cases are removed. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fb8eba1. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** Bumps the STX controller to ^22.5.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: null ## **Related issues** Fixes: ## **Manual testing steps** When a cancelled smart transaction happens, we will log this new prop in the Transaction Finalized event, which will give us more granular reason for cancellation ## **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** > Dependency-only bump with no in-repo logic changes; risk is limited to behavioral changes introduced by the upstream controller update. > > **Overview** > Updates the `@metamask/smart-transactions-controller` dependency from `^22.4.0` to `^22.5.0`. > > Regenerates `yarn.lock` to pin the new `22.5.0` resolution and checksum for this package. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9573cfe. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
<!-- 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 will fix #24546 regarding unknown error display in ledger selection screen. The root cause of this issue is due to mis match of error code returned from ledger sdk. i have setup a constant array to cover all code regarding `Eth not open` and also mapping the error code with localisation string. <!-- 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: Fix #24546 with human readable message ## **Related issues** Fixes: #24546 ## **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** - [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 hardware-wallet error classification and account unlock/pagination paths, so misclassification could change user flows or hide actionable errors; token-list CTA logic also changes gating behavior for Earn CTAs. > > **Overview** > Fixes Ledger UX by introducing a dedicated `EthAppNotOpen` error classification (status-code and message based) and mapping it to new localized strings, so users see a clear “open the Ethereum app” prompt instead of generic/unknown errors. > > Plumbs this error through Ledger flows: `useLedgerBluetooth`, `Ledger` core (`getLedgerAccountsByOperation`, `unlockLedgerWalletAccount`), `LedgerConnect`, and the confirmation modal now render the new error state and tests cover the new mappings and helpers. > > Cleans up token list rendering by removing the `shouldShowTokenListItemCta` prop from `TokenList`/`TokenListItem`/`TokenListItemV2` and having items call `useMusdCtaVisibility` internally; also loosens stablecoin lending CTA gating to rely on the returned `earnToken` rather than an extra BigNumber threshold check (and updates tests accordingly). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 372625a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…6000) ## **Description** Apply the `ensureSubscriptionClient()` pattern consistently to all HIP-3 subscription methods. `createClearinghouseSubscription` and `createOpenOrdersSubscription` were missing `ensureSubscriptionClient()` calls before accessing the subscription client. This creates a potential race condition during WebSocket reconnection where the client could be destroyed between the parent method's check and the child's `getSubscriptionClient()` call. The fix adds the same `ensureSubscriptionClient()` guard already used by `createUserDataSubscription` and `createAssetCtxsSubscription`, ensuring all subscription creation methods follow the same defensive pattern. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Sentry perps socket "Subscription client not available" errors ## **Manual testing steps** ```gherkin Feature: Perps WebSocket subscription resilience Scenario: User reconnects to perps after network interruption Given user has perps positions open and is viewing the perps UI When user experiences a brief network disconnection and reconnects Then clearinghouse and open orders subscriptions resume without errors ``` ## **Screenshots/Recordings** N/A - internal WebSocket fix, no UI changes. ## **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. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…5943) <!-- 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** We currently have E2E tests using skipReactNativeReload: true pass but the test suite fails with Aborted errors from mockttp's streamToBuffer. When mockServer.stop() calls destroy(), it immediately kills all TCP connections. Any in-flight background requests (price polling, token metadata, etc.) from the still-running app have their body-buffering promises rejected as unhandled rejections, which Jest reports as "Test suite failed to run." Example: https://github.com/MetaMask/metamask-mobile/actions/runs/21895017113/job/63209898359 ### Solution Add graceful shutdown to MockServerE2E: - Shutdown flag (_shuttingDown): When set, request handlers consume the body (preventing unhandled rejections) and return 503 immediately instead of processing. - Active request tracking (_activeRequests): Tracks in-flight handler callbacks. stop() waits for them to drain before calling destroy(), so connections are only killed when idle. - Timeout safety net: 5s max wait to avoid hanging on slow CI, with warning logs if requests don't drain in time. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1420 ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A <!-- [screenshots/recordings] --> ### **After** N/A <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [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 E2E request proxying and shutdown behavior; mistakes could hang shutdowns or change which requests are forwarded vs short-circuited, though changes are test-only and include a timeout safety net. > > **Overview** > Prevents E2E failures during `MockServerE2E.stop()` by adding **graceful shutdown**: a `_shuttingDown` gate returns `503` while safely consuming request bodies, and `_activeRequests` tracking drains in-flight handlers before calling `mockttp.stop()` (with a 5s timeout and logging). > > Updates `Gestures.scrollToElement` on iOS to pass `startPositionX/Y` through to Detox scrolling, and adjusts `TrendingView` horizontal quick-action scrolling to use a normalized `startPositionX` (`0.5` instead of `50`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5e3358d. 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** WalletConnect V1 has been fully deprecated. This PR removes leftover codepaths from that integration. <!-- 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: remove WalletConnect V1 support ## **Related issues** Fixes: [WAPI-1033](https://consensyssoftware.atlassian.net/browse/WAPI-1033) ## **Manual testing steps** There's no feature to test, this is removal of dead code. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **After** https://github.com/user-attachments/assets/b8043868-13d1-4922-b2b5-ed8b30f74c38 (WC connections still work) ## **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. [WAPI-1033]: https://consensyssoftware.atlassian.net/browse/WAPI-1033?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it removes approval/UI and connection codepaths that may still be referenced by edge flows (deeplinks/QR) and changes session management behavior to v2-only, though changes are largely deletions with updated tests. > > **Overview** > Removes the legacy WalletConnect v1 integration end-to-end: deletes the `app/core/WalletConnect/WalletConnect.js` implementation, its tests, the `WALLET_CONNECT` approval type, and the `WalletConnectApproval` UI/modal wiring from `RootRPCMethodsUI`. > > Updates the WalletConnect sessions screen to be **v2-only**, sourcing sessions and disconnect actions exclusively via `WC2Manager` and rendering v2 session fields (e.g., `topic`), with tests/snapshots updated accordingly. > > `WC2Manager.connect` now explicitly rejects v1 URIs by logging a deprecation warning and returning early; invalid-URI warnings/tests were adjusted, and v1 dependencies (`@walletconnect/client`, socket transport) were removed from `package.json`/`yarn.lock`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d53d91b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…onGatedFeatureFlag (#25992) ## **Description** Inlines the MYX provider feature flag check in `PerpsController`, removing the dependency on `resolvePerpsMyxProviderEnabled` from the UI selectors layer. Reuses the shared `isVersionGatedFeatureFlag` utility and the controller's existing `featureFlags.validateVersionGated` infrastructure instead. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A ## **Manual testing steps** ```gherkin Feature: Perps MYX provider feature flag Scenario: MYX provider flag resolves correctly Given the app is running with perps enabled When the PerpsController checks the MYX provider flag Then it should resolve the version-gated remote flag via the controller's infrastructure ``` ## **Screenshots/Recordings** N/A — no UI changes. ### **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] > **Low Risk** > Scoped refactor of feature-flag resolution with test updates; primary risk is behavior drift if remote flag shape/version validation differs from the previous selector logic. > > **Overview** > MYX provider enablement is now resolved inside `PerpsController.isMYXProviderEnabled()` instead of calling the UI selector `resolvePerpsMyxProviderEnabled`, using the shared `isVersionGatedFeatureFlag` + `featureFlags.validateVersionGated` path and falling back to `MM_PERPS_MYX_PROVIDER_ENABLED`. > > Tests were updated to stop mocking the selector and instead exercise the new behavior by providing `perpsMyxProviderEnabled` in `RemoteFeatureFlagController:getState` and mocking version validation when switching to `myx`, while keeping the “MYX disabled” fallback-to-`hyperliquid` case. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6ca1246. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… feature tags (#26004) ## **Description** Sentry shows "Unknown error (no details provided)" events/week from perps code because: 1. Most `ensureError()` calls lack the optional `context` parameter — when the caught value is `undefined`/`null`, the error has no identifying info. 2. Several `logger.error()` calls are missing the `feature` tag, making them invisible in the Sentry perps dashboard. ### What changed - Added `context` string (e.g. `'AccountService.withdraw'`) to ~35 bare `ensureError()` calls across 21 files - Added `tags: { feature: PERPS_CONSTANTS.FeatureName }` to ~14 `logger.error()` calls missing it - Replaced 13 hardcoded `feature: 'perps'` with `PERPS_CONSTANTS.FeatureName` No functional behavior changes — only error metadata is enriched. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Sentry "Unknown error (no details provided)" noise from perps layer ## **Manual testing steps** No user-facing changes. Verify existing perps flows (deposit, withdraw, trade) still work. Error reporting improvements are observable only in Sentry. ## **Screenshots/Recordings** N/A — observability-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 - [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** > Logging/telemetry metadata-only changes; functional code paths are unchanged aside from error object/message enrichment when errors are `null`/`undefined`. > > **Overview** > Improves Perps observability by **adding explicit context strings to many `ensureError(...)` calls** so Sentry errors are identifiable even when the thrown value is `null`/`undefined`. > > Standardizes Perps `Logger.error`/`deps.logger.error` payloads by **using `tags: { feature: PERPS_CONSTANTS.FeatureName }` (and removing ad-hoc `feature: 'perps'` fields / message+context strings)** across UI views, hooks, connection/subscription management, controller/services, and provider implementations; updates a few unit tests to match the new logging shape. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 109672c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
) ## **Description** Creates a new FF for token details v2 with min version ## **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** > Feature-flag plumbing and selector behavior changes only; risk is mainly incorrect gating if the new flag payload/override configuration is wrong. > > **Overview** > Adds a new remote feature flag `tokenDetailsV2ButtonLayout` (default `false`) and switches `selectTokenDetailsV2ButtonsEnabled` to evaluate this flag via `validatedVersionGatedFeatureFlag`, including support for override env vars. > > Updates the `AssetOverviewContent` test to mock the feature-flag selectors directly and removes reliance on `RemoteFeatureFlagController.remoteFeatureFlags.tokenDetailsV2Buttons` state. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 276d02c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
#25971) <!-- 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** Geolocation request failures were causing a cascade that reset `userCardLocation` from `'us'` to `'international'` for authenticated US users, breaking the `x-us-env` header required for US operations. **Root cause:** The `useCardAuthenticationVerification` hook dispatched `resetAuthenticatedData()` whenever `isBaanxLoginEnabled` was `false`. Since `isBaanxLoginEnabled` depends on `cardGeoLocation` (IP-based lookup), a transient network failure would set `cardGeoLocation` to `'UNKNOWN'`, making `isBaanxLoginEnabled` evaluate to `false`, which triggered the reset — wiping `userCardLocation` and causing the SDK to re-instantiate with `x-us-env: false`. **The fix has two parts:** 1. **Decouple `userCardLocation` from auth state resets:** `resetAuthenticatedData`, `verifyCardAuthentication.fulfilled` (when no location in payload), and `verifyCardAuthentication.rejected` no longer reset `userCardLocation` to `'international'`. A user's declared/registered region does not change when auth state changes. 2. **Guard session clearing against transient geo failures:** `useCardAuthenticationVerification` now only clears sessions when `isBaanxLoginEnabled` is `false` AND `cardGeoLocation` has been resolved (i.e. is not `'UNKNOWN'`). When geo is `'UNKNOWN'` (initial state or network failure), the session is preserved. Once geo resolves to an unsupported country, the session is cleared as expected. ## **Changelog** CHANGELOG entry: Fixed `x-us-env` header being incorrectly set to `false` for US Card users when geolocation requests fail ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Card x-us-env header resilience to geolocation failures Scenario: US user retains correct x-us-env header when geolocation fails Given a US user is authenticated with the Card feature And userCardLocation is set to 'us' When the geolocation API request fails (e.g. network error) Then userCardLocation remains 'us' And the x-us-env header is 'true' on subsequent Card API calls And the user's session is not cleared Scenario: US user retains correct x-us-env header on app restart with geo failure Given a US user has a valid stored auth token with location 'us' When the app restarts and the geolocation API is unreachable Then the auth verification reads the location from the stored token And userCardLocation is set to 'us' And the x-us-env header is 'true' on subsequent Card API calls Scenario: Session is cleared when geo resolves to unsupported country Given a user is authenticated with the Card feature And the geolocation API resolves to an unsupported country (e.g. 'FR') When the isBaanxLoginEnabled check evaluates to false Then the user's session is cleared via resetAuthenticatedData And userCardLocation is preserved (not reset to 'international') Scenario: Session is not cleared when geo is unknown Given a user is authenticated with the Card feature And the geolocation API has not resolved yet or has failed (cardGeoLocation = 'UNKNOWN') When the isBaanxLoginEnabled check evaluates to false Then the user's session is NOT cleared And the user remains authenticated until the token naturally expires ``` ## **Screenshots/Recordings** <!-- Not applicable — no UI changes --> ### **Before** <!-- N/A --> ### **After** <!-- N/A --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **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 Card authentication reset logic and Redux state persistence (`userCardLocation`), which can affect session handling and regional behavior if the new guards are incorrect; changes are contained and covered by expanded unit tests. > > **Overview** > Prevents Card geolocation failures from cascading into session/location resets by **preserving `userCardLocation`** when clearing authenticated data and when `verifyCardAuthentication` returns/rejects without a location, and by only dispatching `resetAuthenticatedData()` when Baanx login is disabled *and* geolocation has resolved (not `UNKNOWN`). > > Updates Card Home analytics to wait for load even without a priority token, adds a `state` property derived from auth/KYC/warnings/delegated wallets, and avoids emitting priority-token balance properties when no priority token exists. > > Adds a `CARD_BUTTON_CLICKED` analytics event for the push provisioning “Add to wallet” action (new `CardActions.ADD_TO_WALLET_BUTTON`), removes the unused `CARD_ADD_TO_WALLET_CLICKED` event, and simplifies Card SDK geolocation to always call the production endpoint; tests are updated to cover these behaviors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 17c8770. 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** Following #24313 we're looking to centralize all tools and test resources in one place. This marks the final PR deprecating `e2e` by moving all page objects and test specific selectors. A follow up PR will be created to remove all references from scripts and other tools. This PR: - deprecates the `appwright` folder - moves all `appwright/**` files into their appropriate folders inside `tests`. - Marks the first stage of unifying the frameworks Previous related PRs: - #24988 - #24313 - #25031 - #25095 - #25167 - #25198 - #25219 - #25263 - #25279 - #25520 - #25533 - #25598 - #25636 - #25638 - #25698 - #25706 - #25764 - #25785 - #25849 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1235 ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A <!-- [screenshots/recordings] --> ### **After** N/A <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [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** > Moderate risk because it rewires CI workflows, artifact/report paths, and many import paths for the performance test infrastructure; failures would primarily impact performance E2E execution rather than app runtime behavior. > > **Overview** > Consolidates Appwright performance testing under `tests/` by updating GitHub Actions workflows, package scripts, and the aggregation pipeline to use the new locations for the device matrix, config, reports, and aggregated artifacts. > > Refactors the performance test framework and suites to match the new directory structure (updated `testMatch`, fixture/util/reporter imports, and tag sources), adds the new `tests/tags.performance.js` + team mapping, and introduces/relocates performance specs (including a new `asset-view` test and moved launch-time tests). Updates several `wdio` screen objects to pull shared helpers from `tests/framework/utils` instead of `appwright`/Appwright-provided utility paths, and refreshes docs to point to `tests/performance`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 91bab4a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Sentry issues [5E7H](https://metamask.sentry.io/issues/METAMASK-MOBILE-5E7H) (Android) and [5E7K](https://metamask.sentry.io/issues/METAMASK-MOBILE-5E7K) (iOS) report `KeyringController - The operation cannot be completed while the controller is locked.` errors from the Perps trading setup flow. **Root cause**: When a user enters the Perps screen and the app backgrounds or locks, the keyring locks. On the next trade attempt, `ensureReadyForTrading()` runs automatic signing operations (referral setup, builder fee approval, DEX abstraction) that fail because the keyring is locked. These failures are expected but were being reported to Sentry and unnecessarily cached as permanent failures. **Fix**: Guard signing operations against keyring lock state by checking `KeyringController:getState().isUnlocked` before attempting to sign. When the keyring is locked: - Throw a `KEYRING_LOCKED` error from `HyperLiquidWalletService.signTypedMessage()` - Don't cache the failure in the `ensure*` methods (so they can retry on the next attempt) - Don't report to Sentry (expected behavior, not a bug) - Don't mark `tradingSetupComplete = true` (so `ensureReadyForTrading()` re-runs next time) ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [METAMASK-MOBILE-5E7H](https://metamask.sentry.io/issues/METAMASK-MOBILE-5E7H), [METAMASK-MOBILE-5E7K](https://metamask.sentry.io/issues/METAMASK-MOBILE-5E7K) ## **Manual testing steps** ```gherkin Feature: Perps trading setup handles keyring lock gracefully Scenario: user trades after app was backgrounded Given user has navigated to the Perps trading screen And the app is backgrounded long enough for the keyring to lock When user returns to the app and attempts to place a trade Then the trading setup retries the signing operations And no KeyringController errors are reported to Sentry Scenario: user trades without keyring lock Given user has navigated to the Perps trading screen And the keyring is unlocked When user places a trade Then the trading setup completes normally (referral, builder fee, DEX abstraction) And the trade is placed successfully ``` ## **Screenshots/Recordings** N/A - Internal error handling change, no UI changes. ### **Before** KeyringController locked errors sent to Sentry. ### **After** Signing operations gracefully skip when keyring is locked, retry on next trade attempt, no Sentry noise. ## **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 Perps trading readiness/signing and cache behavior; mistakes could cause repeated setup attempts or skipped initialization, but changes are localized and covered by new tests. > > **Overview** > Prevents Perps trading setup from performing signature-required operations when the keyring is locked by introducing a `KEYRING_LOCKED` error path and checking `KeyringController:getState().isUnlocked` before signing. > > Updates HyperLiquid trading-readiness `ensure*` flows to treat keyring-lock failures as *expected*: skip caching failure states (so setup retries after unlock), avoid extra error reporting, and only set `tradingSetupComplete` when the keyring is unlocked. Adds messenger permissions for `KeyringController:getState`, updates UI error translation to never surface the lock error, and extends mocks/tests to cover these scenarios. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 110efc4. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…fig (#25938) <!-- 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** When users leave the Perps order screen (e.g. to check another tab or the Pay-with modal) and return within the 5-minute pending config window, their previously selected "Pay with" token was not restored; the Pay row reverted to the default. This restores the selected pay-with token from pending trade configuration so the Pay row and Pay-with flow reflect the user’s last choice. ## **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: Restored the previously selected "Pay with" token when returning to the Perps order view within 5 minutes. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2523 ## **Manual testing steps** ```gherkin Feature: Perps pending pay-with token restore Scenario: user returns to order view and sees previous pay-with token restored Given user is on the Perps order view for a market And user has selected a specific token in Pay with (e.g. USDC) or left it as Perps balance When user navigates away (e.g. to another tab or screen) and returns within 5 minutes Then the Pay row shows the same token (or Perps balance) that was selected before leaving And opening Pay with modal shows that option pre-selected ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> No visible 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 - [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 Perps state persistence and token-selection synchronization across UI hooks and `PerpsController`, which could cause incorrect token selection or deposits if the pending config mapping is wrong; changes are covered by new unit tests but span multiple layers. > > **Overview** > Restores the previously selected **Perps “Pay with” token** when returning to the order screen by persisting it into the pending trade configuration and syncing it back into the confirmation `payToken` and `PerpsController.selectedPaymentToken`. > > This wires `PerpsPayRow` to read `selectPendingTradeConfiguration(state, initialAsset)` and apply/clear the pending `selectedPaymentToken`, updates `usePerpsSavePendingConfig` to save `selectedPaymentToken`, introduces `parsePayWithToken` + `usePerpsPayWithToken`/`selectPerpsPayWithToken` for safer token parsing, and adjusts controller/types to store an explicit `PerpsSelectedPaymentToken` (incl. optional `description`). Tests are expanded/added to cover the new sync + parsing behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit baeac8c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - Add selectPerpsPayWithAnyTokenAllowListAssets selector (env overrides remote) - Filter pay-with modal tokens by allowlist in usePerpsBalanceTokenFilter - Document PERPS_PAY_WITH_ANY_TOKEN_ALLOW_LIST_ASSETS in .js.env.example and docs - Add unit tests for allowlist parsing and env override ## **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/TAT-2521 ## **Manual testing steps** ```gherkin Feature: Perps pay-with token allowlist Scenario: pay-with modal shows only allowlisted tokens when flag is set Given the app is running with PERPS_PAY_WITH_ANY_TOKEN_ALLOW_LIST_ASSETS set (e.g. "1.0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" for USDC on mainnet) When user opens Perps and triggers the pay-with modal (e.g. from order flow) Then only the Perps balance option and tokens matching the allowlist are shown Scenario: pay-with modal shows all tokens when allowlist is empty Given PERPS_PAY_WITH_ANY_TOKEN_ALLOW_LIST_ASSETS is unset or empty (and remote flag empty) When user opens the pay-with modal Then all eligible tokens appear as before (no filtering) ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> No visible 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 - [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** > Changes which tokens can be presented for funding perps orders based on a remotely configurable allowlist; misconfiguration could unintentionally hide valid tokens, though parsing is designed to fail open. > > **Overview** > Adds a new Perps configuration flag `perpsPayWithAnyTokenAllowlistAssets` (env `MM_PERPS_PAY_WITH_ANY_TOKEN_ALLOWLIST_ASSETS` overrides LaunchDarkly) to define an allowlist of permitted pay-with assets as `chainId.address`. > > Updates `usePerpsBalanceTokenFilter` to filter pay-with modal tokens to the allowlist (while still prepending the synthetic Perps balance token), and introduces `parseAllowlistAssets` to safely parse/normalize flag values (string or array) with a fail-open `[]` fallback. Tests and docs are updated to cover env override, parsing behavior, and filtering. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 39e809c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description**
Three changes to the perps standalone mode:
1. **Rename `readOnly` → `standalone`** across the entire stack (types,
controller, provider, services, hooks, tests, docs). "Standalone" better
describes the intent: lightweight queries via a standalone `InfoClient`
without full initialization.
2. **HIP-3 multi-DEX support in standalone mode.** Standalone
`getPositions` and `getAccountState` now discover and query all
validated HIP-3 DEXs (same as the fully-initialized path), with DEX list
caching and graceful fallback to main DEX on errors.
3. **Store raw `returnOnEquity` — let UI handle formatting.** Removed
`.toFixed(1)` from `returnOnEquity` at the data layer so it stores raw
numeric strings like all other `AccountState` fields. The UI's
`formatPercentage()` handles display precision.
### Key changes
- New `getStandaloneValidatedDexs()` method — discovers DEXs via
standalone `InfoClient`, filters by allowlist, caches results
- `getPositions` standalone path queries all validated DEXs in parallel
and combines positions
- `getAccountState` standalone path aggregates balances and margin
across all validated DEXs
- Removed single-DEX `getStandaloneClearinghouseState` helper
(superseded)
- Added dedicated unit tests for `standaloneInfoClient.ts` (12 tests
covering transport creation, multi-DEX queries, error propagation)
- Updated `perps-architecture.md` to reflect HIP-3 support in standalone
mode
- Removed `.toFixed(1)` from `returnOnEquity` in adapter, accountUtils,
and HyperLiquidProvider (4 call sites)
- `returnOnEquity` now stores raw numeric strings like all other
`AccountState` fields
- Updated test assertions to match raw values (e.g. `'10'` instead of
`'10.0'`)
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: Perps standalone mode
Scenario: Standalone positions include HIP-3 DEXs
Given a user with positions on both main DEX and a HIP-3 DEX
When calling getPositions with standalone: true
Then positions from all validated DEXs are returned
Scenario: Standalone account state aggregates across DEXs
Given a user with balances on multiple DEXs
When calling getAccountState with standalone: true
Then totalBalance and marginUsed are summed across DEXs
Scenario: Graceful fallback
Given the perpDexs() API call fails
When calling getPositions with standalone: true
Then only main DEX positions are returned (no error thrown)
```
## **Screenshots/Recordings**
N/A — internal changes only, no UI impact.
## **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 core perps data-fetch paths (controller/provider) and changes
numeric formatting/aggregation behavior, which could subtly impact
balances/ROE display and discovery logic, though covered by expanded
tests and includes graceful fallbacks.
>
> **Overview**
> Renames the perps lightweight query parameter from `readOnly` to
`standalone` end-to-end
(controller/types/provider/hooks/services/tests/docs), keeping the
behavior of bypassing full perps initialization for discovery-style
queries.
>
> Extends standalone mode to support HIP-3 multi-DEX:
`HyperLiquidProvider` now discovers validated DEXs via the standalone
info client, queries `clearinghouseState` across DEXs in parallel (new
`queryStandaloneClearinghouseStates` helper), combines positions, and
aggregates account state totals.
>
> Stops rounding `returnOnEquity` in the data layer by removing
`.toFixed(1)` and returning raw numeric strings; adds
`aggregateAccountStates` utility and updates/expands unit tests to match
the new semantics and fallback behavior when standalone queries fail.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3758398. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…Socket timeout failures (#26014) ## **Description** Fixes the "Failed to fetch market data" error that is a top Sentry issue for Perps. `getMarketDataWithPrices()` uses the WebSocket-based `InfoClient` for one-shot request/response calls (`metaAndAssetCtxs()`, `allMids()`). When the WebSocket is reconnecting (after app backgrounding or network transitions), messages get buffered and eventually time out — causing all DEX fetches to fail. The fix switches these calls to the existing HTTP-based `InfoClient`, which uses `fetch()` and is independent of WebSocket state. Additionally: - Enriched the aggregate error message with diagnostic context (failed/succeeded DEXs, WebSocket state) - Downgraded per-DEX fetch errors from Sentry to local debug logs to reduce duplicate reporting - Added cache staleness context to `PerpsStreamManager` error reporting ## **Changelog** CHANGELOG entry: Fixed intermittent "Failed to fetch market data" errors on Perps by switching market data fetches from WebSocket to HTTP transport ## **Related issues** Fixes: [METAMASK-MOBILE-521H](https://metamask.sentry.io/issues/METAMASK-MOBILE-521H) ## **Manual testing steps** ```gherkin Feature: Perps market data loading Scenario: user opens Perps after app was backgrounded Given the app has been in the background for 30+ seconds And the WebSocket connection is in reconnecting state When user navigates to the Perps trading screen Then market data loads successfully via HTTP transport And no "Failed to fetch market data" error appears Scenario: user opens Perps on unstable network Given the device has intermittent network connectivity When user navigates to the Perps trading screen Then market data loads via HTTP even if WebSocket is disconnected And cached data is shown if HTTP fetch also fails ``` ## **Screenshots/Recordings** N/A - Backend transport change, no UI changes. ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **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 transport path and error behavior for a critical market-data fetch used during Perps initialization; mistakes could impact data loading or error reporting, though the change is localized and test-covered. > > **Overview** > Fixes intermittent Perps market-data load failures by forcing `HyperLiquidProvider.getMarketDataWithPrices()` to use an HTTP `InfoClient` instead of the WebSocket transport (which can buffer/timeout during reconnect states). > > Tightens observability by logging per-DEX fetch failures only to local debug logs (reducing duplicate Sentry noise), enriching the aggregate "no markets available" error with failed/succeeded DEX lists and WebSocket state, and adding cache staleness + cached-market counts to `PerpsStreamManager` error reporting when refreshes fail. Tests are updated to cover the HTTP client usage and the new diagnostic error message, and the client-service mock now includes `getConnectionState()`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6191349. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
) ## **Description** This PR implements the Continue button functionality in the unified ramps BuildQuote screen to route users to the appropriate flow based on provider type. ### What Changed **Continue Button Routing Logic**: - Native/whitelabel providers (e.g., Transak Native) → Navigate to deposit flow with amount pre-filled - Aggregator providers (e.g., Mercuryo, Banxa) → Fetch widget URL and open Checkout webview - Aggregator providers without URL → Log error (should not occur in production) **New Checkout Component** (`app/components/UI/Ramp/Views/Checkout/`): - Lightweight webview component for aggregator provider widgets - Uses BottomSheet + WebView pattern (consistent with existing aggregator implementation) - Basic error handling for HTTP errors with retry capability - Includes close button with cancel callback hook for future analytics - Order callback processing deferred to future work **Provider Type Detection** (`app/components/UI/Ramp/types/index.ts`): - Extended Quote type to include `providerInfo` metadata - `isNativeProvider(quote)` - Uses `providerInfo.type` instead of suffix pattern matching - `getQuoteProviderName(quote)` - Uses canonical `providerInfo.name` for display - Ensures correct routing regardless of provider ID naming conventions **Navigation Enhancements**: - Wired Checkout screen into unified routes using `Routes.RAMP.CHECKOUT` - Added navbar helper `getRampsNavbarOptions()` for consistent unified flow headers - Deposit flow now accepts and preserves `amount` and `shouldRouteImmediately` params **Controller Integration**: - Added `getWidgetUrl()` method to RampsController hook surface - Added `redirectUrl` parameter to `startQuotePolling()` for callback handling - Updated all test mocks to include new `getWidgetUrl` method ### Why These Changes The unified ramps flow needed a way to handle the Continue button once users select a quote. Different provider types require different navigation paths: - Native providers use our internal deposit flow - Aggregator providers use external widget webviews The implementation ensures type-safe provider detection using metadata instead of string pattern matching, making it resilient to provider naming changes. ### Dependencies Requires updated `@metamask/ramps-controller` package with: - Enhanced `Quote` type including `providerInfo` field - `getWidgetUrl()` controller method The controller changes are in MetaMask/core and bundled in this PR's yarn.lock. ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: [Add issue number if applicable] ## **Manual testing steps** ```gherkin Feature: Unified Ramps Continue Button Flow Scenario: User continues with aggregator provider quote Given user is on the unified ramps BuildQuote screen And user has entered an amount of $100 And user has selected an aggregator provider (Mercuryo/Banxa) And a quote is available and matches the amount When user taps the Continue button Then the app fetches the widget URL from the quote And the Checkout webview opens And the provider name appears in the navbar title And the webview loads the provider's widget Scenario: User continues with native provider quote Given user is on the unified ramps BuildQuote screen And user has entered an amount of $100 And user has selected a native provider (Transak Native) And a quote is available and matches the amount When user taps the Continue button Then the app navigates to the Deposit flow And the amount ($100) is pre-filled in the Deposit BuildQuote screen And the deposit flow starts immediately Scenario: User taps Continue when no quote is available Given user is on the unified ramps BuildQuote screen And user has entered an amount of $100 And quotes are still loading OR no quote is selected When user views the Continue button Then the Continue button is disabled And user cannot proceed Scenario: User closes Checkout webview Given user is in the Checkout webview for an aggregator provider When user taps the Close button in the navbar Then the webview closes And user returns to the BuildQuote screen ``` ## **Screenshots/Recordings** ### **Before** Continue button had no functionality (TODO comment). ### **After** _(Will add after manual testing on device)_ - Screenshot: BuildQuote with Continue button enabled - Recording: Full flow from BuildQuote → Continue → Checkout webview - Recording: Full flow from BuildQuote → Continue → Deposit flow ## **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 navigation paths and an embedded WebView checkout, plus new controller surface (`getWidgetUrl`) and redirect URL handling; issues could impact ramp purchase routing and quote/checkout correctness. > > **Overview** > Implements the unified ramps `BuildQuote` *Continue* flow: validates the selected quote against the current amount/payment method, routes **native/whitelabel** providers into the Deposit flow (passing `amount` + `shouldRouteImmediately`), and routes **aggregator** providers into a new `Checkout` bottom-sheet WebView after fetching a resolved widget URL via `getWidgetUrl`. > > Adds the `Checkout` screen (navigation + tests) with close affordance, optional provider-specific `userAgent`, and HTTP-error handling that only blocks on initial-URL failures. Extends quote polling to pass a `redirectUrl`, plumbs `RampsController.getWidgetUrl` through `useRampsQuotes`/`useRampsController`, introduces quote metadata helpers (`isNativeProvider`, `getQuoteProviderName`, `getQuoteBuyUserAgent`), and updates Deposit `Root`/`BuildQuote` to preserve and initialize from an `amount` param; updates affected tests/mocks accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 179c87f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: George Weiler <georgejweiler@gmail.com>
## **Description** This PR adds analytics for the Perps “pay with any token” flow so we can measure usage and payment method changes. ## **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** Jira issue: https://consensyssoftware.atlassian.net/browse/TAT-2442?atlOrigin=eyJpIjoiZjg3YTQ2NTUyNjQzNDMxMjlkMTU3NzVhYmUxMDljYWYiLCJwIjoiaiJ9 ## **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** No visible change <!-- [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** > Analytics-only changes that add/propagate new tracking fields and events; primary risk is incorrect or inconsistent metric property values rather than functional trading behavior. > > **Overview** > Adds end-to-end MetaMetrics coverage for the Perps “pay with any token” flow. > > Orders now include `trackingData` fields (`trade_with_token`, `mm_pay_token_selected`, `mm_pay_network_selected`) from `PerpsOrderView`, and both `TradingService` and `usePerpsOrderExecution` attach these fields to `PERPS_TRADE_TRANSACTION` events for executed/partially-filled/failed outcomes. > > The pay-with UI now tracks a `PERPS_UI_INTERACTION` event when opening the payment token selector, and `PerpsController.setSelectedPaymentToken` tracks `payment_method_changed` with `initial_payment_method`/`new_payment_method`; event constants/types and docs are updated accordingly, with tests added/updated to assert the new tracking behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 23ad545. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
#25430) …imal precision errors ## **Description** We got a report of a user trying to unstake and getting the error: ``` View: root Error: [number] while converting number 130.96926000000002 to token minimal util, too many decimal places ``` ## **Changelog** CHANGELOG entry: Fixed decimal precision calculation for Tron's staked balance ## **Related issues** n/a ## **Manual testing steps** ```gherkin Feature: Tron TRX Unstaking Scenario: User unstakes TRX when staked balance has decimal values Given the user has TRX staked across Energy and Bandwidth resources with decimal balances And the sum of staked balances would produce floating-point precision artifacts (e.g., 65.48463 + 65.48463 = 130.96926000000002) When user taps "Unstake" on the Tron staking screen Then the unstake flow proceeds without "too many decimal places" error And the staked balance is correctly calculated as 130.96926 TRX ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="1290" height="2796" alt="image" src="https://github.com/user-attachments/assets/ad83eaeb-9b35-4f8d-9c95-a5e6210ca898" /> ### **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] > **Medium Risk** > Touches TRON staking/earn calculation paths and changes the shape of `selectTronResourcesBySelectedAccountGroup` from an array to an object, so any missed call sites could break TRON-specific UI/flows; changes are localized and backed by expanded tests. > > **Overview** > Fixes TRON staking precision bugs by switching staked-balance arithmetic and token minimal-unit conversion to `BigNumber`, preventing floating-point artifacts (e.g. `130.96926000000002`) from causing “too many decimal places” errors. > > Refactors `selectTronResourcesBySelectedAccountGroup` to return a typed `TronResourcesMap` (named fields + precomputed `totalStakedTrx`) and updates TRON UI consumers (`AssetOverview`, `useTokenBalance`, `useTronResources`, Earn/TRON preview) to use the mapped fields instead of scanning arrays. Adds `safeParseBigNumber` and broadens unit tests to cover empty/invalid inputs, APY absence, and precision/rounding edge cases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a7004cb. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ing (#25396) ## **Description** Updated the Cursor rules for unit testing guidelines to focus on **testID-specific guidance** rather than prescribing general mocking philosophy. This change addresses team feedback about respecting MetaMask's support for both sociable and solitary unit testing approaches. **Key changes:** 1. **Focused on testID usage** - Guidelines now specifically address the anti-pattern of mocking components just to inject testIDs 2. **Prefer data test IDs** - Added guidance to always use \`testID\` props for element selection instead of fragile text-based queries 3. **Prefer \`toBeOnTheScreen()\`** - Discourage weak matchers like \`toBeTruthy()\` and \`toBeDefined()\` for element assertions 4. **Child prop objects** - Document that ALL design system and component library components support testID via child prop objects (\`closeButtonProps\`, \`iconProps\`, etc.) 5. **Removed prescriptive mocking guidance** - No longer prescribes "avoid over-mocking" or "prefer real implementations" to respect different testing approaches ### Context from Team Discussion From the Slack thread: - **Joao**: MetaMask supports both sociable and solitary unit tests - shouldn't prescribe one over the other - **Brian**: The specific problem is Cursor mocking components just to inject testIDs when components already support them - **Nico**: Guidelines should be specific to testID usage, not general mocking philosophy ### Research Findings - **84 test files** currently mock \`@metamask/design-system-react-native\` unnecessarily - **3,394 uses** of \`toBeTruthy()\` (many should use \`toBeOnTheScreen()\`) - **2,601 uses** of \`toBeDefined()\` (many should use \`toBeOnTheScreen()\`) ### Example Implementation See **[PR #25548](#25548 for a concrete example of refactoring following these guidelines. That PR demonstrates: - Removed **133 lines of unnecessary mocks** from RegionSelectorModal test - Used \`closeButtonProps={{ testID: '...' }}\` instead of mocking BottomSheetHeader - Kept only justified mocks (external boundaries, imperative handles) with clear documentation - All 22 tests passing ✅ **Before (unnecessary mocking):** \`\`\`tsx // 30+ lines of mock code to inject a testID jest.mock('BottomSheetHeader', () => { return ({ onClose }) => ( <TouchableOpacity testID="close-button" onPress={onClose}>Close</TouchableOpacity> ); }); \`\`\` **After (using child prop objects):** \`\`\`tsx // Zero mocking needed - use the component's API <BottomSheetHeader onClose={handleClose} closeButtonProps={{ testID: 'region-selector-close-button' }} /> \`\`\` ## **Changelog** CHANGELOG entry: null ## **Related issues** Related: #25548 (example test refactoring) ## **Manual testing steps** \`\`\`gherkin Feature: Unit Testing Guidelines Scenario: Developer writes unit tests following guidelines Given the developer is writing a new unit test When they reference the unit-testing-guidelines.mdc Cursor rule Then they see guidance to use testID props instead of mocking And they see guidance to use toBeOnTheScreen() instead of toBeTruthy() And they see guidance to use child prop objects for internal element testIDs \`\`\` ## **Screenshots/Recordings** ### **Before** N/A - Documentation changes only ### **After** N/A - Documentation changes only ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (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** > Documentation-only changes to testing guidelines with no runtime code or behavior changes. > > **Overview** > Updates `.cursor/rules/unit-testing-guidelines.mdc` to push more reliable UI testing practices: prefer selecting elements via `testID`/`getByTestId` (with naming conventions) and prefer `toBeOnTheScreen()` over weak presence matchers. > > Adds explicit guidance and examples to avoid mocking `@metamask/design-system-react-native` / `app/component-library` components solely to inject test IDs, documenting the use of child prop objects (e.g., `closeButtonProps`, `iconProps`) as the standard way to target internal elements, and refreshes the reviewer checklist/common mistakes accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d591bed. 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** The import token flow is not polished enough, it has a couple of bugs: - Import token screen has a network picker that is not on top o the screen - Import token screen shows chains that are not supported for an account - Import token checkbox is not working onPress - Removal of old deprecated code <!-- 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: multiple fixes on import token flow ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2653 & https://consensyssoftware.atlassian.net/browse/ASSETS-2654 & https://consensyssoftware.atlassian.net/browse/ASSETS-2655 & https://consensyssoftware.atlassian.net/browse/ASSETS-2618 ## **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** https://github.com/user-attachments/assets/fb74c776-90f2-4a30-88fd-af84c98710c2 <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/63ebcd78-2d94-416b-be77-24c878132031 <!-- [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 core navigation and asset-import UI flows; risk is mainly regressions in header layout, network selection filtering, and tap handling across multi-select rows. > > **Overview** > Improves the `AddAsset` (import token/NFT) screen by moving safe-area/header rendering into the view (`HeaderCompactStandard` + insets) and simplifying `MainNavigator`’s `AddAsset` route options. > > Fixes selection UX by preventing the nested checkbox wrapper from intercepting presses (`pointerEvents="none"`) across multi-select list/cell usages, and filters the network picker to hide non‑EVM networks unsupported by the current account scope. > > Hardens token list rendering by providing placeholders when fiat/secondary balance values are missing or non-finite, updates tests accordingly, and removes legacy `Collectibles`/`Collectible` screens and their snapshots/tests. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0cc4ff3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** SonarQube reported that we have 6 nested functions/layers here. Decoupled and used curried funcs to reduce nesting to 2 functions/layers. ## **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: refactor: simplify section state management in TrendingView ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2280 ## **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** - [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** > Pure refactor of local React state update callbacks with no functional or data-flow changes expected; risk is limited to potential mistakes in the Set add/remove logic. > > **Overview** > Refactors `TrendingView.tsx`’s `useSectionStateTracker` by extracting the per-section `setActiveSections` updater into a shared curried helper (`curriedSetSectionState`), reducing callback nesting while keeping behavior the same. > > Each section’s `toggleSection*State` callback is now created by partially applying `setActiveSections` and the `sectionId`, instead of inlining the `setState`/`Set` mutation logic inside the `useMemo` loop. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a56f999. 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: Remove deeplink interstitial on dApp deeplinks ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/GE-117 ## **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] ``` - Open deeplink: https://metamask.app.link/dapp/https://payments.coinbase.com/sandbox/payment-links/pl_01kh61hxfcenvtctydzcwbrh1p?action=TO_DAPP_BROWSER_FLOW - You should be directly redirected to the in-app browser tab ## **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 deep link security UX by allowing `dapp` links to bypass the interstitial, which could increase exposure to unsafe links if the whitelist is too broad or parsing differs from expectations. > > **Overview** > Removes the interstitial modal for `dapp` universal links by adding `ACTIONS.DAPP` to the deep link interstitial whitelist in `handleUniversalLink`. > > Updates `handleUniversalLink` tests to assert `dapp` links no longer trigger the modal, and shifts existing interstitial/signature/link-type modal expectations to use `swap` URLs/titles instead. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8fa5273. 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** Add deeplink capabilities to the asset overview page to allow direct navigation to asset details via CAIP-19 addresses. Url: https://link.metamask.io/asset?assetId=CAIP-19 Examples: ``` # PAXG ETH xcrun simctl openurl booted https://link.metamask.io/asset?assetId=eip155:1/erc20:0x45804880De22913dAFE09f4980848ECE6EcbAf78 adb shell am start -W -a android.intent.action.VIEW -d "https://link.metamask.io/asset?assetId=eip155:1/erc20:0x45804880De22913dAFE09f4980848ECE6EcbAf78" io.metamask # USDC BASE xcrun simctl openurl booted https://link.metamask.io/asset?assetId=eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 adb shell am start -W -a android.intent.action.VIEW -d "https://link.metamask.io/asset?assetId=eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" io.metamask # Native BASE xcrun simctl openurl booted https://link.metamask.io/asset?assetId=eip155:8453/slip44:60 adb shell am start -W -a android.intent.action.VIEW -d "https://link.metamask.io/asset?assetId=eip155:8453/slip44:60" io.metamask # PIPPIN Solana xcrun simctl openurl booted https://link.metamask.io/asset?assetId=solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:Dfh5DzRgSvvCFDoYc2ciTkMrbDfRKybA4SoFbPmApump adb shell am start -W -a android.intent.action.VIEW -d "https://link.metamask.io/asset?assetId=solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:Dfh5DzRgSvvCFDoYc2ciTkMrbDfRKybA4SoFbPmApump" io.metamask # Native SOL xcrun simctl openurl booted https://link.metamask.io/asset?assetId=solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501 adb shell am start -W -a android.intent.action.VIEW -d "https://link.metamask.io/asset?assetId=solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501" io.metamask # You must make sure that the token you are trying to find is inside our token API # https://tokens.api.cx.metamask.io/v3/assets?assetIds=eip155:1/erc20:0x45804880De22913dAFE09f4980848ECE6EcbAf78 # https://tokens.api.cx.metamask.io/v3/chains/solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/assets?first=50 ``` ## **Changelog** CHANGELOG entry: feat: add asset overview deeplinks ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2208 ## **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** https://www.loom.com/share/6a9070f6df12464fbe309f0797e6917c https://www.loom.com/share/c638bcd87d0540d7b8b68bcb832fe910 <!-- [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. --- <a href="https://cursor.com/background-agent?bcId=bc-9d82825e-357b-40ad-ab2e-07eb1e042fee"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> <a href="https://cursor.com/agents?id=bc-9d82825e-357b-40ad-ab2e-07eb1e042fee"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds new deep link routing and navigation into the wallet’s Asset screen plus new token-metadata fields (`iconUrl`/`rwaData`), which could misroute users or show incorrect token details if CAIP parsing/metadata lookups behave unexpectedly. > > **Overview** > Adds a new universal-link action `asset` (`ACTIONS.ASSET`) that routes to `handleAssetUrl`, enabling `https://link.metamask.io/asset?assetId=<CAIP-19>` to open the Asset details view. > > `handleAssetUrl` validates the `assetId` as CAIP-19, fetches token metadata via `fetchAssetMetadata`, derives navigation params for EVM vs non-EVM and native (`slip44`) vs token assets (including `rwaData`), and falls back to `Routes.WALLET.HOME` when metadata is missing or errors occur. Deep link analytics is extended with a new `DeepLinkRoute.ASSET` and extracts `assetId` into sensitive props, and docs/tests are updated accordingly. > > Updates `fetchAssetMetadata` to request `includeIconUrl` and `includeRwaData`, return `rwaData`, and fall back to the API-provided `iconUrl` when a static icon URL can’t be derived; unit tests are adjusted for the new query params and returned fields. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f1cdba1. 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 : )