Skip to content

release: 7.80.2#28776

Closed
metamaskbot wants to merge 404 commits into
stablefrom
release/7.80.20
Closed

release: 7.80.2#28776
metamaskbot wants to merge 404 commits into
stablefrom
release/7.80.20

Conversation

@metamaskbot
Copy link
Copy Markdown
Collaborator

Release 7.80.2 (Runway branch: release/7.80.20).

  • App version set to 7.80.2 (normalized from Runway 7.80.20).

cryptodev-2s and others added 30 commits April 2, 2026 15:00
## **Description**

Mirrors [MetaMask/core#8352](MetaMask/core#8352)
for the mobile PerpsController.

- Expand `MESSENGER_EXPOSED_METHODS` from 35 to 84 methods
(alphabetized)
- Auto-generate `PerpsController-method-action-types.ts` using
`messenger-generate-action-types` CLI
- Export `PerpsControllerGetStateAction` and all individual action types
- Add `generate-method-action-types` check/fix scripts to
`lint`/`lint:fix`

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

N/A — type-only changes, no user-facing behavior

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Expands the messenger-exposed surface area of `PerpsController`, which
could affect callers and permissions if any method was not intended to
be remotely invokable. Also adds a new lint-time codegen check that may
introduce CI failures if generation drifts across environments.
> 
> **Overview**
> **Exposes the full `PerpsController` API through the messenger** by
expanding and alphabetizing `MESSENGER_EXPOSED_METHODS`, and introduces
a named `PerpsControllerGetStateAction` type.
> 
> **Switches Perps messenger action typing to generated output**:
`PerpsController-method-action-types.ts` is regenerated to include
JSDoc’d action types for all controller methods and `index.ts` now
re-exports these individual action types.
> 
> **Build/CI enforcement changes**: bumps `@metamask/messenger` to
`^1.1.0` (for the codegen CLI) and wires
`messenger-generate-action-types` into `lint`/`lint:fix` via new
`generate-method-action-types` scripts to keep generated types in sync.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0fe513d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…[GE-168] (#28345)

<!--
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?
-->
Adds Braze Android resource in braze.xml to specify the small and large
push notification icons

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/GE-168

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: resource-only configuration change that just points Braze to
existing mipmap icons; main risk is misconfigured/missing icon resources
affecting push rendering.
> 
> **Overview**
> Adds Braze Android resource overrides in `braze.xml` to specify the
small and large push notification icons
(`com_braze_push_small_notification_icon` and
`com_braze_push_large_notification_icon`), pointing to
`@mipmap/ic_notification_small` and `@mipmap/ic_notification`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
64eef30. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ated APIs (#28115)

## **Description**

Upgraded `@metamask/design-system-react-native` from `^0.11.0` to
`^0.12.0` and migrated affected mobile screens to the latest API.

This removes deprecated `TextFieldSize` and `TextButtonSize` usage,
removes deprecated `TextButton isInverse`, and replaces one
icon/disabled `TextButton` usage with a tertiary `Button` per migration
guidance.

https://github.com/MetaMask/metamask-design-system/releases/tag/v26.0.0

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

```gherkin
Feature: Design system 0.12.0 migration compatibility

  Scenario: user can authenticate and reset password using migrated text fields
    Given the app is running on a branch with this PR
    When user opens Login, Onboarding, Choose Password, and Reset Password flows
    Then password input fields render correctly and accept input without runtime errors

  Scenario: user can copy seed phrase only when reveal state allows it
    Given the user is on the Reveal Secret Recovery Phrase screen
    When the seed phrase is hidden
    Then the copy action is disabled
    When the seed phrase is revealed and user taps copy
    Then the copy action triggers successfully
```

## **Screenshots/Recordings**

### **Before**

Main fix was alignment of TextField for password type


https://github.com/user-attachments/assets/31218d04-876b-4b53-87b3-7349e59416ec

### **After**


https://github.com/user-attachments/assets/1623c271-cee3-4d66-aa8c-2c5430ac4990

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because it upgrades the shared design-system dependency
and changes `TextField`/button props in login, password creation/reset,
and seed phrase screens, which could cause subtle styling/accessibility
regressions in critical authentication flows.
> 
> **Overview**
> Upgrades `@metamask/design-system-react-native` to `^0.12.0` (and
`design-system-shared` to `^0.5.0`) and updates affected screens to
match the new component APIs.
> 
> Removes deprecated `TextFieldSize` usage across `Login`,
`ChoosePassword`, `ResetPassword`, `ManualBackupStep1`, and
`RevealPrivateCredential` components, and adjusts button APIs by
dropping `TextButton` sizing/`isInverse` props and switching the
seed-phrase copy action to a tertiary `Button`.
> 
> Updates Jest snapshots to reflect the new `TextField`
rendering/styling and accessory layout from the design-system upgrade.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1780297. 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?
-->

Migrated `Skeleton` to DSRN usage (confirmations scope).

## **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/DSYS-274

## Manual testing steps

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**


https://github.com/user-attachments/assets/33b4a13d-8b50-45e1-95db-5be88e3d50b6

### **After**


https://github.com/user-attachments/assets/26fe026f-9a9b-4cd6-8690-c604bcfd869f

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only change that swaps the `Skeleton` placeholder
component import paths in confirmations-related screens and one test
mock. Main risk is visual/regression differences if the temp Skeleton
behaves differently, but no business logic is altered.
> 
> **Overview**
> Migrates confirmations-scope loading placeholders to use the new DSRN
`Skeleton` implementation by switching imports from
`component-library/components/Skeleton` to
`component-library/components-temp/Skeleton` across confirmation rows,
footers, keyboards, and related components.
> 
> Updates the send `Recipient` test to mock the new `Skeleton` module
path accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0922bf9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

The Swaps and Bridge screens were navigating without a slide animation,
creating an abrupt transition that felt inconsistent with the rest of
the app. This PR applies `slideFromRightAnimation` to both screens so
they slide in from the right, matching the smooth navigation pattern
already used by Settings, Asset, Stake, Earn, Perps, and other screens
in `MainNavigator`.

## **Changelog**

CHANGELOG entry: Fixed abrupt navigation transition to Swaps and Bridge
screens by adding smooth slide-from-right animation

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Smooth navigation transitions

  Scenario: user navigates to the Swaps screen
    Given the user is on the wallet home screen

    When user taps the Swap action button
    Then the Swaps screen slides in smoothly from the right

  Scenario: user navigates to the Bridge screen
    Given the user is on the wallet home screen

    When user initiates a Bridge action
    Then the Bridge screen slides in smoothly from the right
```

## **Screenshots/Recordings**

### **Before**


https://github.com/user-attachments/assets/4d023c14-1f59-4fec-8a81-01a527e85e42


### **After**



https://github.com/user-attachments/assets/f45809a4-e175-4741-80ef-d496803f31f2


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

<!-- Generated with the help of the pr-description AI skill -->

Made with [Cursor](https://cursor.com)


https://github.com/user-attachments/assets/fcb30371-1684-4cc6-873d-c7c01ea380d5


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only navigation change that adjusts stack screen
transition options; main risk is unintended animation/gesture behavior
differences on these routes.
> 
> **Overview**
> Applies the shared `slideFromRightAnimation` stack transition to the
`Send` and `Bridge` routes in `MainNavigator`, so these screens slide in
consistently with other flows.
> 
> Updates the `MainNavigator` Jest snapshot to reflect the new
`animationEnabled` and `cardStyleInterpolator` options on those screens.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fc1507d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…n-production builds. (#28311)

<!--
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**
Currently the branch name is only displayed for QA builds (isQa check),
leaving RC, beta, and dev builds indistinguishable from production.
This PR:

- replaces isQa check with !isProduction() to show build info for all
non-production builds (RC, beta, dev, etc.)
- prepends uppercased METAMASK_ENVIRONMENT as build type label (e.g., RC
| Branch: release/7.69.0)
- production builds remain unchanged (no branch info displayed) 

Before: Branch: release/7.69.0 (QA only)
After:    RC | Branch: release/7.69.0 (all non-production builds)  

<!--
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/MMQA-1559

## **Manual testing steps**
- Verify non-production builds show {ENV} | Branch: {branch} on About
screen
- Verify production builds do not show branch info
- Run unit tests: yarn jest
app/components/Views/Settings/AppInformation/index.test.tsx
```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only change that tweaks when/what build metadata is
displayed and updates associated Jest tests/snapshots; no runtime
behavior changes for production builds beyond hiding this label.
> 
> **Overview**
> Updates the About MetaMask (`AppInformation`) screen to show a
**build-type label + git branch**
(`${METAMASK_ENVIRONMENT.toUpperCase()} | Branch: ...`) for *all
non-production builds* by replacing the old `isQa` gate with
`!isProduction()`.
> 
> Refreshes tests to mock `isProduction`, adds explicit coverage that
production builds do not render branch info, and updates the snapshot
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6e63822. 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?
-->

When `BridgeView` stayed in zero-state, tapping into the amount input
and then tapping outside without entering an amount could leave the
keypad open.

This change centralizes keypad dismissal into a shared helper and
restores keypad dismissal for zero-state taps and scroll starts so the
keypad closes correctly even when no amount has been entered.

## **Changelog**

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

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

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

CHANGELOG entry: Fixed the bridge keypad staying open when no amount was
entered

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Bridge zero-state keypad dismissal

  Scenario: user dismisses the keypad with no amount entered
    Given I am on the Bridge screen with swaps trending tokens enabled
    And I have tapped the source amount input so the keypad is visible
    And I have not entered an amount

    When user taps or starts scrolling in the content area above the keypad
    Then the source input should blur
    And the keypad should close
```

## **Screenshots/Recordings**

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

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [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.

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI interaction change limited to blur/close behavior for the
amount input and `SwapsKeypad` in `BridgeView`; potential risk is only
unintended extra dismissals on touch/scroll in zero-state.
> 
> **Overview**
> Fixes a zero-state interaction bug in `BridgeView` where the
`SwapsKeypad` could remain open after tapping outside the amount input
when *trending tokens* are shown.
> 
> This centralizes input/keypad dismissal into `dismissInputAndKeypad`
and wires it to zero-state touch and scroll gestures
(`onResponderRelease`, `onScrollBeginDrag`, and `onTouchEnd`) using a
shared `shouldShowTrendingTokens` guard.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
32a9d3e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…oute files (#28093)

<!--
# PR Title

refactor(navigation): deduplicate clearStackNavigatorOptions across
route files

-->
## **Description**

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

The `clearStackNavigatorOptions` object was duplicated across 7 route
files (Bridge, Card, Ramp, Ramp/Aggregator, Ramp/Deposit, Earn, Stake)
with identical definitions. Some used `colors.transparent` while others
used the string `'transparent'`, creating an inconsistency.

This PR removes all 7 local definitions and replaces them with a single
import from `constants/navigation/clearStackNavigatorOptions`, which was
introduced earlier in the migration branch. This reduces duplication and
ensures consistent navigator options across all feature route stacks.

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

N/A — internal refactor with no behavior change.

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches shared React Navigation `screenOptions` used by multiple
modal/stack flows; small changes to animation/overlay configuration
could subtly affect transition behavior across several screens.
> 
> **Overview**
> Deduplicates repeated `clearStackNavigatorOptions` definitions across
Bridge/Card/Ramp (incl. Aggregator + Deposit)/Earn/Stake route stacks by
importing the shared constant from
`constants/navigation/clearStackNavigatorOptions`.
> 
> Updates `MainNavigator` and several modal stacks to use a new exported
variant, `clearStackNavigatorOptionsWithTransitionAnimation`, and adds
that variant in `clearStackNavigatorOptions.ts` (restoring the overlay
`cardStyleInterpolator` while keeping transparent background and
animations disabled).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0a94894. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Nicholas Smith <nick.smith@consensys.net>
…ettings (#28184)

## **Description**

Migrate 4 RootModalFlow assets/settings components from prop-based route
access to `useRoute()` hook (PR 8 of 13).

**Components:** BasicFunctionalityModal, AssetHideConfirmation,
AssetOptions, NftOptions

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring. All 22 existing tests pass.

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk refactor that standardizes React Navigation param access and
removes `any`/`ScreenComponent` casts; primary risk is runtime crashes
if a modal is opened without expected `route.params`.
> 
> **Overview**
> Migrates `BasicFunctionalityModal`, `AssetHideConfirmation`,
`AssetOptions`, and `NftOptions` from prop-based `route` access to typed
`useRoute()` hooks, allowing `RootModalFlow` to stop casting these
screens to `ScreenComponent`.
> 
> Updates and adds tests to mock `useRoute()` params accordingly
(including new coverage for `AssetHideConfirmation` and `NftOptions`),
without changing the underlying user-facing behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
df5b2b8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@consensys.net>
## **Description**

WalletConnect reported 7,818 anomalous relay sessions from MetaMask
Mobile. A relay complexity limit takes effect April 15, 2026. Chain
change amplification is a major contributor — a single chain switch with
20 sessions generates ~80 relay messages instead of the expected ~40.

The root cause is two independent notification paths for chain changes:
1. **Store subscription path**: each `WalletConnect2Session` subscribes
to Redux and calls `handleChainChange()` → sends `updateSession` +
`emitSessionEvent` (2 messages)
2. **WalletConnectPort path**: `BackgroundBridge` emits `chainChanged` →
`WalletConnectPort.postMessage` intercepts and calls `updateSession()` →
sends another `updateSession` + `emitSessionEvent` (2 more messages)

This PR:
- Removes the duplicate WalletConnectPort `chainChanged` forwarding
(path 2 above)
- Adds a `lastEmittedChainId` dedup guard in `handleChainChange` to
prevent sequential duplicates from the `approveRequest` + store
subscription race
- Captures the `store.subscribe()` unsubscribe function and calls it in
`removeListeners()` to prevent leaked subscriptions

**Result**: 1 chain switch × 20 sessions = ~40 relay messages (2 per
session), down from ~80.

## **Changelog**

CHANGELOG entry: Fixed duplicate WalletConnect relay messages when
switching chains

## **Related issues**

Fixes:
[WAPI-1358](https://consensyssoftware.atlassian.net/browse/WAPI-1358)

## **Manual testing steps**

```gherkin
Feature: WalletConnect chain change notifications

  Scenario: dapp requests chain switch
    Given the user has a dapp connected via WalletConnect on Mainnet

    When user approves a wallet_switchEthereumChain request from the dapp
    Then the dapp shows the new chain once (no duplicate notification)

  Scenario: chain round-trip A to B to A
    Given the user has a dapp connected via WalletConnect on Mainnet

    When user switches to Polygon then back to Mainnet
    Then the dapp reflects Polygon, then Mainnet (both transitions work)

  Scenario: account change still works
    Given the user has a dapp connected via WalletConnect

    When user switches the active account in MetaMask
    Then the connected dapp receives the account change notification
```

## **Screenshots/Recordings**

### **Before**

<!-- N/A - relay-level change, not visual -->

### **After**

<!-- N/A - relay-level change, not visual -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes the WalletConnect v2 chain-change notification flow by
removing Redux store subscription and manual `chainChanged` emissions in
`WalletConnect2Session`, which could affect dapp network sync if the
remaining BackgroundBridge/Port path misbehaves. Scope is limited to
WalletConnect session lifecycle and related tests.
> 
> **Overview**
> Reduces WalletConnect v2 chain-change relay noise by removing
`WalletConnect2Session`'s Redux `store.subscribe` chain tracking, the
internal `handleChainChange`/request caching logic, and the extra
`chainChanged` event emission after `switchToChain`.
> 
> Updates tests to drop expectations around store unsubscription and
manual chain-change handling, and adds coverage for `WalletConnectPort`
reacting to `metamask_chainChanged` notifications (via mocked
`AppConstants.NOTIFICATION_NAMES`) by calling `updateSession` with the
selected account + parsed chainId.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a028535. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: jiexi <jiexiluan@gmail.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**

Removes unused code

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk refactor that removes an unused navbar helper and its tests;
main risk is any remaining external call sites that expected this export
at runtime.
> 
> **Overview**
> Removes the legacy `getTransactionsNavbarOptions` helper (and its
`AccountRightButton` dependency) from `Navbar/index.js`.
> 
> Cleans up the unit/integration tests in `Navbar/index.test.js` and
`Navbar/index.test.jsx` by deleting the corresponding
`getTransactionsNavbarOptions` test coverage.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
155917c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ions store (#28290)

## Summary

- **Fixes a bug** where `useOriginSource` misclassified all SDKConnectV2
(MWP) connections as `in-app browser`, causing the `source` property on
`CONNECT_REQUEST_STARTED`, `CONNECT_REQUEST_COMPLETED`, and
`CONNECT_REQUEST_CANCELLED` analytics events to be incorrect for V2
connections.
- The hook's existing check for the `MMSDKCONNECTV2::` prefix was dead
code — the prefix is stripped by `RPCMethodMiddleware` before it reaches
the permission system. V2 connections arrive with a bare UUID as their
origin.
- Adds a lookup against the `v2Connections` Redux store (already
populated by `HostApplicationAdapter.syncConnectionList`) to correctly
identify V2/MWP connections and return `SourceType.SDK_CONNECT_V2`.

## Root cause

The `RPCBridgeAdapter` constructs `middlewareHostname =
MMSDKCONNECTV2::<connId>`, but:
1. `RPCMethodMiddleware.ts` immediately strips the prefix
(`hostname.replace(SDK_CONNECT_V2_ORIGIN, '')`)
2. For the CAIP path (`wallet_createSession`),
`BackgroundBridge.channelIdOrOrigin` returns the bare `channelId` (UUID)
when `isMMSDK=true`
3. The `PermissionController` approval request therefore carries a bare
UUID as `metadata.origin`
4. `useOriginSource` couldn't match this UUID to V2 — it only checked
the V1 `SDKConnect` store

CHANGELOG entry: `null`

## Test plan

- [x] Unit tests: 7 passing (2 new V2-specific tests added)
- [ ] Manual: Open an MWP deeplink, verify `CONNECT_REQUEST_STARTED`
event has `source: 'sdk_connect_v2'` instead of `source: 'in-app
browser'`
- [ ] Verify no regression for V1 SDK connections (`source: 'sdk'`)
- [ ] Verify no regression for WalletConnect connections (`source:
'walletconnect'`)
- [ ] Verify no regression for in-app browser connections (`source:
'in-app browser'`)

## Related

- Fixes:
[WAPI-1380](https://consensyssoftware.atlassian.net/browse/WAPI-1380)
- Related PR: #27864 (wallet-side analytics for SDKConnectV2/MWP — this
fix reduces the scope of new events needed there)


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes the source-classification logic used for connection-request
analytics by introducing a new SDK v2 detection path and reordering
precedence, which could shift event attribution if the v2Connections
store is incomplete or stale.
> 
> **Overview**
> Fixes `useOriginSource` to correctly detect **SDK Connect v2 (MWP)**
permission origins by treating a *bare UUID* as v2 when it exists in the
Redux `sdk.v2Connections` map (instead of relying on a removed/stripped
v2 prefix).
> 
> Refactors the hook to use an explicit priority order (**v2 → v1 →
WalletConnect → in-app browser**) and adds unit coverage for v2
detection (including the case where the same UUID exists in both v1 and
v2, with v2 winning). Tests that build mock Redux `sdk` state were
updated to include an empty `v2Connections` field.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5a7473e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…con/BannerAlert/Button (#28298)

## **Description**

Updates deprecated component docblocks to consistently include links to
both the component README and the component-specific migration section
in the design-system-react-native migration guide.

This aligns `Icon`, `BannerAlert`, and `Button` with the same
deprecation guidance format used by `Text`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Deprecated component doc links are consistent

  Scenario: engineer checks deprecation notices
    Given the component wrapper files for Text, Icon, BannerAlert, and Button
    When viewing each component JSDoc deprecation block
    Then each includes a README link and a migration docs link with the component anchor
```

## **Screenshots/Recordings**

### **Before**

N/A (documentation-only JSDoc updates)

### **After**

N/A (documentation-only JSDoc updates)

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: documentation-only JSDoc link updates with no runtime or
behavior changes.
> 
> **Overview**
> Standardizes the `@deprecated` JSDoc blocks for `Text`, `Icon`,
`BannerAlert`, and `Button` to consistently include a component-specific
anchor link into the design-system React Native `MIGRATION.md`.
> 
> This replaces generic migration guide references with
`#text-component`, `#icon-component`, `#banneralert-component`, and
`#button-component` links alongside the existing README links.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d933095. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…unt sheets (#28182)

## **Description**

Migrate 3 RootModalFlow SDK/account sheet components from prop-based
route access to `useRoute()` hook, removing their `as ScreenComponent`
casts in App.tsx.

Part of the effort to remove `no-explicit-any` violations from route
files (PR 6 of 13).

**Components migrated:**
- `AddNewAccountBottomSheet` - reads optional scope/clientType params
for non-EVM account creation
- `SDKSessionModal` - reads channelId, icon, urlOrTitle, version,
platform, isV2 for SDK session management
- `SDKDisconnectModal` - reads channelId, account, accountName, dapp,
accountsLength, isV2 for SDK disconnect flows

**Changes:**
- Switch each component to `useRoute()` with typed `RouteProp` generic
- Remove dead Props interfaces (`SDKSEssionMoodalProps`,
`SDKDisconnectModalProps`)
- Simplify `AddNewAccountBottomSheet` types to export only `RouteParams`
- Remove 3 `as ScreenComponent` casts from `App.tsx`
- Update all 3 test files to mock `useRoute()`

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring with no user-facing behavior change. All 26
existing tests pass.

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk refactor that only changes how route params are accessed for
three modal sheets and updates tests accordingly; behavior should be
unchanged but regressions could occur if route params are
missing/mistyped at runtime.
> 
> **Overview**
> Refactors three RootModalFlow sheet components
(`AddNewAccountBottomSheet`, `SDKSessionModal`, `SDKDisconnectModal`) to
stop receiving `route` as a prop and instead read typed params via React
Navigation’s `useRoute()`.
> 
> Removes the corresponding `as ScreenComponent` casts in `App.tsx`,
deletes the old prop interfaces in favor of route-param types, and
updates the associated tests to mock `useRoute()` rather than passing
`route` props.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bdc9a64. 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**
- Use push EAS update in the Runway workflow directly
- Fix PR number null issue

## **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]
> **Medium Risk**
> Changes the release/OTA GitHub Actions orchestration by switching from
API dispatch to a reusable workflow and tweaking PR-number resolution;
mistakes here could block OTA publishing or target the wrong ref.
> 
> **Overview**
> Updates the OTA publishing pipeline to call `push-eas-update.yml` as a
*reusable workflow* (`workflow_call`) instead of dispatching it via
`actions/github-script`, simplifying `runway-ota-build-core.yml`.
> 
> Also fixes PR-number discovery to treat `gh pr list` returning `null`
as empty (avoiding false positives), and updates `CODEOWNERS` to include
the new `build-and-upload-to-testflight.yml` workflow under
`@MetaMask/mobile-admins`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
633c2ac. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cal-L <cal.leung@consensys.net>
## **Description**

Integrating the new `money-account-controller`.

If you wish to see the logs of this new controller, make sure to add
this to your `.env.js`:
```
export DEBUG=metamask:money-account-controller
```

To enable with a local feature flag (`.js.env`):
```
export OVERRIDE_REMOTE_FEATURE_FLAGS="true"
export MM_MONEY_ENABLE_MONEY_ACCOUNT="true"
```

You should see logs like this (the first time the Money account gets
created):
```
(NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KN6N42H46T44X2XMFNNGSJBR) not found, creating one... +0ms
(NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KN6N42H46T44X2XMFNNGSJBR) has no accounts, creating one... +4ms
(NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KN6N42H46T44X2XMFNNGSJBR) account created: 0x7fd31648732ad5d5e60d724652d3517184647b2b (d50016b8-6db3-422a-8d74-31514d276073) +34ms
(NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KN6N42H46T44X2XMFNNGSJBR - primary) account is: 0x7fd31648732ad5d5e60d724652d3517184647b2b (d50016b8-6db3-422a-8d74-31514d276073) +1ms
```

And logs like this afterward (e.g after an unlock):
```
(NOBRIDGE) DEBUG  metamask:money-account-controller Money keyring (entropy:01KN6N42H46T44X2XMFNNGSJBR - primary) account is: 0x7fd31648732ad5d5e60d724652d3517184647b2b (d50016b8-6db3-422a-8d74-31514d276073) +8m
```

You can also, visually see the Money account address by applying this
patch:
```diff
diff --git a/app/components/UI/Money/components/MoneyHeader/MoneyHeader.tsx b/app/components/UI/Money/components/MoneyHeader/MoneyHeader.tsx
index 0bd441d..d1348a4cd3 100644
--- a/app/components/UI/Money/components/MoneyHeader/MoneyHeader.tsx
+++ b/app/components/UI/Money/components/MoneyHeader/MoneyHeader.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import { useSelector } from 'react-redux';
 import {
   Box,
   BoxAlignItems,
@@ -7,8 +8,11 @@ import {
   ButtonIcon,
   ButtonIconSize,
   IconName,
+  Text,
+  TextVariant,
 } from '@metamask/design-system-react-native';
 import { MoneyHeaderTestIds } from './MoneyHeader.testIds';
+import { selectPrimaryMoneyAccount } from '../../../../../selectors/moneyAccountController';

 interface MoneyHeaderProps {
   /**
@@ -21,29 +25,40 @@ interface MoneyHeaderProps {
   onMenuPress: () => void;
 }

-const MoneyHeader = ({ onBackPress, onMenuPress }: MoneyHeaderProps) => (
-  <Box
-    flexDirection={BoxFlexDirection.Row}
-    alignItems={BoxAlignItems.Center}
-    justifyContent={BoxJustifyContent.Between}
-    twClassName="px-1 pt-2 pb-5"
-    testID={MoneyHeaderTestIds.CONTAINER}
-  >
-    <ButtonIcon
-      iconName={IconName.ArrowLeft}
-      size={ButtonIconSize.Md}
-      onPress={onBackPress}
-      accessibilityLabel="Back"
-      testID={MoneyHeaderTestIds.BACK_BUTTON}
-    />
-    <ButtonIcon
-      iconName={IconName.MoreVertical}
-      size={ButtonIconSize.Md}
-      onPress={onMenuPress}
-      accessibilityLabel="Menu"
-      testID={MoneyHeaderTestIds.MENU_BUTTON}
-    />
-  </Box>
-);
+const MoneyHeader = ({ onBackPress, onMenuPress }: MoneyHeaderProps) => {
+  const primaryMoneyAccount = useSelector(selectPrimaryMoneyAccount);
+
+  return (
+    <Box
+      flexDirection={BoxFlexDirection.Row}
+      alignItems={BoxAlignItems.Center}
+      justifyContent={BoxJustifyContent.Between}
+      twClassName="px-1 pt-2 pb-5"
+      testID={MoneyHeaderTestIds.CONTAINER}
+    >
+      <ButtonIcon
+        iconName={IconName.ArrowLeft}
+        size={ButtonIconSize.Md}
+        onPress={onBackPress}
+        accessibilityLabel="Back"
+        testID={MoneyHeaderTestIds.BACK_BUTTON}
+      />
+      {
+        primaryMoneyAccount ? (
+          <Text variant={TextVariant.BodySm}>
+            {primaryMoneyAccount.address}
+          </Text>
+        ) : null
+      }
+      <ButtonIcon
+        iconName={IconName.MoreVertical}
+        size={ButtonIconSize.Md}
+        onPress={onMenuPress}
+        accessibilityLabel="Menu"
+        testID={MoneyHeaderTestIds.MENU_BUTTON}
+      />
+    </Box>
+  );
+};

 export default MoneyHeader;
```

And you can navigate to the `MoneyHomeView` (by clicking on `Cash >`).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [ ] 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]
> **High Risk**
> High risk because it adds a new background controller into `Engine`
initialization/state and conditionally introduces a `MoneyKeyring` that
pulls and encodes HD keyring mnemonics, impacting key management and
startup behavior.
> 
> **Overview**
> Integrates `@metamask/money-account-controller` into the background
`Engine` (init wiring, messenger delegation, stateChange subscriptions,
persisted initial state/log snapshots) so its state is available via
`Engine.context`/`Engine.state`.
> 
> Adds a new remote+env gated flag (`moneyEnableMoneyAccount` /
`MM_MONEY_ENABLE_MONEY_ACCOUNT`) and uses it to (a) conditionally
initialize/clear `MoneyAccountController` during account-tree startup
and (b) conditionally register a `MoneyKeyring` builder in
`keyringControllerInit`, including a `getMnemonic` callback that locates
the matching HD keyring and encodes its mnemonic for Money keyring
initialization.
> 
> Introduces selectors for Money accounts (`selectMoneyAccounts`,
`selectPrimaryMoneyAccount`) plus a `selectPrimaryHDKeyring` helper, and
updates/extends unit tests and feature-flag registry accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fda78f6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com>
…nified swaps context cp-7.73.0 (#28361)

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

When a destination token has a security warning (e.g. a Blockaid
malicious/suspicious flag), the unified swaps bridge view was entering
an infinite quote request loop.

**Root cause:** `tokenWarning` was included as a dependency of the
`useMemo` that builds the analytics `context` object in
`useUnifiedSwapBridgeContext`. `tokenWarning` is itself derived from
quote results (blockaid data returned by the bridge controller). This
created a feedback cycle:

```
Quote fetched → tokenWarning updates → context object recreates
→ updateQuoteParams identity changes → useEffect fires
→ new quote request → repeat ∞
```

**Fix:** Remove `tokenWarning` from the `useMemo` dependency array and
clear `security_warnings` to `[]` for now. The `security_warnings` field
will be populated properly in the bridge controller instead, removing
the React dependency cycle entirely.

## **Changelog**

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

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

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

CHANGELOG entry: Fixed a bug that caused repeated quote requests when
swapping to a token with a security warning.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Unified Swaps/Bridge quote fetching with token warnings

  Scenario: user swaps to a token with a Blockaid security warning
    Given the user has opened the Swap/Bridge screen
    And the user has selected a source token with sufficient balance

    When the user selects a destination token that has a Blockaid security warning
    And the user enters a valid source amount
    Then the app fetches a quote once
    And does not repeatedly fire additional quote requests
    And the security warning banner is displayed on screen

  Scenario: user swaps to a normal token (no warning)
    Given the user has opened the Swap/Bridge screen
    And the user has selected a source token with sufficient balance

    When the user selects a destination token with no security warning
    And the user enters a valid source amount
    Then the app fetches a quote once
    And quote results are displayed normally
```

## **Screenshots/Recordings**

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

### **Before**

N/A

### **After**


Uploading Screen Recording 2026-04-02 at 4.24.51 PM.mov…



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

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: small change limited to analytics context memoization, but
it temporarily drops `security_warnings` data which could affect
warning-related telemetry until re-populated elsewhere.
> 
> **Overview**
> Prevents an infinite bridge quote re-fetch loop by removing
destination token warning state from `useUnifiedSwapBridgeContext`’s
memoized context object.
> 
> `security_warnings` is now always an empty array (*TODO*) and the
`useMemo` dependency list no longer includes the warning selector,
stabilizing the `context` identity passed into
`BridgeController.updateBridgeQuoteRequestParams`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
21dec81. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…28285)

## **Description**

Fixes a bug where the network selector icon in the In-App Browser was
stuck displaying the global selected network due to incorrect dapp
origin information being used

## **Changelog**

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

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

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

CHANGELOG entry: Fixed a bug where the network selector icon in the
In-App Browser would not correctly reflect the currently selected
network for the dapp

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/WAPI-1031

## **Manual testing steps**

1. Open Explore
2. Click the top right In-App Browser tab icon
3. Tap the top right network selector icon
4. Select a network that differs from the current icon
5. The icon should change to match

## **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/d68fc3a2-4145-4189-ae97-bc2ece8a018a



### **After**



https://github.com/user-attachments/assets/2cd0a33a-7885-402c-b537-ebbd1448aae1



## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: scoped UI/navigation parameter plumbing to ensure per-dapp
network context is used; main risk is callers missing the new required
`dappOrigin` prop or origin parsing yielding empty origin in edge URLs.
> 
> **Overview**
> Fixes the In-App Browser network picker/avatar to reflect the
*dapp-selected* network by threading an explicit `dappOrigin` through
`BrowserUrlBar` into `AccountRightButton`.
> 
> `AccountRightButton` no longer derives origin from navigation route
params; it now uses `dappOrigin` for `useNetworkInfo` and includes it as
`hostInfo.metadata.origin` when opening the `NetworkSelector` sheet, so
the selector can resolve the per-origin network. Tests were updated
accordingly to supply a non-empty `dappOrigin` and remove the `useRoute`
mock.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9c4cbaa. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Alex Donesky <adonesky@gmail.com>
…28111)

## **Description**

Uses the self reported dapp url when available for the
`CONNECT_REQUEST_COMPLETED` event when the connection is a SDKv1, SDKv2,
or WC connection. It uses the trusted origin otherwise.

## **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/WAPI-1338

## **Manual testing steps**

1. Establish a WC or SDKv1 or SDKv2 connection
2. Check analytics events for a property value `referrer` that should be
the dapp's url, not a UUID

It may be easier to use an expo build and the js debugger to view
analytic network events.

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk analytics-only change that alters the `referrer` value
emitted for `CONNECT_REQUEST_COMPLETED`, potentially affecting
downstream dashboards but not user-facing behavior.
> 
> **Overview**
> Updates analytics for connection approvals so
`MetaMetricsEvents.CONNECT_REQUEST_COMPLETED` now reports a computed
`referrer` (SDK/WC self-reported dapp URL when available, otherwise the
trusted hostname/origin) instead of always using
`request.metadata.origin`.
> 
> Applies the same `referrer` logic in both `AccountConnect` and
`MultichainAccountConnect`, and wires it into the `handleConnect`
tracking dependencies.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ad3bb42. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Alex Donesky <adonesky@gmail.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**

The `trigger-ota` job mixed shell steps with a reusable workflow (`uses:
./.github/workflows/push-eas-update.yml`). In GitHub Actions, a job must
either define `steps:` or call another workflow with job-level `uses:`,
not both.
This splits that into:
1. **`validate-ota-pr`** — Validates a PR number exists before OTA (same
guard as before).
2. **`trigger-ota`** — Only calls `push-eas-update.yml`, with `secrets:
inherit` for caller secrets.
**`create-ota-production-tag`** now sets `tag_name` from
`needs.decide.outputs.ota_version` (same value the old `release_tag`
step echoed). It still `needs: trigger-ota` so tagging runs only after
the OTA workflow finishes.

successful workflow run:
https://github.com/MetaMask/metamask-mobile/actions/runs/23923283109

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

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes the job graph for Runway OTA
publishing/tagging; misconfigured `needs`/`uses`/secrets inheritance
could block OTA releases or trigger the wrong follow-up jobs.
> 
> **Overview**
> Fixes `runway-ota-build-core.yml` to correctly invoke the reusable
`push-eas-update.yml` workflow as a **job-level** `uses:` instead of
mixing it with `steps:`.
> 
> Adds a separate `validate-ota-pr` job to guard OTA runs when no PR
number is resolvable, updates `trigger-ota` to inherit secrets, and
adjusts production tagging to use `needs.decide.outputs.ota_version`
directly (removing the intermediate `release_tag` output).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
92b5c4c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…p-7.73.0 (#28302)

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

Addresses several UAT issues in the Predict buy-with-any-token flow:

- **Auto-select best payment token**: New
`usePredictDefaultPaymentToken` hook auto-selects the token with the
highest fiat balance when Predict balance is below MINIMUM_BET ($1),
instead of requiring manual selection. Resets to Predict balance when
sufficient.
- **Optimistic positions on deposit**: Creates optimistic positions from
the order preview at deposit time so the position appears immediately in
the portfolio while the deposit confirms. Clears optimistic positions on
failure (both direct order failures and failed deposit-and-order
transactions).
- **Navigate back on deposit**: Navigate back when the deposit-and-order
flow begins, so the user isn't stuck on the buy form.
- **Keep token selection always enabled**: Removes the `canSelectToken`
gate — the pay-with-token row is now always interactive (disabled only
while placing an order).
- **"Predict balance first" hint**: Shows "Your Predict balance will be
used first" below the pay-with row when an external token is selected,
so users understand the payment order.
- **Deposit amount guards**: `depositAmount` now returns 0 when the
preview is unavailable or the bet is below minimum, preventing premature
deposit calculations and stale values from triggering the deposit flow.
- **Updated insufficient funds messaging**: Error messages now suggest
trying a different token when funds are insufficient.
- **Fix text overflow on Polymarket terms**: Nests the "learn more" link
inside the disclaimer text and adds horizontal padding to prevent
overflow.
- **Fix premature payment token reset**: Adds a
`totalPayForPredictBalance > 0` guard so the auto-reset effect only
fires when there is an actual bet amount, preventing the selected token
from being cleared immediately after selection.
- **Depositing toast notification**: Shows a "Prediction in progress"
toast with spinner when the deposit phase begins and invalidates
position queries to reflect the optimistic position.


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

https://www.loom.com/share/c25681fd77a444e496f999a23a55b0e6

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Updates buy-with-any-token order state transitions, optimistic
position caching, and navigation/toast behavior; mistakes could cause
incorrect UI state or stale/phantom positions during deposit/order
failures.
> 
> **Overview**
> Improves the *buy-with-any-token* flow by introducing a new `order`
event status `depositing` and publishing it when the flow transitions
into the deposit phase, with a matching “Prediction in progress” toast
and positions query invalidation.
> 
> Adds preview-based **optimistic positions** during deposit via
`PolymarketProvider.createOptimisticPositionFromPreview`, and ensures
cleanup via `clearOptimisticPosition` when `placeOrder` fails or when a
`depositAndOrder` transaction fails.
> 
> Refines buy screen UX: auto-selects a default payment token when
Predict balance is below `MINIMUM_BET` (new
`usePredictDefaultPaymentToken`), removes the `canSelectToken` gate (row
only disabled while placing), navigates back when entering `DEPOSITING`,
adds a “Predict balance will be used first” hint, guards deposit amount
calculation until fees/minimum bet are available, and updates
insufficient-funds copy to suggest trying another token; also adjusts
the Polymarket TOS disclaimer layout to prevent overflow.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7f97218. 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?
-->

Migrated `Button` to DSRN package usage.

## **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/DSYS-445

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**


https://github.com/user-attachments/assets/26db059b-4937-4e94-827c-7ca7b9624596

### **After**


https://github.com/user-attachments/assets/56fbddab-9c75-40fc-bbb5-6ee3560f3ecc

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it swaps button implementations across multiple
settings/network/account screens, which can subtly change
press/disabled/accessibility behavior and snapshot structure.
> 
> **Overview**
> Migrates multiple screens (e.g., `EditAccountName`, network
connect/selector flows, and several Settings sections) from the internal
`component-library` `Button` to `@metamask/design-system-react-native`
`Button`, updating props (`label` -> children, `disabled` ->
`isDisabled`, `width` -> `isFullWidth`, and new `ButtonVariant` enums).
> 
> Updates tests and snapshots to match the new rendered
structure/accessibility output, including tightening the
`NetworkConnectMultiSelector` loading test to assert the update CTA is
disabled and that “select all” is a no-op while loading, and removing
the now-unneeded `disabledOpacity` styling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
136d88e. 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?
-->

Migrated `Skeleton` to DSRN usage (card scope).

## **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/DSYS-274

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**


https://github.com/user-attachments/assets/7e2c714e-7ada-4a25-9073-437b9e4dbe32

### **After**


https://github.com/user-attachments/assets/8a310ad6-e1cd-40f4-b266-3e1bfb979b57

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only change that swaps the `Skeleton` implementation and
updates the associated snapshot; no business logic or data flow changes.
> 
> **Overview**
> Migrates `ViewPinBottomSheet` to use `Skeleton` from
`component-library/components-temp/Skeleton` instead of the deprecated
`components/Skeleton`.
> 
> Updates the Jest snapshot to reflect the new skeleton’s rendered style
structure (notably how border radius/positioning styles are applied).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95dd583. 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 adds Apple Wallet (iOS) in-app provisioning support for the
MetaMask Card feature. Users can now add their MetaMask Card directly to
Apple Wallet from within the app.

### What is the reason for the change?
Users currently cannot add their MetaMask Card to Apple Wallet directly
from the app. They need to manually add the card through the Wallet app,
which provides a suboptimal user experience.

### What is the improvement/solution?
- Implements `AppleWalletAdapter` that integrates with the
`@expensify/react-native-wallet` library for iOS
- Updates the `providers.ts` factory to return `AppleWalletAdapter` for
iOS platform
- Adds the `com.apple.developer.payment-pass-provisioning` entitlement
required for in-app provisioning
- Configures `react-native.config.js` to enable the wallet library for
iOS only
- Updates `Podfile.lock` with the new CocoaPods dependencies

## **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 Apple Wallet in-app provisioning for MetaMask
Card on iOS

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Apple Wallet In-App Provisioning

  Scenario: User adds MetaMask Card to Apple Wallet
    Given user is logged in and has an active MetaMask Card
    And user is on the Card Home screen on an iOS device
    And the "Add to Apple Wallet" button is visible

    When user taps on "Add to Apple Wallet" button
    Then the Apple PassKit provisioning sheet is presented
    And user completes the Apple Wallet verification
    And the card is added to Apple Wallet
    And a success toast is displayed

  Scenario: User sees disabled button when card is already in wallet
    Given user is logged in and has an active MetaMask Card
    And the card is already added to Apple Wallet

    When user navigates to the Card Home screen
    Then the "Add to Apple Wallet" button is not visible

  Scenario: User cannot add card on unsupported device
    Given user is logged in and has an active MetaMask Card
    And the device does not support Apple Pay

    When user navigates to the Card Home screen
    Then the "Add to Apple Wallet" button is not visible
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces new iOS-native provisioning flow and entitlements via
`@expensify/react-native-wallet`, which can affect build/signing and
wallet tokenization behavior. Also adjusts provisioning state/analytics
handling, so regressions could impact add-to-wallet UX and metrics.
> 
> **Overview**
> Adds **Apple Wallet (iOS) in-app provisioning** for MetaMask Card by
introducing a new `AppleWalletAdapter` that calls
`@expensify/react-native-wallet`’s `addCardToAppleWallet` with an
issuer-encryption callback and maps activation events.
> 
> Updates push-provisioning wiring to select Apple on iOS
(`getWalletProvider` + adapter exports), adds comprehensive unit tests
for the new adapter, and tweaks `usePushProvisioning` to treat service
`success` as the primary completion path (with analytics) and to prevent
re-adding after a successful provision.
> 
> Enables the required iOS capability by adding
`com.apple.developer.payment-pass-provisioning` entitlements, and
updates native dependency setup (`Podfile.lock` and
`react-native.config.js`) to autolink `@expensify/react-native-wallet`
for iOS (while keeping Android conditional on the TapAndPay SDK).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2c473ab. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…ttom sheet (#28374)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

Fixes Android scrolling in **Import Token -> Select a Network** by using
`ScrollView` from `react-native-gesture-handler` inside the Add Asset
network selection bottom sheet.

The previous implementation used `ScrollView` from `react-native`, which
can conflict with gesture-handler managed bottom sheets on Android and
cause one-finger scrolling to fail.

## **Changelog**

CHANGELOG entry: Fixed an issue where users could not scroll the Import
Token network selector with one finger on Android.

## **Related issues**

Fixes: #28342

## **Manual testing steps**

```gherkin
Feature: Import token network list scrolling on Android

  Scenario: user scrolls network list with one finger
    Given the wallet is open on Android
    And the user navigates to Tokens and opens Import Token
    When user taps the network selector field
    Then the Select a Network bottom sheet is shown

    When user drags the network list with one finger
    Then the list scrolls normally
    And the user can select a network
```

## **Screenshots/Recordings**

### **Before**

See bug report recordings in PR context.

### **After**

N/A (code-level fix validated with targeted test)

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-96dfdfa7-7d98-48c4-8fb6-af9743689718"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-96dfdfa7-7d98-48c4-8fb6-af9743689718"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@users.noreply.github.com>
Co-authored-by: Bernardo Garces Chapero <bernardo.chapero@consensys.net>
## **Description**

Updates the TOKEN_DETAILS_OPENED analytics event to include
has_perps_market and severity properties, providing richer context about
the token details screen state when the event fires.

## **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 event property to token details opened event

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes when `TOKEN_DETAILS_OPENED` fires by
deferring until market insights and perps market data settle, which can
impact analytics timing/volume. UI behavior is largely unchanged, but
the added async coordination and stale-payload guarding could introduce
missed/duplicated events if incorrect.
> 
> **Overview**
> **Enhances `TOKEN_DETAILS_OPENED` analytics** to include
`has_perps_market` and `severity` (from security data), and refactors
the tracking so it fires only once per token+source.
> 
> Tracking is now **deferred in `TokenDetailsRouteWrapper`** until both
market-insights display resolution and perps market lookup are settled,
with a token-key guard to drop stale market-insights callbacks after
navigation.
> 
> Updates `AssetOverviewContent`’s `onMarketInsightsDisplayResolved`
callback to return `{ isDisplayed, severity }` (instead of a boolean)
and adjusts unit tests accordingly, plus adds an e2e page-object retry
loop for reading the Perps balance value more reliably.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1d0cda9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@users.noreply.github.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
## Version Bump After Release

This PR bumps the main branch version from 7.73.0 to 7.74.0 after
cutting the release branch.

### Why this is needed:
- **Nightly builds**: Each nightly build needs to be one minor version
ahead of the current release candidate
- **Version conflicts**: Prevents conflicts between nightlies and
release candidates
- **Platform alignment**: Maintains version alignment between MetaMask
mobile and extension
- **Update systems**: Ensures nightlies are accepted by app stores and
browser update systems

### What changed:
- Version bumped from `7.73.0` to `7.74.0`
- Platform: `mobile`
- Files updated by `set-semvar-version.sh` script

### Next steps:
This PR should be **manually reviewed and merged by the release
manager** to maintain proper version flow.

### Related:
- Release version: 7.73.0
- Release branch: release/7.73.0
- Platform: mobile
- Test mode: false

---
*This PR was automatically created by the
`create-platform-release-pr.sh` script.*

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
… branch (#28331)

<!--
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 is to make release cherry-pick PRs execute the full smoke e2e
instead of a reduced tag set chosen by ai.

On main, iterating quickly with a risk-scored subset is a reasonable
tradeoff: we accept some residual risk in exchange for speed and we will
catch more in follow-up PRs. A PR into release/* is effectively “this
build is a candidate to ship.”
Smart selection saves CI time on high-volume main development. Release
cherry-picks are low volume and high impact, and we cannot afford to
merge cherry-pick that breaks the CI on release branch due to release
urgency.



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

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

cherry-pick PRs should run all e2e tests

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes CI behavior for release-branch PRs by bypassing AI selection
and forcing full E2E runs, which can affect build time and which tests
execute. Logic is localized to a single composite action and does not
touch product code.
> 
> **Overview**
> Updates the `smart-e2e-selection` composite action to **detect PRs
targeting `release/*`** and skip the AI-based E2E test selection in that
case.
> 
> For `release/*` PRs it now **forces full E2E execution** by setting
`force_run=true` (and `ai_confidence=100`), and it avoids the
checkout/dependency install steps used only for AI analysis; copy
updates output/input descriptions to reflect the new behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
122d8e6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… withdraw (#28271)

## **Description**

Two improvements to the Perps Withdraw confirmation flow (new UI):

### 1. Toast notifications for withdraw lifecycle
Adds pending, success, and failure toast notifications matching the
Predict Withdraw style. Uses `ControllerEventToastBridge` at the App
level to listen for `TransactionController:transactionStatusUpdated`
events on `perpsWithdraw` transactions. Suppresses the generic
"Transaction submitted" / "Transaction Complete!" notifications for
`perpsWithdraw` since dedicated toasts now handle it.

### 2. Insufficient balance validation
Prevents users from withdrawing more than their available Perps balance.
Adds a blocking alert (`useInsufficientPerpsBalanceAlert`) that disables
the Continue/Withdraw button when the entered amount exceeds
`PerpsController.state.accountState.availableBalance`. Mirrors the
existing `useInsufficientPredictBalanceAlert` pattern.

## **Changelog**

CHANGELOG entry: Added toast notifications and insufficient balance
validation for Perps Withdraw transactions

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1117

## **Manual testing steps**

Feature: Perps Withdraw toast notifications

  Scenario: user sees pending and success toasts for perps withdrawal
    Given the user has a funded HyperLiquid Perps account
    And the user navigates to the Perps Withdraw page (new UI)

    When user enters a withdrawal amount and taps Continue then Withdraw
Then a "Withdrawal in progress / Available in about 1 minute" toast is
displayed

    When the withdrawal completes successfully
Then a "Withdrawal complete / $X.XX BNB moved to your wallet" toast is
displayed
And no generic "Transaction submitted" or "Transaction Complete!"
notifications appear

  Scenario: user sees error toast on failed perps withdrawal
    Given the user has a funded HyperLiquid Perps account

    When user initiates a withdrawal that fails
Then a "Something went wrong / Failed to proceed with withdrawal" toast
is displayed

Feature: Perps Withdraw insufficient balance validation

  Scenario: user cannot withdraw more than available balance
Given the user has a funded HyperLiquid Perps account with $45 available
balance
    And the user navigates to the Perps Withdraw page (new UI)

    When user enters $50 as the withdrawal amount
    Then the Continue button is disabled
    And an "Insufficient funds" error message is displayed

  Scenario: user can withdraw within available balance
Given the user has a funded HyperLiquid Perps account with $45 available
balance

    When user enters $30 as the withdrawal amount
    Then the Continue button is enabled

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches transaction confirmation UX by adding new perps-withdraw toast
handling and a blocking balance-validation alert; issues could cause
missing/duplicate notifications or incorrectly block/allow withdrawals.
> 
> **Overview**
> Adds dedicated Perps-withdraw lifecycle toasts
(pending/confirmed/failed) by registering a new
`usePerpsWithdrawToastRegistrations` handler with
`ControllerEventToastBridge` at the app level, and introduces new
localized toast strings.
> 
> Introduces a blocking `InsufficientPerpsBalance` confirmation alert
that compares the entered withdraw amount against
`PerpsController.accountState.availableBalance` and wires it into the
existing confirmation alert pipelines/metrics.
> 
> Refactors Predict’s withdraw-confirmed messaging to use a new shared
`resolveWithdrawTokenInfo` utility (token symbol + post-quote fiat
amount resolution), with unit tests added for the new toast/alert/util
behavior and an explicit test ensuring generic redesigned-transaction
notifications don’t run for `perpsWithdraw`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d427f01. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
…messenger (#28341)

## **Description**

Migrate RewardsController and PredictController to use
`MESSENGER_EXPOSED_METHODS` + `registerMethodActionHandlers` +
auto-generated action types.

- **RewardsController**: Replace 41 manual `registerActionHandler` calls
with `MESSENGER_EXPOSED_METHODS` (58 methods total). Remove old action
interfaces from `types.ts`.
- **PredictController**: Add `MESSENGER_EXPOSED_METHODS` (37 methods).
Previously only 2 methods were exposed.
- Update generate script to scan `app/` recursively
- Add ESLint override for `type` over `interface` in generated files

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

1. `yarn lint:tsc` — passes
2. `yarn generate-method-action-types:check` — passes
3. `yarn jest --no-coverage
app/core/Engine/controllers/rewards-controller` — 469 passed
4. `yarn jest --no-coverage
app/components/UI/Predict/controllers/PredictController.test.ts` — 308
passed

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes how controller methods are
registered/exposed through the messenger (swapping many explicit handler
registrations for a bulk registration list), which could break messaging
at runtime if method lists/types drift from implementations.
> 
> **Overview**
> **Moves `RewardsController` and `PredictController` to the
`registerMethodActionHandlers` pattern** by introducing
`MESSENGER_EXPOSED_METHODS` lists and generating
`*-method-action-types.ts` union types used in each controller’s
`...Actions` type.
> 
> For `RewardsController`, this replaces dozens of manual
`registerActionHandler` calls, removes the old action interface
declarations from `types.ts`, updates tests to assert
`registerMethodActionHandlers`, and re-exports the generated action
types from the controller `index.ts`.
> 
> Tooling/linting is updated to support generated files:
`generate-method-action-types` now scans all of `app/**` (and checks
diffs accordingly), and ESLint applies the perps/Core-alignment override
(including `type` aliases) to `app/**/*-method-action-types*.ts`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bfff5cb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
metamaskbotv2 Bot and others added 20 commits April 13, 2026 12:40
This PR syncs the stable branch to main for version 7.74.0.

*Synchronization Process:*

- Fetches the latest changes from the remote repository
- Resets the branch to match the stable branch
- Attempts to merge changes from main into the branch
- Handles merge conflicts if they occur

*File Preservation:*

Preserves specific files from the stable branch:
  - CHANGELOG.md
  - bitrise.yml
  - android/app/build.gradle
  - ios/MetaMask.xcodeproj/project.pbxproj
  - package.json

  Indicates the next version candidate of main to 7.74.0
<!--
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**

Wires up the Social Leaderboard to live data from the Social API.
Integrate the social-controllers (SocialService + SocialController) into
the Engine, adds useTopTraders hook using useQuery from
@metamask/react-data-query to fetch leaderboard data through the Data
Services pattern.
Also adds the homepage TopTradersSection (horizontal card carousel) and
the full TopTradersView (ranked list) with skeleton loading states.

## **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]
> **Medium Risk**
> Adds a new Social data service/controller to the Engine and wires UI
screens to fetch live leaderboard data from a new `SOCIAL_API_URL`,
which could impact app startup/state persistence and introduce new
network failure modes.
> 
> **Overview**
> Adds live Social Leaderboard integration by introducing Engine-managed
`SocialService` and `SocialController` (new messengers, init wiring,
persisted state, and data-service registration) and configuring a new
`SOCIAL_API_URL` build/env constant.
> 
> Updates the homepage `TopTradersSection` to fetch and render the top 3
traders (cards + skeleton loading, refresh via ref, hide when empty/flag
off) and upgrades `TopTradersView` to display the full ranked list with
a network filter entry point and follow toggles.
> 
> Includes new UI components (`TopTraderCard`, `TraderRow`, skeletons,
`NetworkFilterButton`), a `formatPnl` formatter, the `useTopTraders`
hook built on `@metamask/react-data-query`, plus expanded unit tests and
updated mocks/strings.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5881e59. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/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**
https://consensyssoftware.atlassian.net/browse/RWDS-1163

### Leaderboard tier selector
- Replaced TabsBar with a Pressable trigger that opens a
RewardsSelectSheet bottom sheet for tier selection
- Created RewardsSelectSheet -- a generic, reusable select bottom sheet
registered as a transparentModal in MainNavigator.js at
Routes.MODAL.REWARDS_SELECT_SHEET. Accepts title, options,
selectedValue, and onSelect callback
- Default tier is the user's projected tier (from leaderboard position)
when available, otherwise the top tier (last in list)

### Stats summary
- Added CampaignStatsSummary component displaying Return, Market Value,
Rank, and Tier in a 2x2 grid with loading skeletons and error banners

### Leaderboard neighbor display (preview mode)
- When maxEntries is set and the user's tier matches the selected tier:
- If user rank is within visible range: highlights their row with
bg-background-muted
- If user rank is outside visible range: shows top 3 entries + dot
separator + neighbor entries (rank-1, user, rank+1)
- Handles edge cases: first/last in tier (1-2 neighbors), tier mismatch,
no position data

### Pending tag / Qualified tag
- Add `qualified` and `qualifiedDays` to CampaignLeaderboardEntry and
CampaignLeaderboardPositionDto
- Display `Pending` Tag if qualified: false, `Qualified` tag if true

### Activity view
- Group activity rows by date

### Prize pool
- Add prize pool progress bar according to hardcoded breakpoints given
by PRD
- Fetch total deposit volume from new endpoint
Get(':campaignId/stats/deposits')

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

### Pending
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-09 at 17 59 47"
src="https://github.com/user-attachments/assets/bfdcec83-6f2b-4c29-b416-35b1c3275be9"
/>

<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 15 05"
src="https://github.com/user-attachments/assets/500d7428-f0bc-40f1-ace7-c7048b38e23f"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 15 41"
src="https://github.com/user-attachments/assets/a0af5d73-a265-4c0b-b8c7-d9f928cc10e3"
/>

<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 18 33"
src="https://github.com/user-attachments/assets/c695d664-4465-4f07-9027-668ae1d2fd7d"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 18 40"
src="https://github.com/user-attachments/assets/a1a0da1a-31ed-4207-bf4f-379485655cb5"
/>

### Qualified
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 20 27"
src="https://github.com/user-attachments/assets/29b8def5-4d08-4cf0-9e2f-3272ecdf93c2"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 20 31"
src="https://github.com/user-attachments/assets/9e0c3c85-7a10-4f50-8418-8d40b5f29afb"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 23 10"
src="https://github.com/user-attachments/assets/19f2ab07-f255-4767-b90a-e07dc8265c08"
/>

### Activity view
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 28 48"
src="https://github.com/user-attachments/assets/e8b42158-b6ff-47e9-b44d-ab23ba87ecc1"
/>

### Prize pool
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 24 02"
src="https://github.com/user-attachments/assets/ac0b1219-2252-41ed-bd26-656f188076eb"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 29 36"
src="https://github.com/user-attachments/assets/6f47ff55-db28-4318-919d-ce50319d0010"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 29 58"
src="https://github.com/user-attachments/assets/c4d64e3a-aa0d-44bf-bd50-8f9703986acf"
/>


*

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate UI/behavior changes in Rewards campaign flows plus a new data
fetch (`getOndoCampaignDeposits`) and updated leaderboard rendering,
which could affect navigation and correctness of displayed stats/tier
selection.
> 
> **Overview**
> Updates Ondo campaign rewards UI to support **tier-based
leaderboards** via a new reusable `RewardsSelectSheet` modal (registered
in `MainNavigator`) and localized tier display names.
> 
> Reworks campaign details/leaderboard presentation by replacing
`OndoLeaderboardPosition` with a new `CampaignStatsSummary`
(return/market value/rank/tier, pending/qualified tags, SWR-style
loading/error handling), adding a `OndoPrizePool` progress section
backed by a new `useGetOndoCampaignDeposits` hook, and enhancing
`OndoLeaderboard` with preview mode (`maxEntries`), current-user
highlighting, and neighbor/split-view rendering.
> 
> Refactors the portfolio activity view to be **activity-only**, grouped
by date headers, and updates activity rows to support `timeOnly`, signed
USD formatting, and external outflow address shortening; tests are
updated/added accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ecd1e4b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…-3331] (#28337)

## **Description**

When selecting a token in the UB2 Buy flow, a quick error ("We've
encountered an error") flashes on the amount input screen before the
correct "Powered by [provider]" text appears.

The root cause is a provider ID mismatch: the quotes API can return
provider IDs in a prefixed format (`/providers/transak`) while the
controller state stores them without the prefix (`transak`). This caused
`selectedQuote` to resolve to `null`, briefly rendering the error
banner.

The fix normalizes provider IDs on both sides of the comparison using
`normalizeProviderCode()` and switches from array destructuring to
`.find()` so all returned quotes are searched.

## **Changelog**

CHANGELOG entry: Fixed Buy amount screen sometimes showing a generic
error when quotes returned for the selected provider but provider id
strings differed in format.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-3331
Based on draft PR #27779

## **Manual testing steps**

```gherkin
Feature: Token selection in Buy flow

  Scenario: user selects a token and navigates to amount input
    Given user is on the token selection screen in the Buy flow

    When user selects a token (e.g. ETH)
    Then the amount input screen shows "Powered by [provider]" without any error flash
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->
N/A. Reason: This is an extremely rare race condition. It doesn't happen
often, and after several changes on main, it's even less common.
Nevertheless, we still want to solve this logical condition via this PR.

### **After**

<!-- [screenshots/recordings] -->
N/A. Reason: This is an extremely rare race condition. It doesn't happen
often, and after several changes on main, it's even less common.
Nevertheless, we still want to solve this logical condition via this PR.


## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches Buy flow quote-selection and payment-method loading state;
small logic changes but in a user-critical conversion path and could
affect when errors/continue button appear.
> 
> **Overview**
> Prevents the Buy amount input screen from briefly showing the generic
*no quotes* error by updating `BuildQuote` to **normalize provider IDs**
(handling `/providers/...` vs short codes) and to **search all returned
quotes** via `.find()` when deriving `selectedQuote`.
> 
> Tightens `useRampsPaymentMethods` loading behavior so `isLoading`
stays true while auto-selecting a payment method when the previously
selected method is no longer present, avoiding UI flashes of stale
selection. Adds targeted tests covering provider-ID matching scenarios,
empty/mismatched quote responses, continue-button disabled state, and
the stale-selection loading fallback.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2d4d9d7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…saction confirmation (#28040)

## Summary
- Fixes a race condition in `Toast.showToast` where rapid successive
calls (e.g., transaction approved + confirmed in the same tick on Linea)
cause the success toast to persist indefinitely
- Tracks pending `setTimeout` with a ref so only the latest `showToast`
call wins, ensuring the success toast renders with its proper
auto-dismiss animation
- Adds test coverage for the rapid successive `showToast` scenario


https://github.com/user-attachments/assets/12064e1e-3beb-4d36-82e3-3237b2045eb6

## Test plan
- [x] Toast unit tests pass (`yarn jest
app/component-library/components/Toast/Toast.test.tsx`)
- [x] Manual: trigger a Max DAI→mUSD conversion on Linea and verify the
success toast auto-dismisses after ~3s
- [x] Verify normal (non-rapid) toast transitions still work correctly

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches toast display timing/animation logic; small but could regress
toast sequencing or dismissal behavior if timer clearing interacts with
existing transitions.
> 
> **Overview**
> Fixes a race in `Toast.showToast` where back-to-back calls could leave
multiple queued `setTimeout` updates, causing the wrong toast
state/timeout behavior (e.g., a success toast persisting).
> 
> `Toast` now tracks and clears any pending `setTimeout` via a ref so
only the latest `showToast` call applies. Adds a unit test asserting
rapid successive calls leave a single pending timer and only the latest
toast renders.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
111df6d. 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?
-->
Bringing the following changes to the client:

```markdown
## [1.25.2]

### Fixed

- Relax Trongrid `internal_transactions` validation to avoid sync failures on sparse legacy payloads ([#289](MetaMask/snap-tron-wallet#289))
- Handle TRC10 token identifiers correctly in the current Trongrid account-history transaction flow, without mis-parsing endpoint-specific `asset_name` formats ([#289](MetaMask/snap-tron-wallet#289))
- Decouple assets and transactions synchronization so one failure does not prevent the other from completing ([#289](MetaMask/snap-tron-wallet#289))
```

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

n/a

## **Manual testing steps**

n/a

## **Screenshots/Recordings**

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

### **Before**

n/a

### **After**

n/a

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk dependency bump confined to the Tron snap package; behavior
changes are limited to Tron sync handling and should not affect
unrelated wallet flows.
> 
> **Overview**
> Bumps `@metamask/tron-wallet-snap` from `^1.25.1` to `^1.25.2`,
updating both `package.json` and `yarn.lock` resolution/checksum.
> 
> This pulls in upstream fixes around Tron sync robustness (more
permissive Trongrid `internal_transactions` validation, correct TRC10
token identifier handling, and separating asset vs transaction sync so
one failure doesn’t block the other).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
235931c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…nd update result properties (#28645)

## **Description**

Rename `initModularizedControllers` to `initMessengerClients`, drop
`existingControllersByName`, rename `controllerInitFunctions` to
`initFunctions`, and update return type to `messengerClientsByName`.
Update all consumers in `Engine.ts`, `utils.test.ts`, and test utility
functions.

80 files changed. **PR 3 of 4** — depends on PR 2 (#28641).
- ~~PR 1: Core type renames (`Controller` → `MessengerClient`, etc.)
(#28610)~~
- ~~PR 2: `CONTROLLER_MESSENGERS` → `MESSENGER_FACTORIES` (#28641)~~
- **PR 3 (this):** `initModularizedControllers` → `initMessengerClients`
+ utils/Engine.ts renames
- PR 4: Property renames (`controller` → `messengerClient`,
`getController` → `getMessengerClient`) in all init files + tests

Relates to
[WPC-916](https://consensyssoftware.atlassian.net/browse/WPC-916).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/WPC-916

## **Manual testing steps**

```gherkin
Feature: Messenger client init system

  Scenario: App builds and runs normally
    Given the app is built from this branch

    When user opens the app
    Then the app behaves identically to main (no runtime behavior change)
```

## **Screenshots/Recordings**

N/A — no UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

[WPC-916]:
https://consensyssoftware.atlassian.net/browse/WPC-916?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Refactors the Engine’s initialization wiring for all
controller/messenger clients, so mistakes could break startup order or
dependency resolution despite being a rename-focused change.
> 
> **Overview**
> **Renames and reshapes the Engine init helper** by replacing
`initModularizedControllers` with `initMessengerClients`, renaming
`controllerInitFunctions` to `initFunctions`, and returning
`messengerClientsByName`.
> 
> **Simplifies initialization state** by dropping support for
`existingControllersByName` and updating the dependency lookup
helper/error messaging to `getMessengerClientOrThrow`.
> 
> Updates `Engine.ts` wiring and a large set of controller init tests to
use the new request mock helper (`buildMessengerClientInitRequestMock`)
and the new result property names.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
80bf6e1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/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 polishes the Money feature so the patterns for Headers, List,
Sections, Filtering and Spacing are visually cohesive.

## **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: Money account activity and hub layout polish

  Scenario: User opens Money activity from the Money hub
    Given the user is logged in with a Money account that can show activity
    And the user is on the Money hub (home) screen

    When the user navigates to Money activity (Activity)
    Then the activity screen loads with the expected header and back affordance
    And activity is grouped and readable (date sections and list items render without layout overlap)

  Scenario: User filters Money activity by type
    Given the user is on the Money activity screen
    And there is activity data available for more than one filter category

    When the user changes the activity filter (e.g. All / Deposits / Transfers as applicable)
    Then the list updates to match the selected filter
    And section headers and row content remain correctly aligned and legible

  Scenario: User reviews Money hub summary and quick actions after layout updates
    Given the user is on the Money hub (home) screen

    When the user views the balance summary and the primary action buttons row
    Then balances and labels use the updated typography and spacing (no clipped text or misaligned controls)
    And primary actions remain tappable with expected labels and icons
```

## **Screenshots/Recordings**

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

### **Before**

<img width="1462" height="680" alt="Screenshot 2026-04-13 at 4 30 22 PM"
src="https://github.com/user-attachments/assets/38255e3a-a6c7-4ada-9a5b-7a0b5406eba0"
/>



### **After**

<img width="1442" height="643" alt="Screenshot 2026-04-13 at 4 30 37 PM"
src="https://github.com/user-attachments/assets/5bf37578-baf5-4b7f-8391-2a9611bb11c1"
/>




## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk visual-only tweaks to layout, spacing, and typography within
Money screens; main risk is minor UI regressions like
truncation/clipping on edge device sizes.
> 
> **Overview**
> Improves visual cohesion across Money hub and activity screens by
adjusting padding/spacing, alignment, and typography in headers, section
headers, lists, and filter buttons.
> 
> Updates action buttons and activity rows to better handle sizing and
truncation (larger icons/avatars, centered/stretch layouts,
`min-w-0`/`shrink` Tailwind classes), and lightly refines secondary text
weights and button container padding for consistency.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5ae2126. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Feature Flag Registry Drift Report

Feature flag drift was detected between E2E tests and production.

Download the [`drift-report`
artifact](https://github.com/MetaMask/metamask-mobile/actions/runs/24060043070)
for the full report.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Priya <priya.narayanaswamy@consensys.net>
## **Description**

New: Campaign Stats Screen

A dedicated screen showing the user's personal performance in the
campaign — their current return (positive in green, negative in red),
total portfolio value, rank, tier (Bronze, Silver, Platinum), net
deposit amount, days held, and whether they're Qualified or Pending.

New: Tier-based Leaderboard

The leaderboard now lets users filter by tier (Bronze, Silver,
Platinum). Each entry shows rank, referral code, and return percentage.
Users see their own position highlighted, plus a count of total
participants in that tier.

New: "Qualify for this rank" & "You're qualified" cards

- If a user is pending, they see a card telling them exactly how much
more they need to deposit and how many more days to hold to qualify.
- Once they meet the requirements, the card flips to "You're qualified."

New: After-Hours Trading popup

When a user tries to swap an asset outside market hours, a popup appears
explaining that trading is closed, shows a countdown to when markets
reopen, and warns about wider price spreads.

New: Eligibility warning popup

If there aren't enough days left in the campaign to meet the holding
requirement, a warning popup tells the user their new position won't
count toward the campaign, with options to cancel or proceed anyway.

New: "Entries closed" state

If the campaign has ended and the user never opted in, the join button
is locked and shows "Entries closed." Tapping it shows a message
explaining they missed the opt-in window.

Updated: Portfolio section

Now shows each deposited asset with its current value, shares owned, and
profit/loss percentage. Users can tap a position to swap it for a
different asset, or tap a link to view their full activity history.

Updated: Prize pool display

Shows the current prize pool size and how much additional volume is
needed to unlock the next reward tier.

## **Changelog**


CHANGELOG entry: ondo campaign rewards - stats page

## **Screenshots/Recordings**

- Active Campaign

- Opted in

Negative return but qualified

<img width="952" height="1763" alt="negative-qualified"
src="https://github.com/user-attachments/assets/0e27784a-f5ce-4033-b338-e2916a259427"
/>

<img width="952" height="1763" alt="negative-qualified-2"
src="https://github.com/user-attachments/assets/d07d0535-b2a1-4603-b4b4-4be694dc33c7"
/>

Positive return but pending

<img width="1025" height="1799" alt="positive-pending-1"
src="https://github.com/user-attachments/assets/b4e231a0-a0af-45db-90a8-572551c8322d"
/>

<img width="1025" height="1799"
alt="positive-pendin-2-leaderboard-bottom-20"
src="https://github.com/user-attachments/assets/14e37219-9605-466b-b788-507527fce233"
/>

Leaderboard top 5 (in others its 18th position)

<img width="943" height="539" alt="leaderboard-top-5"
src="https://github.com/user-attachments/assets/55c98e89-0c94-494d-882b-b02516ef6731"
/>

Prize pool variants

<img width="962" height="324" alt="prize-pool-fully-reached"
src="https://github.com/user-attachments/assets/c154f79a-723b-4fa8-ba9b-5885b3fd541b"
/>

<img width="962" height="324" alt="prize-pool-unlock"
src="https://github.com/user-attachments/assets/da6f91f0-d12c-4654-a87d-680412769d4d"
/>

Leaderboard page (positive return pending)

<img width="1025" height="1799" alt="positive-pending"
src="https://github.com/user-attachments/assets/636d6806-c6ee-4635-bd07-6e2761919db0"
/>

Stats page positive but pending

<img width="952" height="1763" alt="positive-pending"
src="https://github.com/user-attachments/assets/6d5c8d1f-e519-47b6-9b43-e26a4df7c8dc"
/>

Stats page positive & qualified 

<img width="951" height="1830" alt="positive-qualified-complete"
src="https://github.com/user-attachments/assets/570f8f11-1d4e-415f-ab48-a0e70a747b47"
/>

Stats page but negative return and cashed out

<img width="952" height="1763" alt="negative-qualified-cashed-out"
src="https://github.com/user-attachments/assets/9298e079-30ff-4625-8ac1-eec3890df4fb"
/>

Open position or swap position but outside of market hours

<img width="957" height="845" alt="open-position-market-hours"
src="https://github.com/user-attachments/assets/52accff5-3d36-4e0b-af50-a2062fb58b78"
/>

Open position but can't qualify for tier treshold  anymore

<img width="1156" height="701" alt="not eligible"
src="https://github.com/user-attachments/assets/b67d484a-0977-4d63-bec5-f4f414273ca4"
/>

- Not Opted in

<img width="916" height="1813" alt="Screenshot from 2026-04-13 15-32-09"
src="https://github.com/user-attachments/assets/afc04260-729d-4867-bdd8-7caad4db9527"
/>

<img width="916" height="1813" alt="Screenshot from 2026-04-13 15-32-12"
src="https://github.com/user-attachments/assets/12cb1a91-c999-4f38-b535-e8aa8a6b6c4a"
/>




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new rewards navigation routes, screens, and bottom sheets with
updated Ondo campaign eligibility/pending logic and new `minDeposit`
data plumbing; mistakes could impact campaign UX and leaderboard/stats
rendering but do not touch security-critical flows.
> 
> **Overview**
> Introduces a dedicated **Ondo campaign Stats** screen
(`RewardsOndoCampaignStats`) and wires it into the rewards navigator,
including navigation from the campaign details stats header.
> 
> Adds new bottom sheets for **Pending** (`RewardsOndoPendingSheet`),
**After-hours trading** (`OndoAfterHoursSheet`), and **Not eligible**
(`OndoNotEligibleSheet`), and updates campaign details/portfolio/CTA
flows to gate swaps/position actions when the user can no longer meet
the `ONDO_GM_REQUIRED_QUALIFIED_DAYS` requirement.
> 
> Extends Ondo leaderboard tier data with `minDeposit` and updates
`OndoLeaderboard`/`CampaignStatsSummary` to show qualify messaging, open
the pending sheet from pending tags/cards, unify stats error handling,
and tweak prize pool/max-tier copy and various UI text/icon styles
(including ET→EST strings).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a7be45e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: sophieqgu <sophieqgu@gmail.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This branch finishes the Card Home migration to `CardController` and
fixes the behavior regressions introduced while moving card auth,
cardholder state, wallet data, and spending-limit flows away from the
old SDK/React Query orchestration.

The motivation for the change was to make `CardController` the source of
truth for Card state, instead of splitting responsibility across the
Redux `card` slice, SDK helpers, and deleted React Query hooks like
`useLoadCardData` / `useGetCardExternalWalletDetails`.

Key changes in this branch:

- **Card authentication and session state now come from
`CardController`**
  - `CardAuthentication` uses `useCardAuth`.
- UI now reads controller-backed selectors such as
`selectIsCardAuthenticated`, `selectIsCardholder`,
`selectCardholderAccounts`, and `selectCardUserLocation`.
- Logout and session validation are handled through
`Engine.context.CardController`.
  - Legacy auth verification helpers and side-effect flows were removed.

- **Card Home was migrated to controller-backed data and split into
smaller hooks/components**
- `CardHome.tsx` was refactored heavily into focused components and
hooks like `useCardHomeActions`, `useCardHomeAnalytics`, and
`useCardProvisioning`.
- Snapshot-based tests touched by this work were removed in favor of
explicit assertions.

- **Push provisioning was aligned with the new controller/provider
architecture**
  - Provisioning eligibility was moved into the provider layer.
- The old Galileo-specific adapter path was removed in favor of the
controller adapter.
- US-only provisioning restrictions and provider-specific feature-flag
behavior were preserved.

- **Unauthenticated cardholder UX was added**
- Cardholders who are not authenticated now see teaser actions on Card
Home instead of a blocking login-required warning.
  - Teaser actions route to Card authentication.
- Card authentication now shows an informational auth prompt banner for
those entry points.
- Terms and Conditions / Contact support remain visible in that state
while Logout stays hidden.

- **Spending Limit / delegation flows broken by the migration were
restored**
- Card Home now passes the full spending-limit payload again
(`priorityToken`, `allTokens`, `delegationSettings`,
`externalWalletDetailsData`) instead of only `{ flow }`.
  - `CardHomeData` now carries `delegationSettings`.
- Supported tokens are enriched with `delegationContract`, which fixes
the `"Missing token configuration"` delegation failure.
- Spending Limit can pre-select the priority asset again and the token
picker no longer stalls on an infinite spinner.
- After successful delegation, `useSpendingLimit` now calls
`CardController.fetchCardHomeData()` so the updated
wallet/priority-token state appears automatically without requiring a
manual refresh.

- **Additional follow-up fixes and test coverage**
- Added/updated controller, provider, Card Home, Spending Limit,
provisioning, authentication, and utility tests.
- Replaced touched card snapshot tests with explicit assertions where
applicable.

## **Changelog**

CHANGELOG entry: Fixed MetaMask Card authentication, unauthenticated
cardholder actions, and spending limit/delegation refresh flows after
the CardController migration.

## **Related issues**

Fixes:

<!-- Add issue links if applicable -->

## **Manual testing steps**

```gherkin
Feature: Card controller migration and follow-up flow fixes

  Background:
    Given I have a build from this branch
    And I have access to a MetaMask Card test account

  Scenario: Card authentication uses controller-backed session state
    Given I am logged out of Card
    When I open Card and log in with a valid account
    Then Card Home should load successfully
    And authentication state should be preserved by CardController

    When I log out from Card
    Then CardController should clear the card session
    And I should return to the logged-out Card state

  Scenario: Unauthenticated cardholder sees teaser actions and auth prompt
    Given I am a cardholder but I am not currently authenticated
    When I open Card Home
    Then I should see teaser actions for card management
    And I should see Terms and Conditions and Contact support
    And I should not see Logout

    When I tap Manage limit
    Then the Card authentication screen should open
    And I should see the informational auth prompt banner

  Scenario: Spending Limit opens with delegation-ready token data
    Given I am authenticated on Card Home
    And I have supported card assets available
    When I tap Manage limit
    Then the Spending Limit screen should open
    And the priority asset should be pre-selected

    When I open the Token selector
    Then the asset list should load without an infinite spinner

  Scenario: Delegation refreshes Card Home automatically
    Given I am authenticated on Card Home
    And I open Spending Limit for a token that is not yet enabled
    When I complete delegation successfully
    Then I should return to Card Home
    And the token list and current priority token should refresh automatically
    And I should not need to pull to refresh manually

  Scenario: Push provisioning still respects provider/controller rules
    Given I am authenticated on Card Home with a supported eligible card
    When I review add-to-wallet availability
    Then provisioning eligibility should reflect the provider response
    And provider-specific feature flags should still be respected
```

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Large refactor of `CardHome` data-flow and interaction handlers to
rely on `CardController`/new hooks, plus navigation/auth gating changes;
regressions are possible in card setup, spending-limit, and sensitive
actions (PIN/details/freeze). Mostly UI-layer changes but they touch
session/logout behavior and several user flows.
> 
> **Overview**
> **Card Home is migrated to controller-backed state and decomposed into
smaller units.** `CardHome` now renders from `useCardHomeData()` and
`CardController` selectors/capabilities, with UI split into components
like `CardAlertSection`, `CardActionsButtons`, `CardImageSection`,
`CardBalanceDisplay`, `ManageCardOptions`, and `CardHomeFooter`, plus
extracted hooks for actions/analytics/provisioning.
> 
> **Unauthenticated cardholder UX is changed from “blocked” to “teaser”
actions.** Manage options (view details/PIN, freeze toggle, cashback,
travel, manage card, etc.) can appear while unauthenticated but now
route to `Routes.CARD.AUTHENTICATION` with `showAuthPrompt: true`;
logout stays hidden.
> 
> **Auth + location handling is adjusted in `CardAuthentication`.** The
screen reads `showAuthPrompt` from route params to show a new info
banner (`CardMessageBoxType.AuthPrompt`), and location selection is now
local state (`selectedLocation`) used during login rather than
immediately calling `CardController.setUserLocation`.
> 
> **Behavioral/test updates.** Tests are updated to mock `useRoute`,
validate new teaser/navigation behavior, switch `CardHome` tests to
`useCardHomeData`, align freeze with separate `freeze/unfreeze`
mutations, update spending-limit copy expectations, and tighten
analytics expectations (don’t emit without a formatted balance).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3baa77b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/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 change **bumps the build version once** in a dedicated job that
calls **`update-latest-build-version.yml`**, then triggers **iOS and
Android** through **`runway-ota-build-core`** in **parallel**. Both jobs
use **`skip_version_bump: true`** and **`source_branch`** set to the
**version-bump commit SHA** so both builds use the same tree. Downstream
steps (PR comment + Slack) now require **both** platform jobs to
succeed.

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-521

## **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.
…2-digits' of github.com:MetaMask/metamask-mobile into wsun/modify-release-pr-creation-workflow-to-accomadate-2-digits
@github-actions
Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Apr 13, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - draft PR

All E2E tests pre-selected.

View GitHub Actions results

@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​metamask/​assets-controller@​2.4.0 ⏵ 3.3.07010080 +197 +2100
Updatednpm/​@​metamask/​snaps-controllers@​18.0.4 ⏵ 19.0.071 +110076 +198 +150
Updatednpm/​@​metamask/​assets-controllers@​101.0.1 ⏵ 103.1.172 +110091 +199100
Addednpm/​@​metamask/​react-data-query@​0.2.0721007392100
Updatednpm/​@​metamask/​keyring-internal-api@​10.0.0 ⏵ 10.0.11001007394 +2100
Addednpm/​@​metamask/​eth-money-keyring@​2.0.0731008191100
Updatednpm/​@​metamask/​logging-controller@​8.0.0 ⏵ 8.0.11001007394 +2100
Addednpm/​@​metamask/​money-account-controller@​0.1.0741007389100
Updatednpm/​@​metamask/​base-controller@​9.0.0 ⏵ 9.0.1100 +11007393 +6100
Updatednpm/​@​metamask/​address-book-controller@​7.1.0 ⏵ 7.1.11001007394 +2100
Updatednpm/​@​metamask/​compliance-controller@​1.0.1 ⏵ 2.0.0741009593 +2100
Addednpm/​@​metamask/​social-controllers@​0.1.0741007589100
Updatednpm/​@​metamask/​multichain-transactions-controller@​7.0.2 ⏵ 7.0.4981007497 +1100
Addednpm/​@​metamask/​keyring-sdk@​1.1.0751008592100
Updatednpm/​@​react-navigation/​bottom-tabs@​5.11.11 ⏵ 6.6.1991007599100
Updatednpm/​@​metamask/​keyring-snap-client@​8.2.0 ⏵ 8.2.1991007594 +3100
Updatednpm/​@​react-navigation/​native@​5.9.4 ⏵ 6.1.189910075 +199 -1100
Updatednpm/​@​metamask/​preferences-controller@​23.0.0 ⏵ 23.1.010010075 +196 +2100
Addednpm/​@​metamask/​hw-wallet-sdk@​0.7.0831007695100
Updatednpm/​@​metamask/​approval-controller@​9.0.0 ⏵ 9.0.11001007693 +2100
Updatednpm/​@​metamask/​snaps-utils@​11.7.1 ⏵ 12.1.29810076 +197 +2100
Updatednpm/​@​metamask/​gas-fee-controller@​26.1.0 ⏵ 26.1.1991007693 +1100
Updatednpm/​@​metamask/​remote-feature-flag-controller@​4.1.0 ⏵ 4.2.09910076 +194 +1100
Updatednpm/​@​metamask/​multichain-network-controller@​3.0.5 ⏵ 3.0.6981007697100
Updatednpm/​@​metamask/​snaps-rpc-methods@​15.0.0 ⏵ 15.0.1981007694 -150
Updatednpm/​@​react-navigation/​stack@​5.14.9 ⏵ 6.4.198 +110077100100
Updatednpm/​@​metamask/​accounts-controller@​37.0.0 ⏵ 37.2.09810077 +198 +1100
Updatednpm/​@​metamask/​controller-utils@​11.19.0 ⏵ 11.20.09710077 +194 +3100
Updatednpm/​@​metamask/​snaps-execution-environments@​11.0.1 ⏵ 11.0.299 +110077 +197 +180
Updatednpm/​@​metamask/​messenger@​0.3.0 ⏵ 1.1.19910078 +294100
Updatednpm/​@​metamask/​keyring-controller@​25.1.0 ⏵ 25.2.098 +110078 +196 +2100
Updatednpm/​@​metamask/​signature-controller@​39.1.0 ⏵ 39.1.2981007898 +1100
See 28 more rows in the dashboard

View full report

@socket-security
Copy link
Copy Markdown

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Block High
Obfuscated code: npm @metamask/snaps-controllers is 98.0% likely obfuscated

Confidence: 0.98

Location: Package overview

From: package.jsonnpm/@metamask/snaps-controllers@19.0.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/snaps-controllers@19.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: npm @metamask/solana-wallet-snap is 91.0% likely obfuscated

Confidence: 0.91

Location: Package overview

From: package.jsonnpm/@metamask/solana-wallet-snap@2.8.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/solana-wallet-snap@2.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/base-data-service in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/react-data-query@0.2.0npm/@metamask/social-controllers@0.1.0npm/@metamask/base-data-service@0.1.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/base-data-service@0.1.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/social-controllers in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/social-controllers@0.1.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/social-controllers@0.1.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm @metamask/transaction-controller is 100.0% likely to have a medium risk anomaly

Notes: The code performs straightforward signature verification using ethers.js, returning true when the recovered signer matches the provided publicKey. While generally safe, the silent catch and potential mismatch between data formatting and signing process should be addressed to avoid silent failures. Overall, a benign utility with moderate input-format sensitivity.

Confidence: 1.00

Severity: 0.60

From: ?npm/@metamask/eip-5792-middleware@2.0.0npm/@metamask/transaction-controller@61.3.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/transaction-controller@61.3.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm jiti is 100.0% likely to have a medium risk anomaly

Notes: The fragment implements a sophisticated on-the-fly loader using JITI for transpilation and execution, with careful handling of JSON interop based on nearby package.json type. There is no explicit malicious behavior identified (no external network activity, no hardcoded secrets). However, the dynamic code execution path introduced by _wrapSource and the synthetic module environment represents a potential risk vector if untrusted inputs are loaded, or if jiti/mjs execution context could be manipulated. This warrants strict review of the loader environment, the version and security of JITI, and checks on the sources being loaded to mitigate potential code execution or supply chain concerns.

Confidence: 1.00

Severity: 0.60

From: ?npm/webdriverio@9.27.0npm/jiti@2.6.1

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jiti@2.6.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
75.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@weitingsun weitingsun closed this Apr 14, 2026
@weitingsun weitingsun deleted the release/7.80.20 branch April 14, 2026 00:00
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size-XL team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.