Skip to content

[pull] main from MetaMask:main#834

Merged
pull[bot] merged 27 commits into
Reality2byte:mainfrom
MetaMask:main
Jun 15, 2026
Merged

[pull] main from MetaMask:main#834
pull[bot] merged 27 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull

@pull pull Bot commented Jun 15, 2026

Copy link
Copy Markdown

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 : )

ccharly and others added 27 commits June 15, 2026 11:35
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Fixing a bug with Ledger where the HD path is auto-reset upon
re-connecting (which can happen when selecting accounts). Resulting in
the wrong accounts being derived (addressed picked in the UI won't match
the account address that will be created).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Fixed a bug that would use different HD paths when
deriving Ledger accounts (if a reconnects to the Ledger happen after
submitting the accounts)

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1909

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Non-default HD path for Ledger accounts

  Scenario: user selects a different HD path in the UI
    Given we use a different HD path than the default "Ledger Live" one

    When user selects his accounts for a different HD path
    Then it gets the proper derived addresses
```

## **Screenshots/Recordings**

> [!NOTE]
> Recordings are pretty slow, this got tested on a Pixel 4A with a
Ledger Nano X, in debug mode. The 2nd recording shows the account name
edition page (because I did hit the account name before the account
address, so that's not a regression).

<!-- mms-check: type=screenshot required=true -->

### **Before**


https://github.com/user-attachments/assets/8e8c9fa5-230c-4aab-a8e7-208789b92bed

### **After**


https://github.com/user-attachments/assets/c047e509-8c10-4fd7-b072-4278cef8e336

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes when and where the Ledger keyring HD path is set, which
directly affects which addresses are derived; scope is limited to Ledger
flows and covered by new ordering/defaulting tests.
> 
> **Overview**
> Fixes Ledger account derivation when the device reconnects during
account selection by **moving HD path initialization** out of
`connectLedgerHardware` and into the **Ledger account selector** mount
flow.
> 
> **`connectLedgerHardware`** no longer calls
`setHdPath(LEDGER_LIVE_PATH)` on every connect, so a reconnect mid-flow
does not overwrite a user-selected path (Legacy/BIP44) and cause the
unlocked address to differ from what the UI showed.
> 
> **`LedgerSelectAccount`** now calls `setHDPath(LEDGER_LIVE_PATH)`
after `ensureDeviceReady` and **before** the first account fetch,
establishing a known default for listing while still allowing path
changes via the dropdown (`onSelectedPathChanged`).
> 
> New tests assert Ledger Live is applied on mount even when a
non-default path was stored, and that `setHDPath` runs before
`getLedgerAccountsByOperation`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6e99354. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…501) (#31639)

## **Description**

The mobile Send flow rejected a valid 20-byte Ethereum hex address with
**"Invalid address"** when its casing did not match the EIP-55 checksum
(e.g. `0xcDCB11f5522eD63552016CA00E92d765Ee4C866d`), even though the
same address works on Extension and works on Mobile once re-cased to the
checksummed form (`0xCdCb11f5522ED63552016Ca00E92d765ee4C866d`).

Root cause: `useToAddressValidation` validated EVM recipients with
`isValidHexAddress(toAddress, { mixedCaseUseChecksum: true })`, which
routes mixed-case input through `ethereumjs-util`'s
`isValidChecksumAddress` and rejects any address whose casing fails the
checksum. All-lowercase and all-uppercase addresses already bypassed
this check, so only mixed-case input was affected.

This change drops `mixedCaseUseChecksum: true` so the Send recipient
gate accepts any valid hex address regardless of case, matching
Extension behavior. The shared `isValidHexAddress` util and its
`mixedCaseUseChecksum` option are left untouched, so Contacts
(`validateAddressOrENS`) and `getAddress` keep their current behavior —
this is a Send-scoped fix. Malformed/invalid addresses are still
rejected.

## **Changelog**

CHANGELOG entry: Fixed the Send flow incorrectly rejecting valid
Ethereum addresses whose casing did not match the EIP-55 checksum.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1501

## **Manual testing steps**

```gherkin
Feature: Send accepts valid non-checksummed addresses

  Scenario: Valid mixed-case address that is not EIP-55 checksummed is accepted
    Given the user is on the Send recipient screen on an EVM network
    When the user enters "0xcDCB11f5522eD63552016CA00E92d765Ee4C866d"
    Then the address is accepted and the Review button is enabled

  Scenario: Invalid address is still rejected
    Given the user is on the Send recipient screen on an EVM network
    When the user enters "0x123"
    Then the "Invalid address" error is shown and the Review button stays disabled
