Skip to content

[pull] main from MetaMask:main#295

Merged
pull[bot] merged 33 commits into
Reality2byte:mainfrom
MetaMask:main
Nov 4, 2025
Merged

[pull] main from MetaMask:main#295
pull[bot] merged 33 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Nov 4, 2025

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 : )

christopherferreira9 and others added 30 commits November 4, 2025 11:51
<!--
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 unifies the approach for all test resourced:
- FixtureServer
- MockServer
- `n` Dapps server
- Anvil-Manager
- CommandQueueServer

All servers now follow the same structure and all implement the same
interface. This means that the management of each service belongs to its
own class reducing the need to have as many helper function in
`FixtureHelper.ts` as we used to.
Each resource now follows:
```typescript
interface Resource {
  stop(): Promise<void>;
  start(): Promise<void>;
  isStarted(): boolean;
  getServerPort(): number;
  getServerStatus(): ServerStatus;
  getServerUrl?: string;
}
```

This also lays the foundation for 100% non deterministic port allocation
as each resource will manage its own port instead of being derived from
outside and passed in to helper functions.

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Unifies E2E test infra around a `Resource` interface, introduces
class-based servers (MockServerE2E, DappServer, enhanced
Fixture/CommandQueue/Anvil), removes legacy helpers, and updates tests
and configs accordingly.
> 
> - **E2E Infrastructure**
> - Introduce `ServerStatus` and unified `Resource` interface; refactor
`FixtureServer`, `CommandQueueServer`, and `AnvilManager` to implement
it (add start/stop/status/port/url APIs).
> - Add `DappServer` (static file server via `serve-handler`) and
replace legacy `e2e/create-static-server.js`.
> - Replace function-based mock server with class-based
`e2e/api-mocking/MockServerE2E.ts` (proxy handling, allowlist,
live-request validation, health endpoints).
> - Rename stop methods for consistency (e.g., `ganache.quit()` ->
`stop()`, `AnvilManager.quit()` -> `stop()`).
> - **Fixture Helper**
> - Consolidate lifecycle management: start/stop servers inline,
`createMockAPIServer`, dapp/local-node handlers, cleanup and
live-request validation.
> - Remove old start/stop helpers; use `getServerPort()`/`getServerUrl`
where needed.
> - **Tests**
> - Update specs to new APIs (`withFixtures`, `MockServerE2E`,
`FixtureServer.start/stop`, `localNode.stop`).
> - Ensure `origin` is included in mocked POST bodies; adjust
timeouts/intervals; launch args use dynamic ports.
> - **Removals/Additions**
> - Remove `e2e/api-mocking/mock-server.ts` and
`e2e/create-static-server.js`.
>   - Add `@types/serve-handler` dev dependency.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8e55cf5. 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**

Fix the inconsistent size of the close button in the "Swap" page "Select
Token" bottom sheet and "Select Network" bottom sheet. We also took some
time to refactor `BridgeNetworkSelectorBase` to use components from the
design system similar to how `BridgeTokenSelectorBase` does it.

<!--
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 the inconsistent size of the close button in the
"Swap" page "Select Token" bottom sheet and "Select Network" bottom
sheet.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-3186

## **Manual testing steps**

```gherkin
  When user navigates to swap page, the close icon button should much the size of the one presented in  "select network"and "select tokens" bottom sheets.
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

<img width="807" height="197" alt="image"
src="https://github.com/user-attachments/assets/af7c767f-6240-4b4e-91e2-d79ce2e877fd"
/>

<img width="807" height="197" alt="image"
src="https://github.com/user-attachments/assets/7418b099-7ca3-445f-86b5-6d0fff492880"
/>

<img width="807" height="197" alt="image"
src="https://github.com/user-attachments/assets/270c1caa-6b72-4164-8bc8-6179ff0d4ee9"
/>


<!-- [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]
> Standardizes close button sizing in Swap/Bridge token and network
selectors and refactors the network selector base to the design-system
header.
> 
> - **UI — Bottom sheets**:
> - Unify close button to `32x32` with `24px` icon via
`ButtonIconSizes.Lg` in `BridgeTokenSelectorBase` and
`BridgeNetworkSelectorBase` (affects source/dest token and network
selectors).
> - Refactor `BridgeNetworkSelectorBase` to use `BottomSheetHeader`;
remove custom `Box`/`useStyles`, simplify header layout and content
scroll.
> - **Tests**:
> - Update snapshots for `BridgeSource/DestTokenSelector` and
`BridgeSource/DestNetworkSelector` to reflect header/layout and button
size changes.
>   - Minor formatting tweak in `TokenInputArea.test.tsx`.
> - **Misc**:
>   - Minor log formatting in `FontPreloader.preloadFontsNative`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0925372. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The `build-android-e2e` workflow now skips restoring the Gradle cache on
runs where it's unused. Gradle dependencies are only needed for the full
build, not for repack.

This should save ~1.5 minutes per repack run.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

N/A

## **Screenshots/Recordings**

Test workflow runs:

- Cache miss (different fingerprint id, restored previous cache):
https://github.com/MetaMask/metamask-mobile/actions/runs/18980303557/job/54219367591
- Cache hit:
https://github.com/MetaMask/metamask-mobile/actions/runs/18980303557/job/54232880801

## **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]
> Skips Gradle cache restoration on repack runs and keys APK/artifact
caches to Gradle config, updating build/repack conditions accordingly.
> 
> - **CI** (`.github/workflows/build-android-e2e.yml`):
>   - **Caching**:
>     - Add Gradle config hash to APK and build artifact cache keys.
>     - Restore Gradle cache only when APK cache misses.
>   - **Build flow**:
>     - Build APKs only on APK cache miss; repack only on APK cache hit.
>     - Update cache/save conditions to align with APK cache status.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b2ee7d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The XCode cache was continuously expanding in size because upon a cache
miss, the previous cache was still restored and combined with the new
updated dependencies.

The workflow has been updated to no longer restore the XCode cache upon
cache miss. This should save ~1.5 minutes per build.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

N/A

## **Screenshots/Recordings**

Test workflows:

- Cache miss:
https://github.com/MetaMask/metamask-mobile/actions/runs/18978738172/job/54205482403
- Cache hit + repack:
https://github.com/MetaMask/metamask-mobile/actions/runs/18978738172/job/54210918267
- Cache hit + rebuild:
https://github.com/MetaMask/metamask-mobile/actions/runs/18981164360/job/54217839569

## **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]
> Updates iOS E2E workflow to use a versioned Xcode cache key and remove
restore-keys to avoid restoring stale caches.
> 
> - **CI / GitHub Actions**
>   - **` .github/workflows/build-ios-e2e.yml`**:
> - Xcode cache: add `env` var `XCODE_CACHE_VERSION: 1` and include it
in cache `key`.
> - Remove `restore-keys` from Xcode derived data cache to prevent
restoring previous caches.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
26a45bb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

PR to upgrade `@metamask/assets-controllers` package. It introduces
multiple breaking changes:
- Fetching exchangeRates from price api and fallback to crypto compare.
- Changes to selector calls to ignore manually selected non-evm assets.
- Changes to the number of networks enabled by default from
`@metamask/controller-utils`.
- This one makes a significant amount of changes to initial state and
onboarding.
- New events added to `AccountTrackerController`.

## **Changelog**

CHANGELOG entry: Fetch currency rates using price api and fallback to
crypto compare

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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


https://github.com/user-attachments/assets/3272157d-b239-4da5-b8f6-a520cbca0b3a

### **After**

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


https://github.com/user-attachments/assets/627db2ca-8458-454b-9d08-587295d1f8f1


## **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]
> Switches currency rates to the Price API (with normalization), enables
more EVM mainnets by default, and updates selectors/tests and configs
accordingly.
> 
> - **Engine/Controllers**:
> - `CurrencyRateController`: initialize with `tokenPricesService`
(Price API) and normalize persisted `currencyRates`.
> - `NetworkController` defaults: add Infura failovers and names for
`arbitrum-mainnet`, `bsc-mainnet`, `optimism-mainnet`,
`polygon-mainnet`, `sei-mainnet`.
> - `NetworkEnablementController` (patched): default-enable `Arbitrum`,
`BNB Chain`, `OP`, `Polygon`, `Sei`.
> - `AccountTrackerController` messenger: listen to
`NetworkController:networkAdded` and `KeyringController:unlock`.
> - **Selectors**:
> - Balances/Assets: include
`MultichainAssetsController.allIgnoredAssets` in calculations; wire
through in selectors; convert multichain asset selectors to memoized
selectors.
> - **UI/Tests**:
> - `AddressSelector` tests/snapshots: expect new EVM networks in
list/order.
> - `OnboardingSuccess`: remove network auto-add side effects; drop
associated test.
> - **E2E/Config**:
> - Allowlist `price.api.cx.metamask.io`; add Infura mock for
`sei-mainnet`; update initial background state and snapshots with new
networks and enabled map.
> - **Dependencies**:
> - Bump `@metamask/assets-controllers` to `^86.0.0`; use patched
`@metamask/network-enablement-controller`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5ab6311. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Bernardo Garces Chapero <bernardo.chapero@consensys.net>
Co-authored-by: salimtb <salim.toubal@consensys.net>
…erps market details (#22090)

## **Description**

### Problem

Users navigating from Perps Market Details to the Activity/Transactions
view were unable to go back to the previous Perps screen. The back
button was missing, leaving them stuck in the Activity tab. The user
also doesn't directly route into the Perps tab.

**Root Cause:** The `navigateToActivity()` function navigated directly
to `Routes.TRANSACTIONS_VIEW`, which is a tab based screen (not a stack
screen). This broke the navigation hierarchy, as jumping from a stack
screen to a tab screen eliminates the navigation stack and back button.

### Solution

Created a stack based Activity route `Routes.PERPS.ACTIVITY` that reuses
the existing `ActivityView` component, enabling proper back navigation
while maintaining all existing functionality as well as making the perps
tab active

## **Changelog**

CHANGELOG entry: Added stack based `Routes.PERPS.ACTIVITY` route with
conditional back button support in `ActivityView` header. Users can now
navigate back from Activity view to previous Perps screens while
maintaining backward compatibility with existing tab based navigation.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MDP-390

## **Manual testing steps**

```gherkin
Feature: Back navigation from Activity View

  Scenario: User navigates from Perps Market Details to Activity and back
    Given user is on Perps Market Details screen for BTC/USD
    And user has Perps transactions history
    
    When user taps "Go to Activity" button
    Then Activity view opens with Perps transactions tab selected
    And back button is visible in the header
    
    When user taps the back button
    Then user returns to Perps Market Details screen for BTC/USD
    And market data is still displayed
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/c791622e-e055-4dff-8be7-db0a25a9128c

