[pull] main from MetaMask:main#834
Merged
Merged
Conversation
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
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 -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )