Skip to content

feat(predict): Live Trade Activity Overlay reusable Hook#30415

Merged
MarioAslau merged 80 commits into
mainfrom
predict/up-down-resuable-hook
May 20, 2026
Merged

feat(predict): Live Trade Activity Overlay reusable Hook#30415
MarioAslau merged 80 commits into
mainfrom
predict/up-down-resuable-hook

Conversation

@MarioAslau

@MarioAslau MarioAslau commented May 20, 2026

Copy link
Copy Markdown
Contributor

Description

This PR delivers two related pieces of work for the Predict crypto up/down details screen:

  1. A reusable usePredictOrderbook hook that streams live Polymarket orderbook depth into the existing LivelineChart so the chart shows real bid/ask activity overlaid on the price line. The hook is plumbed through the existing controller / provider / WebSocket stack — no new APIs needed at the engine layer.

    The data flow:

    flowchart LR
      Hook["usePredictOrderbook(tokenId)"] --> Controller["PredictController.subscribeToOrderbook"]
      Controller --> Provider["PolymarketProvider.subscribeToOrderbook"]
      Provider --> WSManager["WebSocketManager.subscribeToOrderbook"]
      Provider --> REST["getOrderBook (utils.ts)"]
      REST -->|"seed first snapshot"| WSManager
      WS["Polymarket market WS"] --> WSManager
      Hook --> Chart["LivelineChart orderbook prop"]
    
    Loading

    The WebSocket manager handles per-token reference counting, a 250 ms emit throttle to protect the RN↔WebView bridge, book event ingestion, and opportunistic top-of-book pruning on price_change events. The REST bootstrap runs at the provider layer (where the active CLOB protocol is known) and seeds the cache before the first WS event arrives.

  2. Chart UX/UI polish to match the Figma reference for BTC Up or Down:

    • Removed the oversized green/red price pill (badge) — only the orange dot remains.
    • Removed the 36 px dead space above the chart (padding.top: 48 → 12).
    • Made the chart line extend closer to the y-axis labels (padding.right: 80 → 64).
    • Pushed time-axis labels above the WebView's bottom clip zone so they actually render (padding.bottom: 48 → 80).
    • Dropped trailing .00 from the y-axis price labels per design (whole-dollar formatter).
    • Added a compact 12-hour h:mm:ss formatTime so the time-axis labels fit the live 30s window without overlap-culling.
    • Extracted CRYPTO_UP_DOWN_FORMAT_VALUE and CRYPTO_UP_DOWN_FORMAT_TIME as named exports so the WebView-bridged formatter bodies can be regression-tested with it.each.

