[pull] main from MetaMask:main#316
Merged
Merged
Conversation
<!-- 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** We are adding the token balance and APR information to the title for the supply and stake actions, as well as using the correct wording + token name for it, depending on the scenario. Example: "Supply DAI" or "Stake ETH" Earn case -> Supply Stake case -> Stake <img width="389" height="64" alt="Screenshot 2025-10-28 at 10 54 44" src="https://github.com/user-attachments/assets/6b9b526a-2275-4c27-82a6-a05d7811a038" /> <img width="384" height="68" alt="Screenshot 2025-10-28 at 10 55 04" src="https://github.com/user-attachments/assets/5d649beb-facb-4b0c-bc9f-fcfbfddd454f" /> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Update earn and stake view title with the correct wording. ## **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] > Show action-specific titles like "Supply/Stake/Unstake/Withdraw <token>" and display token balance + APR in the Earn/Stake navbar, with confirmations/tests updated and a new i18n key added. > > - **Earn/Stake UI**: > - Dynamic navbar titles in `EarnInputView`, `EarnWithdrawInputView`, and lending confirmation views to include action + token (e.g., `"Supply USDC"`, `"Stake ETH"`, `"Unstake ETH"`, `"Withdraw USDC"`). > - Lending flows use `earn.supply`; staking flows use `stake.stake`/`stake.unstake`. Titles computed from token ticker/symbol/name. > - Pass `earnToken` into `getStakingNavbar`; adjust effect deps accordingly. > - **Navbar**: > - Enhance `getStakingNavbar` to optionally render token `balanceFormatted` and computed APR under the title; add styles and metric-wrapped handlers. > - Add tests validating balance/APR rendering and back/icon button metric behavior. > - **Confirmations**: > - Update lending deposit/withdrawal confirmation screens to set titles as `"Supply <token>"` / `"Withdraw <token>"` and remove cancel where applicable. > - **i18n**: > - Add `earn.supply` string. > - **Tests**: > - Update Earn input/withdraw and confirmation tests to expect new titles and navbar calls; snapshot updates. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e455391. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ks) (#22453) # Phase 2 PR 1: Universal Router Core Note: this PR does not affect current app's behavior. It is **inert**. Testing will occur after the next PR to hook up the new system is merged in. ## Overview This PR introduces the core Universal Router infrastructure - a declarative, handler-based routing system for deep links. This is the minimal foundation that will be extended in subsequent PRs. ## What's Included ### Core Infrastructure (424 lines) 1. **UniversalRouter** (`UniversalRouter.ts` - 235 lines) - Singleton router managing the routing pipeline - Feature flag integration (`MM_UNIVERSAL_ROUTER`) - Fallback to legacy system 2. **HandlerRegistry** (`HandlerRegistry.ts` - 113 lines) - Handler registration and management - Priority-based execution ordering 3. **Interfaces** (`interfaces/UniversalLinkHandler.ts` - 76 lines) - `UniversalLinkHandler` abstract class - `HandlerContext` and `HandlerResult` types ### Tests (310 lines) - `UniversalRouter.test.ts` - 164 lines - `HandlerRegistry.test.ts` - 146 lines **Total: 734 lines** ✅ (under 1000 limit) ## Architecture ``` ┌─────────────────┐ │ Deep Link │ └────────┬────────┘ │ ┌────────▼────────┐ │CoreLinkNormalizer│ (Phase 1) └────────┬────────┘ │ ┌────────▼────────┐ │ UniversalRouter │◄── Feature Flag └────────┬────────┘ │ ┌────┴────┐ │ Registry│ └────┬────┘ │ [No handlers yet] │ ┌────────▼────────┐ │ Legacy System │ └─────────────────┘ ``` ## How It Works 1. Router receives normalized link from CoreLinkNormalizer 2. Feature flag determines if new system should be used 3. Since no handlers are registered yet, falls back to legacy 4. PR 2 will add actual handlers ## Testing ```bash yarn jest app/core/DeeplinkManager/router/ ``` ## Next Steps (PR 2) - Add BaseHandler with common utilities - Add NavigationHandler as example - Add integration with parseDeeplink - Add SwapHandler, SendHandler, BrowserHandler <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces a handler-based deep link routing core with a priority registry, legacy fallback, and analytics tracking, plus comprehensive unit tests. > > - **Universal Router Core** > - Adds `UniversalRouter` singleton to normalize links, select handlers by priority, execute with lifecycle hooks, and fall back to legacy when none handle. > - Tracks successful handler execution via `MetaMetrics` using `MetricsEventBuilder`. > - **Handler Management** > - Implements `HandlerRegistry` to register action-specific and global handlers, de-duplicate, sort by `priority`, find capable handlers, and unregister/clear. > - Provides `getRegisteredActions` for inspection. > - **Handler Interface** > - Adds `UniversalLinkHandler` abstract class with `supportedActions`, `priority`, `canHandle`, `handle`, and optional `beforeHandle`/`afterHandle` hooks. > - Defines `HandlerContext` and `HandlerResult` types. > - **Tests** > - `UniversalRouter.test.ts`: validates routing, priority execution, legacy fallback, error handling, and singleton behavior. > - `HandlerRegistry.test.ts`: validates registration, priority ordering, handler lookup, global deduplication, unregister, and clear. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 47d6f59. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: tommasini <46944231+tommasini@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**
This PR fixes the Android local builds as currently they're building in
CI release mode which is incompatible with local runs.
<!--
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]
> Tightens Android E2E build gating to require METAMASK_ENVIRONMENT=e2e
and E2E=true, and bumps iOS/Android build numbers to 2993.
>
> - **Build Scripts**:
> - Adjust `scripts/build.sh` Android E2E condition to require both
`METAMASK_ENVIRONMENT='e2e'` and `E2E='true'` before invoking E2E build
paths for `main` and `flask`.
> - **Versioning**:
> - Bump Android `versionCode` in `android/app/build.gradle` to `2993`.
> - Update iOS `CURRENT_PROJECT_VERSION` across
`ios/MetaMask.xcodeproj/project.pbxproj` to `2993`.
> - Sync Bitrise envs in `bitrise.yml` (`VERSION_NUMBER`,
`FLASK_VERSION_NUMBER`) to `2993`.}
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f1574e3. 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>
… on market details (#22495) <!-- 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** - Ensures both active and claimable positions are visible under the positions tab on the market details view - Note I've tested with all the possible combinations I can, but a local test would be awesome (view the positions tab for a selection of positions) <!-- 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: NA ## **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="420" alt="image" src="https://github.com/user-attachments/assets/2ce4f958-0a7d-462f-a6aa-63facb6293e8" /> ## **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] > Market details now loads, displays, and refreshes both active and claimable positions, updating tabs, claim logic, and tests accordingly. > > - **PredictMarketDetails** > - Split positions into `activePositions` and `claimablePositions` via two `usePredictPositions` calls; defer load and trigger both after market ready. > - Refresh now refetches market, price history, and both active/claimable positions. > - Tabs show Positions if either list has items; readiness includes both positions states. > - Positions section renders active positions (market status) then claimable positions (closed status). > - Claim button visibility depends on positive PnL in `claimablePositions` when market is closed. > - **Tests** > - Test setup supports split positions overrides (`active`/`claimable`) and mocks hook implementation accordingly. > - Updated pull-to-refresh to expect active positions reload; added claimable positions cases for closed markets and claim flow. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7bcf632. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… polling (#22463) ## **Description** This is the first in a series of PRs removing the `MM_REMOVE_GLOBAL_NETWORK_SELECTOR` feature flag. **Master PR for reference:** #22067 This PR removes the feature flag from polling hooks and their tests. The polling hooks (`useTokenRatesPolling` and `useTokenListPolling`) already use `usePollingNetworks()`, which relies on `NetworkEnablementController` to determine which networks to poll. The tests were updated to: - Remove all `isRemoveGlobalNetworkSelectorEnabled` feature flag mocks - Remove obsolete tests that covered the old behavior (when the flag was OFF) - Update test states to include `NetworkEnablementController` configuration - Rename test describe blocks from "Feature flag scenarios" to "Network enablement scenarios" #### Files Changed: `app/components/hooks/AssetPolling/useTokenRatesPolling.test.ts` - Removed feature flag mocks, updated tests to use NetworkEnablementController state `app/components/hooks/AssetPolling/useTokenListPolling.test.ts` - Removed feature flag mocks, updated tests to use NetworkEnablementController state #### Behavior Change: The default behavior is now equivalent to the feature flag being ON. Polling hooks poll enabled EVM networks based on NetworkEnablementController.enabledNetworkMap instead of using the feature flag to determine behavior. ## **Changelog** CHANGELOG entry: Removed `MM_REMOVE_GLOBAL_NETWORK_SELECTOR` feature flag from asset polling hooks. Polling now uses `NetworkEnablementController` state to determine which networks to poll. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-195 ## **Manual testing steps** ```gherkin Feature: Asset polling hooks without feature flag Scenario: Verify polling works correctly with NetworkEnablementController Given the app is running And multiple EVM networks are configured with some enabled and some disabled When the app loads and polling hooks initialize Then token rates polling should only poll enabled networks And token list polling should only poll enabled networks And disabled networks should not be polled And all unit tests pass ``` ## **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. ## **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] > Removes `isRemoveGlobalNetworkSelectorEnabled` usage across Wallet, selectors, and polling hooks, standardizing behavior to use `NetworkEnablementController`-driven enabled networks and updating tests/snapshots accordingly. > > - **Wallet (`app/components/Views/Wallet`)**: > - Remove `isRemoveGlobalNetworkSelectorEnabled` references; always show `NftGrid` when `collectiblesEnabled`. > - Simplify testnet checks (`enabledNetworksHasTestNet`) to use enabled EVM networks directly. > - In `handleNetworkFilter`, call `selectNetwork(chainId)` when no enabled EVM networks (without flag gating). > - Tests: drop feature-flag mocks; add "Network Manager Integration" cases using `NetworkEnablementController`; snapshots updated. > - **Asset Polling**: > - `use-polling-networks`: remove flag logic; return configs for enabled EVM networks when EVM selected. > - Tests (`useAccountTrackerPolling`, `useCurrencyRatePolling`, `useTokenDetectionPolling`, `useTokenListPolling`, `useTokenRatesPolling`): remove flag mocks and obsolete cases; assert polling only for enabled/popular networks; add `NetworkEnablementController` state; ensure no polling when EVM not selected; unmount cleanup expectations. > - **Selectors (`app/selectors/multichain/evm.ts`)**: > - Remove flag-based branches; filter tokens by `enabledNetworksByNamespace[EIP-155]` when available, otherwise fall back to current-network/all-networks behavior. > - Keep testnet filtering independent of the flag. > - Tests updated to validate enabled-network filtering and fallbacks. > - **Snapshots**: > - Update error text assertions in Wallet error boundary (`...reading 'isNftFetchingProgress'`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 328bfa3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** The header and header icons aren't aligned ## **Changelog** CHANGELOG entry:null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-196 ## **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** `~` ### **Before** <img width="500" alt="before" src="https://github.com/user-attachments/assets/d158d2cf-8f31-44a6-aba2-1823cc3f5669" /> ### **After** <img width="500" alt="after" src="https://github.com/user-attachments/assets/62f27aa9-9b41-44ce-bf80-2367a2b1bedc" /> ## **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] > Vertically centers the Wallet header content and sets a fixed 72px header height, updating snapshots accordingly. > > - **UI (Navbar)**: > - Add `innerStyles.headerContainer` in `app/components/UI/Navbar/index.js` with `height: 72` and `alignItems: 'center'`. > - Apply `style={innerStyles.headerContainer}` to `HeaderBase` in `getWalletNavbarOptions` to enforce alignment and height. > - **Tests**: > - Update Wallet view snapshots to reflect centered header and fixed height (`__snapshots__/index.test.tsx.snap`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 32279d4. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** This PR implements optimistic updates for Predict positions to provide immediate user feedback when placing BUY/SELL orders, significantly improving the user experience by showing skeleton loaders instead of stale data while waiting for API confirmation. ### What is the reason for the change? Previously, when users placed orders in the Predict feature, they had to wait for the API to confirm the transaction before seeing their position update. This created a poor UX where: 1. Users saw outdated position values after placing orders 2. No visual feedback indicated that an order was processing 3. Users were unsure if their action succeeded until API confirmed ### What is the improvement/solution? **Implemented a comprehensive optimistic updates system:** #### Core Features - **Optimistic position creation**: When users BUY, create an immediate optimistic position with expected values - **Optimistic position updates**: When users BUY more of an existing position, optimistically update with accumulated values - **Optimistic position removal**: When users SELL or CLAIM, immediately hide the position from the list - **Smart validation**: Compare API responses with expected sizes to know when to remove optimistic updates - **Auto-cleanup**: Remove optimistic updates after 1-minute timeout if API never confirms - **Defensive checks**: Prevent optimistic updates on claimable positions #### Implementation Details 1. **PolymarketProvider.ts** (~450 lines added): - Added `OptimisticUpdateType` enum (CREATE, UPDATE, REMOVE) - Added `OptimisticPositionUpdate` interface with type, position data, and expected size - Added `#optimisticPositionUpdatesByAddress` Map to track updates per user address - Implemented `createOrUpdateOptimisticPosition()` for BUY orders - Implemented `removeOptimisticPosition()` for SELL/CLAIM orders - Implemented `applyOptimisticPositionUpdates()` to merge optimistic data with API responses - Implemented `isApiPositionUpdated()` with 0.1% tolerance for size validation - Added cleanup logic for expired optimistic updates (1-minute timeout) 2. **UI Components**: - **PredictPosition.tsx**: Added skeleton loaders for current value and PnL when `optimistic: true` - **PredictPositionDetail.tsx**: Added skeleton loaders and disabled "Cash out" button for optimistic positions - **PredictPosition types**: Added `optimistic?: boolean` flag to `PredictPosition` type 3. **Controller**: - **PredictController.ts**: Include fees in optimistic balance calculation for accurate display 4. **Comprehensive Test Coverage** (~1,830 lines of tests): - Fixed 8 failing tests from system migration - Added 21 new tests covering CREATE, UPDATE, REMOVE, integration, and UI scenarios - Achieved 91.53% statement coverage and 91.75% line coverage ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [PRED-294](https://consensyssoftware.atlassian.net/browse/PRED-294) ## **Manual testing steps** ```gherkin Feature: Optimistic updates for Predict positions Scenario: User buys a new position Given user is on the Predict Positions screen And user has no position in a market When user places a BUY order for a position Then user immediately sees the new position in their list And the position shows skeleton loaders for value and PnL And the initial value and shares are displayed When the API confirms the order (within 1 minute) Then the skeleton loaders are replaced with actual values And the position shows real-time current value and PnL Scenario: User sells an existing position Given user is on the Predict Positions screen And user has an existing position When user places a SELL order for the position Then the position immediately disappears from the list When the API confirms the sale Then the position remains hidden (optimistic update removed) Scenario: User buys more of an existing position Given user has an existing position with 10 shares When user places another BUY order for the same position Then the position shows skeleton loaders And the expected accumulated values are displayed When the API confirms the order Then actual updated values replace the skeletons Scenario: API timeout cleanup Given user placed a BUY order 1 minute ago And the API has not yet confirmed When 1 minute has passed since the order Then the optimistic update is automatically cleaned up And user sees either the confirmed API position or no position ``` ## **Screenshots/Recordings** ### **Before** After placing an order, users saw stale position data with no indication that an order was processing. ### **After** After placing an order, users immediately see: - New positions appear with skeleton loaders - Existing positions update with skeleton loaders - Sold positions disappear immediately - Skeleton loaders are replaced with real values when API confirms https://github.com/user-attachments/assets/a2b08c94-f223-41a0-b85f-615abd800780 ## **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. --- ## **Technical Implementation Summary** ### Files Changed - `PolymarketProvider.ts`: +450 lines (optimistic update system) - `PredictPosition.tsx`: +29 lines (skeleton loaders) - `PredictPositionDetail.tsx`: +27 lines (skeleton loaders, disabled button) - `PredictController.ts`: +3 lines (fee calculation) - `types/index.ts`: +1 line (`optimistic?: boolean` flag) - Test files: +1,830 lines (comprehensive coverage) ### Optimistic Update Flow **BUY Order:** 1. User places BUY order → `placeOrder()` called 2. Order submitted to API via `submitClobOrder()` 3. On success, `createOrUpdateOptimisticPosition()` called 4. Optimistic position created with `optimistic: true` flag 5. `getPositions()` merges optimistic position with API data 6. UI shows skeleton loaders for value/PnL 7. When API returns position with expected size → optimistic update removed 8. If API doesn't confirm within 1 minute → optimistic update expires **SELL/CLAIM Order:** 1. User places SELL/CLAIM order → `placeOrder()` or `confirmClaim()` called 2. `removeOptimisticPosition()` marks position for removal 3. `getPositions()` filters out the position 4. Position immediately disappears from UI 5. When API confirms (position gone or size reduced) → optimistic update removed ### Test Coverage **Total: 21 new tests added** **PolymarketProvider (14 tests):** - CREATE scenarios: 7 tests (position creation, value calculation, market details) - UPDATE scenarios: 4 tests (accumulation, avgPrice, preservation) - Integration: 3 tests (BUY→confirm, timeout, BUY→SELL) **UI Components (7 tests):** - PredictPosition: 4 tests (skeleton display, value hiding) - PredictPositionDetail: 3 tests (skeleton display, button state) **Coverage Achieved:** - Statements: 91.53% ✅ - Branches: 83.01% ✅ - Functions: 91.6% ✅ - Lines: 91.75% ✅ All metrics exceed the 80% target. [PRED-294]: https://consensyssoftware.atlassian.net/browse/PRED-294?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds full optimistic position create/update/remove flow with UI skeletons, disables actions during optimism, adjusts balance for fees, and expands tests. > > - **Predict Provider (Polymarket)**: > - Implement optimistic updates system (`CREATE`/`UPDATE`/`REMOVE`) via in-memory map keyed by address and `outcomeTokenId`. > - Merge optimistic state in `getPositions` with timeout cleanup (1 min) and API-size validation tolerance. > - Block orders on claimable positions; add targeted fetch by `outcomeId` in `getPositions`. > - Apply optimistic removal on SELL and CLAIM; create/update optimistic positions on BUY using market details when available. > - **UI**: > - `PredictPosition` and `PredictPositionDetail`: show skeletons for value/PnL when `position.optimistic` is true; disable "Cash out" for optimistic positions. > - **Controller**: > - Deduct total fees from balance during optimistic BUY balance update. > - **Types/Providers API**: > - Add `optimistic?: boolean` to `PredictPosition`; add `outcomeId` to `GetPositionsParams` and wire through provider method. > - **Tests**: > - Extensive new tests covering optimistic create/update/remove flows, integration scenarios, and UI behavior. > - **Misc**: > - Minor hook lint suppression in `usePredictPrices`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 144511a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** This PR reverts commit 74b8745 from PR #21199. **What is the reason for the change?** The font preloader changes introduced in #21199 are causing rendering bugs in the application: - Text is being cut off in various components - Font weights are not loading correctly - The comprehensive font preloading approach is causing unexpected layout issues **What is the improvement/solution?** This revert restores the previous variant-based font preloading approach, which: - Preloads only the specific TextVariant fonts that are actively used - Maintains stable font rendering without text cutoff issues - Ensures font weights load properly across all components - Restores the working implementation until the font loading issues can be properly addressed ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #22301 Reverts: #21199 Original commit: 74b8745 ## **Manual testing steps** ```gherkin Feature: Font rendering after revert Scenario: user views text content across the app Given the user has the app running with the reverted font preloader And the user navigates through different screens with various text components When the user views text content in input fields, headings, and body text Then all text should be fully visible without cutoff And font weights should render correctly (regular, medium, bold) And there should be no layout shifting or text overflow issues ``` ## **Screenshots/Recordings** ### **Before** N/A - This is a revert PR ### **After** N/A - This is a revert PR ## **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. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Reverts/rewrites font preloader to load only TextVariant fonts and updates input styles to set fontWeight from theme while removing hardcoded lineHeight/fontFamily; updates tests and snapshots accordingly. > > - **Fonts**: > - **Preloader** (`app/core/FontPreloader/FontPreloader.ts`): revert to variant-based font loading using `TextVariant` and `getFontFamily`; preload 400/500/700 weights on web; streamline native preload and logging. > - **Tests** (`app/core/FontPreloader/__tests__/FontPreloader.test.ts`): simplify and align with new preloader behavior (singleton, RN preload, concurrency, reset, errors, promise access). > - **UI Styles**: > - **Inputs** (`app/component-library/.../Input.styles.ts`): apply `fontWeight` from `theme.typography[textVariant]`; keep baseline alignment; minor comment/format tweak. > - Remove hardcoded `fontFamily` in custom inputs (`Views/EnterPasswordSimple/index.js`, `Views/RevealPrivateCredential/styles.ts`, `Views/MultichainAccounts/PrivateKeyList/styles.ts`). > - **Snapshots**: update across UI to reflect `fontWeight: "400"` and removal of explicit `lineHeight`/`fontFamily` where applicable. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 09ccad9. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
This PR implements automatic eligibility refresh for the Predict feature
when the app comes to foreground. Previously, eligibility was only
checked on initial load or manual refresh. Now, when a user backgrounds
the app and then returns to it, the eligibility status is automatically
refreshed.
**What is the reason for the change?**
Users may change their network configuration (e.g., switching between
different network connections) while the app is backgrounded. When they
return to the app, the Predict feature should automatically check
eligibility again to reflect any potential changes in their connection
status.
**What is the improvement/solution?**
- Added an `AppState` listener to the `usePredictEligibility` hook that
detects when the app transitions from `background`/`inactive` to
`active` state
- Implemented 1-minute debouncing to prevent excessive API calls if the
user switches in and out of the app multiple times
- Manual refresh functionality remains unchanged and bypasses the
debounce
- Added comprehensive error handling and logging
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: N/A
## **Manual testing steps**
```gherkin
Feature: Auto-refresh Predict eligibility on app focus
Scenario: user returns to app and eligibility is refreshed
Given user has opened the Predict feature
And user is eligible to use Predict
When user backgrounds the app (switches to another app)
And user returns to the app
Then eligibility is automatically refreshed
And user sees updated eligibility status if it changed
Scenario: user rapidly switches in and out of app
Given user has opened the Predict feature
And eligibility was just refreshed
When user backgrounds the app
And user returns to the app within 1 minute
Then eligibility refresh is skipped due to debouncing
And user still has access to Predict feature
Scenario: user returns after debounce period
Given user has opened the Predict feature
And eligibility was refreshed more than 1 minute ago
When user backgrounds the app
And user returns to the app
Then eligibility is automatically refreshed
```
## **Screenshots/Recordings**
N/A - This is an internal behavior change with no visual UI impact.
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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]
> Introduce a singleton-managed AppState listener to auto-refresh
Predict eligibility on app foreground with 1-minute debounce, logging,
and race-condition prevention, plus comprehensive tests.
>
> - **Predict Hook (`usePredictEligibility.ts`)**:
> - **Singleton manager (`EligibilityRefreshManager`)**:
> - Manages a single `AppState` `change` listener across hook instances.
> - Refreshes `Engine.context.PredictController.refreshEligibility()` on
transition to `active`.
> - Debounces auto-refreshes by 60s; manual `refreshEligibility`
bypasses debounce.
> - Prevents concurrent calls by reusing in-flight promise; tracks last
refresh time.
> - Registers/unregisters per hook mount/unmount; adds detailed
`DevLogger` logs and error handling.
> - **Tests (`usePredictEligibility.test.ts`)**:
> - Cover eligibility state selection, singleton
registration/unregistration, app focus auto-refresh, debounce behavior,
manual refresh bypass, error logging/continuation, and
concurrency/race-condition scenarios.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8c94340. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
This PR migrates the Predict feature flag from a simple boolean flag to
a version-gated feature flag structure, aligning it with the pattern
used by Perps and other features.
**What is the reason for the change?**
The Predict feature needs version gating to ensure users have the
minimum required app version (7.60.0) before accessing the feature. The
previous implementation used a simple boolean flag (`predictEnabled`)
which didn't support version checking.
**What is the improvement/solution?**
- Changed flag name from `predictEnabled` to `predictTradingEnabled` to
follow naming conventions
- Implemented version-gated structure with `enabled` and
`minimumVersion` properties
- Added environment variable fallback (`MM_PREDICT_ENABLED`) for local
development
- Updated all references across the codebase (selectors, tests, mocks,
E2E helpers)
- Ensured backward compatibility by maintaining the same boolean return
type
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: Predict feature flag version gating
Scenario: user with app version below minimum cannot access Predict
Given user has app version 7.59.0
And remote feature flag predictTradingEnabled is enabled with minimumVersion "7.60.0"
When user navigates to Wallet screen
Then Predict feature should not be visible/accessible
Scenario: user with app version at or above minimum can access Predict
Given user has app version 7.60.0 or higher
And remote feature flag predictTradingEnabled is enabled with minimumVersion "7.60.0"
When user navigates to Wallet screen
Then Predict feature should be visible and accessible
Scenario: local environment variable overrides when remote flag unavailable
Given remote feature flags are empty or invalid
And MM_PREDICT_ENABLED environment variable is set to "true"
When app initializes
Then Predict feature should be enabled based on local flag
Scenario: remote flag takes precedence over local flag
Given remote feature flag predictTradingEnabled is explicitly disabled
And MM_PREDICT_ENABLED environment variable is set to "true"
When app initializes
Then Predict feature should be disabled (remote flag overrides local)
```
## **Screenshots/Recordings**
Not applicable - This is an internal refactoring with no UI changes.
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
## **Technical Details**
### Files Modified (7 total)
1. **`app/components/UI/Predict/selectors/featureFlags/index.ts`**
- Migrated from boolean flag to `VersionGatedFeatureFlag` structure
- Changed flag name: `predictEnabled` → `predictTradingEnabled`
- Added environment variable fallback: `MM_PREDICT_ENABLED`
- Added comprehensive JSDoc documentation
2. **`app/components/UI/Predict/selectors/featureFlags/index.test.ts`**
- Rewrote tests following unit testing guidelines (AAA pattern)
- Added comprehensive test coverage for version gating
- Added tests for remote flag precedence over local flags
- Added tests for invalid flag scenarios
- All 19 tests passing ✅
3. **`app/components/UI/Predict/mocks/remoteFeatureFlagMocks.ts`**
- Updated mock structure to version-gated format
4. **`app/components/Views/Wallet/index.test.tsx`**
- Updated 5 occurrences of `predictEnabled` → `predictTradingEnabled`
5. **`.js.env.example`**
- Added `MM_PREDICT_ENABLED` environment variable example
6. **`e2e/api-mocking/helpers/remoteFeatureFlagsHelper.ts`**
- Updated default mock to version-gated structure
7. **`e2e/api-mocking/mock-responses/feature-flags-mocks.ts`**
- Updated `remoteFeatureFlagPredictEnabled` function
### Key Implementation Details
- **Flag Structure**: `{ enabled: boolean, minimumVersion: string }`
- **Backend Flag Name**: `predictTradingEnabled`
- **Minimum Version**: `7.60.0`
- **Local Fallback**: `MM_PREDICT_ENABLED` environment variable
(defaults to `false`)
- **Validation**: Uses `validatedVersionGatedFeatureFlag()` utility for
type checking and version validation
### Test Coverage
- ✅ Remote flag precedence over local flags
- ✅ Version gating validation
- ✅ Invalid flag type handling
- ✅ Fallback to local environment variable
- ✅ Edge cases (null, undefined, empty objects)
### Breaking Changes
None - The selector maintains the same boolean return type, ensuring
backward compatibility with existing code.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Migrates Predict flag to version-gated `predictTradingEnabled` (with
minimumVersion and `MM_PREDICT_ENABLED` fallback) and updates selectors,
tests, and mocks accordingly.
>
> - **Predict feature flag**:
> - Rename `predictEnabled` → `predictTradingEnabled`.
> - Adopt version-gated structure `{ enabled, minimumVersion }` (min app
`7.60.0`).
> - Update selector to validate remote flag and fallback to
`MM_PREDICT_ENABLED`.
> - **Tests**:
> - Add/expand unit tests for precedence, version gating, and invalid
scenarios in `selectors/featureFlags`.
> - Update `Wallet` tests to use `predictTradingEnabled` objects.
> - **Mocks/E2E**:
> - Update Predict mocks and remote flags helpers to new structure.
> - Add `MM_PREDICT_ENABLED` to `.js.env.example`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8997c9e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#22499) <!-- 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** Changes the auto-refresh behavior in usePredictOrderPreview from interval-based to sequential pattern. The timer now waits for the preview response before starting the timeout countdown, preventing overlapping requests. Key changes: - Replace setInterval with recursive setTimeout pattern - Add scheduleNextRefresh function to trigger after response - Schedule next refresh after both successful and error responses - Clear pending timers on unmount and parameter changes - Update tests to verify sequential refresh behavior This ensures the autoRefreshTimeout is a delay AFTER each response completes, rather than a fixed interval that could cause overlapping requests when API response times exceed the timeout value. <!-- 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: [PRED-299](https://consensyssoftware.atlassian.net/browse/PRED-299?atlOrigin=eyJpIjoiOTQwNThkMTg4N2UzNDQ1MjljZTEyNGM0MTlhOGZjMjUiLCJwIjoiaiJ9) ## **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] > Replaces interval-based auto-refresh with response-triggered sequential timeouts in `usePredictOrderPreview`, adds cleanup on param changes/unmount, and updates tests accordingly. > > - **Hook `usePredictOrderPreview`**: > - Replace `setInterval` auto-refresh with sequential `setTimeout` scheduled via `scheduleNextRefresh` after each response (success or error). > - Introduce refs for timer and callbacks: `refreshTimerRef`, `calculatePreviewRef`, `scheduleNextRefreshRef`. > - Clear pending refresh timers on unmount and when parameters change; debounce initial calculation. > - Minor safety: optional chaining on `calculatePreviewRef.current?.()`. > - **Tests `usePredictOrderPreview.test.ts`**: > - Rename and add cases to verify response-triggered scheduling, waiting before countdown, scheduling after errors, and clearing timers on parameter changes and unmount. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2c9fb28. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [PRED-299]: https://consensyssoftware.atlassian.net/browse/PRED-299?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
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 : )