Skip to content

[pull] main from MetaMask:main#786

Merged
pull[bot] merged 16 commits into
Reality2byte:mainfrom
MetaMask:main
May 26, 2026
Merged

[pull] main from MetaMask:main#786
pull[bot] merged 16 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 26, 2026

See Commits and Changes for more details.


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

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

vinistevam and others added 16 commits May 26, 2026 12:58
<!--
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.
@pull pull Bot locked and limited conversation to collaborators May 26, 2026
@pull pull Bot added the ⤵️ pull label May 26, 2026
@pull pull Bot merged commit 2ff0844 into Reality2byte:main May 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.