Skip to content

[pull] main from MetaMask:main#533

Merged
pull[bot] merged 15 commits into
Reality2byte:mainfrom
MetaMask:main
Feb 18, 2026
Merged

[pull] main from MetaMask:main#533
pull[bot] merged 15 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Feb 18, 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 : )

wachunei and others added 15 commits February 18, 2026 12:43
## **Description**

Implements a new remote feature flag `homepageSectionsV1` for the
"Homepage without tabs" feature (Epic: TMCU-406).

This feature flag is version-gated, meaning it:
- Can be enabled/disabled from various environments via remote
configuration
- Respects minimum version requirements to ensure compatibility
- Enables testing in experimental nightly builds

### Changes
- Added `homepageSectionsV1Key` constant
- Added `selectHomepageSectionsV1Enabled` selector following the
existing pattern for `selectHomepageRedesignV1Enabled`
- Added comprehensive unit tests for the new selector

## **Changelog**

CHANGELOG entry: null

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Homepage Sections V1 Feature Flag

  Scenario: Feature flag selector returns true when enabled
    Given the remote feature flags include homepageSectionsV1 with enabled: true
    And the app version meets the minimum required version

    When the selectHomepageSectionsV1Enabled selector is called
    Then it returns true

  Scenario: Feature flag selector returns false when disabled
    Given the remote feature flags include homepageSectionsV1 with enabled: false

    When the selectHomepageSectionsV1Enabled selector is called
    Then it returns false

  Scenario: Feature flag selector returns false when version check fails
    Given the remote feature flags include homepageSectionsV1 with enabled: true
    And the app version does NOT meet the minimum required version

    When the selectHomepageSectionsV1Enabled selector is called
    Then it returns false
```

## **Screenshots/Recordings**

### **Before**

N/A - No UI changes

### **After**

N/A - No UI changes

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Adds a new selector and unit tests without changing existing flag
behavior or touching security-sensitive logic.
> 
> **Overview**
> Adds a new version-gated remote feature flag selector,
`selectHomepageSectionsV1Enabled`, alongside
`selectHomepageRedesignV1Enabled`, using the same
`validatedVersionGatedFeatureFlag(...) ?? false` pattern.
> 
> Expands `homepage` feature-flag selector tests to cover the new flag
(enabled/disabled, min-version gating failure, invalid payload shape,
and empty flags) and renames the test suite to **Homepage** selectors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
884b703. 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**

We are force enabling the explore feature. I've modified some tests to
ensure e2e passes

<!--
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: feat: force enable explore feature

## **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 effectively forces a feature flag on
(potentially impacting app behavior across environments) and changes
shared E2E navigation flows, which may introduce broader test and UI
regressions if the Explore/Trending path differs or is unavailable.
> 
> **Overview**
> Forces the `assetsTrendingTokens`/Explore-related feature flag on
unconditionally by making `selectAssetsTrendingTokensEnabled` always
apply a `'true'` override (and skipping the selector’s unit tests).
> 
> Updates Detox navigation to the Browser to assume the new flow
(**Explore → Trending → Browser**) and adds resilience for cases where
the tabs grid opens first by selecting the first tab via new
`BrowserViewSelectorsIDs` (`TABS_OPENED_TITLE`, `TABS_ITEM_REGEX`) and a
new `testID` on the Tabs header; removes the legacy
`TabBarComponent.tapBrowser` path and adjusts affected smoke/page-object
tests accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
42ce6bb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#26220)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
## Summary

- **Appwright patch: Add `geoLocation: 'ES'` to BrowserStack sessions**
— Forces all performance test sessions to run with Spain geolocation,
ensuring Polymarket geo-eligibility checks pass without needing API
mocks.

- **Move `splitAmountIntoDigits` to proper TypeScript** — Converted the
utility to typed TS (`wdio/utils/splitAmountIntoDigits.ts`) and updated
all imports in `AmountScreen.js`, `SwapScreen.js`, and
`PerpsOrderView.js` to use the new path.
- **Perps and Prediction fixes**

## Test plan

- [ ] Verify BrowserStack sessions report `geoLocation: ES` in
capabilities
- [ ] Verify Predict deposit performance test passes geo-eligibility
check
- [ ] Verify `splitAmountIntoDigits` works correctly in swap, perps, and
amount flows
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

### Why React Query?

We're introducing `@tanstack/react-query` to replace hand-rolled data
fetching hooks that manage their own loading/error/caching state with
`useState`, `useRef`, `useSelector`, and manual deduplication logic.
React Query gives us:

- **Automatic caching and deduplication** — multiple components sharing
the same query key get a single fetch
- **Built-in loading/error/refetching states** — no more manual
`isLoading` / `isRefreshing` / `error` state management
- **Declarative invalidation** — `queryClient.invalidateQueries()` with
prefix matching instead of imperative `loadBalance()` callbacks
- **Stale-while-revalidate** — configurable `staleTime` prevents
unnecessary refetches on screen transitions
- **Background refetching** — automatic refetch on app focus (via
`AppState` integration we wired up)

### What's in this PR

**1. React Query infrastructure** (`app/core/ReactQueryService/`)
- `ReactQueryService` singleton class in `app/core/ReactQueryService/` —
owns the `QueryClient` and subscribes to `AppState` (focus) and
`NetInfo` (online) on construction, following the same service-class
pattern used by `LockManagerService` and `ScreenOrientationService`
- `QueryClientProvider` wrapping the app in `Root/index.tsx`, consuming
`reactQueryService.queryClient`

**2. Query key factory pattern** (`app/components/UI/Predict/queries/`)
- `predictQueries.balance.keys.all()` — for invalidation (prefix match)
- `predictQueries.balance.keys.detail(providerId, address)` — for
targeting a specific cache entry
- `predictQueries.balance.options({ address, providerId })` —
`queryOptions()` factory for `useQuery`

This pattern is based on [TkDodo's query key
factory](https://tkdodo.eu/blog/effective-react-query-keys#use-query-key-factories)
convention, widely used across TanStack Query codebases. New Predict
queries (positions, activity, etc.) will follow the same structure.

**3. `usePredictBalance` rewrite** (190 → 46 lines)
- Hook now returns standard `UseQueryResult<number, Error>` — no custom
wrapper
- Consumers destructure standard React Query fields: `{ data, isLoading,
error }`
- `loadOnMount` / `refreshOnFocus` options removed — replaced by React
Query's `enabled` and built-in focus refetching
- Toast hooks (claim/deposit/withdraw) no longer import the balance hook
— they call `queryClient.invalidateQueries()` directly via
`useQueryClient()`

**4. All 10 consumers updated** to use the new interface

### Future considerations

- **React Query DevTools**: [Buoy
Desktop](https://github.com/Buoy-gg/Buoy-Desktop) can be added for React
Native devtools support — not included in this PR to keep scope focused
- **Additional queries**: Other Predict hooks (positions, activity,
etc.) can follow the same `predictQueries.*` pattern

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A — infrastructure improvement

## **Manual testing steps**

```gherkin
Feature: Predict balance display

  Scenario: user views their Predict balance
    Given user has a Predict account with funds

    When user navigates to the Predict screen
    Then balance is displayed correctly with loading state

  Scenario: user deposits funds and balance refreshes
    Given user is on the Predict screen

    When user completes a deposit
    Then balance updates automatically after confirmation toast
```

## **Screenshots/Recordings**

N/A — no visual changes, data fetching refactor only

### **Before**

N/A

### **After**

N/A

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

## **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 a new app-wide React Query client and rewrites Predict
balance fetching/caching/invalidation; risk is mainly around
stale/refetch behavior and ensuring all balance updates correctly
trigger invalidation after deposits/claims/withdraws/orders.
> 
> **Overview**
> Introduces TanStack React Query into the app: adds `ReactQueryService`
(QueryClient + AppState/NetInfo focus/online integration) and wraps
`Root` with `QueryClientProvider`.
> 
> Rewrites `usePredictBalance` to be React Query-backed (new
`predictQueries.balance` key/options factory), and updates Predict
UI/hooks to consume `data` and refresh balance via
`queryClient.invalidateQueries()` (e.g., after deposit completion, order
placement, and toast-confirmed transactions) instead of imperative
`loadBalance`/focus refresh. Tests are updated accordingly, and
`@tanstack/react-query` is added as a dependency.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
22cc257. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR addresses a small Predict tech-debt item by migrating
`PredictOffline` away from legacy `StyleSheet.create` + `useStyles`
usage.

The component now uses `useTailwind()` styles directly, and the obsolete
`PredictOffline.styles.ts` file was removed.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict offline state rendering

  Scenario: user sees predict offline state with retry action
    Given Predict renders an offline error state
    When the offline UI is displayed
    Then the offline title and description are shown
    And the retry button is shown when a retry callback is provided
    And tapping retry triggers the callback
```

