perf(perps): replace REST candle polling with real-time WebSocket#22232
Merged
Conversation
Contributor
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
…ove candle data handling - Added `symbol` prop to `TradingViewChart` for validation against incoming candle data, preventing stale data rendering when switching markets. - Updated `usePerpsLiveCandles` to reset candle data and loading state immediately upon coin or interval changes, ensuring accurate data display. - Enhanced `CandleStreamChannel` to filter subscribers by `cacheKey`, improving WebSocket management and logging for subscription events. - Refactored candle data updates in `HyperLiquidClientService` to trigger React re-renders correctly when new candles are received.
- Added `subscribeToCandles` method in `HyperLiquidProvider` to facilitate live candle updates. - Updated `PerpsController` to utilize the new method for subscribing to candle data. - Introduced `SubscribeCandlesParams` interface to define parameters for candle subscriptions, enhancing type safety and clarity in the codebase.
…vice - Enhanced the `subscribeToCandles` method to prevent processing of events if already unsubscribed, ensuring better resource management. - Updated tests to cover scenarios where unsubscribe is called before WebSocket establishment, improving reliability and performance. - Refactored CandleStreamChannel tests for better readability and consistency.
…Service - Updated error handling in the `subscribeToCandles` method to avoid throwing errors after the function has already returned, preventing potential unhandled promise rejections. - Improved logging for error scenarios to enhance debugging capabilities.
…for improved data handling - Removed conditional rendering of the TradingViewChart in PerpsMarketDetailsView to ensure it always renders, preventing WebView remount issues on interval changes. - Introduced a buffering mechanism in TradingViewChart to handle candle data that arrives before the chart is ready, particularly for Android, ensuring smoother data updates and symbol validation. - Updated skeleton loading logic to display only when the chart is not ready and data is either absent or mismatched, enhancing user experience during loading states.
cb3a621 to
60e8910
Compare
…andle-subscription # Conflicts: # app/components/UI/Perps/hooks/usePerpsPositionData.ts
…andle-subscription
- Added functionality to fetch additional historical candles when the user scrolls to the left edge of the TradingView chart. - Introduced edge detection logic to trigger data fetching based on the visible range of the chart. - Updated `usePerpsLiveCandles` hook to include a `fetchMoreHistory` method for loading more data. - Enhanced `TradingViewChart` component to handle the new `onNeedMoreHistory` callback. - Updated `CandleStreamChannel` to fetch historical candles before the current oldest candle, ensuring a seamless user experience. This change improves the user experience by providing continuous access to historical data without manual refreshes.
…data fetching - Introduced a new optional `duration` parameter in the `subscribeToCandles` method across multiple components, including `PerpsController`, `CandleStreamChannel`, and `HyperLiquidClientService`. - Updated the `usePerpsLiveCandles` hook to accept and utilize the `duration` parameter for fetching live candle data. - Enhanced historical candle fetching logic to dynamically calculate the number of candles based on the provided `duration` and `interval`, ensuring efficient data retrieval. - Improved error handling and logging for subscription and fetching processes to enhance debugging and monitoring capabilities. This change enhances the flexibility and performance of candle data management in the application.
…andle-subscription
60e8910 to
b30747b
Compare
michalconsensys
previously approved these changes
Nov 20, 2025
michalconsensys
previously approved these changes
Nov 20, 2025
7b1912f to
96ce9cb
Compare
michalconsensys
previously approved these changes
Nov 20, 2025
Contributor
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsAnalysis SummaryAll 22 changed files are exclusively within the Key Changes Identified1. Critical File: PerpsController.ts
2. New WebSocket Streaming Architecture
3. Service Layer Updates
4. UI Component Changes
5. Types & Test Files
Impact AssessmentScope: This is a feature enhancement that replaces polling-based candle data fetching with WebSocket streaming for real-time chart updates in the Perps feature. Risk Factors:
User-Facing Impact:
Test Tag SelectionSelected: SmokePerps Rationale:
Why not other tags:
Confidence Level95% confidence - Very high confidence because:
|
|
nickewansmith
approved these changes
Nov 21, 2025
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.


Description
Problem
The
PerpsMarketDetailsViewwas creating duplicate Sentry traces for "Perps Fetch Historical Candles" due to two concurrent REST API calls for the same coin:usePerpsPositionDatausePerpsMarketStatsBoth used
setIntervalpolling, resulting in:Solution
Migrated candle data from REST polling to WebSocket streaming pattern, following the established architecture for prices, orders, and positions:
CandleStreamChannel- Lazy-loaded streaming infrastructure (no prewarm)subscribeToCandles()to HyperLiquidClientService and PerpsControllerusePerpsLiveCandleshook - Drop-in replacement forusePerpsPositionDatausePerpsMarketStatsandPerpsMarketDetailsViewusePerpsPositionDataand testsBenefits
� Eliminates duplicate Sentry traces - Each (coin, interval) combination gets distinct subscription
� Real-time updates - WebSocket push instead of polling (no
setInterval)� Cache sharing - Multiple components using same (coin, interval) = 1 WebSocket connection
� Auto-cleanup - Unsubscribe when components unmount
� Protocol-agnostic - Architecture supports future providers (Binance, dYdX, etc.)
� Consistent pattern - Matches existing streaming channels (prices, orders, positions)
Trade-off
The system maintains 2 WebSocket subscriptions per coin as required by product:
This is not a bug - different granularities are needed for different use cases. If product unifies to a single interval in the future, the architecture will automatically reduce to 1 subscription (no code changes needed).
Android Rendering Fix
During testing, we discovered that the WebSocket migration exposed a race condition on Android devices. The chart data often arrived before the WebView finished initializing (Android WebView is 2-3x slower than iOS), causing:
Fix: Added data buffering to hold early-arriving data until the chart is ready, and kept the chart component mounted during interval switches to avoid expensive WebView reinitialization.
Impact: Chart now loads smoothly on Android with no black screens, even on slower devices. This was caught during testing of the WebSocket streaming feature.
Changelog
CHANGELOG entry: Improved candle data loading with real-time WebSocket updates
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1867
Manual testing steps
Screenshots/Recordings
Before
setIntervalevery 1-4 hours depending on intervalAfter
Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-11-05.at.11.57.28.mp4
Technical Details
Architecture
Files Changed
Created (2):
providers/channels/CandleStreamChannel.ts- Core streaming infrastructurehooks/stream/usePerpsLiveCandles.ts- React hook APIModified (8):
services/HyperLiquidClientService.ts- AddedsubscribeToCandles()methodcontrollers/PerpsController.ts- Added protocol-agnostic delegationproviders/PerpsStreamManager.tsx- Integrated CandleStreamChannelhooks/usePerpsMarketStats.ts- Migrated to new hookViews/PerpsMarketDetailsView/PerpsMarketDetailsView.tsx- Migrated to new hook, removed conditional chart renderingcomponents/TradingViewChart/TradingViewChart.tsx- Added data buffering and fixed skeleton logic for Androidapp/util/trace.ts- Removed unused trace nameDeleted (2):
hooks/usePerpsPositionData.tshooks/usePerpsPositionData.test.tsPerformance Impact
Before (REST Polling):
After (WebSocket Streaming):
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Replaces REST/polling candles with WebSocket streaming across stack, updates UI chart to consume live data and fetch more history, and adds provider/controller support with tests.
subscribeToCandlesin provider (HyperLiquidClientService), controller (PerpsController), and types (SubscribeCandlesParams).CandleStreamChannelinproviders/channelsand wire intoPerpsStreamManagerascandles.usePerpsLiveCandleshook (hooks/stream) for real-time candles (withfetchMoreHistory).PerpsMarketDetailsViewtousePerpsLiveCandles; remove manual refresh of candles.TradingViewChart/template: data buffering, symbol validation,CLEAR_DATA,NEED_MORE_HISTORYedge-detection callback, skeleton logic,onNeedMoreHistoryprop.usePerpsMarketStatsto derive 24h high/low from live 1h candles.endTimeinMarketDataService.fetchHistoricalCandlesand provider client; use dynamic limits and merge older candles on demand.usePerpsPositionDataand related tests; adjust existing tests to WebSocket behavior (no candle refresh expectations).usePerpsLiveCandles,CandleStreamChannel,HyperLiquidClientService.subscribeToCandles, and updated services; updateMarketDataServicetests forendTime.Written by Cursor Bugbot for commit 59514c6. This will update automatically on new commits. Configure here.