Skip to content

[pull] main from MetaMask:main#298

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

[pull] main from MetaMask:main#298
pull[bot] merged 10 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Nov 5, 2025

See Commits and Changes for more details.


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

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

grvgoel81 and others added 10 commits November 5, 2025 12:03
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
* BugFix: #19495
* JIRA: https://consensyssoftware.atlassian.net/browse/SL-273

<!--
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: BugFix:
#19495

## **Related issues**

Fixes:
#19495
## **Manual testing steps**

```gherkin
BugFix:
1)Navigate to the SRP reveal screen.
2)Click inside the password textbox.
3)Click outside to remove focus.
4)Click back into the textbox and try to type.
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**


https://github.com/user-attachments/assets/6289df7c-5841-4d39-b826-080bf838edce


<!-- [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]
> Adds a ref to the password TextInput and focuses it on touch to fix
typing after blur on the SRP/private credential reveal screen.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ccec65f. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

This PR addresses several UI and stability issues to improve the Card
onboarding and home experience on Android devices.

Fixes
- Fixed screen layout being cut off on Android devices with a notch.
- Fixed keyboard overlapping input fields on Android, preventing users
from typing.
- Resolved concurrency issue causing warnings on the Card Home 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 layout issue where the screen was cut off on
Android devices with a notch.
CHANGELOG entry: Fixed keyboard overlapping input fields on Android
devices.
CHANGELOG entry: Resolved concurrency issue causing warnings on the Card
Home screen.

## **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]
> Splits consent into create/link steps with new Redux `consentSetId`,
wraps onboarding/KYC screens for Android safe areas and keyboard
handling, updates hooks and tests, extends delegation SIWE expiry, and
tweaks warning precedence.
> 
> - **Onboarding UI (Android)**:
> - Wrap `OnboardingStep` and `KYCWebview` in `SafeAreaView`; enable
keyboard-aware scroll with Android tweaks.
> - Enhance `KYCWebview` with media/storage/geolocation settings and
loading state.
> - **Consent & Registration Flow**:
> - Introduce two-stage consent hook `useRegisterUserConsent` with
`createOnboardingConsent` and `linkUserToConsent`.
> - Integrate flow in `PhysicalAddress` (create consent before address;
link on completion) and `MailingAddress` (link on completion if
`consentSetId`).
> - **Redux (card slice)**:
> - Add `onboarding.consentSetId` with selectors `selectConsentSetId`,
action `setConsentSetId`, and reset handling.
> - **Other Hooks**:
>   - `useCardDelegation`: extend SIWE message expiration to 2 minutes.
> - `useLoadCardData`: prioritize `CardWarning.NoCard` over token
warning.
> - **Tests**:
> - Update and expand tests for Personal/Physical/Mailing flows, consent
hook, and card slice to reflect new consent flow, UI wrappers, and async
handling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
454e2d5. 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?
-->
Skip eligibility check for Withdraw. Users should always be able to
withdraw their balance, no matter their location.

## **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]
> Removes withdraw geo-block/eligibility checks and calls withdraw
directly; updates PredictBalance and tests accordingly.
> 
> - **UI (PredictBalance)**:
> - Withdraw button now calls `withdraw()` directly (removed
`executeGuardedAction` with `checkBalance`).
>   - Add Funds remains wrapped with `executeGuardedAction`.
> - **Hook (`usePredictWithdraw`)**:
> - Removed `usePredictEligibility` usage and unavailable modal
navigation.
> - Always navigates to confirmation then calls `prepareWithdraw`;
retains error handling with toast and `goBack`.
> - **Tests**:
> - `PredictBalance.test.tsx`: assert direct `withdraw` call and
`executeGuardedAction` for deposit.
> - `usePredictWithdraw.test.ts`: removed eligibility mocks/tests;
updated cases to reflect unconditional withdraw flow and preserved error
scenarios.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
23611ef. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…he new one (#21665)

<!--
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 introduces the trending tab on bottom navigation under feature
flag.

figma:
https://www.figma.com/design/w4EHAWR5h0OTuqeqZKaCAH/Trending?node-id=2067-19515&p=f&m=dev

if you want to enable and make the button visible you have to add the
following vars to `.js.env`:
```
export OVERRIDE_REMOTE_FEATURE_FLAGS="true"
export ASSETS_TRENDING_TOKENS_ENABLED="true"
```



<!--
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: introduces the trending tab on bottom navigation under
feature flag.



## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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


https://github.com/user-attachments/assets/6127ccdb-b176-45e5-896e-5c577ea5454d



## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a feature-flagged Trending tab and screen, wires
navigation/analytics/i18n, integrates with Browser flow, and refines URL
bar actions; updates tests accordingly.
> 
> - **Navigation & Tab Bar**:
> - Add `TabBarIconKey.Trending` with `TrendUp` icon and
`bottom_nav.trending` label; map navigation to `Routes.TRENDING_VIEW`
gated by `assetsTrendingTokens` flag.
> - In `HomeTabs`, conditionally register `TRENDING_VIEW` tab and hide
`Browser` tab button when Trending is enabled.
>   - Update routes to include `Routes.TRENDING_VIEW`.
> - **New Screen**:
> - Implement `Views/TrendingView` (header + WebView placeholder) with a
button to open Portfolio in Browser, passing `fromTrending`.
> - **Browser Integration**:
> - Propagate `fromTrending` param through `Browser` → `BrowserTab`;
when canceling URL bar and flag is on, navigate back to `TRENDING_VIEW`.
> - `BrowserUrlBar`: add optional close icon (`showCloseButton`) and
refactor right-button rendering; minor styling addition.
> - **Analytics & i18n**:
> - Add `MetaMetricsEvents.NAVIGATION_TAPS_TRENDING` and English strings
for Trending.
> - **Types & Tests**:
> - Export `ExtendedBottomTabDescriptor`; update TabBar tests; extend
MainNavigator tests for Trending/Browser visibility; add tests for
TrendingView and BrowserUrlBar behaviors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b3e2289. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…te (#22124)

## **Description**

Very soon there will be multiple places to opt into rewards, which
requires a small change in the `getCandidateSubscriptionId` controller
function. In that function, we detect a subscription id in via `/ois`
and we don't have a subscription object in our store state, we should do
a silent auth for the account tied to the subscription. This will
(re)populate the store state appropriately.

## **Changelog**

CHANGELOG entry: null

## **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]
> Perform silent auth during candidate subscription discovery when state
lacks the subscription, try all accounts and set a sensible
activeAccount fallback, reduce opt‑in cache staleness to 1h, and make
invalidation async with token reset; update tests accordingly.
> 
> - **RewardsController**:
> - **Candidate Subscription**: `getCandidateSubscriptionId` now returns
`sids[i]` only if a valid token exists AND the subscription is in state;
otherwise performs `performSilentAuth` for that account.
> - **Auth Flow**: `handleAuthenticationTrigger` iterates all accounts,
captures the first success, and sets `activeAccount` to the first
success or the first account; calls `performSilentAuth(account, false,
true)`.
> - **Cache/Thresholds**: Shorten not‑opted‑in opt‑in status stale
threshold to 1 hour (`NOT_OPTED_IN_OIS_STALE_CACHE_THRESHOLD_MS`).
> - **Invalidation**: `invalidateAccountsAndSubscriptions` is now
`async`, also clears `lastFreshOptInStatusCheck`, and awaits
`resetAllSubscriptionTokens`; consumers updated to `await` it (e.g., 403
path in `getSeasonStatus`).
> - **Safety/Refactors**: Null-safety tweaks (e.g., `ois?.[0]`) and
clearer CAIP coercion logic in perps discount; small readability fixes.
> - **Tests**:
> - Add/expand coverage for multi-account silent auth behavior, active
account fallback, 1h threshold logic, async invalidation with token
reset, and new `getCandidateSubscriptionId` behavior (silent auth when
`sids` not in state).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
45a6464. 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?
-->

Data point distribution in the X axis was wrong, with the gap between
the latest point and the one behind that being several hours.

The algorithm has been rewritten to evenly distribute data points.

## **Changelog**

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

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

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

CHANGELOG entry: Fixed a bug in which data points for price were not
being evenly distributed

## **Related issues**

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

## **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] -->
<img width="1179" height="2556" alt="Simulator Screenshot - iPhone 15
Pro - 2025-11-05 at 14 40 06"
src="https://github.com/user-attachments/assets/fcfa51d0-1a4c-4f14-863a-e05fff8d8cbd"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - iPhone 15
Pro - 2025-11-05 at 14 39 02"
src="https://github.com/user-attachments/assets/664f83c3-a2f9-4c6f-a13a-ac3772eb2237"
/>

### **After**

<!-- [screenshots/recordings] -->
<img width="1179" height="2556" alt="Simulator Screenshot - iPhone 15
Pro - 2025-11-05 at 14 38 57"
src="https://github.com/user-attachments/assets/b711e861-5dcb-4c21-ab8e-d645188bd856"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - iPhone 15
Pro - 2025-11-05 at 14 38 54"
src="https://github.com/user-attachments/assets/78a53b02-bb54-46f6-b763-afa31104e005"
/>

## **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]
> Reworks `distributeDataPoints` to select 100 evenly spaced points and
adds comprehensive unit tests.
> 
> - **Price chart sampling
(`app/components/UI/AssetOverview/PriceChart/utils.ts`)**
> - Replaces interval-based sampling with even distribution using
`(numDataPoints - 1) / 99` and rounding to always include first/last and
produce 100 points when >100.
>   - Early-return when `<= 100` points; updates inline docs.
> - **Tests
(`app/components/UI/AssetOverview/PriceChart/utils.test.ts`)**
> - Adds unit tests covering exact/fewer/greater than 100 cases,
first/last inclusion, chronological order, even distribution, no
duplicates, empty input, and uniform gap checks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
502b8c2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR introduces a smart routing system for the Ramps feature that
determines whether users should be directed to the native Deposit flow
or the Aggregator based on their region and order history.

**What is the reason for the change?**
We need to intelligently route users to the appropriate ramp experience
based on two factors:
1. Their regional support status (whether native deposit is available in
their region)
2. Their previous provider usage history (to maintain consistency in
user experience)

**What is the improvement/solution?**
- Created a new `useRampsSmartRouting()` hook that implements the
routing decision logic
- Added `RampRegionSupport` enum to track region-level support (DEPOSIT,
AGGREGATOR, or UNSUPPORTED)
- Added `rampRoutingDecision` state to Redux to store the final routing
determination
- Implemented decision tree logic:
  - Users in UNSUPPORTED regions → routed to UNSUPPORTED state
  - Users in AGGREGATOR-only regions → routed to AGGREGATOR
  - Users in DEPOSIT-supported regions:
    - No previous orders → DEPOSIT
    - Last completed order used Transak → DEPOSIT
    - Last completed order used other provider → AGGREGATOR


## **Changelog**

CHANGELOG entry: Added smart routing logic to determine appropriate ramp
flow based on user region and order history

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Smart Ramps Routing

  Scenario: user in supported region with no order history
    Given user is in a DEPOSIT-supported region
    And user has no previous orders
    When app loads
    Then routing decision should be set to DEPOSIT

  Scenario: user in supported region with Transak order history
    Given user is in a DEPOSIT-supported region
    And user's last completed order was with TRANSAK
    When app loads
    Then routing decision should be set to DEPOSIT

  Scenario: user in supported region with non-Transak order history
    Given user is in a DEPOSIT-supported region
    And user's last completed order was with a non-TRANSAK provider
    When app loads
    Then routing decision should be set to AGGREGATOR

  Scenario: user in aggregator-only region
    Given user is in an AGGREGATOR-only region
    When app loads
    Then routing decision should be set to AGGREGATOR

  Scenario: user in unsupported region
    Given user is in an UNSUPPORTED region
    When app loads
    Then routing decision should be set to UNSUPPORTED
```