## **Screenshots/Recordings**

### **Before**

N/A (styling refactor only; no intended visual behavior change)

### **After**

N/A (styling refactor only; no intended visual behavior change)

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] 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**
> Styling-only refactor confined to a single offline/error UI component;
primary risk is minor layout regressions.
> 
> **Overview**
> Refactors `PredictOffline` to drop `StyleSheet.create`/`useStyles` in
favor of `useTailwind()` inline utility styles, aiming for no functional
or visual behavior change.
> 
> Deletes the now-unused `PredictOffline.styles.ts` file and updates the
component to apply spacing/alignment/width styles via `tw.style(...)` on
the `Box`, `Icon`, `Text`, and retry `Button`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6a7479c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…26091)

## **Description**

This PR addresses a small Predict tech-debt item by migrating
`PredictMarketRowItem` from legacy `StyleSheet.create` + `useStyles`
usage to Tailwind-based styling via `useTailwind()`.

The legacy `PredictMarketRowItem.styles.ts` file was removed and
equivalent layout/spacing styles were inlined in the component.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict market row item rendering

  Scenario: user views and opens a market from row item
    Given a Predict market row item is rendered
    When the user views the row
    Then the market title and probability subtitle are shown

    When the user taps the row
    Then the app navigates to Predict market details with the expected params
```

## **Screenshots/Recordings**

### **Before**

N/A (styling migration only; no intended visual behavior change)

### **After**

N/A (styling migration only; no intended visual behavior change)

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] 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**
> Pure styling refactor confined to a single UI component; functional
logic and navigation params are unchanged, with only minor risk of
visual/layout regressions.
> 
> **Overview**
> Refactors `PredictMarketRowItem` to inline Tailwind-based styles via
`useTailwind()`, removing the `useStyles`/`StyleSheet.create` pattern.
> 
> Deletes `PredictMarketRowItem.styles.ts` and replaces the component’s
container/layout/spacing styles with equivalent `tw.style(...)` calls
(including a small subtitle spacing tweak).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2cddf8a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#26092)

## **Description**

This PR addresses Predict tech debt by moving the withdraw transaction
selector out of `usePredictWithdraw` and into the shared predict
selector module.

Changes included:
- Added `selectPredictWithdrawTransaction` in `predictController`
selectors.
- Updated `usePredictWithdraw` to consume the shared selector via
`useSelector`.
- Added selector test coverage for withdraw transaction selection.

This avoids creating a new `createSelector(...)` instance on every hook
render.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict withdraw selector behavior

  Scenario: withdraw hook reads transaction state via shared selector
    Given PredictController state includes a withdrawTransaction
    When usePredictWithdraw is rendered
    Then withdrawTransaction is read from the shared selector

    Given withdrawTransaction is null
    When selectPredictWithdrawTransaction is evaluated
    Then null is returned
```

## **Screenshots/Recordings**

### **Before**

N/A (non-visual refactor)

### **After**

N/A (non-visual refactor)

## **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]
> **Low Risk**
> Refactor-only change that centralizes a Redux selector and adds unit
tests; behavior should be unchanged aside from potential `undefined` vs
`null` edge cases if state is absent.
> 
> **Overview**
> `usePredictWithdraw` now reads `withdrawTransaction` via a shared
selector (`selectPredictWithdrawTransaction`) instead of creating an
inline `createSelector` per render.
> 
> Adds `selectPredictWithdrawTransaction` to `Predict` controller
selectors and exports it, with new unit tests covering both populated
and `null` withdraw-transaction state.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
68d2c66. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#26171)

<!--
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**
Migrates the quality gates system from loose JavaScript files in
tests/framework/utils/ to a dedicated, well-structured TypeScript module
at tests/framework/quality-gates/. The monolithic QualityGatesValidator
class was split by responsibility into focused files:
- types.ts — Shared interfaces (TimerLike, StepResult,
QualityGatesResult, Violation, etc.)
- QualityGatesValidator.ts — Core validation logic only
- QualityGatesReportFormatter.ts — Console, HTML, and CSV report
formatting
- QualityGateError.ts — Custom error class for threshold failures
- helpers.ts — File-based failure tracking across Playwright workers

