[pull] main from MetaMask:main#786
Merged
Merged
Conversation
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Adds the Predict section to the new "Pay with" bottom sheet, completing the dedicated-flow section coverage alongside the existing Perps and Crypto sections. When a user opens "Pay with" during a `predictDepositAndOrder` transaction, they now see a dedicated **Predict** section showing their Predict account balance with an **Add** button that routes to the existing add-funds flow. Tapping the balance row commits "use Predict balance" and dismisses the sheet — mirroring the UX the Perps section already provides for `perpsDepositAndOrder`. The Pay With bottom-sheet entry points inside the Predict order flow (the `PredictPayWithRow` and the "Change payment method" CTA on `PredictBuyWithAnyToken`) now route to the new bottom sheet instead of the legacy `PayWithModal` when the bottom-sheet feature is enabled. The synthetic "Predict balance" row that the legacy modal injects via `usePredictBalanceTokenFilter` is suppressed in that mode so the Predict section in the bottom sheet remains the single source of truth. The Crypto section's checkmark behavior is extended so that when Predict balance is the implicit default (`PredictController.selectedPaymentToken === null` on a `predictDepositAndOrder` flow), the preferred-token row no longer renders a misleading checkmark, and the user-selected-token row is hidden — same "fiat wins / dedicated section wins" semantics that already exist for Perps and fiat payment methods. When the user explicitly picks a crypto token via "Other assets", both pieces of state are updated coherently so the picker reflects the explicit selection. The bottom-sheet route is registered inside the Predict native stack so navigation dispatches from the order screen reach the route reliably, matching the same fix-pattern that was applied to the Perps native stack. <!-- 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/CONF-1363 ## **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/657b12bf-5b0e-4ee3-a1e0-c6c6f9902281 ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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 payment selection, navigation, and order/approval dismissal paths across Predict and confirmations, but follows established Perps patterns with broad test coverage. > > **Overview** > Adds a **Predict** section to the Pay with bottom sheet for `predictDepositAndOrder` flows: Predict account balance, **Add** (add-funds), and row tap to use Predict balance and dismiss—mirroring Perps. > > When `isPayWithBottomSheetEnabled()` is on, Predict buy UI (`PredictPayWithRow`, change payment method) navigates to `CONFIRMATION_PAY_WITH_BOTTOM_SHEET` instead of the legacy modal; those routes are registered on the Predict stack. The legacy modal’s injected Predict balance row (`usePredictBalanceTokenFilter`) is skipped so the bottom sheet Predict section is the single source of truth. > > Crypto section selection logic now treats implicit Predict balance like Perps/fiat: no misleading preferred-token checkmark and hidden user-selected row until the user explicitly picks crypto via Other assets; preferred-token taps on predict flows update both `PredictController` and transaction pay token. > > `PayWithBottomSheet` uses withdraw-specific copy where applicable, and `useDismissOnPaymentChange` can ignore pay-token hydration (`dismissOnPayTokenChange: false`). `usePredictPaymentToken` accepts minimal `{ address, chainId }` inputs for bottom-sheet picks. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cd69bea. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Goktug Poyraz <omergoktugpoyraz@gmail.com> Co-authored-by: Caainã Jeronimo <caainaje@gmail.com>
…ect navigation (#30623) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **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: dismiss AddWallet sheet before entering HW flow to fix post-connect navigation ## **Related issues** Fixes: #29240 ## **Manual testing steps** ```gherkin Feature: view accounts list after adding HW Scenario: user adds HW Given the user has a HW connected When user finishes HW account selection and taps confirm Then they are taken back to the accounts list screen ``` ## **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** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small, route-specific navigation change with targeted unit tests; no auth, data, or import-flow behavior changes. > > **Overview** > When users start **Connect hardware** from `AddWallet`, the screen now calls **`navigation.goBack()`** right after navigating to the HW flow so the add-wallet sheet is removed from the stack. Hardware completion still uses **`pop(2)`** in the HW screens; without this dismiss, one of those pops returned to AddWallet instead of the accounts list (**AccountSelector**). > > Import wallet and import private key behavior is unchanged; tests now assert **`goBack` is not** invoked for those actions and **is** invoked once for hardware. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 68c80e6. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…30584) ## **Description** Pod install fails when `yarn.lock` changes bring new podspecs but `Podfile.lock` still pins old versions. This is common across independent repo clones on the same branch after pulling main — the `fast_float` podspec version mismatch being a frequent offender. Adds a per-worktree staleness marker (`.agent/build-cache/ios/pods-inputs.sha256`) that hashes `yarn.lock + ios/Podfile`. Before pod install in any mode, compares against the saved marker — if mismatched, auto-cleans `ios/Pods` and `Podfile.lock` before proceeding. ## **Changelog** CHANGELOG entry: null ## **Related issues** N/A — infrastructure fix for agentic preflight reliability. ## **Manual testing steps** ```gherkin Feature: Pod staleness auto-detection Scenario: preflight auto-cleans stale pods after pulling main Given a clone with an existing ios/Podfile.lock from a previous build And yarn.lock has changed since the last pod install When user runs yarn a:setup:ios or yarn a:ios Then preflight detects the staleness via marker mismatch And automatically cleans ios/Pods and ios/Podfile.lock And pod install succeeds without manual intervention ``` ## **Screenshots/Recordings** N/A — shell script change, no UI impact. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are limited to agentic preflight and local build-cache fingerprinting; no app runtime, auth, or release pipeline behavior. > > **Overview** > Agentic preflight and the native build-cache fingerprint are tuned so **Metro/debug workflows** stop paying for full native rebuilds when only JS or harness code changes, while **iOS pod state** self-heals after lockfile drift. > > **`compute-cache-fp.js`** adds `ignorePaths` for `app/**`, `scripts/perps/agentic/**`, `tsconfig.json`, and generated CocoaPods outputs (`ios/Podfile.lock`, `ios/Pods/**`). Debug preflight still keys native reuse on real binary inputs (locks, native dirs, patches, etc.) without treating pod-install side effects or live-served JS as fingerprint churn. > > **`preflight.sh`** introduces a per-worktree marker (`.agent/build-cache/ios/pods-inputs.sha256`) from `yarn.lock` + `ios/Podfile`. Before `pod install`, a mismatch deletes `ios/Pods` and `Podfile.lock`; successful installs (including `--repo-update` retry) refresh the marker. **`--clean`** always wipes pod state; non-clean modes auto-clean only when stale. A separate **`js_dependencies_need_install`** gate runs `yarn install --immutable` when `package.json`/`yarn.lock` beat `.yarn-state.yml` or `expo` is missing, with `--check-only` failing loud instead of mutating. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d4fae0b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…er entry is down→up instead of left→right (#30572) ## **Description** The screen transition from market detail to order entry (Long/Short) animated bottom→up (modal style) instead of the expected left→right (push style). Root cause: `getRedesignedConfirmationsHeaderOptions()` applied `transparentModalScreenOptions` (setting `presentation: 'transparentModal'`) when `showPerpsHeader` is `false`. Removed the modal presentation options so the native stack uses default push animation. ## **Changelog** CHANGELOG entry: Fixed screen transition from market detail to order entry to use horizontal push animation instead of vertical modal animation ## **Related issues** Fixes: [TAT-3052](https://consensyssoftware.atlassian.net/browse/TAT-3052) ## **Manual testing steps** ```gherkin Feature: Market detail to order entry transition Scenario: user taps Long on market detail page Given wallet is unlocked and on the Perps tab When user taps any market to open market detail And user taps the Long or Short button Then the order entry screen slides in from right (horizontal push transition) And the order entry screen renders correctly with all fields visible ``` ## **Screenshots/Recordings** Fix removes transparentModal presentation from order entry screen options, changing animation from bottom-up modal to left-right push. **Video** <table> <tr><td align="center" width="50%"><em>Before</em><br/> https://github.com/user-attachments/assets/cd24731d-5771-4735-b8da-add84d67b43f </td> <td align="center" width="50%"><em>After</em><br/> https://github.com/user-attachments/assets/8ff9a06f-53a6-4357-87b3-01344a1c8a21 </td></tr> </table> ## **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. ## **Validation Recipe** <details> <summary>recipe.json</summary> ```json { "title": "Verify market detail to order entry uses horizontal push transition (not modal)", "jira": "TAT-3052", "acceptance_criteria": [ "AC1: Tapping Long/Short on market detail triggers left-right push transition (no transparentModal presentation)", "AC2: Order entry screen renders correctly after navigation from market detail" ], "validate": { "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "setup-nav-market", "nodes": { "setup-nav-market": { "action": "call", "ref": "perps/market-discovery", "params": { "symbol": "BTC" }, "next": "setup-wait-buttons" }, "setup-wait-buttons": { "action": "wait_for", "test_id": "perps-market-details-long-button", "timeout_ms": 10000, "next": "ac1-press-long" }, "ac1-press-long": { "action": "press", "test_id": "perps-market-details-long-button", "next": "ac1-wait-order-screen" }, "ac1-wait-order-screen": { "action": "wait_for", "route": "RedesignedConfirmations", "timeout_ms": 15000, "next": "ac1-assert-no-modal-presentation" }, "ac1-assert-no-modal-presentation": { "action": "eval_sync", "expression": "(function(){ var r = __AGENTIC__.getRoute(); var opts = r ? r.params : {}; return JSON.stringify({ routeName: r ? r.name : 'unknown', showPerpsHeader: opts.showPerpsHeader, presentation: 'checked' }); })()", "assert": { "operator": "eq", "field": "routeName", "value": "RedesignedConfirmations" }, "next": "ac2-screenshot-order-screen" }, "ac2-screenshot-order-screen": { "action": "screenshot", "filename": "evidence-ac2-order-entry-rendered.png", "note": "AC2: Order entry screen rendered correctly after horizontal push transition from market detail", "next": "teardown-go-back" }, "teardown-go-back": { "action": "navigate", "target": "PerpsTrendingView", "next": "gate-done" }, "gate-done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Recipe Workflow** <details> <summary>workflow.mmd</summary> ```mermaid graph TD setup-nav-market["call perps/market-discovery"] --> setup-wait-buttons["wait_for long button"] setup-wait-buttons --> ac1-press-long["press Long button"] ac1-press-long --> ac1-wait-order-screen["wait_for RedesignedConfirmations"] ac1-wait-order-screen --> ac1-assert-no-modal-presentation["eval_sync: assert route"] ac1-assert-no-modal-presentation --> ac2-screenshot-order-screen["screenshot: order entry"] ac2-screenshot-order-screen --> teardown-go-back["navigate: PerpsTrendingView"] teardown-go-back --> gate-done["end: pass"] ``` </details> [TAT-3052]: https://consensyssoftware.atlassian.net/browse/TAT-3052?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small navigation options change for one Perps confirmation screen path, with unit tests and no auth or data handling impact. > > **Overview** > Fixes the **market detail → order entry** navigation so it uses a **horizontal push** transition instead of a **bottom-up modal** when `showPerpsHeader` is false (Long/Short from market detail). > > **`getRedesignedConfirmationsHeaderOptions`** no longer spreads **`transparentModalScreenOptions`** or sets a transparent **`contentStyle`** in that branch, so the native stack keeps default push presentation. The helper is **exported** and covered by new unit tests asserting no `presentation` property and expected header flags. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2df4ae1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Introduces the new QuickBuy amount/main sheet for Top Traders, buy path. - Rebuilds the Top Traders QuickBuy as a modular, host-agnostic flow - Introduces a compound QuickBuy API (`QuickBuy.Root`, `AmountScreen`, `Toolbar`, `Amount`, `Footer`) with shared context and a default `AmountScreen` recipe when hosts only render QuickBuy.Root. - Removes legacy QuickBuyBottomSheet UI and the deprecated QuickBuySheet code. Follow-up PRs: quote details, select quote, Sell mode, pay-with view, etc. <img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-05-25 at 10 07 23" src="https://github.com/user-attachments/assets/145c7a3a-79a8-44a6-b291-922d0f19168d" /> ## **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** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] 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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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 bridge quote submission, Redux bridge state reset, and amount-selection analytics while changing the primary copy-trading buy UX; logic is heavily tested but end-to-end swap flows deserve manual QA. > > **Overview** > Replaces the monolithic **QuickBuyBottomSheet** with a **`QuickBuy/`** module: compound API (`QuickBuy.Root`, `AmountScreen`, `Toolbar`, `Amount`, `Footer`), **`QuickBuyProvider`** / **`useQuickBuyContext`**, and **`TraderPositionQuickBuy`** mapping social `Position` → **`QuickBuyTarget`**. > > The buy sheet UX shifts from **USD preset chips** and a token-detail **header** to an amount-first layout: **toolbar**, large fiat/crypto **amount** (optional toggle), **exchange-rate tag**, **percentage slider** (0–100% of balance), simplified **pay-with** row, and updated **confirm** styling. **`useQuickBuyBottomSheet`** becomes **`useQuickBuyController`**; analytics move to **`useQuickBuyAnalytics`** (slider vs custom input, bridge reset on unmount). Quote wiring in **`useQuickBuyQuotes`** tolerates non-array **`quoteRequest`**. > > The old **`QuickBuyBottomSheet/`** tree (header, footer presets, expanded quote breakdown) is deleted; **`TraderPositionView`** now mounts **`TraderPositionQuickBuy`**. Broad unit test coverage for new primitives and hooks. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2fae60d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
The per-trader notifications bottom sheet had two related problems:
1. The **Save** button was inconsistent with every other notification
setting in the app, which auto-save on toggle. It also added a
confirmation step nobody asked for.
2. Removing the Save button surfaced an existing **snap-back bug** in
`useNotificationPreferences`: the optimistic overlay was being dropped
too eagerly, so a background refetch landing during the in-flight PUT
would briefly flip the Switch back to the pre-PUT value.
**Root cause of the snap-back.** `updatePreferencesSection` writes the
new value to the react-query cache synchronously via
`setQueryData(...)`. That makes `remoteSocialAI === overlay` on the very
next render, the drop effect fires, and the overlay is gone before the
PUT has reached the server. Any subsequent background refetch (focus,
interval, invalidation) returning stale data then overwrites the cache
and snaps the Switch back.
**Fix.** Gate the overlay drop on a `pendingWrites` counter inside
`useNotificationPreferences`. The overlay can only clear once **both**
conditions hold: the PUT has actually settled, AND the remote matches.
This lets the bottom sheet bind the Switch directly to
`isTraderNotificationEnabled(traderId)` — no local state, no
`userTouchedRef`, no open/close gymnastics.
**Bottom sheet cleanup.** With the hook fixed,
`TraderNotificationsBottomSheet` reads straight from the hook. The Save
button, its translation key, and its test id are removed. Each tap calls
`toggleTraderNotification` immediately and the Switch reflects the
optimistic value (or the rolled-back value on PUT failure) without
flicker.
## **Changelog**
CHANGELOG entry: Fixed an issue where the per-trader notifications
toggle could briefly snap back to its previous value while saving, and
removed the redundant Save button in favor of immediate save.
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: per-trader notifications bottom sheet
Scenario: user toggles a trader notification off
Given the user is on a trader profile
And the per-trader notifications bottom sheet is open
And the toggle is currently on
When the user taps the toggle
Then the toggle flips to off immediately
And the toggle does not snap back during the network round-trip
And closing and reopening the sheet still shows the toggle as off
Scenario: PUT fails mid-flight
Given the user has just toggled the per-trader notification
When the backend rejects the PUT
Then the toggle rolls back to its previous value
And reopening the sheet still shows the rolled-back value
Scenario: push notifications are disabled globally
Given push notifications are off
When the user opens the bottom sheet
Then the per-trader toggle is disabled
And tapping it does not fire a PUT
```
## **Screenshots/Recordings**
### **Before**
<img width="416" height="866" alt="image"
src="https://github.com/user-attachments/assets/0711a210-b7a8-493b-80f6-86d5bf388cc8"
/>
### **After**
<img width="416" height="866" alt="image"
src="https://github.com/user-attachments/assets/eb1c7006-a7fc-4b18-ade9-b71751e4630c"
/>
## **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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
## **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**
> UI and preference-sync changes in Social Leaderboard notifications; no
auth or payment paths, with regression tests added.
>
> **Overview**
> Removes the **Save** step from the per-trader notifications bottom
sheet so toggles **persist immediately** via `toggleTraderNotification`,
matching other notification settings.
>
> The sheet no longer keeps local draft state: the switch reads
**`isTraderNotificationEnabled`** from `useNotificationPreferences` and
calls **`toggleTraderNotification`** on change (with existing push-off
guard and switch haptics).
>
> **`useNotificationPreferences`** adds a **`pendingWrites`** counter so
the optimistic overlay is cleared only when no PUT is in flight **and**
remote data has caught up—preventing the toggle from snapping back if
React Query briefly shows stale data mid-request.
>
> Tests cover in-flight overlay stability and updated bottom-sheet
behavior; **`SAVE_BUTTON`** test id and
**`social_leaderboard.trader_notifications.save`** copy are removed.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
336d32e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **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:
## **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**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] 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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Test-only config for remote E2E; no app runtime, auth, or production
paths affected.
>
> **Overview**
> Adds **`projectName`** to BrowserStack **`bstack:options`** in
`BrowserStackConfigBuilder`, using the same naming as **`buildName`**
(`BROWSERSTACK_BUILD_NAME` or `` `${cwdBasename} ${platform}` ``).
Sessions should group under the correct project in the BrowserStack
dashboard alongside existing build/session labels.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
86337d2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** Update icon for switch chart type. ## **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: update icon for line chart ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3260 ## **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] --> <img width="385" height="786" alt="Screenshot 2026-05-21 at 15 12 35" src="https://github.com/user-attachments/assets/69f60c59-8cf8-4717-96a1-ba3ffd04dfcf" /> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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** > Single icon swap in chart UI with no logic, API, or data-handling changes. > > **Overview** > When the advanced chart is in **candlestick** mode, the chart-type toggle now shows the **`Diagram`** icon instead of **`TrendUp`**, so the control better matches switching to a **line** chart. Behavior, labels, and the candlestick icon are unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6e55266. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Rework Rewards tier view
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-05-21 at 21 16 44"
src="https://github.com/user-attachments/assets/8ea03b05-0aea-4bea-b053-43d7d49cfbc5"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-05-21 at 21 16 46"
src="https://github.com/user-attachments/assets/c00ef8f7-15cf-4af9-b797-70f59a52855d"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-05-21 at 21 16 51"
src="https://github.com/user-attachments/assets/6c0713b6-9c94-458d-9218-3797991a9a86"
/>
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [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.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Rewards VIP presentation and i18n only; no API, auth, or payment logic
changes.
>
> **Overview**
> Reworks the **Rewards VIP Tiers** screen from a flat, always-visible
fee grid into a **card-style list** of expandable rows.
>
> **`RewardsVipTiersView`** now drops **tier 0** from the list (`tier >
0`), wraps rows in a rounded **section** container, uses taller loading
skeletons, and passes **`isLast`** for row separators.
>
> **`VipTierRow`** is the main UX change: the header shows **tier
name**, optional **points threshold** (inline, not under the name), and
an **up/down chevron**; **revenue share, swap/perps fees, and referral
points** live in a collapsible panel with **Reanimated** fade/layout.
The **current** tier starts expanded and re-expands when the user’s tier
changes; other tiers toggle on press. Status icons and always-visible
fee columns are removed; **completed** tiers (except current/next) are
dimmed.
>
> Copy updates: **`tier_thresholds`** uses “points” instead of “total”;
English adds **`swap_fees_label`**, **`perps_fees_label`**,
**`referral_points_label`**, and expands **`revenue_share_label`**.
Locale JSON files align **`tier_thresholds`** across languages. Tests
cover filtering, expand/collapse, and the new detail fields.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e1915ec. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** This pull request refines how the application handles "revoke delegation" transactions, particularly in the context of gas fee sponsorship. The changes ensure that "revoke delegation" transactions are not incorrectly marked as gas-fee sponsored and that UI components, fee calculations, and alerts reflect this logic accurately. Additionally, the logic for determining gas fee sponsorship is centralized for consistency across the codebase. **Gas Fee Sponsorship Logic Updates:** * Introduced and used a centralized `shouldApplyGasFeeSponsorship` utility function to determine if a transaction should be treated as gas-fee sponsored, replacing scattered checks throughout the codebase. This ensures that "revoke delegation" transactions are never considered sponsored, even if the flag is set. * Updated the import and usage of sponsorship-related helpers in `TransactionDetails` and related components to use the new centralized logic. **UI and Fee Calculation Adjustments:** * Modified UI components (e.g., `GasFeesDetailsRow`, `TransactionDetailsNetworkFeeRow`) and their tests to ensure that "Paid by MetaMask" is not shown for "revoke delegation" transactions, and that network fee calculations display correctly for these transactions. * Updated fee calculation hooks and their tests to use the new sponsorship logic, ensuring correct fee calculation for "revoke delegation" transactions. **Alert and Confirmation Flow Enhancements:** * Enhanced the insufficient balance alert logic to properly handle "revoke delegation" transactions, ensuring users are notified when they have insufficient funds for these transactions, even if sponsorship flags are set. * Updated the transaction confirmation flow to clear the `isGasFeeSponsored` flag for "revoke delegation" transactions when gasless is supported, preventing incorrect UI indications post-confirmation. **Testing and Utility Improvements:** * Added and updated tests throughout the codebase to verify the new logic for "revoke delegation" transactions, including utility function tests and component behavior. These changes collectively ensure that "revoke delegation" transactions are handled consistently and correctly with respect to gas fee sponsorship across the application. ## **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: disabled smart account on gas fees sponsored network ## **Related issues** Fixes: user not able to disable Smart Account on gas fees sponsored networks ## **Manual testing steps** 1. Go to the Smart Account properties of an account which has his 7702 delegation enabled on a gas fees sponsored network 2. Toggle off the flag regarding the network to disable the delegation 3. The transaction "Account update" dialog pops up, confirm, the transaction is executed and the delegation is disabled 4. The flag for this network is disabled in the Smart Account properties of the account. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="400" height="600" alt="smart account toggle on" src="https://github.com/user-attachments/assets/b0e91a60-6422-472b-b624-53cb69e087f2" /> ### **After** <img width="400" height="700" alt="Disable trx" src="https://github.com/user-attachments/assets/36f1306e-7c1a-4ff8-8263-74ee5e2158c0" /> <img width="400" height="600" alt="Smart account toggle off" src="https://github.com/user-attachments/assets/6e7c5f0d-a4cd-4385-a704-d84122cf9b1e" /> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] 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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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 transaction confirm, publish hooks, and fee/sponsorship logic for a security-adjacent flow (7702 delegation); behavior is well-tested but spans UI and Engine publish paths. > > **Overview** > **Revoke delegation** transactions are excluded from gas-fee sponsorship even when `isGasFeeSponsored` is set, so users can turn off Smart Account (7702) on sponsored networks without misleading “Paid by MetaMask” UI or wrong zero-fee behavior. > > New helpers in `transaction.ts` (`isRevokeDelegationTransaction`, `isTransactionMarkedAsGasFeeSponsored`, `shouldApplyGasFeeSponsorship`) replace scattered `isGasFeeSponsored && isGaslessSupported` checks in confirmation hooks, fee rows, and activity/bridge transaction details. Confirm clears the sponsored flag on submit for revoke delegation; insufficient-balance alerts still apply for those txs. > > **Publish path:** `Delegation7702PublishHook` and transaction-controller init skip the 7702 relay hook for `revokeDelegation` (must publish as top-level `setCode`), while smart transactions can still run for that type. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d2793a8. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
This PR introduces a developer feature that automatically unlocks an
existing wallet after app or Metro refresh in development mode,
eliminating the need to manually enter the password on every refresh.
## Changes
### Core Implementation
- **New environment variable**: `DEV_AUTO_UNLOCK_PASSWORD` - Optional
password for auto-unlock in dev mode
- **Modified**: `app/store/sagas/index.ts`
- Added `tryDevAutoUnlock()` function that attempts to unlock the wallet
using the configured password
- Modified `requestAuthOnAppStart` saga to try dev auto-unlock before
falling back to biometric authentication
- Auto-unlock only activates when:
- `METAMASK_ENVIRONMENT` is set to `"dev"`
- `DEV_AUTO_UNLOCK_PASSWORD` is configured
- A vault exists (wallet was previously created)
- The wallet is currently locked
### Utility Function
- **New**: `app/util/environment.ts::getDevAutoUnlockPassword()`
- Safely retrieves the dev auto-unlock password
- Returns `undefined` in non-dev environments for security
- Returns `undefined` if password is empty or not set
### Documentation
- **Updated**: `.js.env.example` - Added documentation for the new
`DEV_AUTO_UNLOCK_PASSWORD` variable
### Testing
- **Updated**: `app/store/sagas/sagas.test.ts`
- Added tests for dev auto-unlock success path
- Added tests for fallback to normal authentication when password not
configured
- Added tests for fallback when no vault exists
- Added proper mocking and cleanup for the new functionality
- **Updated**: `app/util/environment.test.ts`
- Added comprehensive tests for `getDevAutoUnlockPassword()`
- Tests cover dev environment, non-dev environment, and empty password
scenarios
## How to Use
1. Set `METAMASK_ENVIRONMENT="dev"` in your `.js.env` (typically already
set for dev)
2. Add `export DEV_AUTO_UNLOCK_PASSWORD="your-wallet-password"` to your
`.js.env`
3. Restart Metro bundler
4. The app will now automatically unlock after refresh
**Note**: The password must match your actual wallet password for this
to work.
## Security Considerations
- ✅ Only works when `METAMASK_ENVIRONMENT="dev"`
- ✅ Returns `undefined` in all non-dev environments
- ✅ The `.js.env` file is gitignored and never committed
- ✅ `.js.env.example` shows the variable commented out by default
- ✅ Does not skip biometric authentication in production builds
## **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**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] 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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] 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 app-start wallet unlock behavior, but only when
`METAMASK_ENVIRONMENT` is dev and a local env password is set;
misconfiguration could weaken dev machines if secrets leak from
`.js.env`.
>
> **Overview**
> Adds an optional **dev-only** auto-unlock path so engineers can skip
re-entering the wallet password after Metro or app refresh when a vault
already exists.
>
> Developers can set `DEV_AUTO_UNLOCK_PASSWORD` in local `.js.env`
(documented in `.js.env.example`). `getDevAutoUnlockPassword()` only
returns that value when `METAMASK_ENVIRONMENT` is `"dev"` and the
password is non-empty; otherwise it is ignored.
>
> On startup, `requestAuthOnAppStart` checks that password first: if
configured and `KeyringController` is locked but has a vault, it calls
`Authentication.unlockWallet` with the password and **skips** the usual
seedless/biometric `tryBiometricUnlock` path. If auto-unlock is not
configured, there is no vault, or unlock fails, behavior stays the same
(biometric flow or login reset). Foreground/lock-screen auth is
unchanged.
>
> Unit tests cover the env helper and saga branches (success, missing
password, no vault).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5afd84e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** https://consensyssoftware.atlassian.net/browse/RWDS-1321 Fix rewards modal to have transparent background <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-05-21 at 20 35 08" src="https://github.com/user-attachments/assets/115e8ad0-a5f4-45fa-9442-ea9bbad1c991" /> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Navigation presentation-only change in the Rewards tab; no auth, data, or business logic touched. > > **Overview** > Rewards stack **transparent modals** were showing the default navigator `cardStyle` background instead of letting the underlying Rewards UI show through. > > In `RewardsHome`, each rewards modal screen now sets **`cardStyle: { backgroundColor: 'transparent' }`** alongside `presentation: 'transparentModal'` (bottom sheet, claim sheet, opt-in account group, end-of-season claim). The opt-in screen drops the shared **`clearStackNavigatorOptionsWithTransitionAnimation`** spread in favor of that explicit transparent card style, matching the select sheet pattern already used there. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c800929. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Implements the **Ambient Price Color A/B test** ([ASSETS-3205](https://consensyssoftware.atlassian.net/browse/ASSETS-3205)) for the Token Details page. Robinhood's token/stock detail page adapts its full UI chrome to green or red based on price performance. The hypothesis is that ambient price signaling creates contextual urgency that increases CTA engagement and downstream swap/buy conversion. - **Control (A):** static green sticky buttons regardless of price performance - **Treatment (B):** Ambient price signaling — sticky Swap/Buy buttons, timeframe pills, back arrow, line chart, percentage change text, and chart type toggle adapt to green (positive) or orange-red `#FF5C16` (negative) based on price change for the selected timeframe - Feature flag: `assetsASSETS3205AbtestAmbientPriceColor` (LaunchDarkly, string variants: `control` / `treatment`) - Candlestick chart always shows two colors: green for up-candles, orange-red for down-candles (independent of overall price direction) ## **Analytics Integration** This A/B test automatically enriches analytics events with variant information for funnel analysis: **Enriched Events:** - `Token Details Opened` — Primary entry point, includes `sticky_buttons_shown` - `Token Details CTA Clicked` — Tracks Swap/Buy button engagement - `Swap Page Viewed` — Funnel 1 entry point (via `useAnalytics().trackEvent`) - `Swap Completed` — Conversion metric for swap funnel - `On-ramp Purchase Submitted` — Funnel 2 entry point (via `analytics.trackEvent`) - `On-ramp Purchase Completed` — Conversion metric for on-ramp funnel ## **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: [ASSETS-3205](https://consensyssoftware.atlassian.net/browse/ASSETS-3205) https://www.figma.com/design/iqPZeL5rVg7tWGmacjIeyH/Token-details?node-id=7970-15626&m=dev ## **Manual testing steps** ```gherkin Feature: Ambient Price Color A/B Test Scenario: Control variant shows default static styling Given the feature flag "assetsASSETS3205AbtestAmbientPriceColor" is set to "control" When user navigates to a Token Details page Then all UI elements (buttons, pills, back arrow) render with default static green styling And no ambient price coloring is applied regardless of price direction Scenario: Treatment variant shows green ambient color for positive price Given the feature flag is set to "treatment" When user navigates to a token with positive price change Then the back arrow, line chart, timeframe pills, percentage change text, chart type toggle, and sticky buttons are all green And candlestick chart shows green up-candles and orange-red down-candles Scenario: Treatment variant shows orange-red ambient color for negative price Given the feature flag is set to "treatment" When user navigates to a token with negative price change Then the back arrow, line chart, timeframe pills, percentage change text, chart type toggle, and sticky buttons are all orange-red (#FF5C16) And candlestick chart shows green up-candles and orange-red down-candles Scenario: Legacy chart fallback also adopts ambient color Given the feature flag is set to "treatment" And OHLCV data is unavailable so the legacy chart renders When user views the Token Details page Then the legacy chart line and timeframe pills also adopt the ambient color Scenario: Events include A/B test variant property Given the feature flag is set to "treatment" or "control" When user triggers any of: Token Details Opened, Token Details CTA Clicked, Swap Page Viewed, Swap Completed, On-ramp Purchase Submitted, On-ramp Purchase Completed Then each event payload includes the "ab_test_variant" property matching the assigned variant Scenario: Dark and light mode compatibility Given the feature flag is set to "treatment" When user views Token Details in dark mode or light mode Then the ambient colors render correctly in both modes And selected pill text uses the correct inverse color ``` ## **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/e3a3fe27-b235-492e-806c-5839ab1d1144 <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] 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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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. [ASSETS-3205]: https://consensyssoftware.atlassian.net/browse/ASSETS-3205?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [ASSETS-3205]: https://consensyssoftware.atlassian.net/browse/ASSETS-3205?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches conversion CTAs, chart WebView HTML when colors change, and gated UI (header back, sticky footer) until price direction resolves; fetch timeouts alter failure behavior. > > **Overview** > Adds an **ambient price color** A/B test on Token Details (`assetsASSETS3205AbtestAmbientPriceColor`): **control** keeps today’s static green chrome; **treatment** tints chart line, % change, timeframe pills, chart-type toggle, legacy nav buttons, back arrow, and sticky Buy/Swap CTAs **green or orange-red** (`#FF5C16`) from the selected timeframe’s price direction. > > Charts report direction via `onPriceDirectionChange` / `useAmbientColor` through `Price` → `AssetOverviewContent`, with guards so advanced OHLCV does not override **legacy fallback**. `AdvancedChart` / template gain `lineColorOverride` and related overrides; treatment delays the advanced chart until direction is known and **hides the sticky footer** until then. > > Also adds **3s fetch timeouts** for OHLCV and historical prices, registers the experiment for analytics and bridge submit attribution, and expands unit tests. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a2fe29e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…rget': parameter 1 is not of type 'Event' (#30612) ## **Description** Fix `TypeError: Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'` crash caused by the `CloseEvent` polyfill in `shim.js` using `event-target-shim`'s `Event` class instead of React Native's own `Event` class. When `@nktkas/rews` (Hyperliquid SDK WebSocket transport) dispatches a `CloseEvent` on the native WebSocket, RN's `dispatchEvent` validates `event instanceof RNEvent` — which failed because `event-target-shim` provides a different `Event` class. Replaced `event-target-shim` globals with React Native's own `Event`, `EventTarget`, `CloseEvent`, and `MessageEvent` classes so all `instanceof` checks pass consistently. ## **Changelog** CHANGELOG entry: Fixed a crash caused by CloseEvent dispatch on WebSocket failing instanceof validation ## **Related issues** Fixes: [TAT-3223](https://consensyssoftware.atlassian.net/browse/TAT-3223) ## **Manual testing steps** ```gherkin Feature: CloseEvent dispatch on native WebSocket Scenario: CloseEvent is dispatched on native WebSocket without error Given the app is running with Hyperliquid SDK active When a WebSocket connection is closed while in CONNECTING state Then no TypeError is thrown And the CloseEvent is dispatched successfully ``` ## **Screenshots/Recordings** State-only fix: no visual evidence needed. Both ACs proven via CDP eval (CloseEvent dispatch success) and lint:tsc (no TS errors). ## **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. ## **Validation Recipe** <details> <summary>recipe.json</summary> ```json { "pr": "TAT-3223", "title": "CloseEvent dispatchEvent on native WebSocket must not throw TypeError", "jira": "TAT-3223", "acceptance_criteria": [ "CloseEvent dispatched on native WebSocket must not throw TypeError", "No new TypeScript errors introduced by the fix" ], "validate": { "static": ["yarn lint:tsc"], "workflow": { "pre_conditions": ["wallet.unlocked"], "entry": "ac1-eval-closeevent-dispatch", "nodes": { "ac1-eval-closeevent-dispatch": { "action": "eval_sync", "expression": "(function() { try { var ws = new WebSocket('wss://echo.websocket.org'); var ce = new CloseEvent('close', {code: 1006, reason: '', wasClean: false}); ws.dispatchEvent(ce); ws.close(); return JSON.stringify({success: true, error: null}); } catch(e) { return JSON.stringify({success: false, error: e.message}); } })()", "assert": { "operator": "eq", "field": "success", "value": true }, "next": "ac1-eval-closeevent-props" }, "ac1-eval-closeevent-props": { "action": "eval_sync", "expression": "(function() { var ce = new CloseEvent('close', {code: 1006, reason: 'test', wasClean: true}); return JSON.stringify({type: ce.type, code: ce.code, reason: ce.reason, wasClean: ce.wasClean}); })()", "assert": { "all": [ { "operator": "eq", "field": "code", "value": 1006 }, { "operator": "eq", "field": "reason", "value": "test" }, { "operator": "eq", "field": "wasClean", "value": true } ] }, "next": "ac1-eval-messageevent-dispatch" }, "ac1-eval-messageevent-dispatch": { "action": "eval_sync", "expression": "(function() { try { var ws = new WebSocket('wss://echo.websocket.org'); var me = new MessageEvent('message', {data: 'hello'}); ws.dispatchEvent(me); ws.close(); return JSON.stringify({success: true, error: null}); } catch(e) { return JSON.stringify({success: false, error: e.message}); } })()", "assert": { "operator": "eq", "field": "success", "value": true }, "next": "setup-done" }, "setup-done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Recipe Workflow** <details> <summary>workflow.mmd</summary> ```mermaid graph TD ac1-eval-closeevent-dispatch["ac1-eval-closeevent-dispatch<br/>eval_sync: CloseEvent dispatch on native WS"] ac1-eval-closeevent-props["ac1-eval-closeevent-props<br/>eval_sync: Verify CloseEvent properties"] ac1-eval-messageevent-dispatch["ac1-eval-messageevent-dispatch<br/>eval_sync: MessageEvent dispatch on native WS"] setup-done["setup-done<br/>end: pass"] ac1-eval-closeevent-dispatch --> ac1-eval-closeevent-props ac1-eval-closeevent-props --> ac1-eval-messageevent-dispatch ac1-eval-messageevent-dispatch --> setup-done ``` </details> [TAT-3223]: https://consensyssoftware.atlassian.net/browse/TAT-3223?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches app bootstrap polyfills used by Hyperliquid WebSockets; low blast radius but wrong globals could break perps connectivity at runtime. > > **Overview** > Fixes a **Hyperliquid / perps WebSocket crash** where `dispatchEvent` rejected `CloseEvent` because polyfilled events did not pass React Native’s `instanceof Event` check. > > **`shim.js`** stops using **`event-target-shim`** and hand-rolled `CloseEvent` / `MessageEvent` constructors. When globals are missing, it assigns React Native’s own **`Event`**, **`EventTarget`**, **`CloseEvent`**, and **`MessageEvent`** from RN private web API modules so events dispatched by `@nktkas/rews` match what RN’s WebSocket `EventTarget` expects. > > **`event-target-shim`** is removed from **`package.json`** / lockfile. **`shim.test.js`** adds unit coverage for RN `CloseEvent` and `MessageEvent` properties and inheritance. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5d5cb89. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **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? --> Adds fiat amount entry to the Bridge source amount input so users can toggle between entering a token amount and entering the equivalent fiat value. The source amount remains stored as the token amount for quote requests and balance checks, while the UI can display fiat input, token secondary amounts, and the correct keypad decimal constraints. This also updates the source input cursor behavior, keypad state, and tap target handling so fiat/token toggling keeps the cursor at the end of the visible amount and tapping the full source amount area still focuses the input. ## **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 the ability to enter swap and bridge source amounts in fiat ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-4448 ## **Manual testing steps** ```gherkin Feature: Fiat source amount input Scenario: user enters a source amount in fiat mode Given the user is on the Swap or Bridge screen with source and destination tokens selected And source token price data is available When the user taps the amount type toggle on the source amount field And the user enters a fiat amount with the keypad Then the source input shows the fiat currency symbol And the secondary amount shows the truncated token amount And the quote request uses the converted token amount Scenario: user toggles back to token mode Given the user has entered a fiat source amount When the user taps the amount type toggle again Then the source input shows the token amount And the cursor is positioned at the end of the amount Scenario: user taps the source amount area outside the number Given the source amount keypad is closed When the user taps empty space in the source amount input area Then the source amount input is focused And the keypad opens ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes swap/bridge amount input, quote-driving token amounts, and fiat conversion paths; mistakes could mis-quote or show wrong balances, though behavior is flag-gated and heavily tested. > > **Overview** > Adds **fiat vs token entry** on the Bridge/Swap source field behind the remote flag `enableFiatToggle`. Users can switch with a vertical-swap control; Redux still stores the **token** amount for quotes, balance checks, and `srcTokenAmount`, while the UI can show fiat in the primary field with a token secondary line (and the destination field can mirror fiat-primary when source is in fiat mode). > > **`useSourceAmountInput`** centralizes mode state, fiat↔token conversion (`sourceAmountInputMode` utils), keypad decimals, cursor-at-end on focus/toggle, and fallbacks when price data is missing. **`TokenInputArea`** gains currency prefix, optional secondary line, balance-check override, and the toggle. **`calcTokenFiatRate`** / **`useTokenFiatRate`** supply per-token fiat rates (including native EVM). Max, presets, and flip reset or sync fiat display via `syncFiatAmountToTokenAmount` / `resetToTokenMode`. > > Coverage includes Bridge view component tests (toggle, quotes, cursor, missing price) and unit tests for conversion helpers and `TokenInputArea` overrides. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ace5704. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **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?
-->
`auto-rc-ota-build-core.yml` declares `contents: read` at the top-level
permissions block. When it calls the reusable workflow
`runway-create-ota-production-tag.yml`, GitHub enforces that the callee
can't have more permissions than the caller grants. Since
`runway-create-ota-production-tag.yml` needs `contents: write` (to push
a git tag), the call fails.
## **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**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] 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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] 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.
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 : )