[pull] main from MetaMask:main#450
Merged
Merged
Conversation
## **Description** This PR adds React hooks for subscribing to real-time WebSocket updates in the Predict feature. The hooks integrate with the existing `PredictController` and `WebSocketManager` infrastructure to provide live game updates and market price feeds. **Why:** - Enable real-time UI updates for NFL games (scores, periods, game status) - Provide live market price updates (best bid/ask) without polling - Support the upcoming live NFL game experience **What's included:** - `useLiveGameUpdates` - Hook for subscribing to real-time game state changes - `useLiveMarketPrices` - Hook for subscribing to market price updates with Map-based state - Controller methods to bridge UI hooks with provider WebSocket subscriptions - Comprehensive unit tests (33 tests, 100% passing) ## **Changelog** CHANGELOG entry: null ## **Related issues** [PRED-462](https://consensyssoftware.atlassian.net/browse/PRED-462) ## **Manual testing steps** ```gherkin Feature: Live game updates subscription Scenario: User views live game data Given user is on a market details page for an active NFL game And WebSocket connection is established When game state changes (score update, period change) Then UI receives real-time update via useLiveGameUpdates hook And game information displays updated values Scenario: User views live market prices Given user is viewing market outcomes with token IDs And WebSocket connection is established When market prices change Then UI receives real-time price update via useLiveMarketPrices hook And prices map contains latest bid/ask values ``` ## **Screenshots/Recordings** ### **Before** N/A - New feature (hooks only, no UI changes) ### **After** N/A - New feature (hooks only, 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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Enables real-time data flows in Predict via controller/provider APIs and React hooks. > > - Adds `useLiveGameUpdates` and `useLiveMarketPrices` hooks for subscribing to game state and price updates, with connection polling, cleanup, and state (lastUpdateTime, Map-backed prices) > - Extends `PredictController` with `subscribeToGameUpdates`, `subscribeToMarketPrices`, and `getConnectionStatus` (no-op/disconnected fallbacks when unsupported) > - Updates `PolymarketProvider` to delegate to `WebSocketManager` (`subscribeToGame`, `subscribeToMarketPrices`, `getConnectionStatus`) and map status to `ConnectionStatus` > - Enhances provider `types` with `GameUpdateCallback`, `PriceUpdateCallback`, and `ConnectionStatus`; exports hooks in `hooks/index.ts` > - Adds thorough unit tests for hooks, controller WebSocket methods, and provider delegation > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 23776cb. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [PRED-462]: https://consensyssoftware.atlassian.net/browse/PRED-462?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- 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** Update the browser button styling in TrendingView to match the ExploreSearchBar for visual consistency. <img width="1760" height="842" alt="image" src="https://github.com/user-attachments/assets/2981ed08-2e2a-49b7-b0b9-20721e7c91b4" /> ## **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: style: explore tab button styling ## **Related issues** Fixes: #24344 https://consensyssoftware.atlassian.net/browse/ASSETS-2240 ## **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="389" height="113" alt="Screenshot 2026-01-13 at 15 14 39" src="https://github.com/user-attachments/assets/71a74159-a42b-48f7-8cfa-c73211bbb97e" /> <img width="375" height="98" alt="Screenshot 2026-01-13 at 15 14 47" src="https://github.com/user-attachments/assets/e58b2960-8da8-48b9-b898-da125e2cc51b" /> <!-- [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. --- <a href="https://cursor.com/background-agent?bcId=bc-ea04488d-8041-4b62-a2e4-339551a610af"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-cursor-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in Cursor" src="https://cursor.com/open-in-cursor.svg"></picture></a> <a href="https://cursor.com/agents?id=bc-ea04488d-8041-4b62-a2e4-339551a610af"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-web-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web" src="https://cursor.com/open-in-web.svg"></picture></a> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Aligns the TrendingView browser button with `ExploreSearchBar` styling for consistency. > > - Wraps button content in a rounded, muted `Box` with `min-h/min-w` (44px) instead of bordered square > - Uses `TextVariant.BodyLg` with `TextColor.TextAlternative` for tab count; otherwise `IconName.Explore` at `IconSize.Lg` with `IconColor.IconAlternative` > - Moves `testID` to the `TouchableOpacity` (`trending-view-browser-button`) > - Adds imports for `IconColor` and `TextColor` > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 67b8957. 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: Prithpal Sooriya <prithpal.sooriya@consensys.net>
## **Description** This PR updates the header and footer styling across account-related screens to align with the new design system patterns. The changes migrate multiple screens from legacy navigation headers to the new `HeaderWithTitleLeft` and `HeaderCenter` components from `component-library/components-temp`. **Screens updated:** - **AccountSelector** - Now uses `HeaderCenter` for consistent bottom sheet header styling with a close button - **ImportNewSecretRecoveryPhrase** - Migrated to `HeaderWithTitleLeft` with proper back/scan button props - **SelectHardware (ConnectHardware)** - Migrated to `HeaderWithTitleLeft` with subtitle support - **ImportPrivateKey** - Migrated to `HeaderWithTitleLeft` and replaced raw `TextInput` with `TextField` component - **SeedphraseModal** - Added `HeaderCenter` component and updated button variant from Primary to Secondary **Additional improvements:** - Standardized platform-specific padding for footers (16px on iOS, 0 on Android) - Updated text colors to use `TextColor.Alternative` for subtitle/description text - Cleaned up unused style properties and imports - Improved hardware wallet button layout with proper flex styling ## **Changelog** CHANGELOG entry: Updated header and footer styling across account management screens to align with new design system ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/jira/software/c/projects/MDP/boards/2972?assignee=62afb43d33a882e2be47c36f&quickFilter=3325&selectedIssue=MDP-322 https://consensyssoftware.atlassian.net/jira/software/c/projects/MDP/boards/2972?assignee=62afb43d33a882e2be47c36f&quickFilter=3325&selectedIssue=MDP-324 ## **Manual testing steps** ```gherkin Feature: Account flow header styling Scenario: User views account selector Given the user is on the wallet home screen When user taps on the account selector Then the bottom sheet should display with a centered header and close button Scenario: User imports a wallet with SRP Given the user is on the add account flow When user selects "Import wallet" Then the import SRP screen should display the new left-aligned header with back and scan buttons Scenario: User imports a private key Given the user is on the add account flow When user selects "Import account" (private key) Then the import screen should display with the new left-aligned header And the text input should display with the updated TextField component styling Scenario: User connects hardware wallet Given the user is on the add account flow When user selects "Add hardware wallet" Then the select hardware screen should display with the new left-aligned header and subtitle Scenario: User views seedphrase modal Given the user is on the backup seedphrase flow When user taps on "What is a Secret Recovery Phrase?" Then the modal should display with centered header and close button And the "Got it" button should be styled as secondary variant ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/dd34213c-42a6-4779-8fd1-15dfe2d84616 <!-- [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] > Aligns account-related screens with the new design system headers and spacing. > > - Replaces legacy nav headers with `HeaderWithTitleLeft`/`HeaderCenter` in `ImportNewSecretRecoveryPhrase`, `ImportPrivateKey`, `SelectHardware`, `AccountSelector`, and `SeedphraseModal` > - Standardizes footer/content spacing: `paddingBottom` iOS=16/Android=0; adds `paddingHorizontal`/`paddingTop` where applicable > - Updates text styling to `TextColor.Alternative` for descriptions and refines list/bullet spacing > - Changes `SeedphraseModal` CTA to `ButtonVariants.Secondary`; keeps SRP import CTA primary and moves it to sticky footer area > - Refactors `ImportPrivateKey`: new header with inline learn-more link, updated placeholder, disabled state while loading, and refreshed input/typography styles > - Cleans up unused styles/imports and updates tests/snapshots and e2e selectors to match new headers and layout > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1f1b86b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
This PR adds the ability to populate team information (name, logo,
abbreviation, colors) into the `market.game` object for live sports
markets.
**Why:** Live sports UI needs team data (logos, colors, names) to render
game cards and details pages. Previously, the `market.game` object
existed but had no team information populated.
**Solution:**
- **TeamsCache**: Singleton that fetches and caches team data from the
Polymarket Gamma API (`/teams?league={league}`), keyed by league and
team abbreviation
- **gameParser utilities**: Functions to extract league from event tags,
parse game slugs for team abbreviations, and build complete game data
with team objects
- **Integration**: `PolymarketProvider.getMarkets()` and
`getMarketDetails()` now load team data and populate `market.game` with
home/away team information
The implementation is designed to be league-agnostic via a
`LIVE_SPORTS_LEAGUES` constant - adding a new league just requires
adding it to that array.
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/PRED-463
## **Manual testing steps**
```gherkin
Feature: Team information in live sports markets
Scenario: user views sports markets with team data
Given user has the Predict feature enabled
And there are active NFL game markets
When user navigates to the Sports category
Then markets display with game data including team names, logos, and colors
Scenario: user views market details for a sports game
Given user has the Predict feature enabled
And there is an active NFL game market
When user taps on the market to view details
Then the market details include home and away team information
And team logos and colors are available for rendering
```
## **Screenshots/Recordings**
### **Before**
N/A - This is backend/data layer change, no UI changes in this PR.
### **After**
N/A - This is backend/data layer change, no UI changes in this 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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Introduces live sports team and game data plumbing with conditional
enablement and extensive tests.
>
> - Adds `LIVE_SPORTS_LEAGUES` and `isLiveSportsEnabled` flag to gate
live sports features
> - New `TeamsCache` singleton fetches/caches teams from Gamma API and
exposes lookups (with comprehensive tests)
> - New `gameParser` utilities to detect league, parse slugs, build
`game` data, format period, and parse scores (tests included)
> - Updates types: `PredictMarketGame.score` becomes structured `{ away,
home, raw }`; `elapsed`/`period` are nullable; Polymarket API event type
extended with game fields
> - `GameCache` overlays parsed scores and null-safe clock/period; tests
updated accordingly
> - `parsePolymarketEvents` now accepts options including `teamLookup`;
builds `game` when available; `getParsedMarketsFromPolymarketApi`
threads `teamLookup`
> - `PolymarketProvider.getMarkets`/`getMarketDetails` conditionally
load leagues via `TeamsCache`, pass `teamLookup`, and only overlay
`GameCache` when live sports enabled (tests cover enabled/disabled
paths)
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2896cb7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
When navigating to swaps from a trending token:
1. The source token is set to the native gas token of the same chain as
the trending token
2. The destination token is set as the trending token
If the trending token happens to be the native gas token:
1. Source: default dest token for that chain (usually a stablecoin like
USDC, USDT)
2. Dest: native gas token
This provides a better UX since users can immediately swap using the
native token of that chain.
You will need to force `selectAssetsTrendingTokensEnabled` to return
`true` to test this feature for now.
## **Changelog**
CHANGELOG entry: Set trending token as the dest token when navigating to
swaps
## **Related issues**
Fixes: SWAPS-3688
## **Manual testing steps**
```gherkin
Feature: Trending token swap navigation
Scenario: user taps swap from a trending token on network
Given user is viewing a trending token on network
When user taps the Swap button
Then the swap source token should be native token
And the swap destination token should be the trending token
```
## **Screenshots/Recordings**
### **Before**
<!-- Source token was always ETH on mainnet -->
### **After**
<!-- Source token is now native token of the trending token's chain -->
https://github.com/user-attachments/assets/4a87dfae-031b-4a91-89a9-225fda808c5f
## **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]
> Improves swap/bridge prefill logic and integrates Trending tokens
intent.
>
> - Add `getSwapTokens` in `AssetOverview` to compute
`sourceToken`/`destToken` based on context: native gas tokens use
default pair → native; trending tokens use native → asset; otherwise
asset → (unspecified)
> - Pass computed tokens to `useSwapBridgeNavigation` and export
`isAssetFromTrending`; leverage `isNativeAddress`,
`getNativeSourceToken`, and `getDefaultDestToken`
> - Mark Trending navigation with `isFromTrending` in
`TrendingTokenRowItem` so Asset view enters buy mode; update tests
accordingly
> - Extend tests: capture hook args, add cases for
trending/non-trending, cross-chain, native token paths, and unit tests
for `getSwapTokens`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3e695bd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…2] (#22076) # Pull Request Description ## **Description** This PR migrates MetaMask Mobile from the legacy MetaMetrics system to the new `@metamask/analytics-controller` package. This migration standardizes analytics across MetaMask products and provides a more maintainable, controller-based architecture. **Reason for change:** - Standardize analytics implementation across MetaMask products using the shared `@metamask/analytics-controller` package - Improve maintainability by using a controller-based architecture that integrates with the Engine - Reduce code duplication and improve type safety with shared analytics types - Prepare for future deprecation of the legacy MetaMetrics system **Improvement/Solution:** - Integrated `@metamask/analytics-controller` as a new Engine controller - Created migration 110 to migrate legacy storage keys (METAMETRICS_ID, MIXPANEL_METAMETRICS_ID) to the new ANALYTICS_ID key - Migrated opt-in preference from METRICS_OPT_IN to AnalyticsController state - Created new analytics utility module (`app/util/analytics/analytics.ts`) that provides a clean API for components - Updated all controller initializations to use `analyticsId` instead of `metaMetricsId` - Added AnalyticsController messenger delegation to controllers that need to track events - Maintained backward compatibility by keeping MetaMetrics as a wrapper around the new system - Updated all test files with appropriate mocks for the new analytics system > [!NOTE] > ## Why This PR Was Not Split > > ### Core Reasons > > - **Segment SDK Conflict**: Both MetaMetrics and analytics-controller would instantiate Segment SDK simultaneously, causing conflicts. They must be coordinated atomically > - **Breaking API Change**: `Engine.init()` signature changed from `init({})` to `init(analyticsId: string)` (where `analyticsId` is a UUID string), requiring updates to all test mocks and controller initialization > - **Controller Messenger Updates**: Controllers using MetaMetrics instance methods now call analytics via messenger, requiring init messenger updates across 9+ controllers > - **State Migration**: Migration 110 migrates legacy analytics storage to new AnalyticsController state (depends on full integration) > - **Test Infrastructure**: Extensive test mock updates needed (MetaMetrics singleton → messenger pattern, Engine.init() signature change, AnalyticsController state changes) > > ### Why Atomic > > - Cannot partially migrate due to Segment SDK conflict > - Breaking changes cascade — splitting would leave codebase in broken intermediate state > - State migration depends on AnalyticsController being present in Engine > - Messenger pattern requires full setup to be in place > - Test mocks must be updated together to prevent flakiness ### **Technical Details** #### Key Changes 1. **New AnalyticsController Integration** - Added `@metamask/analytics-controller` 1.0.0 package dependency - Created `analytics-controller-init.ts` to initialize the controller - Created `analytics-controller-messenger.ts` for messenger setup - Created `platform-adapter.ts` to bridge AnalyticsController with Segment SDK - Added `'AnalyticsController:stateChange'` to `BACKGROUND_STATE_CHANGE_EVENT_NAMES` for state synchronization 2. **Storage Migration (Migration 110)** - Migrates `METAMETRICS_ID` and `MIXPANEL_METAMETRICS_ID` to `ANALYTICS_ID` - Migrates `METRICS_OPT_IN` to `AnalyticsController.optedIn` state - Validates UUIDv4 format for analytics IDs - Deletes deprecated `MIXPANEL_METAMETRICS_ID` key 3. **New Analytics Utility Module** - Created `app/util/analytics/analytics.ts` as the main API for components - Created `app/util/analytics/analyticsId.ts` for ID management - Created `app/util/analytics/AnalyticsEventBuilder.ts` for event construction - Created `app/util/analytics/queue.ts` for event queuing before Engine is ready - Updated `generateDeviceAnalyticsMetaData()` to return `AnalyticsUserTraits` type for type safety 4. **Controller Updates** - Updated all controller init functions to use `analyticsId` parameter - Added AnalyticsController messenger delegation to: - TokenDetectionController - TransactionController - NetworkController - DeFiPositionsController - AccountTreeController - SnapController - BridgeController - UserStorageController 5. **Component Updates** - Updated components to use new `analytics` utility instead of `MetaMetrics.getInstance()` - Updated `useMetrics` hook to use new analytics system - Added analytics mocks to test files - Added `updateDataRecordingFlag` mocks to all MetaMetrics test mocks - Updated test mocks to use `Engine.init('')` with string parameter instead of `Engine.init({})` - Added `whenEngineReady` mocks to prevent Engine access after Jest teardown - Fixed `Linking.openUrl` typo to `Linking.openURL` in LendingLearnMoreModal tests 6. **Backward Compatibility** - MetaMetrics and useMetrics marked as deprecated - MetaMetrics class now wraps the new analytics system - Added `updateDataRecordingFlag()` method to MetaMetrics interface for data deletion workflows - Legacy storage keys are preserved for backward compatibility - Existing event tracking continues to work 7. **E2E Test Updates** - Updated `FixtureBuilder.withMetaMetricsOptIn()` to also set up AnalyticsController state - Added comment clarification in analytics helpers about catch-all proxy handler - Updated test utilities to use `analyticsId` instead of `metaMetricsId` #### Files Changed - **New Files:** - `app/core/Engine/controllers/analytics-controller/analytics-controller-init.ts` - `app/core/Engine/controllers/analytics-controller/platform-adapter.ts` - `app/core/Engine/messengers/analytics-controller-messenger.ts` - `app/util/analytics/analytics.ts` - `app/util/analytics/analyticsId.ts` - `app/util/analytics/AnalyticsEventBuilder.ts` - `app/util/analytics/queue.ts` - `app/util/analytics/analytics.types.ts` - `app/store/migrations/110.ts` - `app/core/Analytics/whenEngineReady.ts` - `app/selectors/analyticsController.ts` - **Modified Files:** - All controller initialization files updated to use `analyticsId` - All messenger files updated to delegate AnalyticsController actions - All test files updated with analytics mocks and `updateDataRecordingFlag` mocks - Engine.ts updated to initialize AnalyticsController - `app/core/Engine/constants.ts` - Added AnalyticsController to background state change events - `app/core/Engine/utils/test-utils.ts` - Updated to use `analyticsId` parameter - `e2e/framework/fixtures/FixtureBuilder.ts` - Updated to set AnalyticsController state - Various utility files migrated to use new analytics API ## **Changelog** CHANGELOG entry: null *(This is an internal refactoring that does not change user-facing functionality)* ## **Related issues** Fixes: #22017 ## **Manual testing steps** ```gherkin Feature: Analytics tracking with AnalyticsController Scenario: User opts in to analytics Given the app is installed with legacy analytics storage (METAMETRICS_ID, METRICS_OPT_IN) When the app starts and migration 110 runs Then the legacy analytics ID should be migrated to ANALYTICS_ID And the opt-in preference should be migrated to AnalyticsController state And analytics events should continue to track correctly Scenario: User tracks events after migration Given the user has opted in to analytics When the user performs actions that trigger analytics events (e.g., sends transaction, views dapp) Then events should be tracked through AnalyticsController And events should be sent to Segment via the platform adapter Scenario: User changes analytics preference Given the user is on the Security Settings screen When the user toggles the analytics opt-in/opt-out setting Then the AnalyticsController state should update And the preference should persist across app restarts ``` ## **Screenshots/Recordings** ### **Before** <img width="2992" height="2676" alt="image" src="https://github.com/user-attachments/assets/e8cab114-8324-4da0-9bf8-a191091ed2d2" /> ### **After** same, no 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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Modernizes analytics plumbing and aligns with AnalyticsController while keeping legacy compatibility. > > - Refactors `MetaMetrics` to delegate to new `analytics` utility (adds `updateDataRecordingFlag`, deprecates group/reset/flush) and updates tracking flow > - Migrates components/hooks to `analytics` and `AnalyticsEventBuilder` (`useMetrics`, `AppStateEventListener`, `MetaMetricsAndDataCollectionSection`, `ThemeSettings`) > - Adds `core/Analytics/whenEngineReady` helper and uses it in tests; fixes `Linking.openURL` in tests > - Updates storage constants: introduces `ANALYTICS_ID`, marks legacy keys deprecated, notes migrations > - Test infra overhaul: mocks `analytics` and `updateDataRecordingFlag`, switches `Engine.init('')`, adds navigation/metrics mocks, increases debounce timeouts and wraps `fireEvent` in `act` > - Minor behavioral tweaks: send theme as user trait; preserve data deletion workflows > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b6839ad. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
- remove npx
- add another input field for eas channel to push updates to
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
Fingerprint is working after the changes
<img width="1055" height="302" alt="Screenshot 2026-01-07 at 6 10 59 AM"
src="https://github.com/user-attachments/assets/a8bfea40-3853-4e6f-ae16-76a9d51ab56c"
/>
## **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]
> Modernizes the OTA workflow and build script to support multiple
release channels and cleaner CI.
>
> - Adds `channel` input (exp/rc/production) and maps to environments;
build step now dispatches to `build:expo-update:main:{exp|rc|prod}`
accordingly
> - Simplifies fingerprinting by removing detailed `npx
@expo/fingerprint` diffs and keeping a summary-only compare/output
> - Updates env/secrets for OTA job: replaces QA-specific Segment vars
with generic keys, adds Google client IDs, FCM config, QuickNode URLs,
Branch test key, and standardizes Sentry vars
> - In `scripts/build.sh`, skips env remapping when `PLATFORM` is
`expo-update` to avoid overriding externally provided channel/config
> - Renames workflow and minor logging/summary tweaks
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3fab301. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: tommasini <tommasini15@gmail.com>
…re flag (#24494) ## **Description** Replaces the hardcoded `LIVE_SPORTS_LEAGUES` configuration with a remote feature flag (`predictLiveSports`), allowing live sports functionality to be enabled/disabled and leagues to be configured remotely without app updates. **Motivation**: The live sports feature needs to be controllable via remote config to enable gradual rollout and quick disabling if issues arise. **Solution**: - Added `PredictLiveSportsFlag` type: `{ enabled: boolean; leagues: string[] }` - Added `DEFAULT_LIVE_SPORTS_FLAG` constant (disabled by default, empty leagues) - Renamed `LIVE_SPORTS_LEAGUES` to `SUPPORTED_SPORTS_LEAGUES` (defines what the app supports) - Added `filterSupportedLeagues()` helper to validate remote config against supported leagues - Updated `PredictController.getMarkets()` and `getMarket()` to read the flag from `RemoteFeatureFlagController` - Updated provider interfaces to accept `liveSportsLeagues` parameter - Removed the now-unused `selectPredictLiveNflEnabled` selector and `isLiveSportsEnabled()` function ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/PRED-464 ## **Manual testing steps** ```gherkin Feature: Live Sports Remote Feature Flag Scenario: Live sports disabled by default Given the predictLiveSports flag is not set in remote config When user views prediction markets Then live sports markets are not fetched Scenario: Live sports enabled via remote config Given the predictLiveSports flag is { enabled: true, leagues: ["nfl"] } When user views prediction markets Then NFL live sports markets are included in results Scenario: Unsupported league filtered out Given the predictLiveSports flag is { enabled: true, leagues: ["nfl", "mlb"] } When user views prediction markets Then only NFL markets are fetched (mlb not in SUPPORTED_SPORTS_LEAGUES) ``` ## **Screenshots/Recordings** ### **Before** N/A - Internal refactor, no UI changes ### **After** N/A - Internal refactor, 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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Enables remotely configurable live sports by validating and passing leagues to market fetches. > > - Add `PredictLiveSportsFlag` and `DEFAULT_LIVE_SPORTS_FLAG`; introduce `SUPPORTED_SPORTS_LEAGUES` and `filterSupportedLeagues` to validate remote config > - `PredictController.getMarkets()`/`getMarket()` read `RemoteFeatureFlagController.predictLiveSports`, compute `liveSportsLeagues`, and pass to providers > - Update provider types/interfaces to accept `liveSportsLeagues`; `PolymarketProvider` uses provided leagues (removes `isLiveSportsEnabled` and `LIVE_SPORTS_LEAGUES`), loads `TeamsCache` conditionally, and overlays game data only when leagues provided > - Remove `selectPredictLiveNflEnabled` selector and related tests; refresh tests across controller/provider to cover enabled/disabled and undefined leagues paths > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 68f8e7d. 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 : )