All imports in performance-test.js, custom-reporter.js, and
QualityGatesValidator.js (old) are updated to the new paths. The old JS
files (QualityGateError.js, QualityGatesValidator.js) are no longer
referenced and can be deleted. The tests/performance/README.md is
updated to reflect the new structure.

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**
N/A

## **Screenshots/Recordings**

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

### **Before**
N/A
<!-- [screenshots/recordings] -->

### **After**
N/A
<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Refactors test infrastructure that controls pass/fail and retry
behavior for performance runs; while mostly a move/split, mistakes could
change threshold validation or reporting output across CI.
> 
> **Overview**
> Migrates performance **quality gates** from
`tests/framework/utils/QualityGatesValidator.js` into a new TypeScript
module under `tests/framework/quality-gates/`, introducing shared
`types.ts`, a typed `QualityGatesValidator`, a separate
`QualityGatesReportFormatter` for console/HTML/CSV output, and a typed
`QualityGateError`.
> 
> Updates the performance fixture and `custom-reporter.js` to import
from the new module, use the new formatter for report rendering, and
keep the existing behavior of skipping retries by persisting
quality-gate failures via updated typed helper functions. Documentation
in `tests/performance/README.md` is adjusted to reflect the new module
layout, and the old JS validator implementation is removed.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
28b81a8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…26221)

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

Context
A release shipped with migration 119 labeled as 118. To align the
codebase with what users have, we need to swap these migrations.

Problem
- Migration 119 (MegaETH network name update) was released as migration
118
- Migration 118 (SnapController sourceCode migration) was released as
migration 119

The codebase has them reversed, causing a mismatch with released state

Solution
- Swapped migrations 118 and 119:
- Migration 118 now contains the MegaETH network name update (previously
119)
- Migration 119 now contains the SnapController sourceCode migration
(previously 118)
- Updated all version numbers, imports, and test references

<!--
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 migration numbering to match released version by
swapping migrations 118 and 119