## **Screenshots/Recordings**

Not applicable - backend logic change only

### **Before**

No smart routing logic existed

### **After**

Smart routing automatically determines appropriate ramp flow on app load

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a smart routing hook that sets ramp flow
(DEPOSIT/AGGREGATOR/UNSUPPORTED/ERROR) based on region eligibility and
last completed order, persisted in Redux and initialized on Ramp mount.
> 
> - **Logic**:
> - **`useRampsSmartRouting` hook**
(`app/components/UI/Ramp/hooks/useRampsSmartRouting.ts`): determines
routing via placeholder eligibility API (`global/deposit` flags),
geolocation, and most recent completed order (Transak → `DEPOSIT`,
others → `AGGREGATOR`); handles `UNSUPPORTED` and `ERROR`; gated by
`useRampsUnifiedV1Enabled`.
> - Integrated in `FiatOrders` (`app/components/UI/Ramp/index.tsx`) to
initialize decision on mount.
> - **Redux** (`app/reducers/fiatOrders`):
> - State: add `rampRoutingDecision` to `FiatOrdersState` (default
`null`).
> - Actions/Selectors: add `setRampRoutingDecision` and
`getRampRoutingDecision`; export `UnifiedRampRoutingType`.
>   - Reducer: handle `FIAT_SET_RAMP_ROUTING_DECISION`.
> - **Tests**:
> - New comprehensive hook tests (`useRampsSmartRouting.test.ts`)
covering feature flag, region support, order history, sorting,
lifecycle, and error cases.
>   - Reducer/selector tests for routing decision and geolocation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3de7e37. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ialization (#22178)

## **Description**

This PR adds initialization state machine and guards to prevent
CLIENT_NOT_INITIALIZED errors in the Perps feature.

**Problem:**
- Users experiencing CLIENT_NOT_INITIALIZED errors (1,251 events
affecting 590+ users)
- Errors occur during controller reinitialization when switching
accounts/networks
- `usePerpsPositionData` hook was attempting operations before
controller completed initialization

**Investigation Process:**
- Sentry traces for CLIENT_NOT_INITIALIZED errors pointed to
`usePerpsPositionData.ts`
- Stack traces showed errors occurring during interval-based data
fetching (REST API polling for historical candles)
- Root cause identified: intervals firing during controller
reinitialization
- Reinitialization gap: `providers.clear()` → create new provider →
200ms delay → `isInitialized = true`
- During this gap, `usePerpsPositionData` hook intervals continued
executing, causing CLIENT_NOT_INITIALIZED errors

**Solution:**
1. **PerpsController State Machine**: Added `InitializationState` enum
tracking (UNINITIALIZED � INITIALIZING � INITIALIZED � FAILED) with
retry logic (3 attempts, exponential backoff: 1s, 2s, 4s)
2. **Initialization Guards**: Added checks in `usePerpsPositionData` to
block operations when `initializationState !== 'initialized'`
3. **WebSocket Ready Wait**: Added 500ms delay before marking controller
as initialized to ensure WebSocket transport is ready
4. **Redux Selector**: Created `selectPerpsInitializationState` for UI
components to check initialization status

**Key Changes:**
- `PerpsController.ts`: State machine, retry logic, initialization
tracking
- `usePerpsPositionData.ts`: Guards on historical data loading, price
subscriptions, and interval setup
- `selectors/perpsController/index.ts`: Selector for initialization
state
- `PerpsConnectionManager.ts`: Updated to use new `init()` method
- `wait.ts`: Utility function for delays

**Note on Impact Validation:**
These changes target the identified reinitialization timing gaps that
cause CLIENT_NOT_INITIALIZED errors. Production monitoring after
deployment is required to validate the full impact on all Sentry issues
listed below. Some issues may have multiple contributing factors beyond
the reinitialization gap.

**Android Fix:**
Fixed dependency array issue that caused double-triggering of effects on
Android by removing redundant `isControllerInitialized` from dependency
arrays (kept only `initializationState` since `isControllerInitialized`
is derived from it).

## **Changelog**

CHANGELOG entry: Fixed Perps initialization errors causing
CLIENT_NOT_INITIALIZED failures during account and network switches

## **Related issues**

Expected to address:
https://consensyssoftware.atlassian.net/browse/TAT-1932

**Sentry Issues Expected to Improve:**
- [METAMASK-MOBILE-4RN7](https://metamask.sentry.io/issues/6255388807/)
- CLIENT_NOT_INITIALIZED (933 events, 348 users) **[HIGH confidence]** -
Stack trace directly matches reinitialization gap
- [METAMASK-MOBILE-4QB2](https://metamask.sentry.io/issues/6248653802/)
- getUserAccount failed (164 events, 164 users) **[MODERATE
confidence]** - Same error type, may have multiple code paths
- [METAMASK-MOBILE-4R5X](https://metamask.sentry.io/issues/6253182536/)
- Missing activeProvider (97 events, 46 users) **[MODERATE confidence]**
- Same error type, may have multiple code paths
- [METAMASK-MOBILE-4RZD](https://metamask.sentry.io/issues/6259562071/)
- fetchHistoricalCandles error (38 events, 31 users) **[MODERATE
confidence]** - Same error type, may have multiple code paths
- [METAMASK-MOBILE-4SW3](https://metamask.sentry.io/issues/6268066927/)
- Empty account address (17 events, 5 users) **[MODERATE confidence]** -
Same error type, may have multiple code paths
- [METAMASK-MOBILE-4TR2](https://metamask.sentry.io/issues/6275226234/)
- Empty orderbook (2 events, 2 users) **[MODERATE confidence]** - Same
error type, may have multiple code paths

**Validation Approach:**
The initialization guards specifically target the ~200ms
reinitialization gap that occurs during account/network switches.
Post-deployment monitoring is essential to:
1. Confirm reduction in CLIENT_NOT_INITIALIZED error rates
2. Identify any remaining edge cases not covered by these changes
3. Validate that the improvements don't introduce new issues

## **Manual testing steps**

```gherkin
Feature: Perps Controller Initialization Guards

  Scenario: User opens Perps feature on cold start
    Given the app is not running
    When user launches the app
    And navigates to Perps
    Then PerpsLoadingSkeleton should be displayed
    And controller should initialize within 3 attempts
    And user should see market data without CLIENT_NOT_INITIALIZED errors

  Scenario: User switches accounts while viewing Perps
    Given user is on Perps Trade screen with Account A
    When user switches to Account B via account selector
    Then loading state should appear during reinitialization
    And chart data should refresh for new account
    And no CLIENT_NOT_INITIALIZED errors should occur

  Scenario: User switches networks while viewing Perps
    Given user is on Perps with mainnet
    When user switches to testnet via network selector
    Then loading state should appear during reinitialization
    And provider should reinitialize with testnet configuration
    And no CLIENT_NOT_INITIALIZED errors should occur

  Scenario: Initialization fails due to network issues
    Given the device has poor network connectivity
    When user opens Perps feature
    Then controller should retry initialization 3 times with exponential backoff (1s, 2s, 4s)
    And appropriate error state should be shown if all attempts fail

  Scenario: Android chart rendering
    Given user is on Android device
    When user navigates to Perps Trade screen
    Then chart should render candles without showing skeleton indefinitely
    And candles should load correctly on first try
```

## **Screenshots/Recordings**

### **Before**

CLIENT_NOT_INITIALIZED errors occurring during:
- Account switches
- Network changes
- Rapid navigation
- Cold starts with slow connections

See Sentry dashboard for error frequency (1,251 events affecting 590+
users).

### **After**

- Controller initialization tracked via state machine
- Retry logic handles transient failures
- UI operations deferred until initialization complete
- Existing PerpsLoadingSkeleton provides user feedback during
initialization
- Android charts render correctly without dependency array
double-triggering

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds an initialization state machine with retry/backoff, gates UI work
until initialized, updates connection manager to use new `init()`, and
introduces a shared `wait` utility with corresponding tests and state
fixtures.
> 
> - **PerpsController**:
> - Introduces `InitializationState` state machine with
`initializationState/error/attempts` in Redux.
> - Replaces `initializeProviders()` with `init()`; adds retry with
exponential backoff and `wait` utility; defers `isInitialized` until WS
ready; clearer errors in `getActiveProvider`.
> - Network toggle now re-inits via `init()`; exports
`InitializationState`.
> - **Hooks/UI**:
> - `usePerpsPositionData` defers historical fetch, subscriptions, and
intervals until `initializationState === 'initialized'`.
> - **Selectors**:
>   - Adds `selectPerpsInitializationState`.
> - **Connection Manager**:
> - Uses `PerpsController.init()` and shared `wait`;
reconnection/connection flows updated accordingly.
> - **Utilities**:
>   - Adds `utils/wait` with tests.
> - **Tests/Fixtures**:
> - Updates tests to new init flow and guards; mocks `wait`; adds init
retry test; updates Engine tests, snapshots, and initial background
state with new initialization fields.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
08f44da. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… tab (#22199)

<!--
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 updated main navigator to conditionally show rewards or settings
tab
<!--
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**
<img width="333" height="720" alt="image"
src="https://github.com/user-attachments/assets/d901acf6-4da6-46bb-b771-d7ebf5a12343"
/>

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

### **After**
<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2025-11-05 at 08 55 21"
src="https://github.com/user-attachments/assets/e131190b-cdbb-4d73-b90a-ac6049141f11"
/>

<!-- [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]
> Home tab bar now displays Rewards when enabled; otherwise Settings,
removing the always-present Settings tab.
> 
> - **Navigation**:
>   - **HomeTabs (`app/components/Nav/Main/MainNavigator.js`)**:
> - Conditionally render either `Routes.REWARDS_VIEW` or
`Routes.SETTINGS_VIEW` based on `isRewardsEnabled`.
> - Remove the unconditional `Routes.SETTINGS_VIEW` tab to prevent both
tabs appearing simultaneously.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
86e7f21. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

## **Changelog**

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

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

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

CHANGELOG entry: pump btc snap version to 1.4.4

## **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]
> Update dependency `@metamask/bitcoin-wallet-snap` from `^1.4.3` to
`^1.4.4` in `package.json` and `yarn.lock`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
869e710. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Nov 5, 2025
@pull pull Bot added the ⤵️ pull label Nov 5, 2025
@pull pull Bot merged commit ba31132 into Reality2byte:main Nov 5, 2025
5 of 14 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.

10 participants