Skip to content

[pull] main from MetaMask:main#644

Merged
pull[bot] merged 18 commits intoReality2byte:mainfrom
MetaMask:main
Mar 31, 2026
Merged

[pull] main from MetaMask:main#644
pull[bot] merged 18 commits intoReality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Mar 31, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

asalsys and others added 18 commits March 31, 2026 17:47
… ModalSwitchAccountType (#28118)

## **Description**

Migrate `DetectedTokensConfirmation` and `SwitchAccountTypeModal` from
prop-based route access to `useRoute()` hook, removing their `as
ScreenComponent` casts in App.tsx.

Part of the React Navigation v6 migration effort to remove
`no-explicit-any` violations (PR 4 of 13).

**Changes:**
- **`DetectedTokensConfirmation`**: Switch to `useRoute()` with typed
generic
- **`SwitchAccountTypeModal`**: Switch to `useRoute()`, remove dead
Props interfaces
- **`App.tsx`**: Remove 2 `as ScreenComponent` casts
- **Tests**: Update SwitchAccountTypeModal tests to mock `useRoute()`

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring with no user-facing 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.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk refactor limited to React Navigation route-param wiring and
associated test mocks, with no intended behavior change beyond potential
runtime issues if route params are missing/mistyped.
> 
> **Overview**
> Refactors `DetectedTokensConfirmation` and `SwitchAccountTypeModal` to
read route params via `useRoute()` with explicit `RouteProp` typing,
removing the prop-based `route` interfaces.
> 
> Updates the `App.tsx` stack registration to stop casting
`DetectedTokensConfirmation` as a generic `ScreenComponent`, and adjusts
`SwitchAccountTypeModal` tests to mock `useRoute()` instead of passing a
`route` prop.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
632422d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fix cancel and speed-up so users don’t confirm before the transaction’s
gas state is ready, and so suggested fees align with network conditions
when the medium estimate clearly beats a small % bump.

**What was wrong**  
Confirm could run before `previousGas` was stored and before bumped gas
was applied, which led to inconsistent or premature submissions. Bump
logic also didn’t always prefer the network “medium” estimate when it
was well above the user’s current fee.

**What we changed**  
- Persist **original gas** via `updatePreviousGasParams`, then apply
**bump** via `updateTransactionGasFees` with `gasValues` +
`userFeeLevel`.
- Expose **`isInitialGasReady`** from `useCancelSpeedupGas` and
**disable Confirm** until gas is initialized (`previousGas` set).
- **`getBumpParamsForCancelSpeedup`** now returns `{ gasValues,
userFeeLevel }`, uses **medium market estimates** when `medium > current
fee + 10%`, otherwise **CANCEL_RATE / SPEED_UP_RATE** bumps.
- Centralize estimate parsing/comparison in
**`app/util/confirmation/gas.ts`** (e.g. medium max/priority extraction,
`gasEstimateGreaterThanGasUsedPlusTenPercent`).
- Wire **`updatePreviousGasParams`** through the transaction-controller
util and add tests.

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

## **Changelog**

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

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

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

CHANGELOG entry: Fixed cancel/speedup initial gas is readiness

## **Related issues**

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

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

On Base if send gas too low tx will fail even without use cancel and
speed up.


https://github.com/user-attachments/assets/c0b6569a-0bdf-482f-8aa6-7c39bded0016


Ethereum Mainnet


[eth-send-cancel.webm](https://github.com/user-attachments/assets/b9b1dcc3-b11f-4daf-9faa-4b798b3cf9fb)


<!-- 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**
> Changes replacement transaction gas calculation and when
cancel/speed-up confirmations can proceed, which could affect whether
transactions are mined or fail under certain network conditions. Scope
is moderate and covered by new unit tests, but it touches core
transaction-fee behavior.
> 
> **Overview**
> **Cancel/speed-up flows now persist and rely on `previousGas` before
allowing confirmation.** The `CancelSpeedupModal` disables *Confirm*
until `useCancelSpeedupGas` reports `isInitialGasReady`, preventing
users from submitting replacement transactions before initial gas state
is seeded.
> 
> **Replacement fee calculation has been centralized and hardened.** New
helpers in `util/confirmation/gas` parse “medium” estimates across
shapes, compare market estimates vs *current +10%*, and clamp
user-selected replacement gas via `getGasValuesForReplacement` to ensure
it is at least `previousGas × rate` (legacy and EIP-1559).
`Transactions` and `useUnifiedTxActions` now apply this clamping using
`getPreviousGasFromController`, and the transaction-controller util adds
`updatePreviousGasParams` plus a `getPreviousGasFromController` reader.
> 
> **Tests updated/added** to cover readiness gating, market-estimate
bump selection, and clamping behavior for cancel/speed-up across legacy
and EIP-1559 paths.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5de5e7a. 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**
In OTA workflow, we are adding platform to the display so we are clear
which platform we are pushing it to

## **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]
> **Low Risk**
> Low risk: only changes workflow summary output formatting and does not
affect build/publish logic or secrets handling.
> 
> **Overview**
> The `push-eas-update` GitHub Actions workflow now includes the
selected OTA **platform** (`OTA_PUSH_PLATFORM`) in the rendered **OTA
Update Summary** table in `$GITHUB_STEP_SUMMARY`, making it clearer
whether the update targets `all`, `ios`, or `android`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9c6b584. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Adds UEFA Champions League (UCL) soccer support to the Predict product.
Unlike NFL/NBA where one team always wins, soccer matches can end in a
draw. This introduces 3-way market support throughout the prediction
flow — from data parsing to UI rendering.

**Key changes:**
- New `ucl` league type with home-first team ordering (opposite of
NFL/NBA)
- Draw button (gray/muted theme) rendered between team buttons for
soccer matches
- Polymarket negRisk 3-outcome events parsed into 3 `PredictOutcome`s
sorted by `groupItemThreshold`
- Game chart generalized from hardcoded 2-series to N-series (3rd line
for draw)
- Scoreboard respects home-first ordering for soccer leagues
- Position labels resolved from slug-based team lookup via TeamsCache
(zero network overhead)
- Token titles enriched at parse time for negRisk moneyline markets

## **Changelog**

CHANGELOG entry: Added UCL soccer league support with 3-way draw
predictions

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-755

## **Manual testing steps**

```gherkin
Feature: UCL soccer predictions with draw button

  Scenario: user views a UCL match card in the feed
    Given the UCL league is enabled in the feature flag
    And a UCL match event exists on Polymarket

    When user views the Predict feed
    Then a sport card renders with the UCL match
    And the scoreboard shows home team on the left, away team on the right
    And three action buttons appear: Home | DRAW (gray) | Away

  Scenario: user places a draw prediction
    Given user is viewing a UCL match card

    When user taps the DRAW button
    Then the buy preview opens with the draw outcome
    And after purchase, the position shows "$x on Draw"

  Scenario: user views the game chart for a UCL match
    Given user opens a UCL match detail page

    When user views the price chart
    Then three lines are rendered: Home (team color), Draw (gray), Away (team color)
    And all three endpoint labels are visible

  Scenario: user views existing UCL positions on a card
    Given user has positions on a UCL match

    When user views the sport card
    Then positions show "$x on Team Name" (not "$x on Yes to win")
    And long team names are truncated with ellipsis
```

## **Screenshots/Recordings**

### **Before ** 

N/A — UCL soccer was not previously supported

### **After**

Before vs After screenshots:


<img width="871" height="876" alt="Screenshot 2026-03-30 at 2 05 17 PM"
src="https://github.com/user-attachments/assets/19b07205-b24c-48b4-95ee-e84a29963cef"
/>

<img width="891" height="880" alt="Screenshot 2026-03-30 at 2 03 48 PM"
src="https://github.com/user-attachments/assets/aacc883c-b477-42f0-a54b-58bfa37c0ade"
/>
<img width="881" height="879" alt="Screenshot 2026-03-30 at 2 04 25 PM"
src="https://github.com/user-attachments/assets/fd26d148-dc39-4929-b9fb-e33580387bbb"
/>



## **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 expands core Predict flows (market parsing,
outcome/token selection, live price subscriptions, and chart rendering)
from 2-way to 3-way outcomes, which could cause mismatched outcome/token
mapping or incomplete data rendering if backend data is inconsistent.
> 
> **Overview**
> Adds **3-way (home/draw/away) support** for draw-capable leagues (now
including `ucl`), with a new `isDrawCapableLeague` helper and
`groupItemThreshold` ordering used to consistently sort outcomes/tokens.
> 
> Updates the prediction UI to render an optional **DRAW** bet button
(new `draw` variant + testIDs), split bet button label/price into
separate lines, and ensures bet/preview navigation selects the
**matching outcome** for the tapped token (in `PredictMarketDetails` and
`PredictSportCardFooter`).
> 
> Generalizes game visuals for soccer: `PredictGameChart` now supports
**N-series** (incl. draw line with muted color) and improves endpoint
label collision handling for 3+ labels; the scoreboard and footer copy
adapt to **home-first** leagues.
> 
> Enhances Polymarket integration by adding `ucl` slug parsing
(home-away order), surfacing `groupItemThreshold` on outcomes, improving
negRisk token titles (e.g., “Draw”), and resolving negRisk position
outcome labels from `eventSlug`/slug with optional team lookup.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
024cc19. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…uy-with-any-token issues (#28167)

<!--
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 fixes several issues with the Predict buy flow when using the
pay-with-any-token feature:

1. Order state persists across navigation — When a user places a
deposit-and-order bet and navigates away, the active order state
(DEPOSITING, PLACING_ORDER) is preserved instead of being cleared. This
prevents users from placing concurrent orders and ensures the UI
reflects ongoing background bets when re-entering any buy screen.
2. Per-address active orders — Renamed activeBuyOrder (singular) to
activeBuyOrders (address-keyed map), matching the pattern used by
pendingDeposits and pendingClaims. Each account has its own independent
order lifecycle. The selector resolves the current account address to
read the correct entry.
3. Foreground vs background error notifications — Order failure toasts
are now gated by transactionId matching: foreground errors are shown
inline on the buy screen (no toast), while background errors (user
navigated away) trigger toast notifications. The transactionId is
cleared on navigation back via clearActiveOrderTransactionId() so
subsequent background failures are correctly identified. Success toasts
always fire.
4. Deposit failure recovery — Deposit failures now reset to
PAY_WITH_ANY_TOKEN (was PREVIEW), keeping the external token selected so
the user can retry without re-selecting.
5. Minor fixes — Removed debug code left in placeOrder, removed buttons
from background toasts, fixed error message blinking during order
preview auto-refresh, and updated the README to reflect all changes.

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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes Predict buy order state management and transaction side-effect
handling, which can affect in-flight deposit-and-order flows and user
notifications across navigation/account switches.
> 
> **Overview**
> **Refactors Predict buy order lifecycle state** from a single
`activeBuyOrder` to an address-keyed `activeBuyOrders` map, updating
selectors/hooks/tests so each account tracks its own in-flight order and
state persists across navigation.
> 
> **Adjusts pay-with-any-token order completion and notifications**:
order success always publishes
`PredictController:transactionStatusChanged` confirmed events; failures
only publish toast-triggering events when the `transactionId` no longer
matches the active order (background), while foreground failures remain
inline. Deposit-and-order failures now reset back to
`PAY_WITH_ANY_TOKEN` (keeping the external token flow) and rejection
resets the active order to `PREVIEW` while clearing
`transactionId`/selected token as needed.
> 
> **Updates buy screen behavior**: on screen mount it resets to Predict
balance then initializes `initPayWithAnyToken()`, back navigation now
clears only the active order `transactionId` (via
`clearActiveOrderTransactionId`) instead of clearing the order, and
SUCCESS resets via `onPlaceOrderSuccess()` with navigation pop only if
the current screen initiated the order.
> 
> **Fixes preview UX and toasts**: `usePredictOrderPreview` now uses a
sticky error to prevent error flicker during auto-refresh and clears on
success/size change, and Predict order toasts remove market-based
View/Try Again buttons.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7f2f9e5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **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 staking routes used `type ScreenComponent =
React.ComponentType<any>` with `// eslint-disable-next-line
@typescript-eslint/no-explicit-any` to work around React Navigation type
mismatches when screen components accepted route props directly. This PR
removes that escape hatch by migrating the affected components to use
the `useRoute()` hook with properly typed generics instead of receiving
`route` as a prop.

**Changes:**
- **`routes/index.tsx`**: Removed the `ScreenComponent` type alias and
all `as ScreenComponent` casts
- **`StakeConfirmationView`**: Switched from `({ route }:
StakeConfirmationViewProps)` to `useRoute<RouteProp<...>>()` hook
- **`UnstakeConfirmationView`**: Same migration to `useRoute()` hook
- **`GasImpactModal`**: Same migration to `useRoute()` hook
- **Type files**: Exported `RouteParams` interfaces for use by
`useRoute()` callers; removed dead `StakeConfirmationViewProps` and
`GasImpactModalProps` interfaces (kept `UnstakeConfirmationViewProps` as
it's still used by the confirmations module)
- **Tests**: Updated to mock `useRoute()` instead of passing route as a
component prop

## **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 — this is a pure refactoring with no user-facing behavior change.
Existing unit tests (3 suites, 11 tests) cover the affected components.

## **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 limited to React Navigation wiring and TypeScript
types; main risk is runtime issues if any of these components are
rendered without the expected route params.
> 
> **Overview**
> Refactors `StakeConfirmationView`, `UnstakeConfirmationView`, and
`GasImpactModal` to stop accepting `route` props and instead fetch
strongly-typed route params via `useRoute<RouteProp<...>>()`, reducing
the need for `any`-style screen component casts.
> 
> Updates associated `*.types.ts` to export `RouteParams` types (and
removes now-unused props types where applicable), and adjusts unit tests
to mock `useRoute()` rather than passing `route` props into the
components.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
550a9d6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ed providers (#27942)

<!--
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 updates provider-selection behavior for first-time UB2 users so
we do not lock them into an unsupported provider before they choose a
token.


- Tracks whether the current provider was auto-selected by the system or
chosen from a stronger signal like:
  - the most recent completed order
  - Transak being available as the preferred provider
- Updates provider selection so:
  - completed-order provider remains a strong selection
  - Transak remains a strong preferred selection when applicable
- fallback reliability-based selection is treated as a soft,
system-guessed selection
- Updates Build Quote behavior so that when a token is unsupported:
  - strong selections continue to show the "token not available" modal
- soft auto-selections can switch to a supporting provider instead of
immediately showing the modal
- Adds test coverage for:
  - preferred-provider selection metadata
  - provider auto-selection behavior
  - build-quote unsupported-token flows


Fresh-install UB2 users could land on a provider chosen only from
reliability ordering before selecting a token. If that provider did not
support the selected token, they could see a "token not available for
[provider]" modal for a provider they never explicitly chose.

This PR moves the flow closer to the agreed behavior by distinguishing
system guesses from real provider preference signals.


<!--
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: Updates how the ramp provider is selected

## **Related issues**

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

## **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 provider-selection and unsupported-token handling in the buy
flow, which can alter user navigation and provider choice; mitigated by
extensive new unit tests but still impacts a key conversion path.
> 
> **Overview**
> Improves ramp provider selection to avoid locking first-time users
into an unsupported provider: `determinePreferredProvider` no longer
falls back to the first provider without a strong signal, and provider
selections can now be marked as *auto-selected*.
> 
> `BuildQuote` now (1) auto-selects the first provider that supports the
currently selected token when no provider is selected, and (2) when a
token is unsupported, silently switches to another supporting provider
**only if** the current provider was auto-selected; otherwise it keeps
showing the existing “Token Not Available” modal.
> 
> Adds `providerAutoSelected` plumbing via a new selector
(`selectProviderAutoSelected`), updates `useRampsProviders` to forward
selection options to the controller, extends initial controller
state/log snapshots, bumps `@metamask/ramps-controller` to `^12.1.0`,
and adds/updates tests to cover the new auto-select/auto-switch
behaviors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
24f486e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Pedro Pablo Aste Kompen <wachunei@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**

Ui update the the Market Insights entry card.

<img width="347" height="146" alt="Screenshot 2026-03-31 at 15 02 44"
src="https://github.com/user-attachments/assets/1e2ad270-1fce-4678-83f2-69a598d28d39"
/>
<img width="370" height="302" alt="Screenshot 2026-03-31 at 15 54 56"
src="https://github.com/user-attachments/assets/984c5048-5ab4-4de4-ad82-3da49019b20d"
/>


## **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 UI-only change adding a new disclaimer modal and localized
strings, with tests covering the new open/close behavior.
> 
> **Overview**
> Adds an *info* affordance to the Market Insights entry card footer and
updates the footer copy to a shorter `AI generated` label.
> 
> Pressing the info icon now opens a new
`MarketInsightsDisclaimerBottomSheet` modal (design-system
`BottomSheet`) with localized title/body text and a "Got it" action to
dismiss.
> 
> Updates/extends tests to cover bottom sheet rendering/close behavior
and to assert the card toggles disclaimer visibility, plus adds a test
that the border animation key increments on carousel slide starts.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a5687e3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Migrate BlockExplorersModal from prop-based route access to `useRoute()`
hook with typed `RouteProp` generic, eliminating the `type
ScreenComponent = React.ComponentType<any>` escape hatch from Bridge
routes.

Part of the React Navigation v6 migration effort to remove
`no-explicit-any` violations from route files.

**Changes:**
- **`BlockExplorersModal.tsx`**: Switch from `(props:
BlockExplorersModalProps)` to `useRoute()` hook
- **`routes.tsx`**: Remove `ScreenComponent` type alias and `as
ScreenComponent` cast
- **`BlockExplorersModal.test.tsx`**: Mock `useRoute()` instead of
passing route as prop

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring with no user-facing behavior change. Existing
unit tests cover the affected component.

## **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 limited to how route params are accessed and how
tests set up navigation, with no expected behavioral changes beyond
potential runtime issues if the route params are absent/mis-typed.
> 
> **Overview**
> Refactors `BlockExplorersModal` to stop accepting a `route` prop and
instead pull `evmTxMeta`/`multiChainTx` from React Navigation via
`useRoute()` with a typed `RouteProp`.
> 
> Updates `BlockExplorersModal.test.tsx` to mock `useRoute()` and render
the modal without passing route props, keeping existing assertions
around explorer buttons and webview navigation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f2cc0ca. 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?
-->

Solve TapAndPay SDK CI/CD issue -- empty new lines at the end of the
string.

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes how the TapAndPay SDK SSH key is
materialized in CI; a formatting mistake could still break Android
builds or SSH auth, though the change is small and isolated.
> 
> **Overview**
> Fixes TapAndPay SDK cloning in `build.yml` by **sanitizing the
base64-decoded SSH key** (removes Windows `\r` characters) and
**ensuring a trailing newline** before `ssh-add`, addressing CI failures
caused by malformed key formatting.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b81d81e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Simplify the `PerpsConfirmScreen` wrapper to rely solely on `useRoute()`
hook (which it was already using), removing the redundant `route` prop
type and the `type ScreenComponent = React.ComponentType<any>` escape
hatch.

Part of the React Navigation v6 migration effort to remove
`no-explicit-any` violations from route files.

**Changes:**
- **`routes/index.tsx`**: Remove `route` from `PerpsConfirmScreen`
props, rely on `useRoute()` only. Remove `ScreenComponent` type alias
and `as ScreenComponent` cast.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring with no user-facing 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.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk refactor limited to React Navigation wiring and TypeScript
types; behavior should remain the same aside from how `showPerpsHeader`
is read from route params.
> 
> **Overview**
> Simplifies `PerpsConfirmScreen` to no longer accept/forward navigation
props and instead read `showPerpsHeader` directly from `useRoute()`
params when rendering `Confirm`.
> 
> Removes the `ScreenComponent = React.ComponentType<any>` escape hatch
and the `as ScreenComponent` cast in the stack screen registration,
improving typing as part of the React Navigation v6 migration.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6de9b09. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… branches (#28214)

## **Description**

Consolidates the temporary workflow experiments back into the original
files and deletes the temp copies.

**Changes:**

- **`upload-to-testflight.yml`** — Now supports `workflow_call` (so
other workflows like nightly can invoke it), creates ephemeral build
branches via `create-build-branch.yml` instead of pushing version bumps
directly to protected branches, displays build number in the summary,
and cleans up ephemeral branches after upload.
- **`nightly-build.yml`** — Rewritten from push-triggered (on
`chore/temp-nightly`) to schedule-triggered (4 AM UTC cron). iOS exp/rc
builds now delegate to `upload-to-testflight.yml`. Android exp/rc builds
use `create-build-branch.yml` + `build.yml` with ephemeral branch
cleanup.
- **`nightly-build-temp.yml`** — Deleted (superseded by updated
`nightly-build.yml`)
- **`upload-to-testflight-temp.yml`** — Deleted (superseded by updated
`upload-to-testflight.yml`)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — CI workflow changes only.
1. Trigger `upload-to-testflight` via `workflow_dispatch` and verify:
ephemeral branch is created, build succeeds, build number appears in
summary, branch is cleaned up.
2. Trigger `nightly-build` via `workflow_dispatch` and verify: all four
streams (ios-exp, ios-rc, android-exp, android-rc) start, each creates
its own ephemeral branch.

## **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]
> **Medium Risk**
> Medium risk because it rewires the release build/upload automation
(triggers, dependencies, and branch/version-bump flow), which could
break nightly delivery or leave orphaned branches if misconfigured.
> 
> **Overview**
> **Nightly CI is restructured to run on a 4AM UTC schedule from
`main`** and no longer relies on a persistent temp branch or
push-triggered execution.
> 
> iOS nightly `exp`/`rc` now delegates end-to-end build+upload to
`upload-to-testflight.yml`, while Android nightly creates per-run
ephemeral branches via `create-build-branch.yml`, builds from them with
version bump enabled, and then deletes those branches in a final cleanup
job.
> 
> The former `*-temp.yml` workflows are removed, and
`upload-to-testflight.yml` is updated to be reusable via
`workflow_call`, build from an ephemeral branch (instead of bumping on
the source ref), include build number in the job summary, and clean up
its build branch after upload.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
67852c5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…-615) (#28203)

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

Homepage **Predictions** showed open position amounts and the claim
total in plain text when **privacy mode** was on. This aligns the
section with the Predict tab: monetary lines use `SensitiveText`, and
the claim button uses `PredictClaimButton`’s `isHidden` so the amount is
not readable on-screen.

## **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 homepage Predictions section so open positions
and claim amounts respect privacy mode

## **Related issues**

Fixes:

Refs:
[TMCU-615](https://consensyssoftware.atlassian.net/browse/TMCU-615)

## **Manual testing steps**

```gherkin
Feature: Homepage predictions privacy mode

  Scenario: Position amounts are hidden when privacy mode is on
    Given the user has Predict positions on the homepage
    And privacy mode is enabled in settings
    When the user views the wallet homepage Predictions section
    Then position titles remain visible
    And currency and PnL values are masked

  Scenario: Claim amount is hidden when privacy mode is on
    Given the user has claimable Predict winnings on the homepage
    And privacy mode is enabled
    When the user views the Predictions claim button
    Then the exact claim dollar amount is not shown
    And tapping the button still runs claim
```

## **Screenshots/Recordings**

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

### **Before**

<img width="300"
src="https://github.com/user-attachments/assets/99286ccf-3fcf-46e7-a085-7d24a7ea1ed4"
/>


### **After**

<img width="300"
src="https://github.com/user-attachments/assets/3c7b9d50-7d67-438a-b528-538556dc68ec"
/>


## **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/UX change that only affects how values are displayed under
privacy mode, with added tests to prevent regressions.
> 
> **Overview**
> Homepage **Predictions** now respects *privacy mode* by masking
monetary/PNL text in position rows via `SensitiveText` and passing
`privacyMode` down to `PredictPositionRow`.
> 
> The claim CTA no longer renders the exact dollar amount when privacy
mode is enabled (by omitting the `amount` passed to
`PredictClaimButton`), while still allowing the claim action to be
triggered. Tests were updated/added to cover these privacy-mode
behaviors, including verifying masked output and claim invocation via
the button `testID`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4a1e63e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…cross homepage sections (#28187)

## **Description**

Fixes incorrect `is_empty` values in the `Homepage Viewed` Segment event
across multiple homepage sections.

Sections that show discovery/promotional content (trending markets
carousel) when the user has no primary content were reporting
`is_empty=false`. The `is_empty` property should reflect whether the
user has real content, not whether there is any fallback UI to display.

Changes:
- **Perps**: `isEmpty` was `!hasItems && trendingMarkets.length === 0` —
showing the trending carousel (empty state) incorrectly reported
`false`. Fixed to `!hasItems`.
- **Predictions**: Same pattern — `isEmpty` only became `true` when
there were no markets either. Fixed to `!hasPositions`. Also fixes
`item_count`, which was counting trending markets instead of user
positions.
- **Tokens**: Error state was not counted as empty. Fixed to include
`showTokensError`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-608

## **Manual testing steps**

```gherkin
Feature: Homepage Section Viewed analytics event

  Scenario: user views Perps section with no open positions
    Given the user has no open perps positions or orders
    When the user opens the homepage
    Then the Homepage Viewed event for "perps" fires with is_empty=true and item_count=0

  Scenario: user views Predictions section with no open positions
    Given the user has no open prediction positions
    When the user opens the homepage
    Then the Homepage Viewed event for "predict" fires with is_empty=true and item_count=0

  Scenario: user views Perps section with open positions
    Given the user has open perps positions
    When the user opens the homepage
    Then the Homepage Viewed event for "perps" fires with is_empty=false and item_count > 0
```

## **Screenshots/Recordings**

`~`

### **Before**

`~`

### **After**

`~`

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes only affect analytics payload fields
(`isEmpty`/`itemCount`) for homepage sections, without altering core
trading/token functionality.
> 
> **Overview**
> Corrects `Homepage Viewed` analytics for sections that show
fallback/discovery UI.
> 
> `PerpsSection` now reports `isEmpty: true` whenever the user has no
positions/orders (even if a trending carousel is shown), and updates the
related test expectation. `PredictionsSection` stops counting trending
markets as `itemCount` and marks the section empty whenever the user has
no positions (or on error). `TokensSection` now treats token-load error
states as `isEmpty` for analytics.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e862fd5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Adds Predict live sports support for 36 additional soccer leagues by
registering their slug configs, tag mappings, and draw-capable flags.
Each league's configuration was derived from the Polymarket Gamma API
event data (tag slugs, slug patterns).

**New leagues:** La Liga, UEFA Qualifiers, Brazil Serie B, Turkish Super
League, Colombian Primera, MLS, Liga MX, Bundesliga, Chinese Super
League, EPL, Czech First League, J1 League, J2 League, Ligue 1,
Norwegian Eliteserien, Australian A-League, Danish Superliga, Serie A, K
League, Eredivisie, Saudi Professional League, Brazil Serie A, Primeira
Liga, Chilean Primera, Peruvian Primera, Copa Libertadores, Copa del
Rey, Copa Sudamericana, Egyptian Premier League, Europa League, Romanian
Liga 1, Europa Conference League, Bolivian First Division, Coppa Italia,
DFB-Pokal, Coupe de France.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-755

## **Manual testing steps**

```gherkin
Feature: Predict soccer league support

  Scenario: user views a supported soccer league market
    Given the Predict feature is enabled with live sports leagues
    And one of the 36 new soccer leagues has an active market on Polymarket

    When user navigates to that market in Predict
    Then the market displays with live game data (teams, scores, periods)
    And the draw outcome is available as a betting option
```

## **Screenshots/Recordings**

<!-- N/A — no UI changes, data-layer league registration only -->

### **Before**

<!-- Only 4 leagues supported: NFL, NBA, UCL, FIFA Friendly -->

### **After**

<!-- 40 leagues supported: NFL, NBA, UCL, FIFA Friendly + 36 new soccer
leagues -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Expands live-sports parsing/league detection and draw-handling across
many new soccer leagues, which could misclassify events or break live
game overlays if slug/tag configs are wrong. Changes are mostly
configuration/data-layer, with minimal UI/provider logic impact.
> 
> **Overview**
> **Predict live sports support is expanded to many additional soccer
leagues.** This extends `PredictSportsLeague`,
`SUPPORTED_SPORTS_LEAGUES`, and `DRAW_CAPABLE_LEAGUES`, enabling draw
markets for those leagues.
> 
> `gameParser` now includes per-league slug regexes and optional
`tagSlug` mappings, and `getEventLeague` checks the mapped tag slug
instead of assuming it equals the league code. Separately, the game
details screen sets a default background (`bg-default`) with a snapshot
update, and `PolymarketProvider.getMarketDetails` is refactored slightly
to store the parsed/overlayed result before returning.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d801c15. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…28188)

## **Description**

Migrate 3 Multichain navigator components from prop-based route access
to `useRoute()` hook (PR 10 of 13).

**Components:** AccountDetails, AccountGroupDetails, WalletDetails

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactoring. All 18 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 limited to React Navigation param plumbing and test
adjustments, with no functional changes expected beyond potential
runtime issues if route params are missing/mistyped.
> 
> **Overview**
> Refactors `AccountDetails`, `AccountGroupDetails`, and `WalletDetails`
to stop accepting `route` props and instead pull typed params via
`useRoute()`.
> 
> Updates the multichain stack navigators in `App.tsx` to pass these
screens directly (removing `as ScreenComponent` casts), and adjusts
existing tests to mock `useRoute()`; adds a new `WalletDetails` unit
test to cover the new route-param behavior and null rendering when a
wallet is absent.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e831d3f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **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 nightly iOS TestFlight uploads fail when a previous build in the
same version train is already waiting for beta review. Apple only allows
one build per version to be in beta review at a time, causing a
`Spaceship::UnexpectedResponse` error that fails the CI job even though
the IPA uploaded successfully.

This adds `reject_build_waiting_for_review: true` to the
`upload_to_testflight` Fastlane action, which automatically rejects the
previous build's pending review submission before submitting the new
one. This ensures back-to-back builds (e.g. nightly exp then rc) can
always distribute to external testers without manual intervention.
Previously approved builds remain available in TestFlight — only the
pending review submission is cancelled.

## **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: TestFlight upload with reject_build_waiting_for_review

  Scenario: nightly build uploads when previous build is waiting for review
    Given a previous iOS build is waiting for beta review in App Store Connect

    When a new nightly build triggers the upload-to-testflight workflow
    Then the previous build's review submission should be rejected
    And the new build should be uploaded and submitted for beta review
    And the workflow should complete successfully
```

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

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk CI configuration tweak that only affects TestFlight upload
behavior; main risk is unintended cancellation of a prior build that was
still awaiting beta review in the same version train.
> 
> **Overview**
> Updates iOS Fastlane `upload_to_testflight_only` to pass
`reject_build_waiting_for_review: true` to `upload_to_testflight`,
automatically rejecting any prior build stuck *waiting for beta review*
before submitting a new one.
> 
> This prevents CI/TestFlight uploads from failing when Apple allows
only one build per version to be in review at a time, enabling
back-to-back external distribution without manual intervention.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2af86af. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Mar 31, 2026
@pull pull Bot added the ⤵️ pull label Mar 31, 2026
@pull pull Bot merged commit 1db5526 into Reality2byte:main Mar 31, 2026
0 of 8 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.