### **Before**

<img width="500" alt="before"
src="https://github.com/user-attachments/assets/0d6580b0-874c-4406-9033-444236843a60"
/>

### **After**

<img width="500" alt="before"
src="https://github.com/user-attachments/assets/f2d45a1c-0aa2-4789-9c73-beab229a262f"
/>

## **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]
> Introduce `Routes.PERPS.ACTIVITY` and update Perps navigation to use
it with optional back button, ensuring return from Activity to Perps;
update types, routes, components, and tests.
> 
> - **Navigation/Routes**:
> - Add `Routes.PERPS.ACTIVITY` and register screen in
`app/components/UI/Perps/routes/index.tsx` using `ActivityView` (header
hidden).
> - Update perps nav handlers to `navigate(Routes.PERPS.ACTIVITY, {
redirectToPerpsTransactions: true, showBackButton: true })`.
> - Extend `PerpsNavigationParamList` with `PerpsActivity` params
(`redirectToPerpsTransactions`, `redirectToOrders`, `showBackButton`).
> - **ActivityView**:
> - Add optional in-view back header when `showBackButton` is true; hide
default header via `setOptions({ headerShown: false })`.
> - Handle back press with `canGoBack()`; keep existing tabs and filters
behavior.
> - **Perps Components**:
> - `PerpsRecentActivityList`: "See All" now routes to
`Routes.PERPS.ACTIVITY` with perps redirect + back button.
> - **Tests**:
> - Update/add tests for new route and params in
`PerpsRecentActivityList.test.tsx`, `usePerpsNavigation.test.ts`, and
`ActivityView/index.test.tsx` (including back button
visibility/behavior).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0a0f2c9. 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**

**What is the reason for the change?**

Users with corrupted `metaMetricsId` values (such as `""`, `"null"`, or
other invalid strings) were experiencing empty remote feature flags,
preventing them from receiving A/B test variants, gradual rollouts, and
platform-specific configurations.

**Root Cause:**
The `#getMetaMetricsId` method in `MetaMetrics.ts` only checked for
falsy values (`!metametricsId`), which failed to catch corrupted strings
like `""` (2-character string containing two double-quotes). This
corrupted ID would then be passed to `RemoteFeatureFlagController`,
where `generateDeterministicRandomNumber("")` would throw an error
during user segmentation processing, preventing feature flags from being
cached.

**What is the improvement/solution?**

Added a simple length validation check (`metametricsId.length < 32`) to
detect and regenerate corrupted IDs. Valid IDs are at least 32
characters (UUIDv4 = 36 chars, Hex = 66 chars), so this single check
catches all known corruptions:
- `""` (length 2)
- `"null"` (length 4)  
- `"undefined"` (length 9)
- Any other short corrupted strings

The fix applies the same validation to both legacy Mixpanel IDs and new
MetaMetrics IDs, ensuring consistency and preventing crashes in
`RemoteFeatureFlagController`.

## **Changelog**

CHANGELOG entry: Fixed a bug where corrupted analytics IDs prevented
users from receiving remote feature flags

## **Related issues**

Fixes: #[ISSUE_NUMBER]

## **Manual testing steps**

```gherkin
Feature: MetaMetrics ID corruption recovery

  Scenario: user with corrupted metaMetricsId gets feature flags
    Given the user has a corrupted metaMetricsId stored (e.g., '""')
    When the app initializes MetaMetrics
    Then a new valid UUID is generated and stored
    And remote feature flags are successfully fetched and cached
    And the corruption is logged for monitoring

  Scenario: user with valid metaMetricsId continues normally
    Given the user has a valid metaMetricsId (length >= 32)
    When the app initializes MetaMetrics
    Then the existing ID is preserved
    And remote feature flags work correctly

  Scenario: legacy Mixpanel ID validation
    Given the user has a legacy Mixpanel ID
    When the ID length is >= 32
    Then the legacy ID is migrated to MetaMetrics storage
    When the ID length is < 32
    Then a new UUID is generated instead
```

### **Unit Test Coverage**

Run the following to verify all corrupted ID scenarios are handled:

```bash
yarn jest app/core/Analytics/MetaMetrics.test.ts -t "corrupted ID validation"
```

Tests cover:
- ✅ JSON-stringified empty string (`""`)
- ✅ Too short IDs (`"abc"`)
- ✅ String literals (`"null"`, `"undefined"`)
- ✅ Invalid UUID formats
- ✅ Valid UUID acceptance
- ✅ Valid hex format acceptance
- ✅ Corrupted legacy Mixpanel ID rejection

## **Screenshots/Recordings**
This record goest over a branch switch from main to this branch with the
metametrics hardcoded to a string inside of a string

https://github.com/user-attachments/assets/9fc5bb8f-d61c-461d-8b6a-6315de36c6b8



### **Before**

User state with corrupted ID:
```json
{
  "metaMetricsId": "\"\"",
  "RemoteFeatureFlagController": {
    "remoteFeatureFlags": {},
    "cacheTimestamp": 0
  }
}
```

Console logs would show silent failures in feature flag processing, with
users missing out on:
- A/B test variants
- Gradual feature rollouts
- Platform-specific configurations

### **After**

With the fix applied:
```
MetaMetrics: Corrupted metaMetricsId detected and regenerated. Invalid value: ""
```

User state after fix:
```json
{
  "metaMetricsId": "12345678-1234-4567-89ab-123456789012",
  "RemoteFeatureFlagController": {
    "remoteFeatureFlags": {
      "backendWebSocketConnection": { "value": true },
      "perpsPerpTradingGeoBlockedCountriesV2": { "blockedRegions": [...] }
    },
    "cacheTimestamp": 1699564800000
  }
}
```

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

---

## **Additional Context**

### **Files Changed**
- `app/core/Analytics/MetaMetrics.ts`: Added length validation to
`#getMetaMetricsId` method
- `app/core/Analytics/MetaMetrics.test.ts`: Added comprehensive test
suite for corrupted ID scenarios

### **Performance Impact**
- Negligible: Single length check is O(1) operation
- No additional API calls or storage operations

### **Backward Compatibility**
- ✅ Fully backward compatible
- ✅ Automatically heals users with existing corrupted IDs
- ✅ No migration required
- ✅ No user action needed

### **Monitoring**
The fix includes logging when corrupted IDs are detected:
```typescript
Logger.log(
  `MetaMetrics: Corrupted metaMetricsId detected and regenerated. Invalid value: ${metametricsId}`,
);
```

This allows us to:
- Track how many users are affected
- Identify potential sources of corruption
- Monitor if the issue persists or is resolved

### **Security Considerations**
- No security implications
- Corrupted ID values are logged (for debugging), but they contain no
PII
- New generated UUIDs follow existing security practices



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds strict ID validation (UUIDv4 or legacy hex) for MetaMetrics,
regenerating corrupted IDs and migrating valid Mixpanel hex IDs.
> 
> - **Analytics (`app/core/Analytics/MetaMetrics.ts`)**:
> - Validate stored `metaMetricsId` using `uuid.validate`; regenerate
with `uuidv4()` and log when invalid or corrupted.
> - Accept legacy Mixpanel ID only if it’s a valid hex address
(`isHexAddress(legacyId.toLowerCase())`); migrate to `METAMETRICS_ID`.
>   - Import `validate` (uuid) and `isHexAddress` for the above checks.
> - **Tests (`app/core/Analytics/MetaMetrics.test.ts`)**:
> - Add cases covering valid hex Mixpanel IDs (including uppercase),
rejection of non-hex Mixpanel IDs, and multiple corruption scenarios
(`""`, short strings, `"null"`, `"undefined"`, invalid UUID), plus
acceptance of valid UUIDv4.
> - Use `uuid.validate` and `isHexAddress` assertions; update
expectations for storage interactions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0bddd52. 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**
Upgrade create-release-pr workflow to latest version which upgrades
auto-changelog from v4 to v5

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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/INFRA-3013

