feat(perps): Fix candlestick chart 429 rate limiting on rapid asset navigation#28865
Conversation
|
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. |
Switch fetchHistoricalCandles() from WebSocket to HTTP InfoClient. This eliminates the abort race condition that causes 429 rate limiting during rapid market navigation on extension (TAT-2954). Transport split: - initial chart history load → HTTP - load-more historical candles → HTTP - live candle updates → WebSocket (unchanged)
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - draft PR All E2E tests pre-selected. |
Worker reportTAT-2954 ReportSummaryChanged Changes
Test Plan
Evidence
Ticket |
1 similar comment
Worker reportTAT-2954 ReportSummaryChanged Changes
Test Plan
Evidence
Ticket |
|
|
✅ E2E Fixture Validation — Schema is up to date |



Description
Historical candlestick chart data (
candleSnapshot) was being fetched through the WebSocket-backedInfoClient. On extension, rapid market navigation causes an abort race condition — the UI unmount message arrives too late to cancel in-flight WebSocket requests, leading to bursty candleSnapshot traffic and 429 rate limit errors from Hyperliquid.This PR switches
fetchHistoricalCandles()to use the HTTPInfoClientinstead. Live candle streaming remains on WebSocket. This is the source-of-truth fix in the controller/client-service layer, so both mobile and extension benefit.Transport split after this change:
Changelog
CHANGELOG entry: Fixed candlestick chart 429 rate limiting during rapid market navigation by routing historical candle fetches over HTTP
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2954
Manual testing steps
Screenshots/Recordings
Video
Uploaded artifact links below; replace with manual GitHub video attachments if you want inline playback.
Validation Recipe
recipe.json (27 nodes — rapid market switching validation)
{ "title": "Validate candlestick chart loads correctly during rapid market switching (TAT-2954)", "initial_conditions": { "testnet": false }, "validate": { "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "setup-nav-perps", "nodes": { "setup-nav-perps": { "action": "navigate", "target": "PerpsTrendingView", "next": "setup-wait-list" }, "setup-wait-list": { "action": "wait_for", "test_id": "perps-market-row-item-BTC", "timeout": 10000, "next": "ac1-open-btc" }, "ac1-open-btc": { "action": "press", "test_id": "perps-market-row-item-BTC", "next": "ac1-wait-detail-btc" }, "ac1-wait-detail-btc": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-back-1" }, "ac1-back-1": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac1-wait-list-1" }, "ac1-wait-list-1": { "action": "wait_for", "test_id": "perps-market-row-item-ETH", "timeout": 5000, "next": "ac1-open-eth" }, "ac1-open-eth": { "action": "press", "test_id": "perps-market-row-item-ETH", "next": "ac1-wait-detail-eth" }, "ac1-wait-detail-eth": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-back-2" }, "ac1-back-2": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac1-wait-list-2" }, "ac1-wait-list-2": { "action": "wait_for", "test_id": "perps-market-row-item-SOL", "timeout": 5000, "next": "ac1-open-sol" }, "ac1-open-sol": { "action": "press", "test_id": "perps-market-row-item-SOL", "next": "ac1-wait-detail-sol" }, "ac1-wait-detail-sol": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-back-3" }, "ac1-back-3": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac1-wait-list-3" }, "ac1-wait-list-3": { "action": "wait_for", "test_id": "perps-market-row-item-HYPE", "timeout": 5000, "next": "ac1-open-hype" }, "ac1-open-hype": { "action": "press", "test_id": "perps-market-row-item-HYPE", "next": "ac1-wait-detail-hype" }, "ac1-wait-detail-hype": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-back-4" }, "ac1-back-4": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac1-wait-list-4" }, "ac1-wait-list-4": { "action": "wait_for", "test_id": "perps-market-row-item-BTC", "timeout": 5000, "next": "ac1-open-btc2" }, "ac1-open-btc2": { "action": "press", "test_id": "perps-market-row-item-BTC", "next": "ac1-wait-detail-btc2" }, "ac1-wait-detail-btc2": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-back-5" }, "ac1-back-5": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac1-wait-list-5" }, "ac1-wait-list-5": { "action": "wait_for", "test_id": "perps-market-row-item-ETH", "timeout": 5000, "next": "ac1-open-eth2" }, "ac1-open-eth2": { "action": "press", "test_id": "perps-market-row-item-ETH", "next": "ac1-wait-detail-eth2" }, "ac1-wait-detail-eth2": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout": 8000, "next": "ac1-screenshot-final" }, "ac1-screenshot-final": { "action": "screenshot", "filename": "evidence-rapid-switch-chart-loaded.png", "next": "ac1-back-6" }, "ac1-back-6": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac2-check-no-rate-limit" }, "ac2-check-no-rate-limit": { "action": "log_watch", "window_seconds": 45, "must_not_appear": ["candleSnapshot error", "historical_candles_api", "candle_subscription_async", "initial_candles_fetch"], "watch_for": ["candleSnapshot", "fetchHistoricalCandles", "historical_candles"], "next": "ac2-done" }, "ac2-done": { "action": "end", "status": "pass" } } } } }Validation Logs
Command:
Full output (27/27 passed)
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Cursor Bugbot is generating a summary for commit de043e1. Configure here.