```

## **Screenshots/Recordings**

### **Before**

N/A — behavioral validation change; covered by a unit regression test in
`useToAddressValidation.test.ts`.

### **After**

N/A — see manual testing steps above.

## **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
  - 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**

- [ ] 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**
> Narrow change to Send recipient validation with existing
invalid-address rejection preserved; shared address utilities are
untouched.
> 
> **Overview**
> Fixes the mobile **Send** recipient step rejecting valid 20-byte
Ethereum hex addresses when casing did not match EIP-55 (mixed-case
only; all-lower/upper already worked).
> 
> `useToAddressValidation` now gates EVM recipients with
`isValidHexAddress(toAddress)` instead of requiring checksum validation
via `mixedCaseUseChecksum: true`, aligning with Extension. Malformed
addresses still fail; Contacts/ENS paths that use the stricter option
are unchanged.
> 
> Adds a regression test for a valid mixed-case non-checksummed address.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a63003b. 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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

Bump `@metamask/profile-sync-controller` to `^28.2.0`

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes: Bump `@metamask/profile-sync-controller` to `^28.2.0`

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

<!-- 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**

<!-- mms-check: type=checklist required=true -->

<!--
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.
…31700)

## **Description**

When building the QuickBuy "Pay with" network filter pills, the pills
were ordered by the order in which held tokens appeared, so the network
of the token the user is currently viewing could land anywhere in the
list.

This change reorders the pills so the currently viewed token's network
(`target.chain`) is surfaced first, right after the "All" pill. For
example, when viewing SOL, the "Solana" pill now appears second (after
"All") provided the user holds tokens on that network.

Implementation notes:
- A new shared helper `toFilterChainId` converts the target's CAIP chain
id into the chain-id format the token list carries (hex for EVM,
original CAIP for non-EVM like Solana), returning `null` when conversion
fails.
- `QuickBuyReceiveScreen` was refactored to reuse this helper instead of
its previous inline conversion.
- `QuickBuyTokenSelectList` gained an optional `priorityChainId` prop;
when that chain is among the held tokens it is moved to the front of the
pill list. It is a no-op when the user holds no tokens on that network
(reorder only, never inserts).

## **Changelog**

CHANGELOG entry: Reordered the QuickBuy "Pay with" network filters so
the currently viewed token's network appears first.

## **Related issues**

Fixes: Impractical order of network filters in the QuickBuy "Pay with"

## **Manual testing steps**

```gherkin
Feature: QuickBuy "Pay with" network pill ordering

  Scenario: viewed token's network is prioritized in the pills
    Given I hold tokens across several networks including the viewed token's network
    When I open a token (e.g. SOL) and open the QuickBuy "Pay with" sheet
    Then the first network pill is "All"
    And the second network pill is the viewed token's network (e.g. "Solana")

  Scenario: viewed network is not held
    Given I do not hold any token on the viewed token's network
    When I open the QuickBuy "Pay with" sheet
    Then the pills keep their held-token order and no extra pill is added
```

## **Screenshots/Recordings**

### **Before**

<img width="708" height="847" alt="image"
src="https://github.com/user-attachments/assets/3d554803-1d53-4a4c-8f83-5b2d99b0ff86"
/>

### **After**

<img width="671" height="870" alt="image"
src="https://github.com/user-attachments/assets/7a760fee-195e-42c0-ae14-22f10a4c72a5"
/>

## **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.

Made with [Cursor](https://cursor.com)

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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Quick Buy rate labels (toolbar pill and quote details) showed long zero
runs for very small rates (`0.0000425`). Therefore we reuse the existing
`formatSubscriptNotation` helper via a shared `formatQuickBuyRateValue`
util so rates match asset price formatting (`0.0₄425`).


## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TSA-711

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Quick Buy

 Scenario: pre-quote rate pill uses subscript notation for tiny rates
    Given I am on a trader position with a very low-value token (many leading zeros in the rate, e.g. GIGA/SOL)
    And I open Quick Buy
    When the sheet loads before a quote is fetched
    Then the rate pill shows subscript notation (e.g. "1 GIGA = 0.0₄425 SOL")
    And it does not show a long string of leading zeros
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

<img width="394" height="80" alt="Screenshot 2026-06-15 at 10 30 12"
src="https://github.com/user-attachments/assets/0b81634b-5a74-4854-888c-621377f4d9c3"
/>

### **After**

<img width="416" height="87" alt="Screenshot 2026-06-15 at 10 20 40"
src="https://github.com/user-attachments/assets/295469ab-8a9e-4550-8ad9-addac95c15d2"
/>

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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`.
-->

- [ ] 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.
## **Description**

Migrates all currently running main-branch `SmokeAccounts` smoke flows
from Detox to Appium (MMQA-1938).

**Test migration**
- Adds Appium specs for multi-SRP SRP export from account actions and
settings (`tests/smoke-appium/accounts/`).
- Removes the corresponding Detox specs under `tests/smoke/accounts/`
and `tests/smoke/multisrp/` (wallet details, reveal SRP from settings,
add account, export SRP flows).
- The remaining `SmokeAccounts` Appium coverage (create wallet account,
wallet details, reveal SRP) was landed earlier on main; this PR
completes the tag migration by deleting the Detox duplicates and wiring
CI.

**CI / sharding**
- Adds `appium-smoke-tests-android` to the `check-all-jobs-pass` gate so
Appium smoke is required alongside Detox smoke on PRs.
- Runs `SmokeAccounts` on Appium with a 2-shard matrix on iOS and
Android.
- Removes Detox `accounts-*-smoke` jobs now that no Detox
`SmokeAccounts` specs remain.
- Rebalances `SmokeWalletPlatform` Detox shards from 3 → 2 on iOS and
Android.

**Stability fixes**
- Updates `goToAccountActions` to use the V2 account ellipsis control
and asserts QR on Android Appium during SRP quiz completion.
- Fixes an iOS Appium flake by using `wallet-screen`
(`WALLET_CONTAINER`) for `WalletView.container` instead of the
balance-only `balance-container` locator, which is absent under default
zero-balance mocks.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MMQA-1938

## **Manual testing steps**

N/A — test and CI infrastructure changes only. Validation is via the
Appium `SmokeAccounts` CI jobs and local Appium smoke runs.

## **Screenshots/Recordings**

### **Before**

N/A — no user-facing UI changes.

### **After**

N/A — no user-facing UI changes.

## **Pre-merge author checklist**

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

#### 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**

- [ ] 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.


Made with [Cursor](https://cursor.com)
…31691)

## **Description**

<!-- mms-check: type=text required=true -->

`PerpsScreenStack` had `initialRouteName={Routes.PERPS.PERPS_TAB}` (the
`PerpsRedirect` component). React Navigation initialises a nested stack
as `[initialRoute, targetScreen]` when navigated to with an explicit
`screen` param. This meant all 40+ call sites navigating
`Routes.PERPS.ROOT, { screen: X }` produced a stack of `[PERPS_TAB, X]`.
iOS swipe-back (or the hardware/software back button) from `X` landed on
`PerpsRedirect`, which immediately kicked the user out to wallet home.