## **Manual testing steps**

Testing using a metamask-mobile fork repository in consensys-test org 


https://github.com/consensys-test/metamask-mobile-test-workflow/actions/runs/19055114162/job/54423576490

## **Screenshots/Recordings**

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

### **Before**

N/A - CICD Only

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

### **After**

N/A - CICD Only

<!-- [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]
> Update `.github/workflows/create-release-pr.yml` to use
`MetaMask/github-tools` reusable workflow at `749c0972` and set matching
`github-tools-version`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
83f8d3d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR increases the height of the keyboard buttons from `40px` to
`48px` to improve usability. This also ensures the text isn't cut off at
the default size, `32px`.

## **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 - ui fix

## **Related issues**

Fixes:
https://consensys.slack.com/archives/C09GRCNR6JF/p1761754304249019

## **Manual testing steps**

```gherkin
Feature: Keypad

  Scenario: user interacts with keyboard buttons
    Given the user is on a screen with keyboard input fields

    When user interacts with the on-screen keyboard
    Then they should see larger buttons (48px)
```

## **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/cf5f5eb8-2ac2-42cb-8bdc-fd5a528de044


### **After**



https://github.com/user-attachments/assets/e1bbab6e-38e2-49b4-a638-ab3c76d61a41



## **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]
> Increases keypad (including delete) button height from 40 to 48 across
the app to match text size and improve touch targets.
> 
> - **UI — Keypad**:
> - Update `height` from `40` to `48` for keypad buttons in
`app/components/Base/Keypad/components.tsx` (`keypadButton`,
`keypadDeleteButton`).
> - **Snapshots Updated**:
> - Reflect new 48px keypad button height in `Keypad` and across views
using it: `BridgeView`, `EarnInputView`, `EarnWithdrawInputView`, and
Ramp `BuildQuote` snapshots.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3fa251d. 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?
-->

Update assets-controllers with a set of changes for DeFi position
fetching:

Introduces timeouts and retries.
Only fetches current account.
Prevents any calls before onboarding is finished.


## **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: Changed how DeFi positions are fetch in the client to
reduce amount of calls

## **Related issues**

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

## **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]
> Updates DeFi positions to use account-tree scoped selection and
enabled-network filtering, plus dependency bump to assets-controllers
^87.
> 
> - **Selectors**:
> - Replace `selectLastSelectedEvmAccount` with
`selectSelectedInternalAccountByScope(EVM_SCOPE)` in
`selectDeFiPositionsByAddress` and
`selectDefiPositionsByEnabledNetworks`.
> - Return `{} (NO_DATA)` when no EVM account or no enabled EVM
networks; pass through `undefined` when no positions and `null` when
stored as such.
> - Filter positions by enabled `EIP155` networks only; add deprecation
note to `selectDeFiPositionsByAddress`.
> - **Engine/Messenger**:
> - Delegate actions/events to `AccountTreeController`
(`getAccountsFromSelectedAccountGroup`, `selectedAccountGroupChange`);
remove `AccountsController`/`unlock` usage.
> - **Tests**:
> - Update selector tests to the account-tree model and new return
semantics (`{} | undefined | null`).
> - **Dependencies**:
>   - Upgrade `@metamask/assets-controllers` to `^87.0.0`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c91c19d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Unskips the perps “Add funds” E2E test that deposits $80 and verifies
the updated balance.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a46be4a. 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**
Moves the send native token spec due to flakiness:
https://consensys.slack.com/archives/C02U025CVU4/p1762243312142959

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Moves the send native asset E2E spec to
`e2e/specs/quarantine/send-native-token.failing.ts`, marking it as a
failing quarantine test that exercises send, 50%, and max flows against
a local Anvil RPC.
> 
> - **Tests**:
> - Move/mark the send native asset E2E spec as failing in
`e2e/specs/quarantine/send-native-token.failing.ts`.
>     - Covers sending ETH with fixed amount, 50%, and max.
> - Uses `FixtureBuilder` with custom local RPC (Anvil) and app
login/setup.
>     - Verifies confirmations via Activity tab.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dbba7a1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates onboarding performance test to use MetaMetrics "Continue"
button, remove security modal steps, and add visibility helpers in
screen objects.
> 
> - **Tests (performance/onboarding)**:
> - Update
`appwright/tests/performance/onboarding/new-wallet-account-creation.spec.js`
to tap `MetaMetricsScreen.tapContinueButton()` and remove
`SkipAccountSecurityModal` visibility/continue steps.
> - **Screen Objects**:
>   - `wdio/screen-objects/Onboarding/MetaMetricsScreen.js`:
> - Add `continueButton` getter and `tapContinueButton()` with
visibility wait.
>   - `wdio/screen-objects/Onboarding/OnboardingScreen.js`:
> - Add `isScreenTitleVisible()` to assert visibility of
`createNewWalletButton`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2c1a388. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Fixes bug where chat would render before historical candles would load.
In this scenario, we would only render the latest candles (subscribes to
via websocket connection) so the chart would appear broken since we were
only rendering a single candle.

This PR introduces logic to only render the chart after historical
candles are fetched successfully.

## **Changelog**

CHANGELOG entry: Only render perps candlestick chart when historical
candles are fetched successfully

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1962

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


https://github.com/user-attachments/assets/32df06f9-1252-4df1-87c5-4de053257656

## **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]
> Render the Perps chart only after historical candles are fetched (else
show a skeleton), backed by a new hasHistoricalData flag in
usePerpsPositionData and updated tests.
> 
> - **UI (PerpsMarketDetailsView)**:
> - Render `TradingViewChart` only when `hasHistoricalData` is true;
otherwise show `Skeleton` placeholder.
>   - Compute `tpslLines` via `useMemo` and pass to chart.
> - **Hook (`usePerpsPositionData`)**:
> - Add `hasHistoricalData` state; set true only when valid historical
candles exist.
> - Return `null` `candleData` until historical data loads; update on
refresh with same gating.
> - Maintain live candle logic, merging only when historical data is
present; update refresh logic to set flag appropriately.
> - **Tests**:
>   - Update mocks/usages to include `hasHistoricalData`.
> - Adjust expectations for empty candles (`undefined`) and
loading/default states in `usePerpsMarketStats.test` and
`usePerpsPositionData.test`.
> - Ensure `PerpsMarketDetailsView` test accounts for gated chart
rendering.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f67f84b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…22000)

<!--
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. Adds a new analytics event RAMPS_USER_DETAILS_FETCHED to track when
user details are fetched during the deposit flow, enabling better
visibility into user authentication patterns across different screens.

2. Adds `fetchOnMount` config property to `useDepositUser` which will
eliminate extra calls for user details that were previously being
fetched 3x when the deposit feature was opened.



<!--
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?
3. What is the improvement/solution?
-->
### Changes
- **New Analytics Event**: `RAMPS_USER_DETAILS_FETCHED` tracks:
  - `logged_in`: User authentication status
  - `region`: User's country code (with fallback to selected region)
  - `location`: Screen where the fetch occurred

- **Enhanced Hooks**:
- Added optional `screenLocation`, `onMount` and `shouldTrackFetch`
parameters to `useDepositUser`

- **Integration Points**:
  - `BuildQuote` screen
  - `useDepositRouting` hook

## **Changelog**

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

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

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

CHANGELOG entry: added new analytics tracking event when user details
are fetched

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-2771

## **Manual testing steps**

```gherkin
Feature: User details fetched analytics

  Scenario: user opens the deposit feature 
    Then user details tracking event is triggered and can be seen in segment
```