## **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**
> Touches persisted-state migration ordering and behavior; a numbering
mismatch or subtle state-shape assumption could lead to users skipping
or misapplying a migration during upgrades.
> 
> **Overview**
> Aligns migration numbering with the already-released state by
**swapping the implementations of migrations `118` and `119`**.
> 
> `118` is now the MegaETH Mainnet rename migration (updates
`NetworkController.networkConfigurationsByChainId[MEGAETH_MAINNET]`
network and RPC endpoint names from `MegaEth` to `MegaETH`) and is made
synchronous, while `119` now performs the async SnapController
`sourceCode` extraction to filesystem storage (writing
`${STORAGE_KEY_PREFIX}SnapController:<id>` and deleting `sourceCode`).
Tests were rewritten accordingly to validate the new behaviors for each
migration number.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1367776. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…es (#26116)

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

Remove smart account upgrade splash page and related code and
preferences.

## **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: MetaMask/MetaMask-planning#7007

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

## **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**
> Mostly deletes UI and wiring around a deprecated opt-in flow; primary
risk is unintended removal of a navigation path still referenced
elsewhere.
> 
> **Overview**
> Removes the smart account upgrade *splash/opt-in* experience from
confirmations by deleting the `Splash` overlay and the dedicated
`SmartAccountUpdate*` modal/splash components (and associated
tests/styles).
> 
> Cleans up related plumbing: drops the `Routes.SMART_ACCOUNT_OPT_IN`
route and smart-account navigation helper, removes the
`selectSmartAccountOptIn` selector and `SMART_ACCOUNT_OPT_IN`
MetaMetrics event, and deletes the now-unused i18n strings for the
opt-in UI.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bb7e0f8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Align `docs/ab-testing.md` with the Confluence A/B testing guidance
while keeping useful local implementation details.

This updates doc content to reflect current behavior and standards:
- clarifies app-side bucketing via `RemoteFeatureFlagController` (not
LaunchDarkly native percentage rollout targeting)
- adds/updates JSON examples so thresholds are in variation items
- adds the `ab_tests` Segment schema section and guidance that per-test
schema PRs are not required after setup
- updates LaunchDarkly naming guidance to `{team}{TicketID}{TestName}`
- adds checklist, Mixpanel template dashboard link, and FAQ
clarifications

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

```gherkin
Feature: A/B testing documentation alignment

  Scenario: reviewer validates updated docs guidance
    Given the branch with this PR is checked out

    When the reviewer opens docs/ab-testing.md
    Then the doc reflects app-side bucketing, includes the Segment schema section, and includes the LaunchDarkly naming/checklist/FAQ updates
```

## **Screenshots/Recordings**

### **Before**

N/A (documentation-only changes)

### **After**

N/A (documentation-only changes)

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

This PR adds unit test coverage for the vertical network list acceptance
criteria in Bridge token selection flows.

What changed:
- Added source/destination default network filter coverage in token
selector tests.
- Added destination-with-selected-token default chain scoping coverage.
- Added selected-network filter + search scoping coverage.
- Added shared pill-order persistence coverage across source/destination
picker navigation.
- Added sequential non-visible network selection reorder coverage in
pills.
- Added single-supported-network no-`+N` coverage.
- Added explicit reducer reset proof for `visiblePillChainIds` on
`resetBridgeState`.
- Added network auto-add continuation coverage in `useTokenSelection`
for destination flow, while retaining existing reject-path coverage.

Scope notes:
- Test-only changes.
- No production runtime logic changes.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

```gherkin
Feature: Bridge token selector network filtering and pill order behavior

  Scenario: default picker network behavior
    Given the Bridge token selector is opened for source and destination pickers
    When the selector loads with no destination token selected
    Then token fetch/search hooks are called with all allowed chains

  Scenario: destination selected-token default behavior
    Given the destination picker opens with a selected destination token
    When the selector initializes
    Then token fetch/search hooks are scoped to the selected token chain

  Scenario: network selection updates filter and search scope
    Given the user has entered a search query
    When the user selects a specific network pill
    Then search is reset and re-issued for only the selected chain

  Scenario: sequential non-visible network selections
    Given visible pills are initialized from the default ranking
    When two non-visible networks are selected sequentially
    Then the visible pill order rolls forward with each selection

  Scenario: shared pill order persistence across pickers
    Given visible pill order is modified in source picker
    When the user switches to destination picker and back
    Then the same visible pill order remains in both pickers during the session

  Scenario: reset on flow exit
    Given visible pill chain IDs are set in bridge state
    When resetBridgeState is dispatched
    Then visible pill chain IDs reset to undefined

  Scenario: network auto-add behavior
    Given destination token selection is on a missing network
    When a token is selected
    Then network auto-add is attempted and destination selection continues
```

## **Screenshots/Recordings**

### **Before**

N/A (test-only PR)

### **After**

N/A (test-only 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
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Test-only changes that adjust mocks and add coverage; no production
logic is modified, with minimal risk beyond potential test brittleness.
> 
> **Overview**
> Adds regression tests around Bridge token selection network filtering
and pill ordering.
> 
> Updates `BridgeTokenSelector` tests to use a more realistic mock
bridge reducer (supports `tokenSelectorNetworkFilter` and
`visiblePillChainIds`) and asserts default chain scoping,
chain-selection-driven search reset/re-issue, and persistence of visible
pill order when navigating between source/dest pickers. Extends
`NetworkPills` tests to cover single-network rendering (no "+N more")
and rolling pill reordering across consecutive non-visible selections,
plus adds `useTokenSelection` and bridge-slice tests for destination
network auto-add continuation and `visiblePillChainIds` reset on
`resetBridgeState`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
be4c47b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#25796)

<!--
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 bump `@metamask/assets-controllers` from `^99.0.0` to `^99.3.1`.
The current resolved version in the `yarn.lock` is `99.1.0`, which
includes a change that introduces a bug with Tempo native balances. A
fix has been released in `99.3.1`, so we need to bump to that version to
get the fix.

```markdown
## [99.3.1]

### Fixed

- Remove `Tempo Testnet` multicall address ([#7858](MetaMask/core#7858)).

## [99.3.0]

### Added

- Add optional `rwaData` support when adding tokens in `TokensController` ([#7804](MetaMask/core#7804)).

### Changed

- Lock `@metamask/core-backend` to `5.0.0` ([#7852](MetaMask/core#7852))
- Bump `@metamask/profile-sync-controller` from `^27.0.0` to `^27.1.0` ([#7849](MetaMask/core#7849))
- Fix trending tokens showing incorrect market cap values by adding `usePriceApiData` parameter (defaults to `true`) to use price API data for accurate market data ([#7829](MetaMask/core#7829))
- Bump `@metamask/transaction-controller` from `^62.13.0` to `^62.15.0` ([#7832](MetaMask/core#7832), [#7854](MetaMask/core#7854))

## [99.2.0]

### Added

- Add `HYPEREVM` support ([#7790](MetaMask/core#7790))
  - Add `HYPEREVM` in `SupportedTokenDetectionNetworks`
  - Add `HYPEREVM` in `SUPPORTED_NETWORKS_ACCOUNTS_API_V4`

### Changed

- Simplify TokenListController initialization ([#7740](MetaMask/core#7740))
- Bump `@metamask/storage-service` from `^0.0.1` to `^1.0.0` ([#7797](MetaMask/core#7797))
- Bump `@metamask/transaction-controller` from `^62.11.0` to `^62.13.0` ([#7775](MetaMask/core#7775), [#7802](MetaMask/core#7802))
- Bump `@metamask/preferences-controller` from `^22.0.0` to `^22.1.0` ([#7802](MetaMask/core#7802))

### Removed

- Removed token-search-discovery-controller package ([#7789](MetaMask/core#7789))
```

## **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**
> Dependency upgrade in core asset/balance controller codepaths could
change token balance fetching behavior at runtime; test changes are low
risk but lockfile churn may mask subtle transitive updates.
> 
> **Overview**
> Updates `@metamask/assets-controllers` to `^99.3.1` and drops the
local Yarn patch previously applied to `99.2.0`, letting the app consume
the upstream fixes (including the Tempo native balance regression noted
in the PR context).
> 
> Cleans up `TokenBalancesController`/`TokenDetectionController`
messenger unit tests by removing locally-declared `RootMessenger`
generic types and reusing the shared `RootMessenger` type from
`app/core/Engine/types`. Lockfile/resolution entries are updated
accordingly to reflect the new dependency graph.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0e1ee10. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
<!--
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**

Part 2 of the hardware wallet connection & error management overhaul.
This does not introduce user facing changes.
Cursor summary mentions the PR being medium risk, but nothing is wired
yet, so this is largely low risk.

Final implementation will look like this ([Figma
designs](https://www.figma.com/design/1F3yNWYLOVPFpTPeJugH20/SWAP?node-id=11110-19571&t=tPMZNNiwCgbDfegd-0)):
<img width="1404" height="631" alt="image"
src="https://github.com/user-attachments/assets/68850711-f53b-4060-8b47-6faceb67f82f"
/>

Reference feature branch:
#25519

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

No manual testing steps

## **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**
> New Bluetooth transport and Ledger readiness logic introduces async
state, retry, and timeout behavior that can be error-prone once wired
into flows, though changes are currently additive and well-covered by
unit tests.
> 
> **Overview**
> Introduces a new adapter layer under
`app/core/HardwareWallet/adapters`, including a `LedgerBluetoothAdapter`
that manages BLE connection/disconnection, device discovery (scan +
timeout), Bluetooth availability monitoring, and Ledger app readiness
checks (wrong app, locked device, disconnect retries, and operation
timeouts), emitting `DeviceEvent` callbacks throughout.
> 
> Adds a `NonHardwareAdapter` passthrough implementation so consumers
can call the same adapter API for non-hardware accounts, plus a
`createAdapter`/`requiresBluetooth` factory export and comprehensive
Jest tests for adapter behavior and edge cases. Updates dependencies to
include `@ledgerhq/hw-app-eth`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2a9564e. 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**
Pull request for the ADR: MetaMask/decisions#130
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only deletions with no changes to build, release, or
runtime code paths.
> 
> **Overview**
> Removes the temporary build-system migration documentation
(`.github/MIGRATION.md` and `.github/builds.README.md`) that described
the Bitrise→GitHub Actions transition and `builds.yml` architecture,
shifting that guidance to an external ADR instead.
> 
> No functional build or workflow logic is changed—this PR is strictly
documentation deletion/cleanup.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6ea2e8d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Wei Sun <wei.sun@consensys.net>
@pull pull Bot locked and limited conversation to collaborators Feb 18, 2026
@pull pull Bot added the ⤵️ pull label Feb 18, 2026
@pull pull Bot merged commit cb9a312 into Reality2byte:main Feb 18, 2026
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.