**Fix:**
1. Change `initialRouteName` to `PERPS_HOME` — stack now initialises as
`[PERPS_HOME, X]`, so swipe-back from any Perps screen lands on
`PerpsHomeView` instead of the redirect.
2. Add `navigation.dispatch(StackActions.replace(PERPS_HOME))` in
`PerpsRedirect` after the wallet-home redirect fires — ensures
`PERPS_TAB` is never left in the stack history for a future back-press
to land on.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Fixed a bug where swiping back in Perps would
unexpectedly navigate the user out to the wallet home screen.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: Navigation-only bug fix — no linked Jira ticket. The root cause
(wrong `initialRouteName` on `PerpsScreenStack`) was identified during
exploratory testing of the Perps swipe-back flow.

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Perps back navigation

  Scenario: user enters Perps via Trade menu and swipes back
    Given the user is on the wallet home screen
    When user taps Trade → Perps
    Then PerpsHomeView is shown
    When user swipes back from the left edge
    Then the wallet home screen is shown (no redirect flash, no loading screen)

  Scenario: user enters Perps via a market card and swipes back
    Given the user is on the wallet home screen with a Perpetuals position card visible
    When user taps the position/market card
    Then PerpsMarketDetailsView is shown
    When user swipes back from the left edge
    Then PerpsHomeView is shown (not wallet home, not a redirect loader)

  Scenario: deep link into Perps still works
    Given the app receives a Perps deep link
    Then the user lands on the correct Perps screen
    And the wallet home shows the Perps tab selected
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — navigation-only fix; no visual change to any screen.

### **Before**

Swipe-back from any Perps screen → brief loading flash → kicked to
wallet home.

### **After**

Swipe-back from a deep Perps screen → PerpsHomeView. Swipe-back from
PerpsHomeView → wallet home cleanly.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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
- Not applicable — this is a navigation stack fix with no
performance-critical operations to trace.