## **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
- [ ] 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]
> Introduces `RAMPS_USER_DETAILS_FETCHED` analytics and a configurable
`useDepositUser` (screenLocation, shouldTrackFetch, fetchOnMount),
updates routing and deposit screens to pass context, and extends
analytics enums/tests.
> 
> - **Analytics**:
> - Add `RAMPS_USER_DETAILS_FETCHED` event to `AnalyticsEvents` and
`MetaMetrics.events` enums/options.
> - **Hooks**:
> - Enhance `useDepositUser` with config: `screenLocation`,
`shouldTrackFetch`, `fetchOnMount`; track fetch success/401; optional
fetch-on-mount; maintain logout on 401.
> - Update `useDepositRouting` to accept `screenLocation` and to use
`useDepositUser` with tracking (no mount fetch) and pass context.
> - **Screens/Flows**:
> - Pass `screenLocation` via `useDepositRouting` in
`AdditionalVerification`, `EnterAddress`, `KycProcessing`, and
`KycWebviewModal`.
> - Use `useDepositUser({ screenLocation: 'BuildQuote Screen',
shouldTrackFetch: true, fetchOnMount: true })` in `BuildQuote`.
> - **Tests/Utils**:
> - Expand `useDepositUser` tests for config + analytics and 401
handling; simplify mock implementations.
> - Adjust `useDepositRouting` tests (analytics expectation) and wire
`screenLocation`.
> - Strengthen test utils (`createMockSDKReturn` typed, add defaults
like `selectedRegion`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
25ac4b4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
This PR implements a mechanism for optimistic updates when
selling/claiming market positions.
Reason being that Polymarket sometimes takes a long time to update the
positions data in their API (5-30 seconds).
With this approach, we store an array in memory of the last sold/claimed
positions for the past 5 minutes.
When obtaining positions from the API, we then filter out anything that
we know was sold/claimed recently.

In addition, a fix to the `claimablePositions` state was added, so
claimed positions can be stored on a per account basis.
This required some changes to the Claim confirmations logic.

One last thing was that the `usePredictPositions()` hook now returns
claimable positions directly from the Predict controller state. This
allows for refreshing claimable positions across different parts of the
UI simultaneously (e.g., when claiming positions, we want to clear the
claimable positions list across the whole UI immediately).

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


https://github.com/user-attachments/assets/a7927d4b-0860-490f-9f70-d321d2d02001


## **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]
> Adds optimistic filtering of recently sold/claimed positions and
migrates claimable positions to be keyed by account, updating selectors,
controller, provider, hooks, and UI accordingly.
> 
> - **State & Selectors**
> - Change `PredictController.state.claimablePositions` from array to `{
[address]: PredictPosition[] }`; mark as `usedInUi`.
> - Update selectors to accept `address` and add
`selectPredictClaimablePositionsByAddress`.
> - **Controller**
> - Add `getSigner()` helper and use across
preview/place/deposit/withdraw/claim flows.
> - `getPositions` defaults to `polymarket` and stores claimables per
`address`.
> - Add `confirmClaim({ providerId })` to notify provider and clear
claimed positions for current address.
> - **Provider (Polymarket)**
> - Implement optimistic tracking of `recentlySoldPositions` (5‑min
TTL); filter in `getPositions`.
> - Support `confirmClaim({ positions, signer })` and add sold IDs on
SELL in `placeOrder` (using `preview.positionId`).
> - `previewOrder` accepts `signer`, preserves rate limiting; utils
include `positionId` for SELL.
> - **Hooks & UI**
> - Use selected address with new selectors in header/claim
toasts/confirmations.
> - `usePredictPositions`: when `claimable`, read positions from
controller state; default address fallback `'0x0'`.
>   - `PredictSellPreview`: pass `positionId` to preview.
> - **Tests & Fixtures**
> - Update/extend tests for new state shape, optimistic filtering,
default provider, and address fallbacks.
> - Adjust initial background state fixture to new `PredictController`
schema.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6d6142b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR performs comprehensive cleanup of the Perps codebase to
eliminate technical debt and improve maintainability through better
documentation and code organization.

### What is the reason for the change?

**Technical Debt Accumulated**: As the Perps feature evolved over
multiple iterations (HIP-3 upgrade, stream architecture migration, new
features), several issues accumulated:

1. **Unused Code**: 23 files (~52KB) with zero production references
remained in the codebase
2. **Incomplete Features**: Arbitrum L2 withdrawal feature
implementation was started but never completed/activated
3. **Outdated Documentation**: `PERPS_ARCH.md` in the component
directory was outdated and didn't follow project conventions
4. **Pattern Migrations Incomplete**: Modal components were replaced by
View pattern, but old Modal components remained
5. **Maintainability**: With 400+ files in the Perps directory, unused
code made navigation and contribution more difficult

### What is the improvement/solution?

**Three-Phase Cleanup**:

**Phase 1: Code Deletion** (23 files removed)
- Removed unused performance optimization features (image prefetch
hooks)
- Removed orphaned Arbitrum L2 features (7 files for unimplemented
withdrawal monitoring)
- Removed orphaned utilities with comprehensive tests but zero usage
- Removed deprecated modal components replaced by View pattern

**Phase 2: Documentation Improvement**
- Created comprehensive `docs/perps/perps-architecture.md` - High-level
architectural overview
- Created detailed `docs/perps/perps-screens.md` - All 16 views
documented with data flow
- Followed project conventions (snake_case naming, signal-over-noise
style)
- Migrated old `PERPS_ARCH.md` to proper docs location

**Phase 3: Verification**
- Exhaustive verification: searched entire codebase for all imports
- All 4,275 Perps tests passing
- No TypeScript errors introduced
- Test coverage maintained
- 
### Files Deleted by Category

**Performance Optimization (Unused):**
- `hooks/usePerpsImagePrefetch.ts` + test - Image prefetch feature never
adopted

**Error Tracking (Replaced):**
- `hooks/usePerpsErrorTracking.ts` - Replaced by direct
`track(MetaMetricsEvents.PERPS_ERROR)` calls

**Arbitrum L2 Feature (Unimplemented):**
- `hooks/useArbitrumTransactionMonitor.ts` + test
- `services/ArbitrumWithdrawalService.ts` + test
- `utils/arbitrumWithdrawalDetection.ts` + test
- `utils/arbitrumWithdrawalTransforms.ts`

**Orphaned Utilities (Well-Tested, Zero Usage):**
- `utils/blockchainUtils.ts` + test - Replaced by
`usePerpsBlockExplorerUrl()` hook
- `utils/transactionUtils.ts` + test - 7-day lookback calculator never
called
- `components/TradingViewChart/utils/chartCalculations.ts` + test -
Chart component doesn't use these

**Modal Components (Replaced by View Pattern):**
- `components/PerpsCancelAllOrdersModal/` (3 files)
- `components/PerpsCloseAllPositionsModal/` (3 files)

**Also Deleted:**
- `app/components/UI/Perps/PERPS_ARCH.md` - Migrated to docs/perps/

**Total:** 23 files deleted (~52KB dead code)

### Verification Process

**For each file, verified:**
- ✅ Zero direct imports across entire codebase
- ✅ Not exported from any index files
- ✅ No dynamic or string-based references
- ✅ No usage in E2E tests
- ✅ Tests pass after deletion

**Test Fixes:**
- Fixed `PerpsFundingTransactionView.test.tsx` - Removed dead mock for
deleted `blockchainUtils`

## **Changelog**

CHANGELOG entry: Cleaned up Perps codebase by removing unused code and
improving documentation

## **Related issues**

Internal maintenance - no specific issue

## **Manual testing steps**

```gherkin
Feature: Perps Codebase Cleanup

  Scenario: All core functionality still works
    Given user opens Perps feature
    When user navigates through all screens (Home, Markets, Order Entry, Positions)
    Then all screens load correctly
    And all functionality works as before
    And no errors appear in console

  Scenario: Trading flow unaffected
    Given user is on PerpsOrderView
    When user places a market order
    Then order executes successfully
    And fees calculate correctly
    And position appears in positions list

  Scenario: Position management unaffected
    Given user has open positions
    When user closes a position
    Then position closes successfully
    And P&L calculates correctly

  Scenario: Documentation accuracy
    Given developer opens docs/perps/perps-architecture.md
    When developer reviews hook and component lists
    Then all referenced files exist in codebase
    And architecture diagrams are current

  Scenario: View components replace modal components
    Given user clicks "Close All Positions" from HomeView
    When modal appears
    Then PerpsCloseAllPositionsView is used (not Modal component)
    And "Cancel All Orders" uses PerpsC ancelAllOrdersView
```

## **Screenshots/Recordings**

### **Before**

**Codebase State:**
- 417 total Perps files
- 23 files with zero references (dead code)
- Incomplete Arbitrum L2 feature files
- Modal components alongside View replacements
- Documentation in wrong location

**Issues:**
- Confusing for new contributors (which components to use?)
- Increased maintenance burden
- Outdated documentation

### **After**

**Codebase State:**
- 394 total Perps files (-23 files, -5.5%)
- Zero dead code files remaining
- Clean architectural patterns (Views only, no Modal/View duplication)
- Comprehensive documentation in proper location

**Improvements:**
- Clearer codebase structure
- Better developer onboarding (comprehensive docs)
- Easier to navigate and maintain
- Documented architectural patterns

**Test Results:**
```
Test Suites: 190 passed, 190 total
Tests:       4,275 passed, 2 skipped, 4,277 total
Time:        53.6 seconds
```

**TypeScript Validation:**
```
✅ No new TypeScript errors introduced
✅ No errors related to deleted files
```

**Documentation Created:**
- `docs/perps/perps-architecture.md` (460 lines) - High-level
architectural overview
- `docs/perps/perps-screens.md` (934 lines) - All 16 views documented
- `app/components/UI/Perps/README.md` (117 lines) - Developer quickstart

**Files Deleted:**
```bash
# 23 files total
hooks/usePerpsImagePrefetch.ts + test
hooks/usePerpsErrorTracking.ts
hooks/useArbitrumTransactionMonitor.ts + test
services/ArbitrumWithdrawalService.ts + test
utils/blockchainUtils.ts + test
utils/transactionUtils.ts + test
utils/arbitrumWithdrawalDetection.ts + test
utils/arbitrumWithdrawalTransforms.ts
components/TradingViewChart/utils/chartCalculations.ts + test
components/PerpsCancelAllOrdersModal/* (3 files)
components/PerpsCloseAllPositionsModal/* (3 files)
app/components/UI/Perps/PERPS_ARCH.md
```

## **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 (all existing tests pass, fixed
one test file)
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable (created comprehensive docs)
- [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.

---

## **Impact Summary**

| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| **Total Files** | 417 | 394 | -23 files (-5.5%) |
| **Dead Code** | ~52KB | 0KB | -52KB (100% removal) |
| **Unused Hooks** | 3 | 0 | 100% removed |
| **Unused Components** | 2 modal dirs | 0 | 100% removed |
| **Unused Utils** | 6 | 0 | 100% removed |
| **Documentation Pages** | 1 (outdated) | 3 (comprehensive) | +200% |
| **Test Coverage** | ~95% | ~95% | Maintained |
| **Tests Passing** | 4,275 | 4,275 | No regressions |

## **Key Achievements**

✅ **Zero Functionality Lost** - All deletions exhaustively verified as
unused
✅ **Zero Breaking Changes** - All 4,275 tests passing
✅ **Better Documentation** - Comprehensive architectural docs following
project conventions
✅ **Improved Maintainability** - Cleaner codebase, easier navigation
✅ **Pattern Consistency** - Removed modal/view duplication, clear
patterns

## **For Reviewers**

**What to verify:**
1. All Perps functionality works (trading, positions, withdrawals, etc.)
2. Documentation references match actual files in codebase
3. No console errors when navigating Perps screens
4. Tests pass locally

**Low risk because:**
- Exhaustive verification: zero references found for all deleted files
- High test coverage maintained (95%)
- All automated tests passing
- Only deleted provably unused code


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes dead Perps code and deprecated modals, adds comprehensive
architecture/screens docs, and updates a funding transaction test to use
the block explorer hook.
> 
> - **Perps cleanup and docs**:
> - Remove unused code: Arbitrum withdrawal monitoring
(hooks/services/utils + tests), image prefetch hooks, chart calculation
utils, deprecated modal components (`PerpsCancelAllOrdersModal`,
`PerpsCloseAllPositionsModal`) and their tests/styles, and
`app/components/UI/Perps/PERPS_ARCH.md`.
> - Add comprehensive documentation: `docs/perps/perps-architecture.md`
and `docs/perps/perps-screens.md`.
> - **Tests**:
> - Update `PerpsFundingTransactionView.test.tsx` to use
`usePerpsBlockExplorerUrl` and clean up mocks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f1a2ada. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Nick Gambino <35090461+gambinish@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**

<!--
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?
-->
Following the changes we made for caching the API, we now need to
implement a cascade, as each method in the aggregator depends on the
previous ones.
To support this, we made some parameters required in the SDK:
https://github.com/consensys-vertical-apps/va-mmcx-onramp-sdk/pull/147

We also refined the loading states in this PR to ensure they don’t block
each other.

This change will prevent the 'flash' that happened when opening the
aggregator.

## **Changelog**

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

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

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

CHANGELOG entry: Improved buy/sell feature loading time.

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/browse/TRAM-2746?atlOrigin=eyJpIjoiZTU2ZTNlYzZiZjJkNGM0MjllNmFhMTBmZjhmM2YzZTIiLCJwIjoiaiJ9

## **Manual testing steps**

```gherkin
Feature: Cascading data fetching on BuildQuote screen

  Scenario: User opens the BuildQuote screen
    Given the user is on the Home screen
      And no data has been fetched yet

    When the user presses the "Buy" button
      And the bottom sheet opens
      And the user presses "Buy" again in the bottom sheet

    Then the BuildQuote screen should open
      And the app should first fetch Regions
      And once Regions are loaded, it should fetch Fiat Currencies
      And once Fiat Currencies are loaded, it should fetch Crypto Currencies
      And once Crypto Currencies are loaded, it should fetch Payment Methods
      And each dependent component should show a loading state until its required data is available
      And the "Get Quotes" button should remain disabled until all data is loaded
```

## **Screenshots/Recordings**

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

### **Before**

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


https://github.com/user-attachments/assets/d38f40e1-30b5-4c9f-bf0d-fcb55b7bbd5e

### **After**

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


https://github.com/user-attachments/assets/a802ad10-791b-4799-9912-b58f94e843e5

**∼2s to load, no flashes**

## **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]
> Refactors `BuildQuote` to load data incrementally with precise loading
states, updates hooks/SDK params accordingly, and bumps
`@consensys/on-ramp-sdk` to 2.1.12.
> 
> - **UI — `BuildQuote`**:
> - Integrates `isFetchingLimits` and refines `isFetching` aggregation;
disables actions until required data is present.
> - Adds skeletons/guards for region, fiat, asset, balance, and payment
method selectors (`AmountInput`, `AssetSelectorButton`,
`PaymentMethodSelector`).
> - Adjusts region change flow to re-query default fiat without payment
method dependency.
> - **Hooks**:
> - `useFiatCurrencies`: removes payment method param; splits
`isFetchingFiatCurrency` (default) vs `isFetchingFiatCurrencies` (list);
returns selected currency accordingly.
> - `useCryptoCurrencies`: drops payment method IDs; fetches with
`(regionId, fiatCurrencyId)`.
>   - `useLimits`: exposes `isFetching` and `queryGetLimits`.
> - **SDK Context (`sdk/index.tsx`)**:
> - Initializes `selectedPaymentMethodId` to `null` and stops persisting
it to Redux.
> - **Tests & Snapshots**:
> - Update unit tests to new hook signatures/flags and revised
loading/UI states.
> - **Deps**:
>   - Bump `@consensys/on-ramp-sdk` from `2.1.11` to `2.1.12`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
10a71b7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Updates Hip3 risk disclaimer.

## **Changelog**

CHANGELOG entry: Updates Hip3 risk disclaimer.

## **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]
> Makes the perps risk disclaimer source dynamic (based on market),
updates copy to "TradingView.", and adjusts i18n and tests accordingly.
> 
> - **Perps UI (`PerpsMarketDetailsView.tsx`)**:
> - Add `riskDisclaimerParams` (from `market.marketSource` fallback to
`"Hyperliquid"`) and pass to `strings('perps.risk_disclaimer', ...)`.
>   - Update link label text to `TradingView.`
> - **i18n (`locales/languages/en.json`)**:
> - Change `perps.risk_disclaimer` to use `Powered by {{source}}. Price
chart powered by`.
> - **Tests (`PerpsMarketDetailsView.test.tsx`)**:
> - Expect `TradingView.` label and keep URL
`https://www.tradingview.com/` in link-open assertions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dae3aa8. 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**
Increases timeout of multi srp spec file and removes synchronization
enable step.

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Increase account visibility assertion timeout to 20s and remove a
sync-enable step in the multi-SRP e2e test.
> 
> - **E2E Test
(`e2e/specs/identity/account-syncing/multi-srp.spec.ts`)**:
> - Increase assertion timeout to `20000` for account visibility checks.
> - Remove `device.enableSynchronization()` before verifying accounts
after importing the second SRP.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d637d8c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This pull request adds support for a new "unified buy" button to the
`FundActionMenu` component, which conditionally appears based on the
result of the `useRampsUnifiedV1Enabled` hook. The changes update both
the UI logic and the associated tests to ensure the new button is
rendered and behaves as expected. Additional test coverage is added for
the new feature, and new selector/test IDs and localization strings are
introduced.

**Feature: Unified Buy Button Integration**
* Added a new "unified buy" button to the `FundActionMenu`, which is
shown only when `useRampsUnifiedV1Enabled` returns true. The button uses
its own test ID and localized label/description, and its navigation
currently matches the standard buy button. The visibility of the
existing "deposit" and "buy" buttons is updated to be mutually exclusive
with the unified buy button. (`FundActionMenu.tsx`,
`WalletActionsBottomSheet.selectors.ts`, `en.json`)
[[1]](diffhunk://#diff-da0da05b6572b7ac895a5e513d491d8f73c7c9d01d1ce4035b5dc5c402eb3db5R37)
[[2]](diffhunk://#diff-da0da05b6572b7ac895a5e513d491d8f73c7c9d01d1ce4035b5dc5c402eb3db5R54)
[[3]](diffhunk://#diff-da0da05b6572b7ac895a5e513d491d8f73c7c9d01d1ce4035b5dc5c402eb3db5R107-R142)
[[4]](diffhunk://#diff-da0da05b6572b7ac895a5e513d491d8f73c7c9d01d1ce4035b5dc5c402eb3db5L129-R160)
[[5]](diffhunk://#diff-da0da05b6572b7ac895a5e513d491d8f73c7c9d01d1ce4035b5dc5c402eb3db5L175-R211)
[[6]](diffhunk://#diff-6c99823ce7c6a0af29e6a36f587b71f2e6107cd6e4a059f60e63836198415d66R6)
[[7]](diffhunk://#diff-c31c440a532cfa87d12df6a7c76ac83d0e80ee9b8b7fe38a274204000eaa0948R2959-R2960)

**Testing: Expanded Test Coverage**
* Updated and expanded tests in `FundActionMenu.test.tsx` to mock the
new hook, verify the conditional rendering of the unified buy button,
and ensure its navigation behavior matches the standard buy button.
(`FundActionMenu.test.tsx`)
[[1]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R17)
[[2]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R58)
[[3]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R84-R87)
[[4]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R137)
[[5]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247L224-R231)
[[6]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R242-R255)
[[7]](diffhunk://#diff-9d0f1d3a614826d7433c48bcc9735f974b5c2d84a875695b50ac701ce391d247R303-R316)
## **Changelog**

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

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

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

CHANGELOG entry: Adds a unified Buy button behind a feature flag

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-2804

## **Manual testing steps**

```gherkin
Feature: Unified Buy button

  Scenario: User wants to buy a token
    Given unified v1 feature flag is off

    When user opens the Buy menu
    Then they see Deposit and Buy buttons

  Scenario: User wants to buy a token
    Given unified v1 feature flag is on

    When user opens the Buy menu
    Then they see a single Buy button
```

## **Screenshots/Recordings**

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

### **Before**

<img width="399" alt="image"
src="https://github.com/user-attachments/assets/6e4719b3-c2f4-4265-8d3a-466b1e914a88"
/>


### **After**

<img width="399" height="2622" alt="image"
src="https://github.com/user-attachments/assets/4742e980-d830-480d-8620-a62f20dc99ad"
/>


## **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]
> Adds a feature-flagged unified Buy button to `FundActionMenu`, updates
visibility logic, selectors, i18n, and tests to support it.
> 
> - **UI/FundActionMenu**:
> - Add `buy-unified` action in `FundActionMenu.tsx` controlled by
`useRampsUnifiedV1Enabled`; uses existing Buy navigation and analytics
(skips when `customOnBuy`).
> - Adjust visibility: hide legacy `buy` and `deposit` when unified is
enabled; keep existing `sell` behavior; update memo deps.
> - Extend `ActionConfig.type` with `"buy-unified"` in
`FundActionMenu.types.ts`.
> - **Testing**:
> - Expand `FundActionMenu.test.tsx` to mock `useRampsUnifiedV1Enabled`,
verify conditional rendering of `BUY_UNIFIED_BUTTON`, and ensure
navigation matches Buy.
> - **E2E Selectors**:
>   - Add `WalletActionsBottomSheetSelectorsIDs.BUY_UNIFIED_BUTTON`.
> - **Localization**:
> - Add `fund_actionmenu.buy_unified` and
`fund_actionmenu.buy_unified_description` strings in `en.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
18f1131. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…1) (#21869)

# Deep Link Consolidation - Phase 1: Core Types & Normalizer

Fixes:
https://github.com/MetaMask/mobile-planning/issues/2343

https://consensyssoftware.atlassian.net/jira/polaris/projects/MWMR/ideas/view/8845676?selectedIssue=MWMR-10

## Overview
This PR introduces the foundational infrastructure for consolidating
MetaMask Mobile's fragmented deep link handling system. It creates a
unified representation and normalization layer for all deep links,
establishing a consistent pattern for handling `metamask://` and
`https://` protocols.

## Problem
The current deep link system has routing logic spread across multiple
files using nested switch-case statements, making it difficult to:
- Understand the complete set of supported deep links
- Maintain consistency across different protocols
- Add new deep link actions
- Test deep link handling comprehensively

## Solution
This PR implements:
1. **Unified Type System** - Single source of truth for deep link
structure
2. **CoreLinkNormalizer** - Converts all deep link formats to a
standardized representation
3. **Protocol Conversion** - Bidirectional transformation between
`metamask://` and `https://` formats
4. **Comprehensive Testing** - 30 test cases covering all functionality

## Testing

### Run Tests
```bash
yarn jest app/core/DeeplinkManager/CoreLinkNormalizer.test.ts
```

**Expected Output:**
```
PASS app/core/DeeplinkManager/CoreLinkNormalizer.test.ts
  ✓ All 30 tests passing
```

### Run Linting
```bash
yarn eslint 'app/core/DeeplinkManager' --fix
```

### Run TypeScript Check
```bash
yarn lint:tsc
```

All commands should pass without errors.

## Examples

### Normalizing a Deep Link
```typescript
import { CoreLinkNormalizer } from './core/DeeplinkManager/CoreLinkNormalizer';

// Normalize a metamask:// link
const link = CoreLinkNormalizer.normalize(
  'metamask://swap?from=ETH&to=DAI&amount=100',
  'qr-code'
);

console.log(link);
// {
//   protocol: 'metamask',
//   action: 'swap',
//   params: {
//     from: 'ETH',
//     to: 'DAI',
//     amount: '100',
//     swapPath: 'swap?from=ETH&to=DAI&amount=100'
//   },
//   source: 'qr-code',
//   timestamp: 1698765432000,
//   originalUrl: 'metamask://swap?from=ETH&to=DAI&amount=100',
//   normalizedUrl: 'https://link.metamask.io/swap?from=ETH&to=DAI&amount=100',
//   isValid: true,
//   isSupportedAction: true,
//   isPrivateLink: false,
//   requiresAuth: false
// }
```

### Converting Protocols
```typescript
// Convert to metamask:// protocol
const metamaskUrl = CoreLinkNormalizer.toMetaMaskProtocol(link);
// 'metamask://swap?from=ETH&to=DAI&amount=100'
```

### Building Deep Links
```typescript
// Build a new deep link
const sendLink = CoreLinkNormalizer.buildDeeplink('metamask', 'send', {
  to: '0x1234567890abcdef',
  value: '1000000000000000000',
  hr: true
});
// 'metamask://send?to=0x1234567890abcdef&value=1000000000000000000&hr=1'
```

### Validating Deep Links
```typescript
// Check if a URL is a supported deep link
const isValid = CoreLinkNormalizer.isSupportedDeeplink('metamask://swap');
// true

const isInvalid = CoreLinkNormalizer.isSupportedDeeplink('metamask://unknown-action');
// false
```

## Backward Compatibility
This PR introduces new infrastructure but **does not modify existing
deep link handling**. The new system runs in parallel with the existing
system and has no impact on current functionality.

The next PR (Legacy Adapter) will provide the bridge between this new
system and the existing deep link handlers.

### Follows Guidelines
- ✅ AAA test pattern (Arrange, Act, Assert)
- ✅ No "should" in test descriptions
- ✅ One behavior per test
- ✅ Comprehensive edge case coverage
- ✅ Proper TypeScript types (no `any`)
- ✅ All dependencies mocked
- ✅ JSDoc comments on public methods
- ✅ MetaMask coding standards

## Next Steps
**Phase 1, PR 2**: Legacy Adapter
- Create `LegacyLinkAdapter` to bridge new and old systems
- Implement conversion between CoreUniversalLink and legacy formats
- Enable gradual migration without breaking changes

**Phase 2**: Universal Router
- Create `UniversalRouter` singleton
- Implement handler registry
- Define handler interfaces

**Phase 3**: Integration
- Integrate router into DeeplinkManager
- Add feature flag for gradual rollout
- Full migration from legacy system

## Risk Assessment
**Risk Level**: Low

**Rationale:**
- No modifications to existing code
- Isolated to new files
- Comprehensive test coverage
- No runtime impact until integration

## Related Documentation
- Project Prompt: `/DEEPLINK_CONSOLIDATION_PROMPT.md`
- Implementation Summary:
`/.kylan-docs/deep-link-consolidation-pr1-summary.md`

---

## Reviewer Checklist
- [ ] All tests pass (`yarn jest
app/core/DeeplinkManager/CoreLinkNormalizer.test.ts`)
- [ ] No linting errors (`yarn eslint 'app/core/DeeplinkManager' --fix`)
- [ ] TypeScript compiles without errors (`yarn lint:tsc`)
- [ ] Code follows MetaMask coding guidelines
- [ ] Test coverage is comprehensive (30 test cases)
- [ ] No breaking changes to existing functionality
- [ ] JSDoc comments are clear and accurate
- [ ] Type definitions are appropriate and safe


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces a unified deep link normalizer and core link types, adds
tests, updates hr handling, and registers the ramp action.
> 
> - **Core deep link infrastructure**:
> - **CoreLinkNormalizer**
(`app/core/DeeplinkManager/CoreLinkNormalizer.ts`): normalizes
deeplinks, converts protocols, validates support, and builds links.
> - **Types** (`app/core/DeeplinkManager/types/CoreUniversalLink.ts`):
defines `CoreUniversalLink`/`CoreLinkParams` and action/protocol
groupings (auth-required, SDK, ramp, perps, supported protocols, default
action).
> - **Tests** (`app/core/DeeplinkManager/CoreLinkNormalizer.test.ts`):
covers normalization, protocol conversion, validation, and param
handling.
> - **Deeplink handling tweaks**:
> - Ensures `hr` is treated boolean (`!!params.hr`) in
`handleMetaMaskDeeplink` and parsed from `'1'` in `extractURLParams`.
> - **Constants**:
>   - Adds `ACTIONS.RAMP` to `app/constants/deeplinks.ts`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
eb455f3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: SteP-n-s <stylianos.panagakos@consensys.net>
## **Description**

This PR enhances the Carousel component with a polished empty state
experience and fixes several animation flow issues:

1. **Added Rive Confetti Animation to Empty Card**: Integrated the
`Carousel_Confetti.riv` animation as a background layer that triggers
when the empty card transitions to the main stage, playing once before
auto-dismiss.

2. **Fixed Last Card Dismissal Flow**: Resolved bugs where:
- The empty card would appear and disappear too quickly without proper
animation
   - Cards would reappear after dismissal on app reload
- The last card's close animation was being interrupted by Redux state
updates

3. **Improved Animation Sequencing**: Ensured smooth transitions where:
   - The last non-empty card fades out
   - The empty card properly transitions from background to main stage
   - Confetti animation plays during the 1000ms idle period
   - The carousel then auto-dismisses without visual glitches

The implementation uses animated value listeners to detect when the
empty card reaches full visibility, ensuring the confetti animation only
triggers at the right moment in the transition sequence.

## **Changelog**

CHANGELOG entry: Enhanced carousel empty state with confetti animation
and improved dismissal flow animations

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/jira/software/c/projects/DSYS/boards/1888?selectedIssue=DSYS-175

## **Manual testing steps**

```gherkin
Feature: Carousel empty state animation

  Scenario: User dismisses last carousel card
    Given the wallet page displays a carousel with 1+ slides
    
    When user clicks the close button on the last slide
    Then the card fades out smoothly
    And the empty state card transitions from background to main stage
    And confetti animation plays once as the empty card becomes visible
    And after 1000ms the carousel auto-dismisses with fold-up animation
    And the carousel does not reappear on app reload

  Scenario: Empty card does not show on reload when all slides dismissed
    Given all carousel slides have been dismissed
    
    When user closes and reopens the app
    Then the carousel does not render
    And no empty state card appears
```

## **Screenshots/Recordings**

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

### **Before**

### **After**

https://github.com/user-attachments/assets/50db5a1a-2ce4-4326-a071-3f7db0524d5a

When theres no more card

https://github.com/user-attachments/assets/b0597dd0-cade-4835-9785-60944237162b




---

## **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]
> Adds a confetti-animated empty state and refactors carousel
transitions to reliably dismiss the last card and auto-hide the
carousel.
> 
> - **Carousel/Empty State**:
> - **Rive Confetti**: Triggers on empty card when `emptyStateOpacity`
~1 using an Animated listener; robust error handling and cleanup for
timers/listeners.
> - **Auto-dismiss**: Uses `ANIMATION_TIMINGS.EMPTY_STATE_IDLE_TIME`
(2000ms) to fold up via `useTransitionToEmpty`.
> - **Last-card flow**: Tracks dismissal with `dismissingLastCardRef` to
keep the empty card visible during the final transition; conditionally
injects `empty` slide; resets flags in transition callback.
> - **Transition fixes**: Adjusts current/next card animation states
when transitioning to the empty card; only passes `onTransitionToEmpty`
when empty card is current.
> - **StackCard**:
> - Removes empty-card handling and `onTransitionToEmpty`; always
renders regular card layout.
> - **Animations**:
> - Centralizes timings via `AnimationDuration`; updates card enter/exit
and empty-state idle/fold timings in `animations/animationTimings.ts`.
> - **Tests**:
> - Expands `StackCardEmpty` tests (timeouts, listener setup/cleanup,
overlay) and mocks `rive-react-native`.
> - Updates transition hook tests to use shared `ANIMATION_TIMINGS` and
fake timers.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
614648b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… fails cp-7.58.0 (#22142)

<!--
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**
Improved error catching block to know when feature flag update fails
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Improve feature flag update error logging and update onboarding tests
to handle security modal and use the “I Agree” CTA.
> 
> - **Engine**:
> - Refine error handling in
`app/core/Engine/controllers/remote-feature-flag-controller-init.ts` to
log a clearer message on failure: `Logger.log('Feature flags update
failed: ', error)`; retain success log `Feature flags updated`.
> - **Tests**:
>   - `remote-feature-flag-controller-init.test.ts`:
> - Mock `Logger` and add assertions for success and failure logs when
`updateRemoteFeatureFlags` resolves/rejects.
> - Preserve checks for controller initialization, arguments, and
disabled behavior.
> - **Onboarding E2E/Appwright**:
> -
`appwright/tests/performance/onboarding/new-wallet-account-creation.spec.js`:
handle `SkipAccountSecurityModal` and switch from `tapContinueButton` to
`tapIAgreeButton`.
> - `wdio/screen-objects/Onboarding/MetaMetricsScreen.js`: remove
`continueButton`/`tapContinueButton`; use `iAgreeButton` and
`tapIAgreeButton`.
> - `wdio/screen-objects/Onboarding/OnboardingScreen.js`: remove unused
`isScreenTitleVisible` method.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
854f2a8. 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**

- Various visual tweaks on the predict market details screen
- Moves the resolved outcomes dropdown below the active outcome list

<!--
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: NA

## **Related issues**

Fixes: NA

## **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]
> Adjusts outcome status rendering to show Winner/Loser text with icon
and tweaks resolved outcomes list styling; adds new localization
strings.
> 
> - **UI/Predictions**:
> - `PredictMarketOutcome.tsx`: Replace icon-only result with
`Winner`/`Loser` label (i18n) and show confirmation icon only for
winners; remove previous winner badge.
> - `PredictMarketDetails.tsx`: Update resolved outcomes list spacing
and conditional text color; add confirmation icon when the leading token
is first.
> - **Localization**:
> - Add `predict.outcome_winner` and `predict.outcome_loser` to
`locales/languages/en.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
363f272. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The network badges for the tokens are missing a border

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MDP-381

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

`~`

### **Before**

<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 11 57 17"
src="https://github.com/user-attachments/assets/27f35526-db30-4ee3-85cf-61554fa38bda"
/>

### **After**
<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 12 08 40"
src="https://github.com/user-attachments/assets/97ae6d44-cdb7-4b2a-b642-5a2ac5e5fc36"
/>

<!-- [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]
> Set the token network badge border to white and update BridgeView
snapshots accordingly.
> 
> - **UI**:
> - `TokenButton`: Remove custom `networkBadge` style and stop passing
it to `Badge`, resulting in a white (`#ffffff`) border for
`BadgeVariant.Network`.
> - **Tests**:
> - Update `BridgeView` snapshots to reflect the white network badge
border.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ad56eed. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Convert quotes copy from title case to sentence case

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MDP-382

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

`~`

### **Before**

<img width="500" height="2868" alt="Simulator Screenshot - iPhone 16 Pro
Max - 2025-11-04 at 11 34 48"
src="https://github.com/user-attachments/assets/36bbc25e-b786-4dbe-abaa-75bdb7edc181"
/>

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

### **After**

<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 11 57 17"
src="https://github.com/user-attachments/assets/ade40e0a-1af0-4bff-9682-515846894ed1"
/>

## **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]
> Converts Bridge quote details copy to sentence case and updates i18n,
tests, and snapshots accordingly.
> 
> - **Bridge UI – Quote details**:
> - Change labels to sentence case: `Network fee`, `Price impact`,
`Minimum received`.
> - **i18n**:
> - Update English strings in `locales/languages/en.json` to sentence
case for corresponding Bridge keys (`network_fee`, `price_impact`,
`minimum_received`).
> - **Tests**:
> - Adjust `QuoteDetailsCard.test.tsx` expectations and snapshots to
match new casing.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6654c36. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#22149)

## **Description**

This PR adds comprehensive test coverage for UUID version 4 validation
in the MetaMetrics ID generation logic and fixes related TypeScript type
errors.

**What is the reason for the change?**

The validation logic at `MetaMetrics.ts:313-316` checks that stored
MetaMetrics IDs are valid UUIDv4 format using `validate()` and
`version()` checks. However, there were no test cases covering the
`version(metametricsId) !== 4` condition, and several existing tests
were using invalid UUIDs (NIL UUID with all zeros) which is not a
version 4 UUID.

Additionally, TypeScript was reporting errors because
`getMetaMetricsId()` was typed to return `Promise<string | undefined>`,
but the implementation always returns a string (generates a new UUID if
none exists).

**What is the improvement/solution?**

1. **Added 4 new test cases** to cover UUID version validation:
   - Regenerates ID when stored ID is version 1 UUID (time-based)
   - Regenerates ID when stored ID is version 3 UUID (MD5-based)
   - Regenerates ID when stored ID is version 5 UUID (SHA1-based)
   - Regenerates ID when stored ID is NIL UUID (all zeros)

2. **Fixed 3 existing tests** that were incorrectly using
`'00000000-0000-0000-0000-000000000000'` (NIL UUID, version 0) as test
data. Changed to use valid UUIDv4 format
`'12345678-1234-4234-b234-123456789012'`.

3. **Fixed TypeScript errors**:
- Changed `getMetaMetricsId()` return type from `Promise<string |
undefined>` to `Promise<string>` in `MetaMetrics.ts`
- Updated `ControllerInitRequest` type to reflect that `metaMetricsId`
is always provided at runtime
- Added temporary `@ts-expect-error` comment in `Engine.ts` (see Related
issues below)

All tests now pass and properly validate that only UUIDv4 format is
accepted.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: #22148

> **Note**: This PR adds a temporary `@ts-expect-error` comment in
`Engine.ts` to handle a type compatibility issue. The complete fix
(restructuring Engine constructor parameters) will be addressed in the
follow-up issue #22148 to avoid scope creep.

## **Manual testing steps**

```gherkin
Feature: MetaMetrics UUID Version Validation

  Scenario: user has corrupted MetaMetrics ID with wrong UUID version
    Given the app has a stored MetaMetrics ID that is not version 4 UUID
    
    When the app initializes and MetaMetrics configures
    Then a new valid UUIDv4 should be generated
    And the new ID should be stored
    And a log message should indicate the corrupted ID was detected

  Scenario: user has valid UUIDv4 MetaMetrics ID
    Given the app has a stored valid version 4 UUID
    
    When the app initializes and MetaMetrics configures
    Then the existing UUID should be preserved
    And no new ID should be generated
```

**Testing commands:**
```bash
# Run the specific test suite
yarn jest app/core/Analytics/MetaMetrics.test.ts

# Run with coverage
yarn test:unit:coverage -- app/core/Analytics/MetaMetrics.test.ts
```

## **Screenshots/Recordings**

N/A - This is a test coverage and TypeScript fix PR with no UI changes.

### **Before**

- 3 tests failing due to NIL UUID validation
- TypeScript errors for `metaMetricsId` type mismatches
- No test coverage for UUID version validation

### **After**

- All 57 tests passing (54 existing + 3 newly fixed tests)
- 4 new test cases covering UUID version validation (v1, v3, v5, NIL)
- TypeScript errors resolved
- Complete test coverage for the UUID validation logic

## **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.
Fixes: https://github.com/MetaMask/mobile-planning/issues/2340

This PR implements dynamic signature parameter verification for
deeplinks by respecting the `sig_params` query parameter when validating
signed URLs.

### What is the reason for the change?

Previously, the client-side signature verification was verifying ALL URL
parameters when checking deeplink signatures. However, the server-side
`link-signer-api` supports signing only specific parameters (listed in
`sig_params`), allowing for flexible link generation where additional
parameters can be added without breaking the signature. The client
verification logic was not aligned with this server behavior.

### What is the improvement/solution?

Updated the `canonicalize()` function in `verifySignature.ts` to:
- Check for the presence of `sig_params` in the URL
- When present, only include the parameters listed in `sig_params` (plus
`sig_params` itself) in the canonical URL used for signature
verification
- Maintain backward compatibility by falling back to the old behavior
(verify all params) when `sig_params` is absent

This enables:
- **Dynamic signing**: Server can sign links with arbitrary parameter
subsets
- **Forward compatibility**: New unsigned parameters can be added to
links without invalidating signatures
- **Alignment**: Client verification now matches server signing logic

Added comprehensive unit tests covering:
- Basic `sig_params` functionality
- Edge cases (empty values, missing parameters, special characters)
- Backward compatibility scenarios
- Parameter sorting and canonicalization

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: <!-- Add issue number if applicable -->

## **Manual testing steps**

```gherkin
Feature: Dynamic deeplink signature verification

  Scenario: user opens a deeplink with sig_params
    Given a signed deeplink URL contains sig_params=channel,source
    And the URL has additional unsigned parameters
    
    When the app verifies the signature
    Then only the parameters listed in sig_params are used for verification
    And the signature validation succeeds

  Scenario: user opens a legacy deeplink without sig_params
    Given a signed deeplink URL without sig_params parameter
    
    When the app verifies the signature
    Then all parameters (except sig) are used for verification
    And backward compatibility is maintained
```

## **Screenshots/Recordings**

Not applicable - internal signature verification logic change with 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 (✅ Added 10 new comprehensive
unit tests)
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable (✅ Added inline comments explaining critical logic)
- [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).


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates canonicalization to verify only parameters listed in
`sig_params` (plus `sig_params`), with legacy fallback when absent, and
adds comprehensive tests for these cases.
> 
> - **Deeplink signature verification (`verifySignature.ts`)**:
> - Update `canonicalize(url)` to, when `sig_params` is present, include
only listed existing params plus `sig_params`, then sort and build the
canonical URL.
> - Preserve legacy behavior by removing `sig` and sorting all params
when `sig_params` is absent.
> - **Tests (`verifySignature.test.ts`)**:
> - Add cases covering inclusion of only `sig_params`-listed params,
inclusion of `sig_params` itself, empty/missing params, multiple params
with sorting, special characters, trailing commas, and backward
compatibility without `sig_params`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
41551fe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR is to temporally disable the prediction automation test. 

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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **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]
> Comments out the prediction market smoke test jobs and removes them
from report dependencies in both Android and iOS E2E workflows.
> 
> - **CI / GitHub Actions**:
>   - **Android**:
>     - Disable `prediction-market-android-smoke` job (commented out).
> - Remove `prediction-market-android-smoke` from
`report-android-smoke-tests.needs`.
>   - **iOS**:
>     - Disable `prediction-market-ios-smoke` job (commented out).
> - Remove `prediction-market-ios-smoke` from
`report-ios-smoke-tests.needs`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
818e339. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
caieu and others added 3 commits November 4, 2025 23:03
)

<!--
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**

- fix market details header
- fix market feed header
- fix avatars

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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **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]
> Refactors Predict headers and avatar sizing, passes `title`/`image` to
market details for instant header render, and adds `estimateLineCount`
with tests.
> 
> - **Predict UI**:
> - **Market Details header**: New structure/alignment using
`estimateLineCount`; accepts `title`/`image` from route params; spacing
and icon sizes tweaked.
>   - **Feed header**: Adjusts vertical padding (`pt-2 pb-4`).
> - **Avatars/images**: Standardize to `w-10 h-10` in market cards and
position details; minor skeleton/card margin tweaks in `PredictBalance`.
> - **Navigation**:
> - Extends `PredictMarketDetails` params with optional `title` and
`image`.
> - Updates `PredictMarketSingle`/`Multiple` to pass `title` and `image`
when navigating; tests updated accordingly.
> - **Utils & Tests**:
> - Adds `estimateLineCount` in `utils/format` and extensive unit tests.
> - Updates `PredictMarketDetails` to use the utility and adjusts
related mocks/tests.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
10a03fa. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Update copy for perps trade action menu

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MDP-378

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

`~`

### **Before**

<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 13 09 26"
src="https://github.com/user-attachments/assets/9e207819-4ef9-40c4-96c2-56d5ddf06064"
/>

### **After**

<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 13 08 45"
src="https://github.com/user-attachments/assets/0685f22a-c19f-4886-b59b-76678bb2b80d"
/>

## **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]
> Updates the `perps_description` string in `locales/languages/en.json`
from “Trade perp contracts” to “Trade perps contracts”.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0e57cca. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…22143)

## **Description**

Remove padding and border radius from order type bottom sheet

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MDP-392

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

`~`

### **Before**

<img width="500" alt="image"
src="https://github.com/user-attachments/assets/2662e9b0-adaa-4fc3-b89d-128b32f2c478"
/>

### **After**

<img width="500" alt="Simulator Screenshot - iPhone 16 Pro Max -
2025-11-04 at 11 22 56"
src="https://github.com/user-attachments/assets/84b8a77e-5512-4a6c-9876-13c9a4f8e7ae"
/>

## **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]
> Removes container horizontal padding and option border radius in
`PerpsOrderTypeBottomSheet` styles.
> 
> - **UI/Styles**
(`app/components/UI/Perps/components/PerpsOrderTypeBottomSheet/PerpsOrderTypeBottomSheet.styles.ts`):
>   - Remove `container` `paddingHorizontal`.
>   - Remove `option` `borderRadius`.
>   - Keep spacing and selection colors unchanged.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
99111f7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Nov 4, 2025
@pull pull Bot added the ⤵️ pull label Nov 4, 2025
@pull pull Bot merged commit 0ad3a8c into Reality2byte:main Nov 4, 2025
6 of 39 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.