[pull] main from MetaMask:main#628
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**
<!--
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?
-->
Use updated image field from CampaignDto to render campaign tile
background.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Medium risk because it changes the `CampaignDto` shape (removing
`statusLabel`, moving `details.image` to top-level `image`) and updates
UI rendering to depend on the new field, which could break if upstream
data isn’t migrated consistently.
>
> **Overview**
> Rewards campaign data is updated to **remove `statusLabel`** and
introduce an optional top-level **`image`** (theme-aware URLs), with
`details.image` removed from the type/state shapes.
>
> UI components (`CampaignTile`, `CampaignStatus`) now render their
background images from `campaign.image` instead of
`campaign.details.image`, and tests across rewards
views/controller/reducer are updated to match the new DTO shape.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5cf9e9f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#27873) …ind CSS <!-- 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 migrates the ChoosePassword view and its FoxRiveLoaderAnimation sub-component away from legacy StyleSheet.create()-based styling toward the MetaMask design system and Tailwind CSS. Jira Link: https://consensyssoftware.atlassian.net/browse/TO-636 ## **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: migrate reveal-srp-ui to design system components and Tailwind CSS ## **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/719aeac1-bb97-424f-af35-7cba9cf84d50 https://github.com/user-attachments/assets/e4e16264-12ed-40be-9d0c-66947522b91e ## **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** > Primarily a UI/styling refactor, but it touches Secret Recovery Phrase reveal/quiz screens where regressions could impact critical security UX and automated flows (Detox selectors/accessibility). > > **Overview** > Migrates `RevealPrivateCredential` (SRP quiz, password entry, SRP text/QR tabs, seed phrase concealer/display) from legacy component-library buttons/text + `StyleSheet.create()` to **design-system React Native components** with **Tailwind (`twClassName`/`tw.style`)** and deletes `RevealPrivateCredential/styles.ts` plus the `styles` prop wiring in related components/types. > > Reuses the shared `SeedPhraseConcealer` in `ManualBackupStep1` (replacing an inline `ImageBackground` blur implementation) and updates the snapshot accordingly. > > Improves testability by adding an `accessibilityLabel` to the password field and updating the Detox page object to locate it via label instead of testID. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d5fa10c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…27861) ## **Description** Adds two new reference documents for the Perps domain: - **perps-caching-architecture.md** — Documents the three-tier caching strategy (real-time WS, session, legacy preload), explains how data flows, and identifies legacy preload as partially redundant now that `PerpsAlwaysOnProvider` keeps WS connected from wallet mount. - **perps-review-antipatterns.md** — Catalogues domain-specific anti-patterns to watch for during code review (controller portability, magic strings, placeholder values, etc.). ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A ## **Manual testing steps** Documentation only — no runtime changes. ## **Screenshots/Recordings** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] 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] > **Low Risk** > Low risk: adds documentation only and does not change runtime behavior, APIs, or data handling. > > **Overview** > Adds a new `perps-caching-architecture.md` reference documenting the current three-tier Perps caching model (WS real-time, session/provider caches, and legacy REST preload), including cache lifetimes/clearing behavior and a roadmap to simplify (disk-backed cold-start cache, removing REST polling, and unifying DEX discovery caches to prevent desync). > > Adds `perps-review-antipatterns.md`, a code-review checklist of Perps-specific pitfalls (controller portability for core sync, avoiding magic constants/placeholders, enforcing provider abstraction, consistent metrics/tracing, WS lifecycle rules, cache invalidation, and testID requirements for agentic/E2E testability). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2511ffb. 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** ERC1155 NFTs were not sendable from the NFT details screen because the `isTradable` guard only allowed `ERC721` tokens, even though the underlying send flow already supports ERC1155. This PR: 1. **Enables the "Send" button for ERC1155 tokens** in `NftDetails` by extending `isTradable` to accept both `ERC721` and `ERC1155` standards when `isCurrentlyOwned` is true. 2. **Adds a loading skeleton on the Amount screen** while `useEVMNfts` asynchronously processes the NFT (resolves IPFS image URLs, fetches ERC1155 balance, computes `networkBadgeSource`). Without this, the screen briefly shows `0 units available` and no image before the data arrives. 3. **Replaces the deprecated `StyledButton` with `Button`** from `@metamask/design-system-react-native` on the NFT details send button, using its built-in `isLoading` and `isDisabled` props to give feedback during the network-switch step. The loading state is propagated through `useEVMNfts` → `useRouteParams` → `Amount`, keeping the data flow explicit and avoiding any inference from data absence (which would cause the skeleton to hang if the NFT is not found). <!-- 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: Added support for sending ERC1155 NFTs from the NFT details screen ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2908 ## **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** https://github.com/user-attachments/assets/bfd2d8d7-1c67-4a87-8d38-ddef60bb7f55 <!-- [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** > Moderate risk because it changes send entry conditions and refactors `useEVMNfts` to be async with a new loading state that affects multiple send screens; bugs could block NFT selection/sending or cause incorrect asset resolution. > > **Overview** > **Enables sending owned ERC1155 NFTs from `NftDetails`** by widening the tradable guard to include `ERC1155` (in addition to `ERC721`) and updating the Send CTA to use the design-system `Button`. > > **Improves Send Amount UX while NFT data resolves** by adding an `isLoading` state to `useEVMNfts`, plumbing it through `useRouteParams`, and showing skeleton placeholders (including balance) on the `Amount` screen. > > **Tightens NFT resolution for send navigation** by matching NFTs by `address` + `chainId` + `tokenId` (important for ERC1155), and updates mocks/snapshots/tests accordingly (including an ERC721 mock and new loading/error-path coverage). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 068ef91. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…on) (#27685) ## **Description** Stop loss and take profit pills were not rendering on activity rows because the HyperLiquid fills API does not return order type information. Fills now get enriched with `detailedOrderType` by cross-referencing historical orders at the provider level. Additionally, the merge logic in both `usePerpsHomeData` and `usePerpsTransactionHistory` now preserves enrichment when WebSocket fills overwrite REST fills. Also fixes the "Liquidated" pill rendering on a separate row by adding the missing `fillTag` style with `flexDirection: 'row'` to PerpsTransactionsView.styles.ts. ## **Changelog** CHANGELOG entry: Fixed stop loss and take profit pills not appearing on recent activity rows in Perps Home and Activity screens ## **Related issues** Fixes: [TAT-2668](https://consensyssoftware.atlassian.net/browse/TAT-2668) ## **Manual testing steps** ```gherkin Feature: Activity pill rendering for TP/SL orders Scenario: Stop loss pill on closed position Given a position was closed via stop loss When the user views recent activity on Perps Home Then the activity row shows a "Stop loss" pill Scenario: Take profit pill on closed position Given a position was closed via take profit When the user views the Activity page Then the activity row shows a "Take profit" pill Scenario: No regression on other pill types Given a position was liquidated When the user views the Activity page Then the "Liquidated" pill renders inline on the Closed Long row ``` ## **Screenshots/Recordings** ### **Before** Pills missing on activity rows for TP/SL closes. "Liquidated" pill on separate row instead of inline with "Closed Long". https://github.com/user-attachments/assets/ef394ef1-97dc-48a9-9780-292bcfd09cd7 ### **After** - Video: `automation/27685/after.mp4` — Perps Activity page with fix applied - CDP eval evidence: 4/4 TP/SL fills enriched (`Stop Market`, `Take Profit Limit`) - `fillTag` style added to ensure pills render inline (row layout) https://github.com/user-attachments/assets/4aa46bef-6bf5-478c-8769-2f0f08509344 ## **Validation Recipe** <details> <summary>Automated validation recipe (validate-recipe.sh)</summary> ```json { "pr": "27685", "title": "Stop loss and take profit pills appear in recent activity", "jira": "TAT-2668", "acceptance_criteria": [ "Stop loss and take profit pills appear inline on the activity row when a position is closed via stop loss or take profit", "The Liquidated pill renders on the same row as the Closed Long label", "No other activity pill types are broken or misaligned", "Behavior is consistent across Perps Home, Perp Market screen, and Activity page" ], "validate": { "static": ["yarn lint:tsc"], "runtime": { "pre_conditions": [ "CDP connected", "Wallet unlocked on Wallet route", "Active account has TP/SL fill history (e.g. 0x316bde)" ], "steps": [ { "id": "nav_activity", "description": "Navigate to Perps Activity with Trades tab", "action": "navigate", "target": "PerpsActivity", "params": { "redirectToPerpsTransactions": true } }, { "id": "wait_load", "description": "Wait for transaction data to load", "action": "wait", "ms": 8000 }, { "id": "verify_enrichment", "description": "Verify REST fills are enriched with detailedOrderType from historical orders", "action": "eval_async", "expression": "Engine.context.PerpsController.getActiveProviderOrNull().getOrderFills({aggregateByTime:false}).then(function(fills){var tpsl=fills.filter(function(f){return f.detailedOrderType&&(f.detailedOrderType.indexOf('Stop')>=0||f.detailedOrderType.indexOf('Take Profit')>=0)});return JSON.stringify({total:fills.length,tpslCount:tpsl.length})})", "assert": { "operator": "not_null" } }, { "id": "scroll_flashlist", "description": "Scroll the FlashList to verify testID targeting works", "action": "scroll", "test_id": "perps-transactions-flash-list", "offset": 400 }, { "id": "scroll_back", "description": "Scroll back to top to show first rows with pills", "action": "scroll", "test_id": "perps-transactions-flash-list", "offset": 0 }, { "id": "check_no_errors", "description": "No errors in Metro logs during Activity page load", "action": "log_watch", "window_seconds": 5, "must_not_appear": ["TypeError", "undefined is not an object"] }, { "id": "screenshot_evidence", "description": "Screenshot showing TP/SL pills on activity rows", "action": "screenshot", "filename": "activity-tpsl-pills.png" } ] } } } ``` </details> ## **Pre-merge author checklist** - [x] I've followed MetaMask Contributor Docs and Coding Standards - [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 format if applicable - [x] I've applied the right labels on the PR ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes how REST and WebSocket fills are merged and enriched across provider, subscription, and UI activity hooks, which can affect transaction history correctness and ordering. > > **Overview** > Restores *Take Profit/Stop Loss* (and related) pills in Perps activity by enriching HyperLiquid `getOrderFills` responses with `detailedOrderType` via a parallel `historicalOrders` lookup, and enriching WebSocket fills using cached order data. > > Updates merge/dedup logic in `usePerpsHomeData` and `usePerpsTransactionHistory` to **preserve REST-derived enrichment** (including liquidation details / non-`Standard` `fillType`) when live WS data overwrites duplicates, with new unit tests covering these cases. > > Adds E2E selectors (`FlashList` + fill tag testIDs) and a small layout fix (`fillTag` row style) so pills render inline and are targetable in automation. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 71223e1. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ent margin rejections (#27417) <!-- 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** When users place a long/short Perps order with the amount slider at 100% (or tap "Max"), the app was sending the full theoretical maximum (available balance × leverage). The HyperLiquid API sometimes rejects these with "Order 0: Insufficient margin to place order" due to fees, rounding, and exchange-side margin checks. **Solution:** Introduce a 0.5% margin buffer on the maximum order amount so that "100%" uses 99.5% of the theoretical max. This is applied in a single place (`getMaxAllowedAmount`), and the order form uses this buffered value for the slider max, Max button, and 100% quick button so all paths stay consistent. The buffer is configurable via `MAX_ORDER_MARGIN_BUFFER` in perps config for future tuning or smarter logic (e.g. fee-based). **Changes:** - **perpsConfig**: Added `MAX_ORDER_MARGIN_BUFFER = 0.005` (0.5%). - **getMaxAllowedAmount**: After existing rounding logic, multiply max by `(1 - MAX_ORDER_MARGIN_BUFFER)` and return `floor(bufferedMax)`. - **usePerpsOrderForm**: `handleMaxAmount` and `handlePercentageAmount(1)` now set amount to `maxPossibleAmount` (the buffered max) instead of computing `balance × leverage` directly. - **Tests**: Updated expectations for low-balance scenarios (e.g. $2 @ 3x → max 5 instead of 6); added test that max is below theoretical after buffer. ## **Changelog** CHANGELOG entry: Fixed Perps orders at 100% margin sometimes failing with "Insufficient margin" by applying a small buffer to the maximum order amount. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2502 ## **Manual testing steps** ```gherkin Feature: Perps order placement at maximum margin Scenario: user places order at 100% (slider or Max) without insufficient margin error Given user is on Perps order view with available balance and an asset selected When user sets amount to 100% via the slider or taps the Max / 100% button Then the amount field shows the buffered max (slightly below theoretical max) And placing the order does not result in "Insufficient margin" rejection from the exchange ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A (behavioral fix; no UI change) ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adjusts core order-sizing calculations for max/percentage selections, which can affect how much users trade and may surface edge cases around rounding and balance updates. Changes are localized and covered by updated/additional tests. > > **Overview** > Reduces Perps *maximum order amount* by applying a configurable **0.5% margin buffer** so “Max”/100% selections are less likely to be rejected as *Insufficient margin*. > > This adds `MAX_ORDER_MARGIN_BUFFER` and applies it in `getMaxAllowedAmount`, then updates `usePerpsOrderForm` handlers to clamp percentage-based amounts and set Max to `maxPossibleAmount` (the buffered max). Tests are updated to reflect new buffered expectations and add coverage for near-100% clamping and buffered-max behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 03168c3. 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** Seedless/OAuth rehydration was prompting biometrics with a wrong password entry too **Solution** Now the flow is password-first: unlockWallet runs with password only. After a successful unlock, post-unlock steps (including optional biometric upgrade). Failed unlocks no longer trigger biometric prompts. Jira: https://consensyssoftware.atlassian.net/browse/TO-600 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TO-600 ## **Manual testing steps** ```gherkin Feature: Seedless OAuth rehydration password before biometrics Scenario: Wrong password does not trigger biometrics before unlock Given the user is on the OAuth rehydration screen with a seedless wallet And device biometrics are available When the user enters an incorrect password and submits Then the app shows an invalid password error And the system biometric prompt is not shown before unlock fails Scenario: Correct password offers biometrics after successful unlock (rehydration) Given the user is on the OAuth rehydration screen And device biometrics are available When the user enters the correct password and submits Then unlock completes successfully And the app may prompt for device biometrics / keychain upgrade only after unlock succeeds ``` ## **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/e5ade971-0f7e-4316-b272-9f2aa7c58fb8 <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the seedless/OAuth rehydration login flow and post-unlock auth preference updates, which can affect authentication UX and keychain storage behavior. Scope is limited to `OAuthRehydration` and adds/adjusts tests to cover ordering and failure cases. > > **Overview** > Updates `OAuthRehydration` so biometric/device-auth prompts no longer occur *before* password verification: `unlockWallet` is called with `currentAuthType: PASSWORD`, and an optional post-unlock step (`upgradeKeychainAuthAfterSuccessfulUnlock`) requests device auth and persists the result via `updateAuthPreference`. > > Extends `OAuthRehydration` tests to assert call ordering (unlock precedes biometrics) and to ensure biometrics/auth-preference updates are not triggered when password unlock fails, including the outdated-password flow. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f0c3963. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…on, env var centralization (#27899) ## **Description** Resolves several core-parity and architecture concerns for the perps controller: ### 1. Backport core-only changes (existing) - **`stopEligibilityMonitoring()`** — Disables geo-blocking eligibility checks when `useExternalServices` is toggled off. - **Dynamic MYX import** — `await import()` → `.then()/.catch()` to avoid bundling heavy MYX dependencies in extension. ### 2. Nested `providerCredentials` on `PerpsControllerConfig` - Restructures flat MYX config fields (`myxAppIdTestnet`, `myxProviderEnabled`, etc.) into `providerCredentials.myx.*`. - Adds `providerCredentials.hyperliquid.*` for builder fee wallet addresses. - New types: `PerpsProviderCredentials`, `HyperLiquidCredentials`, `MYXCredentials`. ### 3. Builder fee address injection - `HyperLiquidProvider` accepts optional `builderAddressTestnet`/`builderAddressMainnet` via constructor. - Falls back to hardcoded `BUILDER_FEE_CONFIG` defaults when env vars are empty. - New env vars in `.js.env.example`: `MM_PERPS_HL_BUILDER_ADDRESS_TESTNET`, `MM_PERPS_HL_BUILDER_ADDRESS_MAINNET`. ### 4. Env var centralization in mobile adapter - New `createMobileClientConfig()` in `mobileInfrastructure.ts` — all `process.env.*` reads in one place. - Engine init (`perps-controller/index.ts`) reduced from ~73 to ~37 lines — pure controller wiring, no env var reads. ### 5. MYX dynamic import race condition fix - `await import()` inside non-async `#createProviders(): void` → `.then()/.catch()` chain. - Removes `@ts-expect-error` suppression. Fixes provider setup race condition flagged by bugbot. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A — architecture cleanup + core parity ## **Manual testing steps** ```gherkin Feature: Provider credentials and builder fee injection Scenario: HyperLiquid uses env-var builder address when set Given MM_PERPS_HL_BUILDER_ADDRESS_TESTNET is set in .js.env When a trade is placed on testnet Then the builder fee uses the env-var address (not hardcoded default) Scenario: HyperLiquid falls back to default when env var is empty Given MM_PERPS_HL_BUILDER_ADDRESS_TESTNET is empty When a trade is placed on testnet Then the builder fee uses BUILDER_FEE_CONFIG.TestnetBuilder Scenario: MYX provider registers via dynamic import Given MYX provider is enabled When PerpsController initializes Then MYX registers asynchronously via .then()/.catch() And initialization completes without waiting for MYX Scenario: Engine init uses adapter for config Given the app starts When PerpsController is initialized Then clientConfig comes from createMobileClientConfig() And no process.env reads exist in the Engine init file ``` ## **Screenshots/Recordings** 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] > **Medium Risk** > Touches Perps provider initialization/selection and geo-eligibility monitoring, which can impact trading availability and protocol routing if misconfigured. Changes are largely additive but include async/dynamic-import ordering and new config wiring that should be validated across networks/providers. > > **Overview** > **Refactors Perps controller configuration to use a nested `providerCredentials` structure** and centralizes all Perps `process.env` reads into `createMobileClientConfig()`, simplifying `perpsControllerInit` to pure wiring. > > **Adds HyperLiquid builder-fee address injection** via new env vars and passes these through `PerpsController` into `HyperLiquidProvider`, falling back to hardcoded defaults when env values are empty. > > **Hardens MYX provider registration and eligibility controls** by switching MYX to a dynamic `import()` flow with explicit error handling/awaiting during initialization, adding `stopEligibilityMonitoring()` (and messenger action typing) to defer geolocation checks, and extending tests to cover these behaviors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 30f6e0a. 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 : )