## **Pre-merge reviewer checklist**

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ation (#31684)

## **Description**

The magnifying glass icon on the Perps market detail screen was
navigating to the market list with the current market's category filter
(`defaultMarketTypeFilter`) preselected. This caused users to see a
filtered subset of markets instead of the full list.

This change removes the category filter from the navigation parameters
so users land on an unfiltered market list when tapping the search icon.
The `MARKET_CATEGORY` analytics property and unused
`getMarketTypeFilter` import were also removed.

## **Changelog**

CHANGELOG entry: Fixed magnifying glass on perps market detail screen to
open market list without preselected filters

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3358

## **Manual testing steps**

```gherkin
Feature: Perps market detail search navigation

  Scenario: user taps magnifying glass icon on market detail screen
    Given the user is viewing a perps market detail screen (e.g. BTC-PERP)

    When user taps the magnifying glass icon in the header
    Then the market list screen opens without any category filter applied
    And all available markets are shown (not filtered to crypto/forex/etc.)
```

## **Screenshots/Recordings**

N/A — no visual change, only navigation parameter behavior.

### **Before**

### **After**


https://github.com/user-attachments/assets/2efb178e-9ae4-4f26-b332-845559b3104f


## **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
  - 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**

- [ ] 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.
…list (#31698)

## **Description**

Tokens that the user has hidden via "long tap -> hide" in the wallet
token list were still showing up in the Quick Buy **"Pay with"** source
list.

**Reason:** the "Pay with" list (`usePayWithTokens`) sources held tokens
from `useTokensWithBalance`, which reads EVM tokens from `allTokens`.
Hiding a token does not remove it from `allTokens` — under
unified-assets state it sets
`AssetsController.assetPreferences[assetId].hidden`, and for non-EVM it
lives in `MultichainAssetsController.allIgnoredAssets`. The main wallet
list filters on those, the Quick Buy "Pay with" list did not.

**Solution:** filter hidden tokens out in `usePayWithTokens`, reusing
the *same* consolidated ignored-token selectors the wallet list already
relies on (`getTokensControllerAllIgnoredTokens` for EVM and
`selectMultichainAssetsAllIgnoredAssets` for non-EVM — both already
merge `assetPreferences.hidden` with the legacy ignored collections
behind the unify flag). The per-token check lives in a small, pure,
unit-tested `isPayWithTokenHidden` helper.

## **Changelog**

CHANGELOG entry: Fixed hidden tokens still appearing in the Quick Buy
"Pay with" token list.

## **Related issues**

Fixes: [TSA-649](https://consensyssoftware.atlassian.net/browse/TSA-649)

## **Manual testing steps**

```gherkin
Feature: Hidden tokens are excluded from Quick Buy "Pay with"

  Scenario: a manually hidden token does not appear as a pay-with option
    Given I hold ETH plus a spam token (e.g. POSI) that I have hidden via long tap -> hide
    When I open Quick Buy on an asset and open the "Pay with" token picker
    Then the hidden token is not listed
    And my non-hidden holdings (e.g. ETH) are still listed
```

## **Screenshots/Recordings**

### **Before**

<img width="1244" height="816" alt="image"
src="https://github.com/user-attachments/assets/d175d0e7-c03b-42aa-bf33-779d69059e4d"
/>

### **After**

<img width="497" height="838" alt="image"
src="https://github.com/user-attachments/assets/caca1a6a-8627-4a75-b17e-9ac95dcc043b"
/>

## **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.

Made with [Cursor](https://cursor.com)

[TSA-649]:
https://consensyssoftware.atlassian.net/browse/TSA-649?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…31572)

## **Description**

Bumps `@metamask/transaction-controller` from `67.0.0` to `68.0.0` and
removes all code paths that relied on the incoming-transaction
subsystem.

Changes:
- Remove the `incomingTransactions` constructor option and
`isIncomingTransactionsEnabled` helper from TC init.
- Remove `startIncomingTransactionPolling`,
`stopIncomingTransactionPolling`, and `updateIncomingTransactions`
wrapper functions from `util/transaction-controller` and all call sites
(Nav/Main, Transactions, UnifiedTransactionsView,
MultichainTransactionsView, useSwitchNetworks, useNetworkOperations,
useTokenTransactions).
- Remove the `TransactionController:incomingTransactionsReceived` event
from the token-balances and assets-controller messenger allow-lists.
- Remove `AccountActivityService:statusChanged`,
`AccountsController:selectedAccountChange`, and
`BackendWebSocketService:connectionStateChanged` from the TC messenger
allow-list (TC no longer subscribes to them internally).
- Remove the `gotIncomingTransaction` method from `NotificationManager`
and the `Engine` subscription that called it.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — dependency bump removing deleted APIs; no functional behaviour
change for the user.

## **Screenshots/Recordings**

N/A

### **Before**

### **After**

## **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
  - 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

## **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.
…essages (#31594)

<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

The localization library we use is now configured to only support
placeholders with the syntax "{{ }}", rather than "{{}}" or "%{ }". The
latter format was causing problems with the Turkish locale, where the %
sign would sometimes come directly before a placeholder.

All localized messages have been updated to use "{{ }}" over "%{ }".

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Related: #29951

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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**
> String-only i18n config and JSON updates; low risk aside from
verifying no `%{…}` keys remain in strings that still need
interpolation.
> 
> **Overview**
> **i18n placeholder handling** is tightened so only `{{variable}}`
strings are interpolated, dropping the library default that also matched
`%{variable}`—a change aimed at Turkish strings where a literal `%` next
to `{{…}}` could break parsing.
> 
> Across **locale JSON files** (many languages), remaining `%{…}`
interpolation tokens are converted to `{{…}}` so dynamic copy (fees,
chain IDs, login confirmations, network errors, etc.) still resolves
after the new placeholder rule.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3b3b388. 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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**
Improve the price-alerts feature so that we allow users to edit and
delete alerts

<!-- mms-check: type=text required=true -->

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

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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: allow editing and deleting alerts

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

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

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```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**

<!-- mms-check: type=screenshot required=true -->

<!-- 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**

<!-- mms-check: type=checklist required=true -->

<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

QuickBuy failed to fetch quotes for native EVM tokens (MON on Monad,
HYPE on HyperEVM).
Token Details passes natives as `0x000…0000`, but `useQuickBuySetup`
only handled the CAIP `slip44` path. Bare zero addresses went through
the metadata API, making `destToken` stay `undefined`, and quotes never
ran.
We now detect that and build the destination token from the chain’s
native registry instead of asking the metadata API for a fake ERC-20
address.

<img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-12
at 18 26 13"
src="https://github.com/user-attachments/assets/54caa5f9-16a7-4fbb-9cf1-a749518ff340"
/>


## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TSA-710

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: QuickBuy native token quotes from Token Details

  Scenario: user buys native MON from Token Details
    Given the user has a pay-with balance on Monad or another chain
    And the user opens Token Details for native MON on Monad
    When the user opens QuickBuy and releases the slider after selecting an amount
    Then a quote loads and the receive amount shows MON (not "0 MON")
    And the Buy button becomes enabled when the quote is valid
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

<!-- 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**

<!-- mms-check: type=checklist required=true -->

<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

Fix insufficient fund alert on money account deposit page.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1557

## **Manual testing steps**
NA

## **Screenshots/Recordings**
NA

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.
…31513)

This PR is now focused on the crypto up/down chart outage path: the live
websocket can remain subscribed while producing no renderable live chart
data.

- Keep the chart in loading while the current 30s live window has fewer
than two renderable points.
- Bound that live-window check to points at or before the newest live
tick so future historical or merged points cannot clear loading
prematurely.
- Surface a localized connection-error state after a live market has no
renderable data for the grace period.
- Keep the live subscription active while the error state is shown so
the chart can recover automatically when data resumes.
- Remove unrelated/riskier changes from earlier revisions, including the
Liveline append-delta bridge, parent price throttling,
historical-disable option, paused viewport plumbing, and price-history
sanitization.

<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section blocks the PR
check.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Fixes a Predict crypto up/down chart state where Liveline could be
handed stale or off-window data and render blank even though the
websocket subscription was active. The hook now tracks live stream
freshness and whether the current live window has enough points to draw,
with the count bounded to points at or before the newest live tick so
future historical or merged points cannot falsely clear loading. If no
renderable live data arrives for the grace period, the chart component
shows a localized connection error using
`predict.error.chart_connection_error` while keeping the live
subscription active so it can recover automatically.

## **Changelog**

<!-- mms-check: type=changelog required=true -->

CHANGELOG entry: Fixed a bug that could leave the Predict crypto up/down
chart blank when live price data stopped flowing.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: #31513

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

Automated coverage:

```bash
yarn jest app/components/UI/Predict/hooks/useCryptoUpDownChartData.test.ts app/components/UI/Predict/components/PredictCryptoUpDownChart/PredictCryptoUpDownChart.test.tsx --runInBand --forceExit
```

```gherkin
Feature: Predict crypto up/down live chart outage state

  Scenario: live websocket is connected but no renderable chart data arrives
    Given a live crypto up/down market with historical chart data already loaded
    When the live price stream produces no renderable points for the grace period
    Then the chart area shows the connection error state instead of a blank Liveline canvas

  Scenario: future merged data is outside the live viewport
    Given a live crypto up/down market has one live tick and a future historical point
    When the chart evaluates the current 30 second live viewport
    Then loading remains active until two points exist at or before the newest live tick

  Scenario: live stream resumes
    Given the connection error state is visible for a live crypto up/down market
    When two live price ticks arrive inside the chart window
    Then the connection error clears and the chart loading state resolves
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

### **Before**

N/A - no screenshot captured; the no-live-data blank-chart state is
covered by unit tests.

### **After**

N/A - no screenshot captured; the connection-error recovery state is
covered by unit tests.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes live chart gating and timed outage UX in Predict; behavior is
localized to chart data hooks/UI with broad test coverage and no auth or
payment impact.
> 
> **Overview**
> Fixes Predict **crypto up/down** live charts that could stay
subscribed but show a **blank Liveline** when ticks were missing,
off-window, or stale.
> 
> `useCryptoUpDownChartData` now treats **live loading** as needing at
least **two points inside the 30s viewport** (not just two points
total), marks the stream **stale** after 30s without a tick (spinner
instead of an empty chart), and sets **`connectionError`** after a **12s
grace period** when a live market still has no renderable window data.
The websocket subscription and history polling **stay active** during
the error so the chart can recover when data resumes.
> 
> `PredictCryptoUpDownChart` swaps Liveline for a centered **wifi-off**
message using `predict.error.chart_connection_error` when
`connectionError` is true. Hook and component tests cover reconnect,
stale stream, grace-period, and UI swap behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f68a1d9. 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>
#31718)

<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Removed the trailing slash from the Arc explorer URL defined in
`app/util/networks/customNetworks.tsx` so now the URL is correctly
generated.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```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**

<!-- mms-check: type=screenshot required=true -->

<!-- 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**

<!-- mms-check: type=checklist required=true -->

<!--
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.
…or authenticated Card users (#31707)

## **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?
-->

A Card user who is authenticated but whose KYC verification has not yet
resolved to `VERIFIED` (e.g. `PENDING`, `UNVERIFIED`, `REJECTED`) was
being shown the Money Account ↔ Card linking UI and could attempt to
link, even though the backend cannot complete delegation for them. This
produced a dead-end/error flow for users who are not yet eligible.

This PR introduces a strict KYC gate based on the logged-in Card user's
verification outcome and threads it through the linking logic and the UI
surfaces that expose the link/upsell CTAs:

- Adds `selectCardVerificationStatus` and `selectIsCardVerified`
selectors. `selectIsCardVerified` is `true` only when the account's
`verificationStatus === 'VERIFIED'`. It intentionally does **not**
include the on-chain `isCardholder` signal (that drives CTA visibility,
not link gating).
- `useMoneyAccountCardLinkage` now exposes `isCardVerified` and requires
it for `canLink`/`canSubmitDelegation`. The `startLinkFlow` and resume
(`pendingMoneyAccountCardLink`) effects no-op (and clear the pending
flag) when the user is authenticated but not verified.
- `MoneyHomeView` hides the MetaMask Card section for
authenticated-but-unverified users (`metamaskCardMode = null`) instead
of showing `link`.
- `MoneyOnboardingCard` only shows the link-card action when the
authenticated user is also verified, falling back to the no-card step
otherwise.

Tests were added/updated across the selectors, the hook, and both views
to cover the new not-`VERIFIED` paths.

## **Changelog**

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

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

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

CHANGELOG entry: Fixed the MetaMask Card linking flow so that
authenticated Card users who are not yet verified no longer see the
Money Account card-linking CTA.

## **Related issues**

Fixes: CARD-428

## **Manual testing steps**

```gherkin
Feature: MetaMask Card linking gated on verification status

  Scenario: Authenticated Card user who is not VERIFIED
    Given I am an authenticated Card user
    And my Card account verification status is PENDING (or UNVERIFIED/REJECTED)
    When I open the Money home view
    Then the MetaMask Card section is not displayed
    And the Money onboarding card shows the no-card step instead of the link-card step
    And no card linking flow can be started

  Scenario: Authenticated and VERIFIED Card user
    Given I am an authenticated Card user
    And my Card account verification status is VERIFIED
    And I have the Money account requirements
    When I open the Money home view
    Then the MetaMask Card section is displayed in "link" mode
    And I can start the card linking flow

  Scenario: Cardholder account (on-chain)
    Given my selected wallet is a cardholder account
    When I open the Money home view
    Then the MetaMask Card section is displayed and the link CTA remains available
```

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### 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 -->
…hSell cp-7.82.0 (#31673)

<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Users reported that selecting/deselecting tokens on the Batch Sell
token-select screen felt unresponsive — taps on the checkbox frequently
didn't register, requiring two or three attempts.

The root UX cause is hit-target size: the checkbox and the token row
were two separate press targets, and the checkbox itself is only ~22px.
Taps that landed just outside the checkbox were missed.

This PR makes the **entire token row a single press target**. The
checkbox becomes display-only and the whole row (including the checkbox
column) toggles selection through one `TouchableOpacity`. This is
implemented as an opt-in capability on the shared `TokenSelectorItem` so
other consumers are unaffected:

- `TokenSelectorItem` gains `shouldIncludeChildrenInPressTarget` and
`pressTargetAccessibilityLabel`. When enabled, `children` render
**inside** the row's `TouchableOpacity` (with `pointerEvents="none"`),
and the row press target exposes `accessibilityRole="checkbox"`,
`accessibilityState={{ checked }}`, and the provided label.
- `BatchSellTokenRow` opts in, and its `Checkbox` is now purely visual
(`pointerEvents="none"`, hidden from the accessibility tree, no-op
`onChange`).

Default behavior for all existing `TokenSelectorItem` callers is
unchanged (the flag defaults to `false`).

Note: earlier exploratory changes (a `setSelectedTokens`
functional-update refactor and row memoization) were intentionally
reverted after analysis — they did not address the actual cause. This PR
is scoped to the hit-target fix only.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

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

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

CHANGELOG entry: Fixed unresponsive token selection in Batch Sell by
making the entire token row tappable instead of just the small checkbox.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:
[SWAPS-4616](#31675)

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Batch Sell token selection

  Scenario: user toggles a token by tapping anywhere on its row
    Given Batch Sell is enabled and the user has multiple sellable tokens on a supported chain
    And the user is on the Batch Sell token-select screen

    When the user taps anywhere on a token row (token info, balance area, or the checkbox)
    Then the token's selection toggles on the first tap
    And the checkbox reflects the selected state

  Scenario: user selects and deselects quickly
    Given the user is on the Batch Sell token-select screen

    When the user taps several token rows in quick succession to select and deselect them
    Then every tap registers and the selection count / primary button label updates accordingly

  Scenario: accessibility
    Given a screen reader (VoiceOver/TalkBack) is enabled

    When focus lands on a token row
    Then it is announced as a checkbox with its checked state and the token label
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

<!-- Author: please attach a short screen recording of
selecting/deselecting tokens, since this is a touch-responsiveness
change. -->

### **Before**

<!-- [screen recording: tapping the checkbox often misses; selection
needs 2–3 taps] -->

N/A

### **After**

<!-- [screen recording: tapping anywhere on the row toggles selection on
the first tap] -->

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.


[SWAPS-4616]:
https://consensyssoftware.atlassian.net/browse/SWAPS-4616?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section blocks the PR
check.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Fixes Arc support for mobile client.

Same fixes than the ones added in extension:
MetaMask/metamask-extension#43509

Includes changes from
#31644

This includes:
- Only Arc USDC native token is shown in the main wallet list and the
send flow. The Arc USDC ERC20 is hidden.
- Only Arc USDC ERC20 is shown in the swaps flow. The Arc USDC native is
hidden.
- Aggregated balance is only counted once. No double counting for USDC
native + ERC20.

## **Changelog**

<!-- mms-check: type=changelog required=true -->

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

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

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

CHANGELOG entry: Fixed Arc native token support

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```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**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

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

### **After**

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


https://github.com/user-attachments/assets/e96de5ee-307a-467a-9467-61fb2c568d0a


## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.
## **Description**

Expands the Swap/Bridge amount input currency-mode toggle so users can
tap the full secondary denomination row, including values like `$100.00`
or `1 ETH`, instead of only the swap-arrow icon. This makes the
crypto/fiat toggle easier to hit while preserving the existing secondary
amount display when toggling is unavailable.

## **Changelog**

CHANGELOG entry: Fixed a bug that made the swaps crypto/fiat amount
toggle difficult to tap

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-4619

## **Manual testing steps**

```gherkin
Feature: Swap amount currency-mode toggle

  Scenario: user toggles the source amount display from the secondary denomination row
    Given the user is on the Swap screen with a source token selected and an entered amount
    And the secondary denomination value is visible below the primary amount
    When user taps the secondary denomination value, such as "$100.00" or "1 ETH"
    Then the source amount display toggles between crypto and fiat modes
```

## **Screenshots/Recordings**

N/A - interaction target change covered by focused unit and component
view tests.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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**

- [ ] 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.

## **Testing**

- `yarn jest
app/components/UI/Bridge/components/TokenInputArea/TokenInputArea.test.tsx
--collectCoverage=false`
- `yarn jest -c jest.config.view.js
app/components/UI/Bridge/Views/BridgeView/BridgeView.view.test.tsx
--runInBand --silent --coverage=false`
- `git diff --check`
…1702)

## **Description**

The Related Markets rail on the market detail page previously rendered a
horizontal-scrolling row of `PerpsMarketTileCard` tiles with sparklines,
which caused performance pressure from the `useHomepageSparklines`
subscription.

This PR replaces the rail with a compact 2-row × 6-pill grid (max 12
markets) using the `PerpsPillItem`/`ExplorePill` style — showing symbol
and 24h% with no sparkline. The section header is now a tappable link
that navigates to `PerpsMarketListView` filtered by the collection's
market category, with a new `RELATED_MARKETS_HEADER_TAPPED` analytics
event.

**Changes:**
- Replaced `ScrollView` + `PerpsMarketTileCard` with a 2×6 pill grid
layout
- Removed `useHomepageSparklines` dependency entirely
- Made section header tappable (navigates to filtered market list)
- Added `RELATED_MARKETS_HEADER_TAPPED` interaction type analytics
- Removed `handleScrollBeginDrag` and its slide analytics
- Updated tests to cover header navigation and grid rendering

## **Changelog**

CHANGELOG entry: Changes related markets to use 2-row × 6-pill grid 

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3357

## **Manual testing steps**

```gherkin
Feature: Related Markets pill grid

  Scenario: User views related markets as pills
    Given user is on a market details page with related markets

    When the related markets section loads
    Then it displays up to 12 markets in 2 rows of 6 compact pills
    And each pill shows the market symbol and 24h% change
    And no sparkline charts are rendered

  Scenario: User taps the Related Markets header
    Given user is on a market details page with related markets

    When user taps the "Related Markets" section header
    Then user is navigated to the market list view filtered by the collection's category
    And a RELATED_MARKETS_HEADER_TAPPED analytics event is fired

  Scenario: User taps a market pill
    Given user is on a market details page with related markets

    When user taps a pill in the related markets grid
    Then user is navigated to that market's detail page
    And a RELATED_MARKET_CLICKED analytics event is fired with correct position
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/4b519a97-4e98-4084-8172-81550e4416ef


## **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)

- [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
- [ ] 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**

- [ ] 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.
…ect (#31667)

## **Description**

When connecting a dapp via WalletConnect, the connection screen shows
the correct dapp domain, but the `eth_signTypedData` (V3/V4) signature
request screen showed a random long hex string in the "Request from"
field. This caused user confusion and could trigger false
deceptive/security warnings.

**Root cause:** The typed sign V3/V4 confirmation component
(`InfoSectionOriginAndDetails`) read `approvalRequest.origin` for the
"Request from" value. For WalletConnect (and SDK) connections, `origin`
is the permission subject — the pairing topic / channelId hex — not the
dapp domain. Other parts of the codebase (e.g. `useApprovalInfo`,
`useOriginTrustSignalAlerts`) already derive the signature origin from
`approvalRequest.requestData.meta.url`, which holds the dapp's
self-reported URL.

**Solution:** Use `approvalRequest.requestData.meta.url` for the
"Request from" field, falling back to `approvalRequest.origin` when the
metadata URL is absent. This is consistent across connection types

## **Changelog**

CHANGELOG entry: Fixed an issue where signTypedData requests over
WalletConnect showed a random hex string instead of the dapp domain in
the "Request from" field

## **Related issues**

Fixes: #29072

## **Manual testing steps**

```gherkin
Feature: Signature request origin for WalletConnect

  Scenario: user signs typed data over WalletConnect
    Given a dapp is connected to MetaMask Mobile via WalletConnect
    And the connection screen showed the correct dapp domain

    When the dapp triggers an eth_signTypedData (V3/V4) request
    Then the signature request screen shows the dapp domain in "Request from"
    And no random hex/string is displayed
    And no false deceptive warning is triggered
```

## **Screenshots/Recordings**

### **Before**


https://github.com/user-attachments/assets/43c84567-a9b2-4cce-992d-99efe909983a


<!-- "Request from" shows a long hex/pairing-topic string (see issue
#29072) -->

### **After**


https://github.com/user-attachments/assets/0252e191-3112-4088-a356-a7ab7793e238


<!-- "Request from" shows the dapp domain, matching the connection
screen -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Reverts the temporary Crowdin workflow post-processing for Turkish
percentage placeholders.
We are standardizing on `{{}}` placeholders only, so we no longer need
the script/job step that rewrites `%{{...}}` / `%%{...}` placeholder
formats after Crowdin downloads translations.
This removes:
- the custom Crowdin localization branch override
- the Turkish placeholder fix step from the Crowdin download workflow
- `scripts/fix-turkish-percentage-placeholders.js`


## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```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**

<!-- mms-check: type=screenshot required=true -->

<!-- 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**

<!-- mms-check: type=checklist required=true -->

<!--
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.
…trics, MetricsEventBuilder) and remove saveDataRecording chain (#31256)

## **Description**

The final deletion step of the analytics migration. Removes all legacy
analytics symbols that are no longer referenced (PRs #31249#31255
remove the last consumers).

> ⚠️ **Merge order**: This PR must be merged **after** PRs #31249#31255
(the owner-based consumer migrations). CI will show expected failures
until those PRs land on `main`.

**Deleted files:**
- `app/components/hooks/useMetrics/` (hook + HOC + types)
- `app/core/Analytics/MetaMetrics.ts` + test
- `app/core/Analytics/MetricsEventBuilder.ts` + test
- `app/core/Analytics/MetaMetricsTestUtils.ts` + test
- `app/components/hooks/useAnalytics/withAnalyticsAwareness.tsx` + types
+ test (superseded by the hook directly)

**Modified:**
- `MetaMetrics.types.ts` — converted to a re-export barrel
(data-deletion types stay local)
- `app/core/Analytics/index.ts` — removes `MetaMetrics` class export
- `useAnalytics.ts` / `useAnalytics.types.ts` — removes
`addTraitsToUser` field

**Removes the `saveDataRecording`/`dataRecorded` chain (F.1):**
The chain (`SAVE_DATA_RECORDING_FLAG` → `AppStateEventListener` →
`useAnalyticsDataDeletion` → `DeleteMetaMetricsData`) was redundant. The
"Delete MetaMetrics Data" button is disabled while the deletion is
in-flight using component state (`isDataDeleteStarted`), which is
already sufficient. Removing this chain eliminates unnecessary
AsyncStorage reads on every app-state change.

**Also updates:** CODEOWNERS, `analyticsMock.ts` (removes stale
`addTraitsToUser`/`isDataRecorded`), `testSetup.js`, and related test
mock cleanup.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: #26686

## **Manual testing steps**

N/A — analytics-only refactor, no behaviour change.

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed MetaMask Contributor Docs and MetaMask Mobile Coding
Standards.
- [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 format if applicable
- [x] I've applied the right labels on the PR (see labeling guidelines).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
- [x] I've tested with a power user scenario
- [x] 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.

Made with Cursor

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Large deletion/refactor across analytics, privacy settings, and
app-state tracking; delete-metrics UX now relies on local state and
metrics opt-in rather than persisted “data recorded” flags.
> 
> **Overview**
> Completes the analytics migration by **removing legacy entry points**
(`useMetrics`, `withMetricsAwareness`, `withAnalyticsAwareness`,
`MetaMetrics`, `MetricsEventBuilder`, `MetaMetricsTestUtils`) and
slimming **`useAnalytics`** to delegate directly to `analytics` /
`AnalyticsEventBuilder` (drops `addTraitsToUser`, `isDataRecorded`, and
the `trackEvent(..., saveDataRecording)` side effects).
> 
> **Deletes the `saveDataRecording` / `ANALYTICS_DATA_RECORDED`
pipeline:** no more `updateDataRecordingFlag` on track, no
`hasCollectedDataSinceDeletionRequest` from Segment status checks, and
**`DeleteMetaMetricsData`** resets local “data tracked since deletion”
on successful task creation instead of syncing from storage on mount.
> 
> `MetaMetrics.types.ts` becomes a **re-export barrel** toward
`util/analytics`; CODEOWNERS and global test mocks are updated
accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1dea68e. 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>
)

## **Description**

<!-- mms-check: type=text required=true -->

On Android, **Settings → Advanced → Download State Logs** was slow to
respond, and when the share window finally appeared it only offered
"send to" targets (email/messaging/apps) with no way to actually save or
download the logs file.

The cause was that Android shared the logs as a base64 `data:text/plain`
URL via `Share.open`. Encoding the entire state to base64 was slow for
large states, and the result was a text-only share intent with no file
to save.

This PR makes state logs a real file download on both platforms:

- The logs are written to a file (as iOS already did) and shared by
their **plain path** with a `filename` and `application/json` MIME type.
`react-native-share` copies the file into its own FileProvider and
shares a `content://` URI, so Android's share sheet now offers "Save to
Files"/Drive. (A raw `file://` URI is intentionally avoided — it would
crash Android with `FileUriExposedException`.)
- Dropping the base64 encoding step also removes the delay that prompted
the report.

iOS behavior is unchanged in practice (it already wrote and shared the
file); the share path is now unified across platforms.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Fixed Download State Logs on Android so the logs can be
saved/downloaded as a file, and removed the delay before the share sheet
appears

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: #24359

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Download state logs on Android

  Scenario: User downloads and saves state logs
    Given I am on an Android device with the wallet unlocked
    And I navigate to Settings > Advanced

    When I tap "Download state logs"
    Then the share sheet appears promptly
    And it offers an option to save/download the file (e.g. "Save to Files"/Drive)

  Scenario: User saves the file
    Given the share sheet is open
    When I choose "Save to Files" (or Drive) and confirm
    Then a "state-logs-v<version>-(<build>).json" file is saved and can be reopened
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

### **Before**

<!-- Recording: share sheet appears delayed with only "send to" targets,
no save/download option (per issue #24359). -->

Not applicable

### **After**

<!-- Recording: share sheet appears promptly and offers "Save to Files";
file is saved. -->

Not applicable
## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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**

- [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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

**Problem**

When editing a position's TP/SL and tapping directly from the price
field to the % gain/loss field, typing a percentage did not auto-fill
the trigger price and the Set button stayed disabled. iOS-only bug.

**Root cause**

The iOS keyboard-dismiss fix introduced a boolean guard
(`isProgrammaticDismissRef`) that was set synchronously on every input
focus. On iOS, the new field's `onFocus` fires before the old field's
`onBlur`, so the guard was active when the price field's blur arrived —
suppressing it and leaving `tpPriceInputFocused` stuck `true`. The
percentage→price auto-fill was gated on `!tpPriceInputFocused`, so it
never ran.

**Fix**

Scoped the guard to a specific input — replaced the boolean ref with a
string | null ref that stores the id of the field being dismissed. Only
that field's programmatic blur is suppressed; all other fields' genuine
blurs (including the previously-focused price field) are delivered
normally and correctly clear focus state.

Hardened the hook — removed the `!tpPriceInputFocused` /
`!slPriceInputFocused` gate from the percentage change handlers
entirely. When the user is typing a percentage, that field is by
definition the active source of truth and the trigger price must always
be computed, regardless of stale focus flags.

**Tests**

Added a regression test for the iOS focus/blur race (focus % before blur
on price, no timer flush) verifying the price field's blur handler still
fires.

Updated and added hook-level tests confirming percentage→price auto-fill
works even when a price field's focus flag is stale.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```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**

<!-- mms-check: type=screenshot required=true -->

Android:


https://github.com/user-attachments/assets/eb2b8f2a-4243-409b-9660-4c01a862237b

iOS:

https://github.com/user-attachments/assets/20902575-80bf-4a70-bf9b-d5c8a2d10bb1


## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.
<!--
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.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section blocks the PR
check.

Sections without a directive are checked for structural presence only.
-->

## **Description**
* Default-check the marketing updates opt-in on ChoosePassword for
social login (OAuth) users whose device locale indicates the USA.
Rest-of-world social login users keep marketing unchecked by default.
SRP / non-OAuth flows are unchanged.

* Jira: https://consensyssoftware.atlassian.net/browse/TO-776
<!-- mms-check: type=text required=true -->

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

## **Changelog**

<!-- mms-check: type=changelog required=true -->

<!--
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: Default-checked marketing updates opt-in for USA social
login users during onboarding password setup.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: https://consensyssoftware.atlassian.net/browse/TO-776

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature:  USA marketing opt-in default for social login users

  Scenario: USA social login user sees marketing opt-in checked by default
    Given seedless onboarding is enabled
    And the device/simulator region is set to United States (en-US locale)
    And the app is freshly installed or reset

    When the user creates a wallet via social login (e.g. Google)
    And the user reaches the Choose Password screen

    Then the marketing updates checkbox is checked by default
    And the user can submit without manually checking the box
    And marketing opt-in is sent as true on wallet creation

  Scenario: non-USA social login user sees marketing opt-in unchecked by default
    Given seedless onboarding is enabled
    And the device/simulator region is set outside the USA (e.g. United Kingdom)
    And the app is freshly installed or reset

    When the user creates a wallet via social login (e.g. Google)
    And the user reaches the Choose Password screen

    Then the marketing updates checkbox is unchecked by default
    And marketing opt-in is sent as false unless the user checks the box

```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

<!-- 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/9b4f24a9-4d09-4f3a-b958-d8a15330016c


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

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes default marketing consent for OAuth users in US locales, which
is compliance-sensitive; logic is localized and covered by tests, with
safe fallbacks when Intl fails.
> 
> **Overview**
> **ChoosePassword** now initializes the marketing / acknowledgement
checkbox from **`getDefaultMarketingOptInChecked`**, which depends on
OAuth onboarding (`oauthLoginSuccess`) and **`isUsaDeviceRegion()`**
(device `Intl` locale, `US` region only—no geolocation).
> 
> For **social login (OAuth)** users, the marketing opt-in starts
**checked in the USA** and **unchecked elsewhere**; submitting without
toggling the box sends the matching value to
**`OAuthLoginService.updateMarketingOptInStatus`**. **SRP / non-OAuth**
flows are unchanged: the checkbox stays **unchecked** by default
(including USA), and submit still requires checking it.
> 
> New helpers live under **`app/util/region`** and
**`app/util/onboarding`**, with unit and **`ChoosePassword`**
integration tests.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c650e7c. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Jun 15, 2026
@pull pull Bot added the ⤵️ pull label Jun 15, 2026
@pull
pull Bot merged commit 9ad1a2d into Reality2byte:main Jun 15, 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.