[pull] main from MetaMask:main#777
Merged
Merged
Conversation
## Summary
- Adds a `cleanup-ci-js-deps` job that deletes the `ci-js-deps` workflow
artifact via the GitHub REST API once all consumers have finished.
- The artifact is ~635 MB and was previously retained for the full
`retention-days: 1` minimum. With 30+ PRs/day this accumulates **~19+
GB** of live artifact storage at any given time, none of which is ever
reused (every push re-creates it from scratch).
- The cleanup job runs with `if: always()` so it fires on pass, fail,
and the `merge_group` case where `merge-unit-and-component-view-tests`
is skipped.
- Guarded by `inputs.runner_provider != 'namespace'` — same condition as
the upload/download steps. On Namespace runners the artifact is never
created so there is nothing to clean up.
- This is a **TEMP** fix like the upload/download steps themselves; all
four should be removed together once Namespace becomes the default
runner.
## How it works
```
prepare-ci-js-deps → unit-tests (×10) ↘
→ component-view-tests (×2) → merge-unit-and-component-view-tests
↓
cleanup-ci-js-deps ← deletes artifact
```
The artifact now lives only for the duration of the CI run (~20–40 min)
instead of up to 24 hours.
## Test plan
- [ ] Verify the `cleanup-ci-js-deps` job appears in the Actions run
after unit/CV tests and merge job complete
- [ ] Confirm the `ci-js-deps` artifact is absent from the run's
artifact list after the cleanup job finishes
- [ ] Confirm that a failed unit-test shard does not prevent the cleanup
job from running (`if: always()`)
- [ ] Confirm that on a `merge_group` event (where
`merge-unit-and-component-view-tests` is skipped) the cleanup job still
runs
Made with [Cursor](https://cursor.com)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk CI-only change; main failure mode is the new
artifact-deletion step lacking permissions or not finding the artifact,
which could cause an extra job to fail without affecting product code.
>
> **Overview**
> Reduces GitHub Actions artifact storage by adding a **temporary**
`cleanup-ci-js-deps` job that, on non-Namespace runs, uses
`actions/github-script` to find and delete the `ci-js-deps` artifact
after `unit-tests`, `component-view-tests`, and
`merge-unit-and-component-view-tests` complete (runs even on failures
via `always()`).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c689475. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Adds missing ab testing properties to whats happening events.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: no-changelog
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: expands analytics allowlisting for an existing A/B test and
adds unit coverage; no changes to business logic beyond which events get
enriched.
>
> **Overview**
> Ensures the Whats Happening Explore A/B test assignment
(`active_ab_tests`) is attached to additional Whats Happening analytics
events, not just `EXPLORE_INTERACTED`.
>
> Updates the allowlist in `TrendingView/abTestConfig.ts` to include
scroll, details open/view/close, and interaction events, and extends
`enrichWithABTests` test coverage via a parameterized test to validate
enrichment across those event types.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f6e0a02. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary This PR prevents Predict claim confirmations from being stranded when the user dismisses the full-screen confirmation with a back gesture instead of the close button. The Predict claim screen now opts into the existing full-screen confirmation back-swipe cleanup hook, so gesture and Android hardware-back dismissals reject the active confirmation instead of only removing the route. The shared confirmation loader also disables gestures and consumes Android back presses while there is no approval request yet, so users cannot leave the loading screen before there is a request that can be rejected. ## Root Cause Predict claim used a custom close button that called the normal reject path, but the screen did not install the existing back-swipe cleanup hook used by other full-screen confirmations. A route-level back dismissal could therefore remove the confirmation UI while leaving the approval and unapproved transaction in controller state. In the real claim flow, that can leave the Predict pending claim entry active, causing later claim attempts to be treated as already in progress. Original ticket: https://consensyssoftware.atlassian.net/browse/CONF-1375 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes navigation gesture/back-button handling in the confirmations flow, which could affect user ability to exit confirmations if conditions are wrong. Main behavioral change is gated to the pre-`approvalRequest` loading state and full-screen Predict claim dismissals, with added tests to reduce regressions. > > **Overview** > Prevents users from dismissing the `Confirm` loading state before an `approvalRequest` exists by **disabling navigation gestures** and **consuming Android hardware back presses** until there’s something to reject. > > Updates the Predict claim confirmation info screen to opt into the shared `useClearConfirmationOnBackSwipe` cleanup so back-swipe/hardware-back dismissals trigger the normal reject path, and adds focused unit tests for both behaviors. Also updates fixture validation ignore lists to exclude `engine.backgroundState.MoneyAccountController.moneyAccounts` from schema comparisons. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 86388d2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…detection modals (#30499) ## **Description** Part of the analytics cleanup workstream (#26686). Renames `.addTraitsToUser()` → `.identify()` in the NFT auto-detection modal components (`NFTAutoDetectionModal` and `CollectibleDetectionModal`). Updates the corresponding test file to use the `identify` override in `createMockUseAnalyticsHook`. Files touched: - `NFTAutoDetectionModal/NFTAutoDetectionModal.tsx` — rename `.addTraitsToUser` → `.identify` - `CollectibleDetectionModal/index.tsx` — rename `.addTraitsToUser` → `.identify` - `NFTAutoDetectionModal/NFTAutoDetectionModal.test.tsx` — update mock and assertions to use `identify` ## **Changelog** CHANGELOG entry: null ## **Related issues** Closes: #26822 Refs: #26686 ## **Manual testing steps** N/A ## **Screenshots/Recordings** ### **Before** N/A — no UI changes. ### **After** N/A — no UI changes. ## **Pre-merge author checklist** - [x] I've followed the [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)) ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, test affected areas) - [ ] I confirm that this PR addresses what is claimed in the PR title - [ ] I confirm that I've manually reviewed the changes if not manually tested Co-authored-by: Cursor <cursoragent@cursor.com>
…29465) ## **Description** TLDR: Adds Telegram as a third OAuth provider (alongside Google and Apple) for seedless onboarding, behind the existing onboarding flow surfaces. This wires a new `TelegramLoginHandler` into the existing `OAuthService` infrastructure. The flow is backend-mediated: 1. App opens an in-app browser session against the auth server's `/api/v2/telegram/login/initiate` endpoint with a PKCE code challenge. 2. Backend handles the redirect to Telegram, exchanges the Telegram code, and stores tokens keyed by the code challenge. 3. Backend redirects back to the app via deep link. 4. App calls `/api/v2/telegram/login/verify` with the code verifier, exchanges the resulting OIDC token through Hydra's JWT-bearer grant, and mints the standard auth-service token set used by seedless onboarding. Telegram entries have been added to `OAUTH_CONFIG` for every build type (development, main_*, flask_*) and platform (Android/iOS), and Telegram is exposed in the `Onboarding`, `OnboardingSheet`, and `WalletRecovery` views. Architecture and bot-management notes are captured in `docs/frontend-telegram-integration-architecture.md`, `docs/telegram-oidc-bot-creation-management.md`, and `docs/auth-backend-consolidation-strategy.md`. Jira: https://consensyssoftware.atlassian.net/browse/TO-738, https://consensyssoftware.atlassian.net/browse/TO-751 ## **Changelog** CHANGELOG entry: Added Telegram as a login option for seedless onboarding. ## **Related issues** Fixes: ## **Manual testing steps** \`\`\`gherkin Feature: Telegram OAuth onboarding Scenario: New user creates a wallet via Telegram Given the app is freshly installed And the user is on the Onboarding screen When the user taps "Continue with Telegram" And completes the Telegram authentication in the in-app browser Then the user is returned to the app And a new seedless wallet is created And the account name is "Telegram <idp_sub>" Scenario: Returning user recovers a wallet via Telegram Given a wallet was previously created with Telegram And the app is freshly installed When the user taps "Continue with Telegram" on the WalletRecovery screen And completes Telegram authentication Then the existing wallet is rehydrated Scenario: User cancels the Telegram auth session Given the user is on the Onboarding screen When the user taps "Continue with Telegram" And dismisses the in-app browser Then the app remains on the Onboarding screen with no error \`\`\` Test on both Android and iOS — Android required a session-persistence fix (commit \`bce106c633\`). ## **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. ## **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] > **High Risk** > High risk because it extends seedless onboarding authentication/token flows with a new Telegram provider, new redirect/exchange logic, and updated client ID handling that could impact login, token refresh, and account identity data. > > **Overview** > Adds Telegram as a third OAuth provider for seedless onboarding, gated by a new remote feature flag `telegram_login_enabled` (with env override) and surfaced in the onboarding bottom sheet when enabled. > > Implements a new `TelegramLoginHandler` and extends the OAuth factory/config/constants to support Telegram-specific redirect URIs, connection IDs, and a backend-mediated verify → Hydra token exchange → mint flow; token refresh logic is updated to use Telegram’s platform-specific client IDs and the OAuth pipeline now derives `{userId, accountName}` via `loginHandler.getUserInfo()` (including Telegram-provided `account_name`). > > Updates onboarding/recovery UI and analytics to recognize Telegram accounts (new `AccountType` variants, Telegram-specific copy, icon/styling), adds registry/CI flag constant wiring, and adjusts several UI tests/snapshots to assert loading via `accessibilityState.busy` instead of a `spinner-container` test id. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6bd5282. 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: hung <hung@tor.us> Co-authored-by: Gaurav Goel <grvgoel19@gmail.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…30508) ## **Description** When the user taps "Add" on the Predict balance row in the pay-with picker during a `predictDepositAndOrder` confirmation, the existing flow creates a `predictDeposit` transaction **on top of** the active `predictDepositAndOrder` confirmation. This causes two issues: 1. Stacking confirmations is unsafe - we assume a single active transaction at a time 2. The pay-with modal doesn't work on the second confirmation because it's on the wrong navigation stack ### Fix Mirror the Perps pattern (`usePerpsBalanceTokenFilter`): 1. **`dismissActivePreviewSheet()`** - instantly removes the `PredictPreviewSheet` overlay (module-level function that calls `setBuyParams(null)` on the active provider) 2. **`onReject()`** - rejects the existing `predictDepositAndOrder` approval 3. **`navigation.navigate(ADD_FUNDS_SHEET)`** - opens the deposit flow cleanly ### Changes - **`usePredictBalanceTokenFilter.ts`** - `handleAddFunds` now calls `dismissActivePreviewSheet()` + `onReject()` before navigating to Add Funds - **`PredictPreviewSheetContext.tsx`** - Extended `SheetModeProviderEntry` with `dismissPreviewSheet` callback; added exported `dismissActivePreviewSheet()` function that dismisses the active provider's sheet from anywhere (including outside the context tree) - **`contexts/index.ts`** - Export `dismissActivePreviewSheet` - **`usePredictBalanceTokenFilter.test.ts`** - Updated test to mock `useApprovalRequest`, `usePredictDeposit`, and assert `onReject` is called ## **Manual testing steps** 1. Open a prediction market and tap a bet outcome 2. In the buy sheet, tap "Pay with" to open the token picker 3. Tap "Add" next to "Predict balance" 4. Verify: the buy sheet and `predictDepositAndOrder` confirmation are dismissed 5. Verify: the Add Prediction Funds flow opens cleanly on top ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** https://github.com/user-attachments/assets/f5b3bce0-324b-4f47-aaaa-6568d8258433 ### **After** https://github.com/user-attachments/assets/0862c578-d0bb-464c-b380-d6401fc41997 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) - [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 - [x] I've properly set the title of this PR - [x] If applicable, I've included the `Run Smoke E2E` and/or `Run Full E2E` label to run smoke/full E2E tests <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes Predict confirmation flow by programmatically dismissing the active preview sheet and rejecting the current approval before starting the Add Funds navigation; mistakes could interrupt user order/confirmation state or leave UI in an inconsistent dismissal state. > > **Overview** > Prevents stacking a new Add Funds deposit flow on top of an active `predictDepositAndOrder` confirmation when users tap **Add** on the Predict balance row. > > Introduces a module-level `dismissActivePreviewSheet()` in `PredictPreviewSheetContext` (tracked per active provider) and updates `usePredictBalanceTokenFilter` to call `onReject()` + `dismissActivePreviewSheet()` before navigating to `ADD_FUNDS_SHEET`; associated unit test now mocks `useApprovalRequest` and asserts both calls occur. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f4d9f81. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
This PR adds a confirm-time Predict market state guard so orders cannot
be submitted after a Polymarket market has entered a post-active state,
even if the user reached the market through a stale feed card, deeplink,
search result, or cached details screen.
The change:
- Propagates Polymarket `active`, `acceptingOrders`, resolved, and UMA
resolution status fields into Predict market/outcome models.
- Adds a live market details check inside `PredictController.placeOrder`
before forwarding the order to the provider.
- Blocks pending resolution, dispute, finalized/resolved, closed,
inactive, and non-accepting markets with specific Predict error codes.
- Shows the parsed market-state error in the buy sheet banner instead of
a generic order-failed message, with generic copy as a fallback.
- Resets the confirm/loading state when an immediate guard error is
returned, preventing the buy sheet CTA from getting stuck disabled.
Scope note: this is the client/controller guard only. No server-side
forwarding guard is included.
## **Changelog**
CHANGELOG entry: Fixed a bug that could allow prediction orders on
markets that are no longer accepting bets.
## **Related issues**
Fixes: PRED-828
Related: PRED-747
## **Manual testing steps**
```gherkin
Feature: Predict market state guard
Scenario: user tries to place a prediction on a market pending resolution
Given a Predict market has entered proposed resolution or dispute
And the user opens the buy sheet from the market details screen
When the user taps Confirm
Then the order is not submitted
And the buy sheet shows "This market is pending resolution."
Scenario: user tries to place a prediction on a market that is no longer accepting bets
Given a Predict market is closed, resolved, inactive, or no longer accepting orders
And the user opens the buy sheet from the market details screen
When the user taps Confirm
Then the order is not submitted
And the buy sheet shows "This market is no longer accepting bets."
Scenario: live market state cannot be confirmed
Given the confirm-time market details check fails
And the user has entered a valid prediction amount
When the user taps Confirm
Then the order is not submitted
And the buy sheet shows "We couldn't confirm this market is accepting bets. Try again."
Scenario: active market still accepts predictions
Given a Predict market is open, active, unresolved, and accepting orders
And the user has enough Predict balance
When the user taps Confirm
Then the order submission flow proceeds normally
```
## **Automated testing**
- `yarn jest
app/components/UI/Predict/controllers/PredictController.test.ts
app/components/UI/Predict/providers/polymarket/utils.test.ts
app/components/UI/Predict/views/PredictBuyWithAnyToken/hooks/usePredictBuyActions.test.ts
app/components/UI/Predict/views/PredictBuyWithAnyToken/hooks/usePredictBuyError.test.ts`
- Result: 4 suites passed, 491 tests passed.
- `git diff --check`
- Result: passed.
## **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. Not applicable: no new public API requiring JSDoc was
added.
- [ ] 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. Not applicable: no Android-specific
behavior changed.
- [x] I've tested with a power user scenario. Not applicable: no
account/token scaling behavior changed.
- [x] I've instrumented key operations with Sentry traces for production
performance metrics. Not applicable: this uses existing Predict order
submission tracing.
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]
> **Medium Risk**
> Adds a confirm-time live market lookup that can block order placement
and alters pay-with-any-token state/cleanup behavior; risk is mainly
around false negatives or new failure paths that could prevent valid
orders.
>
> **Overview**
> Adds a confirm-time *market bettability* guard before
`PredictController.placeOrder` submits to the provider, rejecting orders
when the live market/outcome is inactive, closed/resolved, in
dispute/pending resolution, or not accepting orders (and failing closed
when the check can’t be performed).
>
> Propagates Polymarket `active`/`acceptingOrders` fields into Predict
market/outcome models, introduces new Predict error codes + localized
messages for these blocked states, and updates buy-sheet hooks to avoid
stuck confirming state and to display the specific parsed guard error
(with logging and generic fallback).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3cbeec2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** VIP dashboard rework In conjunction: consensys-vertical-apps/va-mmcx-rewards#573 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-05-20 at 16 20 00" src="https://github.com/user-attachments/assets/69735975-76c6-4dd4-91db-34b5a5173fe7" /> <img width="1220" height="2712" alt="image" src="https://github.com/user-attachments/assets/661022c0-bbd3-4e9c-9591-f90c840d5c56" /> <img width="1220" height="2712" alt="image" src="https://github.com/user-attachments/assets/f9e990a1-8d65-435a-8819-fe406f069a25" /> <img width="1220" height="558" alt="image" src="https://github.com/user-attachments/assets/47a998b8-3bab-453c-bc7f-2cd38f9540b6" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk: updates VIP UI flows and expands VIP dashboard DTOs (points-based progress, new fields like equity rebate/referral carryover), which could break rendering if backend/Redux data mismatches. > > **Overview** > Reworks the Rewards VIP experience to align with the updated VIP dashboard contract: progress and tier thresholds move from swaps/perps requirements to *points-based* metrics, and VIP volume now includes points, referral points, and referral counts. > > Updates the VIP UI to use new backend-provided localized strings, adds a member ID display, introduces an optional **Equity rebate** fee tile, and revamps styling with a new `vip.svg` icon and shared gold theme constants. Also enhances the referral details screen to show a VIP-specific info section with loading/error states driven by `useVipDashboard`, and adds `formatCompactValue` for non-currency compact number formatting. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b8206f3. 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: Rik Van Gulck <vangulckrik@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** This PR adapts the FixtureHelper (`withFixtures`) to work properly with appium and playwright. ### Main changes: - `launchApp` utility inside `withFixtures` now sends launchArgs so that FixtureServer and other resources can properly be used - `MockServer` is completely tool agnostic - App interaction is now segregated in specific handlers for `adb` and `xcrun` with an abstract CommandHandler - These are also exposed via test callback so that individual tests can interact with the device to clear app data, uninstall, install and so on - Android amulator name is now automatically derived from its friendly name. Eg: `PIXEL_XL_API_34` is not translated in the proper serial as `emulator-5554` - FixtureServer now waits for an initial request to avoid early test start - Tests now only start once Metro has finished loading. This prevents early fast fails where metro would take longer to load than the test would start. 1. FixtureServer now counts completed GET /state.json requests. 2. Before launching the app in Appium mode, withFixtures creates a waiter with fixtureServer.waitForNextStateRequest(). 3. Then PlaywrightUtilities.launchApp(...) launches the app with the fixture/mock/command server launch args. 4. The app loads JS from Metro, runs the E2E bootstrap, and requests /state.json. 5. When that request finishes, FixtureServer resolves the waiter. 6. Only then does withFixtures continue to dismiss dev screens and run the actual test body. - Appium server log level has been bumped to INFO to avoid clutter - A boilerplate test using `withFixtures` has been added to be used as a guide for debugging - Implemented different conditions to run tests locally on emulator: - `buildPath` is not provided - Framework checks for installed app, deletes app data and launches the app. Throws if the app is not installed. - `buildPath` is provided - App is uninstalled and installed back. Throws if the artifact does not exist. ### Introduction of test shims: This PR also adds a Playwright-only Node shim so `FixtureBuilder` can load in Playwright without changing app runtime behavior. We need this shim mechanism because some app dependencies patch CommonJS packages to call native modules such as `@metamask/native-utils`. Those calls are valid in the mobile app, but Playwright loads the same dependency graph in Node where React Native/Nitro native modules are unavailable. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: - https://consensyssoftware.atlassian.net/browse/MMQA-1784 - https://consensyssoftware.atlassian.net/browse/MMQA-1742 ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A <!-- [screenshots/recordings] --> ### **After** N/A <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches core E2E test harness startup/cleanup (app launching, fixture boot gating, and device commands) across both Detox and Appium, so failures could block large portions of the test suite despite being test-only code. > > **Overview** > **Adds first-class Appium/Playwright support to `withFixtures`.** App restarts now branch by framework: Detox continues using `TestHelpers.launchApp`, while Appium launches via `PlaywrightUtilities.launchApp` with resolved `launchArgs` (fallback ports, URL blacklist, mock/command/WS ports), optionally clears local app data, and waits for the app’s first `/state.json` fetch before running the test body. > > **Introduces local device management commands for tests.** Adds `DeviceCommandHandler` (Android `adb`, iOS `xcrun simctl`) and exposes it to test callbacks via `TestSuiteParams.deviceCommands`, plus updates types accordingly. > > **Improves Playwright Node compatibility and local ergonomics.** Registers a Node-only CommonJS shim for `@metamask/native-utils` in Playwright entrypoints, adds Playwright-specific dev-screen dismissal flow, lowers Appium server log level to INFO, tweaks performance specs/config to use new activation/fixture patterns, and adds unit coverage for `PlaywrightUtilities.launchApp` and device command handlers. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c658438. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Pass the hook to BridgeController so it acts based on the feature flag. No behaviour changes with the flag off. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3198 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes `BridgeController` initialization behavior by consulting remote feature flags and wiring new messenger permissions; could affect bridge rate sourcing when the flag is enabled or if flag state retrieval fails. > > **Overview** > Adds a `getUseAssetsControllerForRates` hook to `BridgeController` initialization that checks the `assetsUnifyState` remote feature flag (v1) via `RemoteFeatureFlagController:getState`, defaulting to `false` on missing/invalid state or errors. > > Updates the bridge init messenger types/delegation to allow calling `RemoteFeatureFlagController:getState`, and extends unit tests to cover enabled/disabled/absent/exception cases for the new hook. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 26c05d6. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Renames the Top Traders / social leaderboard analytics event from
**Follow Trade Notification Clicked** to **Follow Trading Notification
Clicked** so it matches the segment-schema definition and naming used by
other follow-trading events.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk rename of a single analytics event constant and its usage;
main risk is breaking downstream analytics dashboards if consumers still
expect the old event name.
>
> **Overview**
> Renames the social leaderboard analytics event from
`SOCIAL_FOLLOW_TRADE_NOTIFICATION_CLICKED` to
`SOCIAL_FOLLOW_TRADING_NOTIFICATION_CLICKED` (and updates the emitted
string to **"Follow Trading Notification Clicked"**) in
`MetaMetrics.events`.
>
> Updates `handleSocialTraderPositionUrl` to track the renamed event
when handling notification-driven deeplinks.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d2b7147. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** Fixes missing token icons in confirmation rows when token metadata is unavailable in local token state. The confirmation `TokenIcon` now falls back to the shared MetaMask token icon URL when it has an address, chain ID, and symbol, while still rendering nothing when neither token metadata nor a symbol is available. This also passes the receive token symbol from `PayWithRow` into `TokenIcon`, so Perps and Predict deposit/withdraw rows can render the token icon fallback for mUSD and other supported ERC-20 tokens with missing local metadata. ## **Changelog** CHANGELOG entry: Show fallback token icons in confirmation rows ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1411 ## **Manual testing steps** ```gherkin Feature: Confirmation token icon fallback Scenario: user withdraws mUSD from Perps or Predict Given the user has an mUSD balance And the user starts a Perps or Predict withdraw flow When the Receive row displays mUSD Then the mUSD token icon is shown next to the token symbol ``` ## **Screenshots/Recordings** ### **Before** ### **After** N/A ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [x] 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** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI change that only affects how token icons are resolved/rendered in confirmation rows. Main risk is incorrect fallback URL generation for some chains, but it’s covered by new unit tests. > > **Overview** > Fixes missing token icons in confirmation flows by updating `TokenIcon` to accept an optional `symbol` and, when local token metadata is absent, fall back to a MetaMask-hosted token icon URL (while still rendering nothing when neither metadata nor `symbol` is available). > > Updates `PayWithRow` to pass the displayed token `symbol` into `TokenIcon` (notably for *Receive/withdraw* rows), and expands unit tests to validate symbol propagation and fallback URL generation across multiple supported chains. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8921cc4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… Perps (#30439) ## **Description** Adds VIP tier badge and discounted fee display across Bridge and Perps features. When a user has an active VIP tier from the Rewards program, the UI now shows: - A **VIP badge** (e.g. "VIP 1") next to fee displays in both Bridge and Perps views - The **original fee struck through** alongside the discounted fee, making the discount visually clear - A refactored `PerpsFeesDisplay` component that accepts raw `fee`/`originalFee` numbers instead of pre-formatted text, enabling it to handle discount presentation internally On the controller side, the VIP fees fetch logic (`#getVipFeesForSubscriptionId`) is extracted into a reusable private method, and a new public `getVipTierForAccount` method is exposed via the messenger so any feature can query the user's VIP tier. ## **Changelog** CHANGELOG entry: Added VIP badge and discounted fee display for Bridge and Perps views when user has an active Rewards VIP tier ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: VIP fee discount display in Bridge Scenario: VIP user sees discounted fee in Bridge footer Given the user has an active Rewards VIP tier And the user navigates to the Bridge view with an active quote When the quote returns a discounted quoteBpsFee lower than baseBpsFee Then a VIP badge is displayed next to the fee disclaimer And the original (base) fee percentage is shown with a strikethrough And the discounted fee percentage is shown alongside it Scenario: Non-VIP user sees standard fee disclaimer Given the user does not have a VIP tier And the user navigates to the Bridge view with an active quote When the quote fee data is returned Then no VIP badge is displayed And the standard "Includes X% MetaMask fee." disclaimer is shown Feature: VIP fee discount display in Perps Scenario: VIP user sees discounted fee in Perps order view Given the user has an active Rewards VIP tier with a perps fee discount And the user opens a Perps order or close-position view When fees are calculated and displayed Then a VIP badge is shown next to the fee amount And the original (undiscounted) fee is shown with a strikethrough And the discounted fee is displayed beside it ``` ## **Screenshots/Recordings** ### **Before** N/A ### **After** <img width="1320" height="2868" alt="Simulator Screenshot - iPhone 17 Pro Max - 2026-05-21 at 09 26 18" src="https://github.com/user-attachments/assets/61a020a5-2cb7-4127-89c9-2a4ca95b689c" /> N/A <img width="1320" height="2868" alt="simulator_screenshot_830FC063-45B4-422F-BBBF-E1D6F041F69F" src="https://github.com/user-attachments/assets/4dfe56a7-f2e3-4dd4-8043-5798d48e357a" /> ## **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] > **Medium Risk** > Updates fee calculation/formatting and display across Perps order/close flows and Bridge footer, and gates discount retrieval behind a new remote feature flag; mistakes could lead to incorrect fee presentation. Behavior is mostly UI-level with added tests and a flag fallback to 0 discount when disabled. > > **Overview** > Adds VIP fee-discount presentation across Bridge and Perps: fee rows now show a `RewardsVipBadge` and, when discounted, a struck-through *original* fee/rate alongside the discounted value. > > Refactors `PerpsFeesDisplay` to take numeric `fee`/`originalFee` (plus placeholder) and handle formatting/discount visuals internally, and extends perps fee hooks/results to return `undiscountedTotalFee` for UI use. > > Introduces a new version-gated remote flag `vipProgramEnabled` (`selectVipProgramEnabled`) and uses it to short-circuit rewards discount/tier fetching (returning 0/none when disabled), plus updates tooltip copy/styles and broadens mocks/tests to cover the new VIP badge/discount behaviors. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f85265c. 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: micaelae <micaela.estabillo@consensys.net>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Adds the new Predict-specific empty state experience for wallet home users with no Predict positions. The treatment replaces the generic/trending-only empty state with a sports discovery layout featuring World Cup/NBA championship discovery rows, bracket/stage CTAs, and feature-flagged BTC up/down row scaffolding that is hidden for now. This PR also implements Segment/MetaMetrics tracking for the Predict Empty State A/B test: - Tracks `Empty State Viewed` exposure for zero-position Predict users. - Tracks treatment CTA engagement with `cta_name` and optional `category_name`. - Threads `active_ab_tests` through market entry and bet placement paths for downstream attribution. - Preserves trending experiment attribution when the trending-only section renders the treatment/list layout. - Normalizes championship CTA category tracking so the FIFA World Cup winner row reports `category_name: "world_cup"` instead of the internal row kind. - Adds remote feature flags for the Predict discovery NBA champion row and empty-state experiment handling. **The BTC 5m up/down row is intentionally left hidden** and its data/navigation wiring is commented for now because the shared live-market hook work lives on `predict/crypto-updown-feed-card` and has not merged into `main` yet. The current branch keeps the row scaffold in place behind `SHOW_BTC_UP_DOWN_5M_ROW = false` so the later integration should be a small, low-risk follow-up instead of rebuilding the row wiring from scratch. When `predict/crypto-updown-feed-card` is merged, enable the BTC row by: - Removing the temporary `SHOW_BTC_UP_DOWN_5M_ROW` guard, or setting it to `true` if the team still wants a short-lived rollout switch. - Uncommenting the shared hook imports and hook call in `HomepagePredictWorldCupDiscovery`. - Replacing the temporary BTC placeholder values with the hook values for spot price, price-to-beat, countdown, market id, and market metadata. - Uncommenting the `navigateToMarketDetails` branch in `handleBtcRow` so the row opens the current 5m up/down market directly when available. - Keeping the fallback Predict crypto market-list navigation for cases where no current 5m market is available. ## **Changelog** CHANGELOG entry: Added a new Predict discovery empty state for users with no Predict positions ## **Related issues** Refs: https://consensyssoftware.atlassian.net/browse/TMCU-749 https://consensyssoftware.atlassian.net/browse/TMCU-750 https://consensyssoftware.atlassian.net/browse/TMCU-754 ## **Manual testing steps** ```gherkin Feature: Predict empty state discovery Scenario: user with no Predict positions views the Predict section Given Predict is enabled And the user has zero active or claimable Predict positions When the user lands on the wallet home Predict section Then the Predict empty state is displayed And the Empty State Viewed event is emitted with surface "predict", the assigned variant, and active_ab_tests Scenario: user taps a treatment CTA Given the user is assigned to the treatment variant And the Predict empty state sports discovery layout is visible When the user taps a World Cup, NBA, category, or explore CTA Then the Empty State CTA Clicked event is emitted with the correct cta_name And category_name is included for category-specific CTAs And the World Cup winner row reports category_name "world_cup" And downstream Market Viewed and Bet Placed attribution includes active_ab_tests Scenario: trending-only treatment list preserves attribution Given the homepage Predict section is rendered in trending-only mode And the discovery experiment assigns the list treatment When the user opens a market from the sports discovery list Then the Predict market navigation params include the trending experiment transactionActiveAbTests ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Updates homepage Predict rendering and navigation/analytics plumbing to support a new A/B-tested empty-state discovery experience; risk is mainly UI/UX and event attribution correctness across multiple entry points. > > **Overview** > Adds an A/B-tested **Predict homepage empty-state** experience: when users have no Predict positions, the section can switch from the existing trending carousel to a *sports discovery list* (World Cup + NBA champion rows, bracket/stage CTAs, and scaffolded BTC 5m up/down row behind a kill switch). > > Threads `transactionActiveAbTests` through Predict navigation and buy flows (cards, row items, feed/search/world-cup routes) and extends analytics to include `active_ab_tests` for market-details opens plus new empty-state `VIEWED`/`CTA_CLICKED` events with `surface`/`variant`/`cta_name`/`category_name` properties. > > Improves World Cup tab behavior by adding fallback stage keys when remote `stages` is empty and normalizing requested stage keys (hyphen vs underscore), and introduces a new remote feature flag/selector to gate the NBA champion discovery row. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5189335. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…0484) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** This PR hardens the Predict crypto up/down experience. It keeps feed-card and details-screen prices fresh by pairing live Polymarket prices with REST polling fallback, hides expired time slots from the details picker, adds a series-aware "Your positions" section, and renders inline cash-out / claim actions for positions in the selected series. It also polishes the BTC Up or Down chart and live UI by removing the oversized price badge, tightening the chart presentation, formatting y-axis values as whole dollars, using compact live-window time labels, applying the design-system green to the live control, and temporarily hiding the orderbook overlay until the live duplicate-order issue is resolved. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Improved crypto up/down price freshness, chart polish, and position management in Predict ## **Related issues** Fixes: N/A - follow-up hardening for Predict crypto up/down. ## **Manual testing steps** ```gherkin Feature: Crypto up/down price, chart, and position management Scenario: user views crypto up/down details Given the Predict feature is enabled and the user has crypto up/down positions When user opens the crypto up/down market details screen Then user sees fresh live prices across the feed card and details screen And expired time slots are hidden from the time-slot picker And the chart renders with the compact BTC Up or Down styling And the orderbook overlay is not shown When user scrolls to the positions section Then user sees the "Your positions" section below the chart When user taps Cash out on an open position Then the Predict cash-out flow opens for that position When user taps Claim on a claimable position Then the Predict claim action starts for claimable positions ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** <img width="401" height="730" alt="Screenshot 2026-05-20 at 10 37 31 PM" src="https://github.com/user-attachments/assets/13aca817-195c-4c6f-8147-15793be334f2" /> <img width="388" height="778" alt="Screenshot 2026-05-20 at 10 36 23 PM" src="https://github.com/user-attachments/assets/1082fc31-1a39-4041-bbd4-7f1dd6ae60d2" /> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches Predict trading UX and real-time price plumbing (REST polling fallbacks, WebSocket reconnect/heartbeat, and new cash-out/claim UI), which can impact price freshness and position actions if incorrect. Changes are well-covered by new/updated unit tests but still warrant careful QA on device/network edge cases. > > **Overview** > Improves the crypto up/down details experience by **adding a series-aware `Your positions` section** (new `PredictCryptoUpDownPositions`/`PredictCryptoUpDownPosition`) that shows per-position PnL with inline **Cash out** (open) and **Claim** (claimable resolved) actions, and updates the details screen layout to shrink the chart when positions exist. > > Hardens price freshness by **combining live WebSocket best-ask with REST polling fallbacks** in the crypto up/down feed card and `useOpenOutcomes`, and updates `usePredictPrices` polling to **continue after transient errors while preserving last-good results**. > > Polishes the crypto up/down chart and picker: disables the Liveline badge/momentum and temporarily disables the orderbook overlay, formats chart values as **whole डॉलर** with compact `h:mm:ss` labels, hides expired time slots from the picker, and updates the live pill styling to design-system green. > > Strengthens Polymarket `WebSocketManager` reliability/observability with **cached market price snapshots for late subscribers**, per-subscriber error isolation, structured `Logger.error` reporting, heartbeat-based stale-connection reconnects, and reconnect scheduling that avoids stacking timeouts. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b521867. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… useAnalytics (#30501) ## **Description** Part of the analytics cleanup workstream (#26686). Migrates `TradeTabBarItem` from the deprecated `useMetrics` to `useAnalytics`. Moves the `MetaMetricsEvents` import from the `useMetrics` barrel to `core/Analytics` directly, consistent with other already-migrated components. Files touched: - `TradeTabBarItem/TradeTabBarItem.tsx` — replace `useMetrics` import with `useAnalytics`, move `MetaMetricsEvents` import to `core/Analytics` ## **Changelog** CHANGELOG entry: null ## **Related issues** Closes: #30514 Refs: #26686 ## **Manual testing steps** N/A ## **Screenshots/Recordings** ### **Before** N/A — no UI changes. ### **After** N/A — no UI changes. ## **Pre-merge author checklist** - [x] I've followed the [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_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)) ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, test affected areas) - [ ] I confirm that this PR addresses what is claimed in the PR title - [ ] I confirm that I've manually reviewed the changes if not manually tested Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
> Adds new component-view test coverage for Ramps flows, including
Aggregator (V1) `BuildQuote`/`Quotes` and V2 unified-buy `BuildQuote`,
validating deeplink params, token/payment selection, account switching,
settings→order-history navigation, and quote fetching.
>
> Introduces Ramp-specific component-view infrastructure: nock-based
Ramp SDK API mocking (`tests/component-view/api-mocking/ramp.ts`), new
ramps state presets/fixtures (`tests/component-view/presets/ramps.ts`),
and reusable renderers that mount Ramp screens with modal routes +
react-query (`tests/component-view/renderers/ramps.tsx`). Updates shared
test scaffolding to support these flows (nock localhost allowlist
behavior, `Engine` mocks for `RampsController.getQuotes` and
account-tree selection).
>
> Removes several legacy e2e/spec files that previously covered these
ramps scenarios.
>
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: changes are primarily test infrastructure and new
component-view coverage; production code changes are limited to swapping
hardcoded `testID`s to shared constants.
>
> **Overview**
> Adds new component-view test suites for Ramp Aggregator
`BuildQuote`/`Quotes` and V2 unified-buy `BuildQuote`, covering deeplink
initialization, token/payment selection, account switching,
settings→order-history navigation, and quote-fetching behavior.
>
> Introduces Ramp-focused component-view infrastructure: nock-based Ramp
SDK HTTP mocking (`tests/component-view/api-mocking/ramp.ts`), reusable
render helpers that mount Ramp screens with modal routes + react-query
(`tests/component-view/renderers/ramps.tsx`), and state presets/fixtures
for common ramp scenarios (`tests/component-view/presets/ramps.ts`).
>
> Cleans up legacy Detox/e2e ramps specs (including previously
failing/skipped suites) and tweaks shared test scaffolding
(`disableNetConnect` localhost allowlist, additional `Engine` controller
mocks). Also standardizes a couple of UI `testID`s via constants
(`NavbarSelectorsIDs.DEPOSIT_CONFIGURATION_BUTTON`,
`BUILD_QUOTE_TEST_IDS.PAYMENT_PILL`).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
59bdbe2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Added pagination on Explore predictions search plus the "View X more" support <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: added pagination on Explore predictions search plus the "View X more" support ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3250 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ### **After** https://github.com/user-attachments/assets/d1a6d5f8-4786-4ce8-87d9-96dfca337f75 <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes the `searchMarkets` return shape across controller/provider layers and reworks search fetching to `useInfiniteQuery`, which can affect Explore search results, pagination, and error handling. > > **Overview** > **Predictions search now supports pagination and server totals.** `PredictProvider.searchMarkets` (Polymarket + controller) now returns `{ markets, totalResults }`, plumbed from the Polymarket `public-search` pagination response. > > **Explore search consumes paged results and drives “View X more”.** `usePredictSearchMarketData` switches to `useInfiniteQuery`, adds `fetchMore`/`hasMore`/`totalResults`, and fixes next-page logic to avoid infinite loops when client-side filtering reduces visible items; `usePredictionsFeed` and `useExploreSearch` forward pagination/total fields so header labels can compute hidden counts from server totals (and skip local Fuse re-ranking for server-ranked searches). > > **UI/test cleanup.** Search results lists use shared `searchTypes` and stable item keys, and tests/mocks are updated for the new search result shape and new pagination behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a24e1e2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Migrates the Perps modal navigators (`PerpsModalStack` and
`PerpsClosePositionBottomSheetStack`) from `@react-navigation/stack` (JS
stack) to `@react-navigation/native-stack`, matching the existing native
`PerpsScreenStack`.
**Why:** The Perps screen stack is already native — the nested modal
stacks were the last JS-stack holdouts inside
`app/components/UI/Perps/routes/index.tsx`. Native stack uses platform
navigators, which gives better performance, gesture handling, and a
single consistent navigator API across the Perps surface. This also
removes a few JS-stack-only workarounds (the zero-opacity
`cardStyleInterpolator` trick on the tooltip stack, redundant per-screen
`cardStyle` transparency).
**What:**
- `ModalStack = createStackNavigator()` → `createNativeStackNavigator()`
- Navigator screen options swap `clearStackNavigatorOptions` +
`presentation: 'transparentModal'` for
`clearNativeStackNavigatorOptions` + `transparentModalScreenOptions`
- `PerpsClosePositionBottomSheetStack` drops its `presentation: 'modal'`
+ `cardStyleInterpolator` overlay-clear hack in favor of the same native
presets (semantically equivalent: transparent, non-dimming overlay)
- Removes per-screen `cardStyle: { backgroundColor: 'transparent' }`
(navigator-level `contentStyle` now covers it)
- Drops the `@react-navigation/stack` import from this file
`MainNavigator`'s outer registration of `Routes.PERPS.MODALS.ROOT` is
unchanged — the parent stack there is still JS-stack and continues to
mount `PerpsModalStackWithErrorGate` via `transparentModal`.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: Perps modal navigation on native stack
Scenario: user opens the GTM modal from the wallet
Given the Perps feature flag is enabled
And the `@MetaMask:perpsGTMModalShown` storage flag is cleared
When user opens the Wallet tab
Then the Perps "What's new" modal appears full screen
And tapping "Not now" returns to the wallet without errors
And tapping "Try now" navigates to the Perps tutorial
Scenario: user closes all open positions
Given the user is on Wallet → Perps tab
And the user has at least one open position
When user taps "Close all" in the Positions header
Then the Close All Positions bottom sheet opens
And dismissing it returns to the Perps tab with no leftover backdrop
Scenario: user cancels all open orders
Given the user is on Wallet → Perps tab
And the user has at least one pending order
When user taps "Cancel all" in the Open orders header
Then the Cancel All Orders bottom sheet opens and dismisses correctly
Scenario: user opens a close-position tooltip
Given the user has an open position
When user opens Close position from market details
And user taps the info icon next to "Fees" or "You'll receive"
Then the tooltip bottom sheet (PerpsClosePositionModals → PerpsTooltip) appears
And tapping outside or the close button dismisses it without dimming the parent screen
Scenario: user opens the provider selector (multi-provider builds)
Given multi-provider is enabled
When user taps the provider badge in Perps
Then the Select Provider modal opens with a transparent background
Scenario: user triggers cross-margin warning
Given the user has a cross-margin position on the underlying exchange
When user attempts to place an order on that market
Then the Cross Margin Warning modal appears
Scenario: user enters deposit / trade confirmation
Given the user is on the Perps trade flow
When the Redesigned Confirmations screen mounts inside the Perps stack
Then the header / transparent overlay behavior is unchanged from main
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<img width="350" height="720" alt="perps modal before"
src="https://github.com/user-attachments/assets/f8856292-435a-4f29-b289-b5c2efefd8dc"
/>
<!-- [screenshots/recordings] -->
### **After**
<img width="350" height="720" alt="perps modal after"
src="https://github.com/user-attachments/assets/9d7f3ff4-856a-4415-82c9-ce50bc25f284"
/>
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Moderate risk because it changes navigation stack implementation and
screen options for Perps modals, which could affect modal
presentation/gestures and overlay behavior across key trading flows.
>
> **Overview**
> Migrates the Perps modal navigators in
`app/components/UI/Perps/routes/index.tsx` from the JS stack
(`@react-navigation/stack`) to `createNativeStackNavigator`, aligning
them with the existing native Perps screen stack.
>
> Updates modal/tooltip navigator `screenOptions` to use
`clearNativeStackNavigatorOptions` + `transparentModalScreenOptions`,
and removes JS-stack-only transparency/overlay workarounds (per-screen
transparent `cardStyle` and the tooltip stack’s zero-opacity overlay
interpolator).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2e6c012. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
Applies the seven design-review polishes called out for MUSD-827 on the
Money Account Home surface:
- **Item 1** — `MoneyMusdTokenRow` subtitle on Home now reads
`${balance} • mUSD` instead of just `mUSD`. The row consumes the
existing `useMoneyAccountBalance` hook's `musdFiatFormatted` field
(spendable mUSD only — not the aggregated total).
- **Item 2** — "No MetaMask fee" badge on stables/aTokens rows in the
Earn Crypto section → "No fee".
- **Item 3** — "Convert" button label on per-asset rows in the Earn
Crypto section → "Add". The locale key name stays `convert` so call
sites are untouched.
- **Item 4** — The move-mUSD row in `MoneyAddMoneySheet` is hidden when
the user has no mUSD balance (`totalFiatRaw` non-positive or
unparseable). An unparseable value fails open and keeps the row visible.
- **Item 5** — When that row is shown, its label changes from "Transfer
your $X mUSD" → "Add your $X mUSD". The now-dead `move_musd_no_amount`
key is removed from `en.json`.
- **Item 8** — `MoneyHowItWorksView` description 1 is updated to mention
"curated by Veda and Steakhouse Financial" and to drop the em dash; a
new description 3 paragraph "Money account is powered by Monad." renders
after description 2.
- **Item 10** — The small How-It-Works tile in `MoneyCondensedInfoCards`
swaps `mm_how_it_works.png` for the new green bar-chart icon exported
from Figma (committed separately at the top of the branch as
`c3b1fc37af`).
Items 6, 7, and 9 from the parent design review are intentionally out of
scope (handled by MUSD-824, ticketed separately, and out-of-scope per
design direction respectively).
Only `locales/languages/en.json` is touched — non-English translations
come from the localization pipeline.
## **Changelog**
CHANGELOG entry: Polished the Money Account Home with the spendable mUSD
balance in the token row subtitle, a "No fee" badge and "Add" button on
Earn Crypto rows, a hidden "Add your $X mUSD" entry on the Add money
sheet when the balance is zero, a refreshed "How it works" description
and a new Monad attribution paragraph, and an updated How It Works tile
image.
## **Related issues**
Fixes:
[MUSD-827](https://consensyssoftware.atlassian.net/browse/MUSD-827)
## **Manual testing steps**
```gherkin
Feature: MUSD-827 Money Home design-review polishes
Scenario: mUSD row subtitle on Home
Given the user has a positive mUSD spendable balance
When the user opens the Money tab
Then the mUSD row subtitle reads "$<balance> • mUSD" (e.g. "$1.00 • mUSD")
Scenario: Earn Crypto badge label
Given the user has stablecoin or aToken balances eligible for the Earn Crypto section
When the user scrolls to the Earn Crypto section on Money Home
Then each subsidised-fee row shows the badge "No fee"
And the per-asset action button reads "Add"
Scenario: Add money sheet hides the move-mUSD row when balance is zero
Given the user has $0 spendable mUSD
When the user opens the Add money sheet from the Money Home Add button
Then the sheet shows only "Convert crypto", "Deposit funds", and the disabled "Receive from external wallet" row
And the "Add your $X mUSD" row is not rendered
Scenario: Add money sheet shows the move-mUSD row with positive balance
Given the user has a positive spendable mUSD balance (e.g. $12.34)
When the user opens the Add money sheet from the Money Home Add button
Then the third row reads "Add your $12.34 mUSD"
Scenario: How It Works full screen
Given the user is on the Money tab
When the user opens "How it works"
Then description 1 mentions "curated by Veda and Steakhouse Financial"
And a third paragraph reads "Money account is powered by Monad."
Scenario: How It Works tile image
Given the user is on the Money tab in milestone or empty state
When the user views the condensed info cards row
Then the How-It-Works tile shows the new green bar-chart icon
```
## **Screenshots/Recordings**
### **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
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
## **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.
[MUSD-827]:
https://consensyssoftware.atlassian.net/browse/MUSD-827?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Primarily UI copy/label updates, but it also changes when the Add
Money sheet shows the mUSD move/add option based on parsed balances,
which could hide a user action if balance/rates are miscomputed.
>
> **Overview**
> Polishes Money surfaces around mUSD and Earn Crypto CTAs: the Money
Home mUSD row now displays a formatted spendable balance in its subtitle
(via `useMusdBalance`), and per-token Earn Crypto actions/badges switch
to **“Add”** and **“No fee”**.
>
> Updates the Add Money sheet to source balances from `useMusdBalance`,
**hide the mUSD move/add row when the user has no balance**, and format
the label as **“Add your {amount} mUSD”** (falling back to token amount
when fiat rates are unavailable). The How It Works screen copy is
refreshed and adds a third description paragraph attributing Monad;
tests and `en.json` strings are updated accordingly.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c2ea309. Bugbot is set up for automated
code reviews on this repo. 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 : )