The PR also includes a self-review pass that fixed:

  • Stale orderbook state surviving WebSocket reconnects (cleared orderbookState + throttle timers in disconnectMarket).
  • Dead error field on the orderbook hook's public type.
  • Empty-string tokenId slipping past the subscribe guard.
  • Misleading comment vs. implementation for applyTopOfBook (it prunes, doesn't splice).
  • Vague "with correct props" test name renamed per the repo's unit-testing guidelines.
  • Dead createMockChartRef helper + 19 unused chartRef locals + 2 orphaned appendPoint assertions in useCryptoUpDownChartData.test.ts (the hook signature dropped its chartRef arg upstream).
  • Magic-number documentation for chart padding and chart-height bounds.

Deferred to follow-ups (intentional)

  • patch-package on liveline for: (a) orderbook depth fade threshold (currently fades only in the top 45% — design wants midpoint), (b) time-axis edge-fade reduction, (c) palette opacity bumps. All require modifying node_modules/liveline/dist/index.js and rebundling via yarn build:liveline-webview; tracked separately because they coordinate with chart-team work.
  • Imperative setOrderbook on LivelineChartRef to skip a full SET_PROPS round-trip on every depth tick (perf optimization that needs upstream liveline cooperation).
  • i18n keys for Price to beat / Current price / Target (no predict.crypto_up_down namespace exists yet — broader Predict-feature concern).

Changelog

CHANGELOG entry: Added live orderbook depth visualization and refined the chart layout for Crypto Up/Down markets.

Related issues

Refs:

Manual testing steps

Feature: Crypto Up/Down details screen — live chart with orderbook depth

  Scenario: user opens a live Crypto Up/Down market and sees the redesigned chart
    Given the user has the Predict feature flag enabled
    And the user has navigated to a live "BTC Up or Down" market

    When the details screen finishes loading

    Then the chart line renders with the orange dot at the current price
    And no green or red price pill appears next to the dot
    And the y-axis price labels render to the right of the chart without trailing ".00"
    And there is no large empty band between the "Price to beat" header and the chart line
    And time labels in "h:mm:ss" format render along the bottom of the chart, above the action buttons
    And the dashed "Target" reference line renders at the target price

  Scenario: user observes live orderbook depth on the chart
    Given the user is on a live Crypto Up/Down market with active liquidity

    When the user watches the chart for a few seconds

    Then small green ($) labels for bids and red ($) labels for asks animate upward from the bottom-left of the chart
    And the labels update within ~250 ms of new orderbook events
    And on reconnect (e.g. toggle airplane mode briefly) the orderbook re-bootstraps without showing stale prices

  Scenario: user navigates away and the chart cleans up
    Given the chart is rendering with active orderbook depth

    When the user taps the back button

    Then the chart unmounts and the orderbook subscription is released
    And no further WebSocket traffic for that token is observed in the network log

Screenshots/Recordings

Before

After

Uploading upDown.mov…

Pre-merge author checklist

  • I've followed MetaMask Contributor Docs and MetaMask Mobile Coding Standards.
  • I've completed the PR template to the best of my ability
  • I've included tests if applicable
    • usePredictOrderbook.test.ts (new) — subscribe/unsubscribe lifecycle, snapshot mapping, mount/unmount safety, connection polling.
    • WebSocketManager.test.ts — extended with positive coverage for book events, REST seed, reference counting, reconnect, throttle, opportunistic TOB prune.
    • PolymarketProvider.test.tssubscribeToOrderbook REST bootstrap success/failure.
    • PredictController.test.ts — passthrough + MESSENGER_EXPOSED_METHODS registration.
    • PredictCryptoUpDownChart.test.tsx — orderbook wiring, prop forwarding, CRYPTO_UP_DOWN_FORMAT_VALUE and CRYPTO_UP_DOWN_FORMAT_TIME it.each regression suites.
  • I've documented my code using JSDoc format if applicable
    • JSDoc on usePredictOrderbook, CRYPTO_UP_DOWN_FORMAT_VALUE, CRYPTO_UP_DOWN_FORMAT_TIME, CHART_HEIGHT_VIEWPORT_FRACTION, and the new WebSocketManager orderbook methods.
  • I've applied the right labels on the PR (see labeling guidelines). Not required for external contributors.
    • Apply at PR creation time: team-predict (or the appropriate Predict team label), area-predict. Add needs-qa if the on-device cadence of orderbook depth needs review.

Performance checks (if applicable)

  • I've tested on Android
    • Pending — primary development was iOS; should be smoke-tested on an Android mid-range device because the WebView bridge cadence differs.
  • I've tested with a power user scenario
    • Not applicable to the orderbook layer specifically; the chart is sized for a single market view.
  • I've instrumented key operations with Sentry traces for production performance metrics
    • Not added in this PR. The WebSocketManager already logs orderbook lifecycle events via DevLogger. If Sentry traces are desired on subscribeToOrderbook REST + WS handshake timing, can add in a follow-up.

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.

Appendix — quality gate

Check Result
yarn lint:tsc clean (0 errors)
yarn jest (focused Predict suites: chart, details, hooks, WebSocketManager) 197 / 197 tests pass
ESLint on changed files 0 errors. 7 pre-existing warnings (deprecated controller types, runAfterInteractions, an existing React shadow in mocks) all predate this branch — not introduced here.

Appendix — files touched (high level)

  • New: app/components/UI/Predict/hooks/usePredictOrderbook.ts (+ test)
  • Modified: WebSocketManager.ts (orderbook subscription map, throttle, lifecycle), PolymarketProvider.ts (passthrough + REST seed), PredictController.ts (passthrough + MESSENGER_EXPOSED_METHODS), types/index.ts (OrderbookLevel/Snapshot/Callback), providers/types.ts (optional method in interface).
  • Chart UX: PredictCryptoUpDownChart.tsx (+ test), PredictCryptoUpDownDetails.tsx, useCryptoUpDownChartData.ts (+ test).

Note

Medium Risk
Adds a new real-time orderbook subscription pipeline (controller/provider/WebSocketManager) and feeds it into a WebView-backed chart, which can impact live data correctness and reconnect/unsubscribe behavior.

Overview
Adds live orderbook depth streaming for Predict crypto Up/Down charts. Introduces a reusable usePredictOrderbook hook, exposes PredictController.subscribeToOrderbook, and implements PolymarketProvider.subscribeToOrderbook with a REST getOrderBook bootstrap that seeds the WS cache.

Extends WebSocketManager to support book events. Adds per-token orderbook subscriptions with cached snapshot replay, REST seeding, and a 250ms emit throttle; updates unsubscribe/reconnect/cleanup logic and connection status to account for orderbook subscribers.

Updates chart wiring and formatting. PredictCryptoUpDownChart now forwards orderbook into LivelineChart, adds a compact CRYPTO_UP_DOWN_FORMAT_TIME formatter, and expands test coverage across the new hook, controller/provider passthroughs, WS behavior, and formatter regression cases; also tweaks Crypto Up/Down details chart height calculation constant usage and fixes websocket mock tests to use OS-assigned ports.

Reviewed by Cursor Bugbot for commit 33c3365. Bugbot is set up for automated code reviews on this repo. Configure here.

ghgoodreau and others added 30 commits May 11, 2026 14:56
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread app/components/UI/Predict/providers/polymarket/PolymarketProvider.ts Outdated
Comment thread app/components/UI/Predict/hooks/usePredictOrderbook.ts
const tw = useTailwind();
const { colors } = useTheme();
const navigation =
useNavigation<NavigationProp<PredictNavigationParamList>>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused navigation import in market card component

Low Severity

The useNavigation call at line 995–996 assigns to navigation, which is only passed to usePredictActionGuard({ navigation }). However, navigateToMarketDetails (from usePredictNavigation) internally calls its own useNavigation, meaning the card component obtains navigation twice — once explicitly and once inside usePredictNavigation. The explicit useNavigation plus the NavigationProp type import exist solely to pass navigation to the action guard, adding unnecessary coupling.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 54dd5f7. Configure here.

@MarioAslau

Copy link
Copy Markdown
Contributor Author

@metamaskbot update-mobile-fixture

@github-actions

Copy link
Copy Markdown
Contributor

🔄 Fixture update started. Running workflow from branch predict/up-down-resuable-hook. View workflow runs

@github-actions

Copy link
Copy Markdown
Contributor

E2E fixture update failed.\n\nCommon causes:\n- CI workflow is still running — wait for 'Build iOS Apps' to complete\n- CI workflow was skipped — ensure your PR has iOS-impacting changes or use skip-smart-e2e-selection label\n- iOS build failed — check the CI workflow for errors\n\nView logs and retry

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.61538% with 128 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.07%. Comparing base (3ee5c69) to head (f5ebdb2).
⚠️ Report is 29 commits behind head on main.

Files with missing lines Patch % Lines
...UpDownMarketCard/PredictCryptoUpDownMarketCard.tsx 83.71% 25 Missing and 32 partials ⚠️
...I/Predict/providers/polymarket/WebSocketManager.ts 81.28% 9 Missing and 23 partials ⚠️
app/components/UI/Predict/utils/series.ts 80.00% 9 Missing and 10 partials ⚠️
...Predict/providers/polymarket/PolymarketProvider.ts 81.25% 1 Missing and 5 partials ⚠️
.../Predict/hooks/useCurrentCryptoUpDownMarketData.ts 91.17% 2 Missing and 1 partial ⚠️
...Predict/hooks/useCurrentPredictMarketFromSeries.ts 88.88% 3 Missing ⚠️
...iews/PredictMarketDetails/hooks/useOpenOutcomes.ts 78.57% 2 Missing and 1 partial ⚠️
...iews/PredictMarketDetails/PredictMarketDetails.tsx 86.66% 0 Missing and 2 partials ⚠️
...nents/UI/Predict/hooks/useCryptoUpDownChartData.ts 96.96% 0 Missing and 1 partial ⚠️
...components/UI/Predict/hooks/usePredictOrderbook.ts 96.96% 0 Missing and 1 partial ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #30415      +/-   ##
==========================================
+ Coverage   82.03%   82.07%   +0.04%     
==========================================
  Files        5454     5470      +16     
  Lines      145830   147196    +1366     
  Branches    33411    33815     +404     
==========================================
+ Hits       119629   120812    +1183     
- Misses      18016    18080      +64     
- Partials     8185     8304     +119     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5976a54. Configure here.

Comment thread app/components/UI/Predict/hooks/useCryptoUpDownChartData.test.ts
@caieu

caieu commented May 20, 2026

Copy link
Copy Markdown
Contributor

One item from codex review:

[P2] getCryptoPriceHistory no longer fetches the requested historical window. The previous request sent eventStartTime/endDate; the new Chainlink request only sends symbol, interval, and limit, then filters locally. That works for fresh/live data, but older details views and selected past slots can get an empty chart even when historical data exists.

@ghgoodreau

Copy link
Copy Markdown
Contributor

One item from codex review:

[P2] getCryptoPriceHistory no longer fetches the requested historical window. The previous request sent eventStartTime/endDate; the new Chainlink request only sends symbol, interval, and limit, then filters locally. That works for fresh/live data, but older details views and selected past slots can get an empty chart even when historical data exists.

@caieu @MarioAslau disregard this for this PR; this is being handled in my next PR.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePredictions, SmokeWalletPlatform, SmokeConfirmations
  • Selected Performance tags: @PerformancePredict
  • Risk Level: medium
  • AI Confidence: 88%
click to see 🤖 AI reasoning details

E2E Test Selection:
The PR adds real-time orderbook (depth chart) functionality to the Predict/Polymarket crypto up/down markets. Key changes:

  1. PredictController - New subscribeToOrderbook method exposed via messenger, new action type PredictControllerSubscribeToOrderbookAction
  2. WebSocketManager - Substantial new orderbook subscription infrastructure: subscribe/unsubscribe lifecycle, REST snapshot seeding, book WebSocket event handling, throttled emit (250ms), proper cleanup on disconnect/destroy
  3. PolymarketProvider - New subscribeToOrderbook implementation combining REST bootstrap + WebSocket live updates
  4. usePredictOrderbook - New React hook consuming orderbook data from PredictController
  5. PredictCryptoUpDownChart - Integrated orderbook data and time formatter into LivelineChart; removed chartRef (minor cleanup)
  6. PredictCryptoUpDownDetails - Minor refactor extracting viewport fraction constant
  7. types - New OrderbookLevel, OrderbookSnapshot, OrderbookCallback types
  8. tests/websocket/account-activity-mocks.test.ts - Fixed flaky port collision (port 0 instead of random fixed port) - unit test fix only, no E2E impact

Tag reasoning:

  • SmokePredictions: Directly impacted - new orderbook subscription in PredictController, new chart features in PredictCryptoUpDownChart, WebSocket infrastructure changes affect the Predict feature
  • SmokeWalletPlatform: Required per SmokePredictions tag description - Predictions is a section inside the Trending tab
  • SmokeConfirmations: Required per SmokePredictions tag description - opening/closing positions are on-chain transactions

No other tags are affected - changes are isolated to the Predict/Polymarket feature area with no impact on accounts, networks, swaps, browser, snaps, or other wallet features.

Performance Test Selection:
The WebSocketManager changes add a new throttled orderbook emit system (250ms throttle with trailing emit logic) and new subscription state management. The PredictCryptoUpDownChart now receives real-time orderbook data that feeds into the LivelineChart WebView bridge. These changes could affect rendering performance of the prediction market chart, particularly the frequency of state updates and WebView bridge message passing. @PerformancePredict covers prediction market list loading, market details, deposit flows, and balance display - all of which could be affected by the new orderbook data flow.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@MarioAslau MarioAslau added this pull request to the merge queue May 20, 2026
@MarioAslau MarioAslau changed the title feat(predict): Live Trade Activity Overlay reusable Hook feat(predict): Live Trade Activity Overlay reusable Hook cp-7.78.0 May 20, 2026
Merged via the queue into main with commit c9cb162 May 20, 2026
192 of 201 checks passed
@MarioAslau MarioAslau deleted the predict/up-down-resuable-hook branch May 20, 2026 22:03
@github-actions github-actions Bot locked and limited conversation to collaborators May 20, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.79.0 Issue or pull request that will be included in release 7.79.0 label May 20, 2026
@MarioAslau MarioAslau added release-7.78.0 Issue or pull request that will be included in release 7.78.0 and removed release-7.79.0 Issue or pull request that will be included in release 7.79.0 labels May 20, 2026
@matallui matallui changed the title feat(predict): Live Trade Activity Overlay reusable Hook cp-7.78.0 feat(predict): Live Trade Activity Overlay reusable Hook May 20, 2026
@ghgoodreau ghgoodreau added release-7.79.0 Issue or pull request that will be included in release 7.79.0 and removed release-7.78.0 Issue or pull request that will be included in release 7.78.0 labels May 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.79.0 Issue or pull request that will be included in release 7.79.0 size-XL team-predict Predict team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants