Skip to content

feat(perps): Fix candlestick chart 429 rate limiting on rapid asset navigation#28865

Merged
abretonc7s merged 2 commits into
mainfrom
feat/tat-2954-http-candle-snapshot-fix
Apr 15, 2026
Merged

feat(perps): Fix candlestick chart 429 rate limiting on rapid asset navigation#28865
abretonc7s merged 2 commits into
mainfrom
feat/tat-2954-http-candle-snapshot-fix

Conversation

@abretonc7s

@abretonc7s abretonc7s commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Description

Historical candlestick chart data (candleSnapshot) was being fetched through the WebSocket-backed InfoClient. 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 HTTP InfoClient instead. 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:

  • Initial chart history load → HTTP
  • Load-more historical candles → HTTP
  • Live candle updates → WebSocket (unchanged)

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

Feature: Candlestick chart loads during rapid market switching

  Scenario: User rapidly switches between 5+ market detail pages
    Given the user is on the Perps trending markets list

    When user taps BTC, then back, then ETH, then back, then SOL, then back, then HYPE, then back, then BTC again, then back, then ETH again
    Then each market detail page loads successfully with chart visible
    And no candleSnapshot errors appear in Metro logs

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:

bash scripts/perps/agentic/validate-recipe.sh .task/feat/tat-2954-0415-2218/artifacts/ --skip-manual
Full output (27/27 passed)
Running recipe: Validate candlestick chart loads correctly during rapid market switching (TAT-2954)
Pre-conditions: wallet.unlocked, perps.feature_enabled
Workflow nodes: 28

Pre-conditions: PASS

[setup-nav-perps] navigate to PerpsTrendingView — PASS
[setup-wait-list] wait for perps-market-row-item-BTC — PASS
[ac1-open-btc] press perps-market-row-item-BTC — PASS
[ac1-wait-detail-btc] wait for perps-market-details-view — PASS
[ac1-back-1] press perps-market-header-back-button — PASS
[ac1-wait-list-1] wait for perps-market-row-item-ETH — PASS
[ac1-open-eth] press perps-market-row-item-ETH — PASS
[ac1-wait-detail-eth] wait for perps-market-details-view — PASS
[ac1-back-2] press perps-market-header-back-button — PASS
[ac1-wait-list-2] wait for perps-market-row-item-SOL — PASS
[ac1-open-sol] press perps-market-row-item-SOL — PASS
[ac1-wait-detail-sol] wait for perps-market-details-view — PASS
[ac1-back-3] press perps-market-header-back-button — PASS
[ac1-wait-list-3] wait for perps-market-row-item-HYPE — PASS
[ac1-open-hype] press perps-market-row-item-HYPE — PASS
[ac1-wait-detail-hype] wait for perps-market-details-view — PASS
[ac1-back-4] press perps-market-header-back-button — PASS
[ac1-wait-list-4] wait for perps-market-row-item-BTC — PASS
[ac1-open-btc2] press perps-market-row-item-BTC — PASS
[ac1-wait-detail-btc2] wait for perps-market-details-view — PASS
[ac1-back-5] press perps-market-header-back-button — PASS
[ac1-wait-list-5] wait for perps-market-row-item-ETH — PASS
[ac1-open-eth2] press perps-market-row-item-ETH — PASS
[ac1-wait-detail-eth2] wait for perps-market-details-view — PASS
[ac1-screenshot-final] capture screenshot — PASS
[ac1-back-6] press perps-market-header-back-button — PASS
[ac2-check-no-rate-limit] scan metro log — PASS

Results: 27/27 passed
Recipe: PASS

Pre-merge author checklist

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.

Note

Cursor Bugbot is generating a summary for commit de043e1. Configure here.

@abretonc7s abretonc7s added DO-NOT-MERGE Pull requests that should not be merged agentic labels Apr 15, 2026
@github-actions

Copy link
Copy Markdown
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.

@metamaskbot metamaskbot added the team-perps Perps team label Apr 15, 2026
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)
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - draft PR

All E2E tests pre-selected.

View GitHub Actions results

@abretonc7s abretonc7s marked this pull request as ready for review April 15, 2026 15:10
@abretonc7s abretonc7s requested a review from a team as a code owner April 15, 2026 15:10
@abretonc7s abretonc7s removed the DO-NOT-MERGE Pull requests that should not be merged label Apr 15, 2026
@abretonc7s abretonc7s enabled auto-merge April 15, 2026 15:20
@abretonc7s

Copy link
Copy Markdown
Contributor Author
Run Duration Model Nudges Grade Cost
d2ddceb9 ? sonnet 0 ungraded $46.4620
Worker report

TAT-2954 Report

Summary

Changed fetchHistoricalCandles() in HyperLiquidClientService to use HTTP transport instead of WebSocket for candleSnapshot requests. This eliminates the abort race condition that causes 429 rate limiting during rapid market navigation on extension.

Changes

File Change
app/controllers/perps/services/HyperLiquidClientService.ts getInfoClient()getInfoClient({ useHttp: true }) in fetchHistoricalCandles()
app/controllers/perps/services/HyperLiquidClientService.test.ts Updated 25 mock references from mockInfoClientWs to mockInfoClientHttp; added explicit HTTP transport assertion test

Test Plan

  • Unit tests: 77/77 passed (HyperLiquidClientService.test.ts)
  • Type check: tsc --noEmit passed
  • Lint: no errors
  • Recipe validation: 27/27 nodes passed — rapid switching across 6 markets (BTC → ETH → SOL → HYPE → BTC → ETH), no candle-related errors

Evidence

  • after.mp4 — simulator recording of recipe execution
  • evidence-rapid-switch-chart-loaded.png — screenshot of final market detail page after rapid switching

Ticket

https://consensyssoftware.atlassian.net/browse/TAT-2954

1 similar comment
@abretonc7s

Copy link
Copy Markdown
Contributor Author
Run Duration Model Nudges Grade Cost
d2ddceb9 ? sonnet 0 ungraded $46.4620
Worker report

TAT-2954 Report

Summary

Changed fetchHistoricalCandles() in HyperLiquidClientService to use HTTP transport instead of WebSocket for candleSnapshot requests. This eliminates the abort race condition that causes 429 rate limiting during rapid market navigation on extension.

Changes

File Change
app/controllers/perps/services/HyperLiquidClientService.ts getInfoClient()getInfoClient({ useHttp: true }) in fetchHistoricalCandles()
app/controllers/perps/services/HyperLiquidClientService.test.ts Updated 25 mock references from mockInfoClientWs to mockInfoClientHttp; added explicit HTTP transport assertion test

Test Plan

  • Unit tests: 77/77 passed (HyperLiquidClientService.test.ts)
  • Type check: tsc --noEmit passed
  • Lint: no errors
  • Recipe validation: 27/27 nodes passed — rapid switching across 6 markets (BTC → ETH → SOL → HYPE → BTC → ETH), no candle-related errors

Evidence

  • after.mp4 — simulator recording of recipe execution
  • evidence-rapid-switch-chart-loaded.png — screenshot of final market detail page after rapid switching

Ticket

https://consensyssoftware.atlassian.net/browse/TAT-2954

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
11 value mismatches detected (expected — fixture represents an existing user).
View details

@abretonc7s abretonc7s added this pull request to the merge queue Apr 15, 2026
Merged via the queue into main with commit 351ead7 Apr 15, 2026
137 of 138 checks passed
@abretonc7s abretonc7s deleted the feat/tat-2954-http-candle-snapshot-fix branch April 15, 2026 16:32
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 15, 2026
@metamaskbot metamaskbot added the release-7.74.0 Issue or pull request that will be included in release 7.74.0 label Apr 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

agentic release-7.74.0 Issue or pull request that will be included in release 7.74.0 size-S team-perps Perps team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants