[pull] main from MetaMask:main#298
Merged
Merged
Conversation
<!-- 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 -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )