[pull] main from MetaMask:main#594
Merged
pull[bot] merged 20 commits intoReality2byte:mainfrom Mar 11, 2026
Merged
Conversation
## **Description** Update the background colors on confirmation/transaction pages from `background.alternative` to `background.default` to improve visual hierarchy and consistency across the app. **Changes include:** - Main confirmation container (`confirm-component.styles.ts`) - Confirmation footer (`footer.styles.ts`) - Confirmation navbar (`navbar.tsx`) - Stake confirmation views (StakeConfirmationView, UnstakeConfirmationView) - Earn lending confirmation views (EarnLendingDepositConfirmationView, EarnLendingWithdrawalConfirmationView) - Staking confirmation footer (`ConfirmationFooter.styles.ts`) ## **Changelog** CHANGELOG entry: Updated background colors on confirmation pages for improved visual hierarchy ## **Related issues** Fixes: #26018 ## **Manual testing steps** ```gherkin Feature: Confirmation page background colors Scenario: user views confirmation page backgrounds Given the app is running in dark mode When user initiates a transaction or confirmation flow Then the confirmation page background should display with the updated background.default color And the visual hierarchy should be improved compared to the previous background.alternative color ``` ## **Screenshots/Recordings** ### **Before** Confirmation pages used `background.alternative` (#f3f5f9 in light mode) ### **After** <img width="434" height="891" alt="Screenshot 2026-02-27 at 09 09 20" src="https://github.com/user-attachments/assets/d4e1eae3-2e58-4f42-adc9-9a5df85e1910" /> <img width="424" height="895" alt="Screenshot 2026-02-27 at 09 12 28" src="https://github.com/user-attachments/assets/f0971dbf-beb4-47c3-aa49-98a918380c99" /> <img width="430" height="889" alt="Screenshot 2026-02-27 at 09 10 45" src="https://github.com/user-attachments/assets/a1b4bbdb-2fe0-41ac-aff9-8fb54f3ce609" /> <img width="423" height="893" alt="Screenshot 2026-02-27 at 09 11 45" src="https://github.com/user-attachments/assets/a4e6e3f1-d4fc-4b16-b19a-e80e8c724c6f" /> <img width="428" height="893" alt="Screenshot 2026-02-27 at 09 18 28" src="https://github.com/user-attachments/assets/14268c3c-d927-4f90-8fdf-eec81753ac66" /> <img width="433" height="892" alt="Screenshot 2026-02-27 at 09 18 54" src="https://github.com/user-attachments/assets/b087ff6b-bbc5-4265-8d53-bb67b8d2800a" /> <img width="425" height="890" alt="Screenshot 2026-02-27 at 09 19 51" src="https://github.com/user-attachments/assets/5e40dd6a-9d6c-495d-a854-6176ae33ecee" /> <img width="425" height="891" alt="Screenshot 2026-02-27 at 09 20 56" src="https://github.com/user-attachments/assets/9776beaa-b885-43eb-9a0c-af097dd8fe21" /> <img width="431" height="894" alt="Screenshot 2026-02-27 at 09 21 32" src="https://github.com/user-attachments/assets/78fa6cab-b30b-45ff-b24b-df6c8195f1cf" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **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** > Styling-only changes (theme token swaps) with snapshot/test updates; minimal functional risk aside from potential visual regressions across light/dark themes. > > **Overview** > Updates confirmation-related UI surfaces to use the new theme background hierarchy: primary containers/navbars/footers in Earn lending + Stake + generic confirmation flows now use `background.default`, while secondary cards/steps/pills/rows shift to `background.muted`/`background.section` for clearer contrast. > > Also tweaks a few confirmation UI details (e.g., tooltip icon color to `Muted`, modal/accordion/expandable backgrounds) and refreshes associated unit tests and snapshots to match the new colors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7c35b39. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Bárbara Schorchit <bschorchit@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **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? --> Migrated `Label` component to design-system usage (Earn team scope). ## **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/DSYS-276 ## **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** <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/c8acb44b-21f3-4251-b532-612c7d235e49" /> ### **After** <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/3348fc1d-8b4d-46dd-95e3-6d15c083f313" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only component migration to design-system primitives with no business logic or data flow changes; main risk is minor visual/regression and snapshot churn. > > **Overview** > Migrates Earn `EarningsHistoryList` to use the design-system `Label` component (`@metamask/design-system-react-native`) and replaces legacy `variant`/theme color props with design-system `fontWeight` and `TextColor` tokens. > > Updates the Stake earnings history snapshot to match the new `Label` rendering output (style array changes / removal of `testID="label"`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 69507ec. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR explores possible fixes for the swap test. ### Disable reactNative bundle reload at the end of the test Runs: 1. https://github.com/MetaMask/metamask-mobile/actions/runs/22714957885/job/65863758791?pr=27051 2. https://github.com/MetaMask/metamask-mobile/actions/runs/22714957885/job/65868657133?pr=27051 3. https://github.com/MetaMask/metamask-mobile/actions/runs/22714957885/job/65872904276?pr=27051 <!-- 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? 4. 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` 3. 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** - [ ] 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. ## **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 because changes are limited to smoke-test configuration; the main impact is on CI test isolation/cleanup behavior, which could mask state-leak issues if misused. > > **Overview** > Re-enables the `Swap from Actions` smoke suite by removing `describe.skip`. > > Updates the test’s `withFixtures` options to set `skipReactNativeReload: true`, avoiding the React Native bundle reload during cleanup to reduce flakiness and preserve state between the suite’s `it` blocks. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 05f74a0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…#27321) ## **Description** When viewing EVM transactions from the "Popular networks" activity feed while a non-EVM network was active, the "View on [Explorer]" link incorrectly resolved to the non-EVM block explorer (e.g. Mempool) instead of the correct EVM explorer (e.g. Etherscan). Switching to an EVM network and back would fix it temporarily. The root cause was that `getBlockExplorerForChain` used `chainId` (the currently active network from Redux) rather than `txChainId` (the transaction's own chain) for the non-EVM block explorer check. The fix uses `txChainId` consistently throughout the function, and removes the now unused `chainId` prop and its associated Redux selector subscriptions. ## **Changelog** CHANGELOG entry: Fixed a bug where switching to a non-EVM network caused EVM transaction details to display the wrong block explorer link ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-550 #27253 ## **Manual testing steps** ```gherkin Feature: Block explorer link in transaction details Scenario: user views EVM transaction while on a non-EVM network Given the user has a non-EVM network active (e.g. Bitcoin) And the activity feed is filtered by "Popular networks" When user taps a confirmed EVM transaction (e.g. Ethereum, Arbitrum) Then the correct EVM block explorer link appears (e.g. "View on Etherscan") And tapping it opens the correct transaction URL Scenario: user views a non-EVM transaction Given the user has transactions on a non-EVM network When user taps a confirmed transaction Then the correct non-EVM block explorer link appears (e.g. "View on Mempool") ``` ## **Screenshots/Recordings** https://github.com/user-attachments/assets/2a823c20-9663-4e7b-8e17-bd223ec7f8e6 ### **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. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI bug fix that only changes how the block explorer URL is selected for the transaction details link, plus a small test update to match the new props. > > **Overview** > Fixes the **"View on [Explorer]"** link in `TransactionDetails` to consistently derive the block explorer from the transaction’s `txChainId`, preventing EVM transactions from incorrectly using a non‑EVM explorer when the active network is non‑EVM. > > Removes the now-unused `chainId`/`providerConfig` Redux props and updates the unit test to stop passing `chainId` explicitly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bd46296. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Scanning verbiage only shows when actually scanning in hardware QR scanning flow ## **Changelog** CHANGELOG entry:null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-431 ## **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** | Scanning | Not Scanning | | -------- | ------- | |  |  | ### **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. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI-only conditional rendering change; no changes to scanning/decoding logic or data handling. > > **Overview** > Updates `AnimatedQRScanner.tsx` so the "Scanning" progress text is **conditionally rendered only when `progress > 0`**, preventing the label from appearing when the scanner is idle. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2241229. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
Restructure the `PerpsMarketTileCard` header layout so the ticker symbol
sits on its own row with ellipsis overflow, and the percentage variation
+ leverage badge share a second row where the percentage can grow and
ellipsis when too wide.
Changes:
- Replace `View`-based layout styles (`topRow`, `symbolSection`,
`symbolRow`) with `Box` components using typed props (`flexDirection`,
`alignItems`, `gap`) and `twClassName`
- Move `PerpsLeverage` badge from the ticker row to the percentage row
- Add `numberOfLines={1}` to ticker and percentage `Text` for truncation
- Use `flex-1` + `min-w-0` on the left column to enable ellipsis inside
flex children
- Use `shrink` on the percentage text so it truncates before pushing the
leverage badge off-screen
## **Changelog**
CHANGELOG entry: null
## **Related issues**
N/A
## **Manual testing steps**
```gherkin
Feature: Perps market tile card header
Scenario: user views a market card with a short ticker
Given the Perps section carousel is visible on the homepage
When user views a market card (e.g. BTC, ETH)
Then the ticker is on the first row
And the percentage and leverage badge are on the second row
Scenario: user views a market card with a long ticker or large percentage
Given the Perps section carousel is visible on the homepage
When user views a market card with a long ticker symbol
Then the ticker text truncates with ellipsis
And the percentage text truncates with ellipsis if too wide
And the leverage badge remains visible
```
## **Screenshots/Recordings**
### **Before**
<img width="300"
src="https://github.com/user-attachments/assets/e14aa77c-e3bd-4a48-9ccb-15209f5c1dee"
/>
### **After**
<!-- [screenshots/recordings] -->
<img width="300"
src="https://github.com/user-attachments/assets/e06096c2-3213-4f74-80df-4d498a685941"
/>
#### Video showing ellipsis truncation
https://github.com/user-attachments/assets/b8e4ad3f-8682-4e3e-9bfa-22ddd4c7620a
## **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]
> **Low Risk**
> Low risk UI-only layout refactor in the perps market tile header; main
risk is minor visual regression in text wrapping/spacing across devices.
>
> **Overview**
> Refactors `PerpsMarketTileCard` header layout to place the market
symbol on its own single-line row (ellipsis via `numberOfLines` +
`min-w-0`) and move the 24h percent change + `PerpsLeverage` onto a
second row.
>
> Replaces several custom `View` style blocks
(`topRow`/`symbolSection`/`symbolRow`) with design-system `Box` layout
props and tailwind classes (e.g., `shrink`) to ensure long percent
values truncate without pushing the leverage badge off-screen.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
42970d1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…#27345) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - Fixes unhandled crash in `launchAppWithRecovery` when `adb reverse --remove` fails with "listener not found" - Adds diagnostic instrumentation to identify the root cause of intermittent port collisions on CI ### Problem On CI, `device.launchApp()` occasionally fails when Detox tries to set up its internal adb reverse: ``` adb -s emulator-16526 reverse tcp:37351 tcp:37351 adb: error: cannot bind listener: Address already in use ``` The recovery code then attempts `adb reverse --remove tcp:37351`, which also fails ("listener not found") — and this **unhandled error crashes the test**. The port is occupied at the OS socket level inside the emulator but is NOT tracked in adb's reverse table. This happens on a fresh emulator (`-wipe-data`), first test in the shard, single worker — ruling out stale state from previous tests or parallel interference. **Leading hypothesis:** TIME_WAIT from Detox's own device initialization. During the ~83s boot phase, Detox may set up and tear down an initial adb reverse for its server port. The adb entry is removed, but the socket inside the Android VM enters TIME_WAIT (~60s). When `device.launchApp()` tries to re-bind the same port, `bind()` fails. ### Changes 1. **`removeAndroidReversePort`** — wraps `adb reverse --remove` in try-catch so "not found" errors no longer crash the test, allowing the retry to proceed 2. **`diagnoseEmulatorPort`** (new) — on port collision, reads `/proc/net/tcp6` inside the emulator and logs the socket state (`06`=TIME_WAIT, `0A`=LISTEN, `01`=ESTABLISHED). The next CI failure will confirm what's holding the port. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** 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** - [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] > **Low Risk** > Low risk; changes are confined to Detox test helpers and add logging/defensive error handling around `adb reverse --remove`, which could slightly mask unexpected failures but only impacts test runs. > > **Overview** > Improves Detox Android app-launch recovery when `adb reverse` fails due to an “Address already in use” collision. > > `removeAndroidReversePort` now catches `adb reverse --remove` failures (including “listener not found”) so tests still proceed to the single retry, and a new `diagnoseEmulatorPort` hook logs the emulator’s `/proc/net/tcp{,6}` socket state for the conflicting port to help root-cause intermittent CI port binds. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fd2ca96. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ap (#27303) ## **Description** The Predict game UI was hardcoded for NFL football — helmet icons, football possession indicators, and NFL-specific JSDoc comments. This PR introduces a `SportLeagueConfig` abstraction so the scoreboard rendering is driven by a per-league configuration map, enabling multi-sport support starting with NBA. **Why:** We need the Predict sports game UI to support basketball (NBA) and future sports without duplicating scoreboard logic or creating sport-specific component trees. **How:** A simple config map keyed by `PredictSportsLeague` determines which team icon and possession indicator to render. Leagues without a config entry fall back to team logo images (from the Polymarket API) and skip possession indicators entirely. ### Key changes: - **`sportLeagueConfigs.ts`** — New `SportLeagueConfig` interface + config map + `getLeagueConfig()` lookup with safe fallback for unknown leagues - **`PredictSportTeamLogo`** — New component that renders remote team logo images with colored circle placeholder and error fallback - **`PredictSportScoreboard`** — Refactored from directly importing helmet/football icons to resolving them from the league config. NFL games still render helmets + football possession; NBA games render team logos with no possession indicator - **`PredictGamePeriod` type** — Added string escape hatch for future sports with different period formats - **JSDoc updates** — Removed NFL-specific language from component documentation ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/PRED-742 ## **Manual testing steps** ```gherkin Feature: Generic sports UI in Predict Scenario: NFL game renders with football helmet icons Given a Predict market with an NFL game attached When user views the sport card or game details Then football helmet icons are shown for both teams And football possession indicator appears for the team with possession Scenario: NBA game renders with team logo images Given a Predict market with an NBA game attached When user views the sport card or game details Then team logo images are shown for both teams (circular, with team color background) And no possession indicator is rendered Scenario: Existing NFL behavior is unchanged Given a Predict NFL market in any game state (scheduled, ongoing, halftime, final) When user views the scoreboard Then all scores, periods, status text, and winner trophies render identically to before ``` ## **Screenshots/Recordings** <!-- Screenshots to be added after visual verification on simulator --> ### **Before** <!-- NFL-only hardcoded UI --> https://www.loom.com/share/da2e5b857a7e42cc8cd00de1b9864e13 ### **After** <!-- League-driven UI with NFL helmets and NBA team logos --> https://www.loom.com/share/d929e65021df4981981b936be33b738a ## **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] > **Medium Risk** > Moderate risk due to UI rendering refactor and testID changes in `PredictSportScoreboard`, plus widening `PredictGamePeriod` to arbitrary strings. The Polymarket description selection tweak could subtly change displayed copy across markets. > > **Overview** > Predict sports UI is refactored to be **league-driven**: `PredictSportScoreboard` now resolves `TeamIcon` and `PossessionIcon` via `getLeagueConfig()` instead of hardcoding NFL helmet/football components, falling back to a new `PredictSportTeamLogo` remote-image renderer and omitting possession indicators when not configured (e.g., NBA). > > Adds `constants/sportLeagueConfigs.ts` (+ tests) defining the per-league config (currently NFL only), updates scoreboard tests accordingly (including NBA fallback assertions), and broadens `PredictGamePeriod` with a string escape hatch for future leagues. Separately adjusts Polymarket market parsing to prefer a moneyline market description (then first market) over the event description, and updates sports UI JSDoc/test color fixtures. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fb02b52. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Replaces the eager bulk league loading strategy in `PolymarketProvider` with lazy per-team loading. **Problem:** `getMarkets()` and `getMarketDetails()` called `ensureLeaguesLoaded(allSupportedLeagues)` which fetched **all** teams for **all** supported leagues (~62 teams across 2 API calls) before any market parsing — even if the current page had zero sports markets. **Solution:** Markets are now fetched first, then slugs are scanned to extract only the team abbreviations actually referenced. Only those specific teams are fetched via the Polymarket API's `abbreviation` filter parameter (`GET /teams?league=nfl&abbreviation=SEA&abbreviation=DEN`). | Scenario | Before | After | |---|---|---| | Market list with 0 sports games | 2 API calls (~62 teams) | **0 API calls** | | Market list with 1 NFL game | 2 API calls (~62 teams) | **1 API call (2 teams)** | | Market detail for 1 game | 2 API calls (~62 teams) | **1 API call (2 teams)** | | Subsequent pages (teams cached) | Cache hit | **Cache hit** | ### Key changes: - **`TeamsCache.ts`**: Added `ensureTeamsLoaded(league, abbreviations[])` with batch dedup. Unified `fetchAndCacheTeams`/`fetchAndCacheSpecificTeams` into shared `fetchAndCacheFromUrl` with replace/merge modes. Fixed `isLeagueLoaded` semantics with a `fullyLoadedLeagues` Set so partial lazy loads don't false-positive. Normalized `TEAM_COLOR_OVERRIDES` lookup to lowercase. - **`gameParser.ts`**: Added `extractNeededTeamsFromEvents()` utility that scans events for team abbreviations by league. - **`utils.ts`**: Extracted `fetchEventsFromPolymarketApi()` from `getParsedMarketsFromPolymarketApi()` to split fetch from parse (backward compatible). - **`PolymarketProvider.ts`**: Refactored `getMarkets()` and `getMarketDetails()` to use the new lazy flow. Extracted `#createTeamLookup` and `#getSupportedLeagues` helpers. Replaced unsafe `as typeof SUPPORTED_SPORTS_LEAGUES` cast with `filterSupportedLeagues()` runtime validation. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/PRED-743 ## **Manual testing steps** ```gherkin Feature: Lazy per-team loading for sports markets Scenario: user views markets page with no sports games Given user is on the Predict markets feed When user views a page with no sports game markets Then no teams API call is made Scenario: user views markets page with sports games Given user is on the Predict markets feed When user views a page containing 1 NFL game (SEA vs DEN) Then only SEA and DEN teams are fetched from the API And the game market displays team logos and colors correctly Scenario: user views a single sports market detail Given user taps on an NFL game market When the market detail page loads Then only the 2 teams for that game are fetched And game data (score, status) displays correctly Scenario: user navigates between pages with overlapping teams Given user viewed page 1 with SEA vs DEN When user navigates to page 2 which also has SEA vs KC Then only KC is fetched (SEA is already cached) ``` ## **Screenshots/Recordings** <!-- Not applicable — no UI changes, performance optimization only --> ### **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] > **Medium Risk** > Changes the Polymarket markets/details fetch pipeline and introduces new lazy-loading/caching paths, which could affect live sports rendering and API call patterns if parsing/league detection is off. The changes are well-covered by updated unit tests, reducing but not eliminating integration risk. > > **Overview** > Optimizes Polymarket Predict market fetching by **fetching events first** and then **lazily loading only the specific teams referenced by those events** before parsing/overlaying live sports data. > > `PolymarketProvider.getMarkets()` now uses new `fetchEventsFromPolymarketApi()` + `parsePolymarketEvents()` flow (instead of `getParsedMarketsFromPolymarketApi`), filters search results based on the returned `isSearch` flag, and gates live-sports behavior via runtime `filterSupportedLeagues()`. `getMarketDetails()` similarly loads only required teams for the single event. > > `TeamsCache` adds `ensureTeamsLoaded(league, abbreviations)` with batch deduping and merge-caching, fixes “league loaded” semantics via a `fullyLoadedLeagues` set (partial loads no longer mark a league as fully loaded), and normalizes `TEAM_COLOR_OVERRIDES` lookup to lowercase. `gameParser` adds `extractNeededTeamsFromEvents()` to derive required team abbreviations, and tests are updated/expanded to cover the new flow and caching behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit afe169e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…27339) # Pull Request <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## Description 1. **Homepage sort is independent of View all** The homepage (Tokens and DeFi sections) always sorts by balance/market value. The sort choice in "View all" (token list or DeFi list) no longer affects the homepage. View all continues to use the user's saved sort preference (balance vs name). 2. **Popular networks when opening View all** When the user focuses the Wallet/Homepage (e.g. switches to the Wallet tab or returns to it), we call `enableAllPopularNetworks()`. So the first time they open "View all" (tokens or networks), all popular networks are already selected instead of a single network. **Summary of changes:** - Added `selectSortedAssetsBySelectedAccountGroupForChainIdsByBalance` and use it in the homepage Tokens section so homepage tokens are always sorted by balance. - Homepage DeFi section always sorts by market value (no longer uses user sort preference). - Full token list and full DeFi list still use the user's sort preference. - Homepage uses `useFocusEffect` to run `enableAllPopularNetworks()` when the screen is focused so popular networks are selected before opening any section or View all. - Balance refresh: removed `AbortController` from the refresh flow and simplified the timeout (no NFT abort on timeout). --- *1. What is the reason for the change?* Homepage should show a consistent balance-based order; View all should keep the user's sort and have popular networks selected when opened from the homepage. *2. What is the improvement/solution?* Homepage always sorts by balance; View all keeps its own sort and gets popular networks selected on focus. --- ## Changelog CHANGELOG entry: Homepage tokens and DeFi now always sort by balance/value; View all keeps your sort preference. Popular networks are selected when opening the Wallet so View all shows all popular networks by default. --- ## Related issues Fixes: --- ## Manual testing steps ```gherkin Feature: Homepage sort and popular networks Scenario: Homepage shows balance order regardless of View all sort Given the user has tokens and has set "View all" sort to "Name A–Z" When the user is on the Wallet tab with homepage sections (Tokens / DeFi) Then Tokens and DeFi sections on the homepage are ordered by balance/value (highest first) And changing sort in "View all" (tokens or DeFi) does not change homepage section order Scenario: View all has popular networks selected when opened from homepage Given the user is on the Wallet tab (homepage focused at least once) When the user taps "View all" on Tokens or opens the network filter for the first time Then "Popular networks" (all popular) is selected And the list shows data for all popular networks Scenario: View all respects user sort preference Given the user has set token sort to "Name A–Z" in View all When the user opens the full token list (View all) Then tokens are sorted by name A–Z And the homepage Tokens section still shows balance order ``` --- ## Screenshots/Recordings ### Before <!-- Add screenshots/recordings --> ### After <!-- Add screenshots/recordings --> https://github.com/user-attachments/assets/e379560d-de47-46dd-b2c7-f78aebb2fa3d --- ## 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 - [ ] 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. --- ## 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** > Medium risk because it changes homepage sorting behavior and triggers network-enable side effects on every homepage focus, which could impact perceived ordering and network selection state. > > **Overview** > **Homepage token/DeFi ordering is now decoupled from the user’s “View all” sort preference.** The homepage Tokens section switches to a new selector (`selectSortedAssetsBySelectedAccountGroupForChainIdsByBalance`) that always sorts by fiat balance desc, and the homepage DeFi hook now always sorts positions by `aggregatedMarketValue` desc. > > **Homepage focus now reapplies popular network enablement.** `Homepage` calls `enableAllPopularNetworks()` via `useFocusEffect`, and both `TokensFullView` and `DeFiFullView` reset `PreferencesController.tokenSortConfig` to a shared `DEFAULT_TOKEN_SORT_CONFIG` on exit (behind `selectHomepageSectionsV1Enabled`). Tests were updated/added to lock in these behaviors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit aabdb38. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
## PR Summary
### What changed
- Added new DeFi page objects:
- `tests/page-objects/wallet/DefiView.ts`
- `tests/page-objects/wallet/DefiPositionView.ts`
- Extended `WalletView` with stable section navigation helpers for:
- `DeFi`, `Perpetuals`, `Predictions`, `Tokens`, and `NFTs`
- Updated Perps smoke and regression tests to use the same homepage
navigation flow.
- Improved Predict open-position assertions to target the correct UI
context.
- Fixed E2E mock issues affecting Perps/homepage behavior.
- Removed brittle fixed waits and replaced them with framework-based
stable interactions.
### Reliability improvements
- Replaced timing-based waits with retry/stability-aware framework
methods.
- Added scroll-until-visible + stable tap patterns for homepage
sections.
- Scoped assertions to avoid false negatives when duplicate text appears
in multiple UI areas.
- Fixed mock payload shape and RPC nonce format issues that caused
runtime failures.
### Technical fixes included
- **Perps candles mock shape**: now returns expected object structure
instead of a raw array.
- **RPC nonce mock**: changed odd-length hex to valid even-length format
(`0x00`).
- **Predict assertion robustness**: added a POM helper to assert
position title within the positions-tab context.
- **DeFi POM coverage**: added container-level visibility checks and
reusable screen interactions.
### Outcome
These changes make the E2E flows more deterministic, reduce flakiness in
wallet homepage navigation, and align smoke/regression behavior across
Perps and Predict scenarios.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] 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.
## **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**
> Primarily test and mock changes plus non-functional `testID` additions
to UI components; low likelihood of impacting runtime behavior beyond
automation identifiers.
>
> **Overview**
> Improves E2E determinism for the redesigned wallet homepage by adding
missing `testID`s (homepage container, homepage section titles, wallet
scroll view, and DeFi position rows) and extending `SectionTitle` to
accept an optional `testID`.
>
> Refactors Detox page objects and specs to navigate via homepage
sections (Tokens/Perps/Predictions/DeFi/NFTs) using new scroll-and-tap
helpers, plus new DeFi page objects for list/details screens; updates
many smoke/regression tests to enable `homepageSectionsV1` via a new
remote flag mock.
>
> Hardens test mocks to reduce flakiness: fixes RPC hex formatting in
perps mocks, adjusts perps candles stream mock payload shape, resets
Polymarket mock global state between tests, and adds higher-priority
Polymarket overrides (including a late-registered claimable-positions
mock) to avoid race conditions during cash-out/claim flows.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
72a09e8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: javiergarciavera <javiergarciavera@users.noreply.github.com>
Co-authored-by: Luis Taniça <matallui@gmail.com>
## **Description**
This PR updates typography in the Bridge token selector item so ticker
text weight matches the Send flow token item and Trending token row.
- Updated bridge token symbol text from `TextVariant.BodyMD` to
`TextVariant.BodyMDMedium`
- Updated bridge right-side secondary balance text from
`TextVariant.BodyMD` to `TextVariant.BodyMDMedium`
## **Changelog**
CHANGELOG entry: Fixed a visual inconsistency where bridge token
selector ticker text appeared thinner than other token lists.
## **Related issues**
Fixes: N/A
## **Manual testing steps**
```gherkin
Feature: Bridge token selector typography
Scenario: user views token rows in Bridge token selector
Given the wallet is unlocked
And the user is on the Bridge flow
When user opens the token selector
Then token ticker text is rendered with medium body typography
And right-side token amount text is rendered with medium body typography
And typography matches the visual weight used in send flow and trending token rows
```
## **Screenshots/Recordings**
### **Before**
N/A
### **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).
- [x] 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.
## **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-only typography change limited to the bridge token
selector item; no logic, data flow, or side effects are modified.
>
> **Overview**
> Updates `TokenSelectorItem` in the bridge UI so the token ticker
(`token.symbol`) and the right-side secondary balance text both use
`TextVariant.BodyMDMedium` instead of `BodyMD`, aligning typography with
other token lists.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2769bb2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **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? --> Remove remaining occurrences of the BIP-44 flag and `isMultichainAccountsState1Enabled`. ## **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: null ## **Manual testing steps** Not applicable ## **Screenshots/Recordings** Not applicable ## **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 - [ ] 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. ## **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** > Small refactor removing dead feature-flag code and related test scaffolding; minimal runtime impact limited to callers that might have relied on the deleted export. > > **Overview** > Removes the deprecated multichain accounts *state 1* flag path by deleting `isMultichainAccountsState1Enabled` and stopping any implicit “state1-or-state2” enablement checks. > > Updates unit tests to drop mocks/selectors related to the removed flag (`remote-feature-flag` mocking and `selectMultichainAccountsState2Enabled` wiring), keeping tests focused on the remaining state-2-only behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9770d79. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
This PR moves hardcoded strings into dedicated `*.testIds.ts` files so
they can be used through the multiple test parts to avoid duplication.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] 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.
## **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 refactor that only replaces hardcoded `testID` strings with
exported constants; main risk is breaking E2E/unit selectors if any IDs
changed (they appear unchanged).
>
> **Overview**
> Moves several hardcoded React Native `testID` strings into new
dedicated `*.testIds.ts` modules and updates components to reference
these constants.
>
> This standardizes selectors for multichain account list cells
(`AccountListCell`, `ExternalAccountCell`), Backup & Sync toggles
(`BackupAndSyncToggle`, `BackupAndSyncFeaturesToggles`), and Smart
Account UI (`SmartAccountModal`, `SmartAccountNetworkList`,
`LearnMoreBottomSheet`) without changing UI behavior.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fdbbda0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Accept "." and "0." as "0" in the send flow. ## **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: MetaMask/MetaMask-planning#6971 ## **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** <img width="399" height="852" alt="Screenshot 2026-03-09 at 7 09 02 PM" src="https://github.com/user-attachments/assets/050fe43e-3a4d-4432-82e7-a2edfbf93231" /> ## **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] > **Medium Risk** > Touches send amount handling used for both validation and transaction submission; a bug here could alter the value sent, though the change is narrowly scoped to '.'/trailing-dot edge cases with added tests. > > **Overview** > Fixes the send amount flow to treat intermediate inputs like `'.'`, `'0.'`, and `'5.'` as valid by **normalizing** them (standalone dot becomes `'0'`, trailing dot is stripped) before validation. > > Applies the same normalization when submitting both EVM (`submitEvmTransaction`) and non-EVM snap transactions, and adds unit tests covering the new normalization behavior and submission payloads. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 89f2a9f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This closes https://consensyssoftware.atlassian.net/browse/GE-137 <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **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? --> Updates the deeplinking markdown doc with a callout to make developers aware that each new mobile deeplink also needs a matching deeplink for extension and an entry in the Branch LinkHub. ## **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/GE-137 ## **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** - [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 - [ ] I've included tests if applicable - [ ] 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] > **Low Risk** > Documentation-only change with no impact to runtime behavior. > > **Overview** > Adds an **IMPORTANT** callout to `docs/readme/deeplinking.md` warning that every new mobile deeplink must also be implemented identically in the MetaMask extension and registered in Branch LinkHub to avoid broken flows, with guidance for mobile-only experiences to redirect extension users to an informational webpage. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bc60b54. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… homepage sections, perps, and activity (#26976) ## **Description** Introduces a shared `SectionHeader` component in components-temp to standardize homepage and Perps section headers across the app. Previously, each section had its own inline `TouchableOpacity` + `Text` + `Icon` header pattern (or the local `SectionTitle` component), leading to inconsistent styling and duplicated logic. New `SectionHeader` component `component-library/components-temp/SectionHeader`: - Displays a title with an optional trailing arrow icon when `onPress` is provided - `endAccessory` prop for rendering arbitrary content to the right of the title (e.g. info icon, badge) - `justifyContent` prop to support `BoxJustifyContent.Between` layout (e.g. Perps "Your positions ···") - `endIconName` / `endIconColor` props to customize the trailing icon - `twClassName` / style props for container overrides - Full tap target on the row when `onPress` is provided; accessibility role and label set automatically Refactored callers: - `TrendingView`/`SectionHeader` — replaced local `TouchableOpacity` + `Text` + `Icon` with the library component - `PerpsMarketTypeSection` — replaced inline local header component with `SectionHeader` - `PerpsHomeSection` — updated to `justifyContent={Between}` + `endAccessory` pattern for the "···" action - `DeFiSection`, `NFTsSection`, `PerpsSection`, `TokensSection`, `PredictionsSection` — replaced `SectionTitle` with `SectionHeader` ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-511 ## **Manual testing steps** ```gherkin Feature: SectionHeader component Scenario: user views homepage sections Given the user is on the homepage When the user scrolls through Tokens, DeFi, NFTs, Perpetuals, and Predictions sections Then each section header renders with the correct title and arrow icon And tapping a section header navigates to the full section view ``` ## **Screenshots/Recordings** https://github.com/user-attachments/assets/e854f7bb-ce90-4cef-8e3d-a472c5f0a89c ### Explore | before | after | | -------- | ------- | |  |  | ### Perps | before | after | | -------- | ------- | |  |  | ### **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. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches many homepage/Perps/Trending headers and changes press targets (e.g., Perps action now an explicit button), so small UI regressions or broken navigation/test selectors are possible. No security- or data-sensitive logic changes. > > **Overview** > Adds an interim shared `components-temp/SectionHeader` (with stories + unit tests) to standardize section header rendering, including optional press-to-navigate, configurable trailing icon, `endAccessory`, and layout control via `justifyContent`/`twClassName`. > > Refactors homepage sections (Tokens/DeFi/NFTs/Perpetuals/Predictions), Perps components (`PerpsMarketTypeSection`, `PerpsHomeSection`), and TrendingView to use `SectionHeader`, deleting the old homepage `SectionTitle` component. Updates Perps tests to press the new action button via a dedicated `PerpsHomeSectionTestIds.ACTION_BUTTON` testID. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit db0814b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Pedro Pablo Aste Kompen <wachunei@gmail.com>
) ## Summary - Migrate `usePredictAccountState` hook from manual state management to React Query (`useQuery`) - Extract query key factory and query options into `queries/accountState.ts` - Simplify hook logic by leveraging React Query for caching, deduplication, and refetch ## Test plan - [x] Unit tests updated and passing - [ ] Verify account state loads correctly on Predict screens - [ ] Verify wallet connection flow still works end-to-end <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the hook’s public return shape and refresh semantics, and moves Polygon network enable/add logic into the query execution path, which could affect Predict screen loading and network configuration behavior. > > **Overview** > `usePredictAccountState` is rewritten to return a React Query `useQuery` result (with an `enabled` option), removing the hook’s manual `isLoading`/`isRefreshing` state, `loadAccountState` API, and navigation focus refresh behavior. > > Account-state query configuration is extracted into new `queries/accountState.ts`, including a shared query key, `staleTime`, and a queryFn that ensures the Polygon network is present/enabled (adding it via `NetworkController` when missing) before calling `PredictController.getAccountState`. Tests are updated to use a `QueryClientProvider`, assert `data`/`refetch`/invalidation behavior, and verify error logging via `Logger.error` is de-duped. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 648f063. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Luis Taniça <matallui@gmail.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
This bumps Snaps dependencies to the latest versions.
## **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: Add support for additional icon colors in Snaps `Icon`
component.
## **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**
- [ ] 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.
## **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 multiple `@MetaMask/snaps-*` packages and wires new/changed
SnapInterface controller actions, which could subtly affect Snap UI
rendering and interface lifecycle behavior. Main functional change is
limited, but dependency upgrades and messenger action-surface changes
increase regression risk.
>
> **Overview**
> **Bumps Snaps dependencies** (notably `@metamask/snaps-sdk` to
`^11.0.0` and related `snaps-controllers`, `snaps-rpc-methods`,
`snaps-utils`, execution environments), updating `yarn.lock`
accordingly.
>
> Extends the Snap UI `Icon` renderer to support additional color
variants (`error`, `warning`, `success`). Aligns Snap interface plumbing
with updated controller APIs by switching `getInterfaceState` to call
`SnapInterfaceController:getInterfaceState`, adding
`SnapInterfaceController:setInterfaceDisplayed` to allowed messenger
actions/permission specs, and updating Snap UI test utilities to include
`displayed: true`. Also bumps the test-snaps fixture URL to `3.4.1`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0702f6e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR bumps `@metamask/profile-sync-controller` to version `^28.0.0`. ## **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** no manual testing steps ## **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** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Dependency bump plus type-level changes around `AuthenticationController:getBearerToken` could cause compile/runtime integration issues if other controllers/messengers still reference the old action type. Smoke-test logic now parses SRP identifiers from JWTs, which could change expectations for identity-related tests. > > **Overview** > Bumps `@metamask/profile-sync-controller` to `^28.0.0` (updates `yarn.lock` accordingly). > > Updates several controller messenger type definitions to use the renamed `AuthenticationControllerGetBearerTokenAction` type (replacing the prior `AuthenticationControllerGetBearerToken` alias). > > Adjusts identity smoke-test helpers to derive the SRP E2E identifier by decoding the JWT from the `Authorization` header via `AuthenticationController.Mocks.getE2EIdentifierFromJwt`, instead of using a static fallback string. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2c4a09f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=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 : )