Skip to content

fix: Perps chart viewport breaking when revisiting a candle interval#29344

Merged
gambinish merged 4 commits into
mainfrom
perps/fix/chart-flicker-2h
Apr 28, 2026
Merged

fix: Perps chart viewport breaking when revisiting a candle interval#29344
gambinish merged 4 commits into
mainfrom
perps/fix/chart-flicker-2h

Conversation

@gambinish

@gambinish gambinish commented Apr 24, 2026

Copy link
Copy Markdown
Member

Description

Fixes a bug where the Perps trading chart's viewport would break, flicker, or "jump between views" when navigating back to a previously visited candle interval (e.g. 4h → 8h → 4h). The first visit to an interval worked correctly, but revisits would render the wrong zoom, drop candles older than the visible range, and reset continuously on every live tick.

Root causes
There were two independent bugs compounding each other:

  1. Cache was overwritten on revisit, shrinking the dataset
    In CandleStreamChannel, the first visit to an interval fetches OneWeek of candles (~42 for 4h). On revisit, we intentionally do a lighter OneDay refetch (~6 candles) to conserve rate limit budget. However, the subscription callback was doing a full cache.set(cacheKey, incoming) — replacing the cached 42 candles with only 6.

When that shrunken dataset propagated to the WebView, TradingView's stored visible range pointed outside the new data, causing the viewport to collapse and candles older than the visible window to disappear.

  1. Every live tick triggered a full chart reset
    In TradingViewChart, every new candleData prop (including live ticks) sent SET_CANDLESTICK_DATA to the WebView, which called candlestickSeries.setData(fullDataset). setData is a destructive operation that resets the chart's internal state. On revisit this collided with the shrunken-cache propagation, producing the flicker and zoom reset the user experienced.

Changes

CandleStreamChannel.ts — merge instead of replace

  • Added a static mergeCandleData helper that merges incoming candles into the cached dataset by timestamp (incoming wins on overlapping times, older cached candles are preserved), capped at 1000 candles to prevent unbounded growth.
  • Updated the subscribeToCandles callback in connectNow to merge instead of replace, so a lighter refetch on revisit no longer drops history.

TradingViewChart.tsx — route live ticks to an incremental path

  • Added a lastSentSignatureRef that tracks { symbol, interval, firstTime, count, lastTime } of the last dataset sent to the WebView.
  • SET_CANDLESTICK_DATA (full reload) for initial load, symbol/interval change, history prepend, count decrease, or multi-bar jump.
  • UPDATE_LAST_CANDLE (incremental, 1–2 candles) for live ticks and single-bar appends on the same symbol/interval/firstTime.
  • CHART_READY clears the signature so a WebView remount always forces a full reload.
  • CLEAR_DATA clears the signature so the next send is a full reload (empty chart can't be incrementally updated).

TradingViewChartTemplate.tsx — handle incremental updates

  • Added a new UPDATE_LAST_CANDLE message handler that calls candlestickSeries.update(candle) for each candle in the payload, keeps window.allCandleData in sync, mirrors the update on the volume series, and refreshes Y-axis decimal precision without touching the visible range or zoom.

Changelog

CHANGELOG entry: fixes bug related to chart re-rendering and flickering

Related issues

Fixes: #29232 https://consensyssoftware.atlassian.net/browse/TAT-2973

Manual testing steps

Feature: Perps chart interval revisit
  Scenario: User revisits a previously loaded candle interval
    Given the user has loaded the Perps chart on the 4h interval
    And the user has switched to the 8h interval
    When the user switches back to the 4h interval
    Then the chart renders with its full candle history preserved
    And the viewport stays zoomed to the same visible range as before
    And no skeleton loader or flicker is shown
  Scenario: User receives a live tick on a revisited interval
    Given the user is viewing the Perps chart on a revisited interval
    And the chart is fully rendered with live data
    When a live candle tick arrives
    Then only the last candle is updated in place
    And the chart's visible range and zoom remain unchanged
    And no full chart reload occurs
  Scenario: User returns after a new candle has closed
    Given the user has loaded the Perps chart on the 4h interval
    And the user has been away long enough for at least one new 4h bar to close
    When the user switches back to the 4h interval
    Then the chart reloads with the merged history and the new bars
    And the chart re-zooms cleanly to the latest candles
    And no older candles are dropped from view
  Scenario: User switches to a different symbol
    Given the user is viewing the Perps chart for BTC
    When the user navigates to the chart for ETH
    Then the chart performs a full reload with the new symbol's data
    And the previous symbol's candles are not shown

Screenshots/Recordings

Before

Screen.Recording.2026-04-24.at.12.23.06.PM.mov

After

Screen.Recording.2026-04-24.at.12.19.40.PM.mov

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

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

Medium Risk
Touches candle caching/merging and the WebView messaging path used to render the Perps chart; mistakes could cause stale/incorrect candles, memory growth, or regress zoom/viewport behavior across symbols/intervals.

Overview
Fixes Perps chart flicker/viewport jumps when revisiting candle intervals by preserving candle history in cache and avoiding full chart resets on every tick.

CandleStreamChannel now merges incoming candle updates into the existing cached dataset (timestamp-based, incoming wins) and caps cached history at 1000 candles, notifying subscribers with the merged result instead of replacing the cache.

TradingViewChart introduces signature-based routing to send either a full SET_CANDLESTICK_DATA reload (initial load, symbol/interval/history changes, WebView remount, or cleared data) or an incremental UPDATE_LAST_CANDLE message (live ticks / single-bar append, sending only the last 1–2 candles). The WebView template adds an UPDATE_LAST_CANDLE handler that applies series.update() and keeps internal candle/volume state in sync.

Adds focused regression tests for both the incremental update routing (TradingViewChart.incremental.test.tsx) and the candle cache merge invariants (CandleStreamChannel.test.ts).

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

@metamaskbotv2 metamaskbotv2 Bot added the team-perps Perps team label Apr 24, 2026
@gambinish gambinish marked this pull request as ready for review April 24, 2026 19:53
@gambinish gambinish requested a review from a team as a code owner April 24, 2026 19:53
@gambinish gambinish changed the title fix: chart jumping fix: Perps chart viewport breaking when revisiting a candle interval Apr 24, 2026

@geositta geositta 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.

I tested, looks good, could we add some unit tests for CandleStreamChannel.mergeCandleData ?

Comment thread app/components/UI/Perps/providers/channels/CandleStreamChannel.ts
@github-actions

Copy link
Copy Markdown
Contributor

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

@gambinish gambinish requested a review from geositta April 27, 2026 22:23
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
All 5 changed files are confined to the Perps feature area (app/components/UI/Perps/). The changes are:

  1. TradingViewChart.tsx: Added incremental update routing - live ticks now send UPDATE_LAST_CANDLE instead of full SET_CANDLESTICK_DATA to avoid viewport flicker/jumps when revisiting cached intervals.

  2. TradingViewChartTemplate.tsx: Added UPDATE_LAST_CANDLE handler in the WebView JS template using series.update() instead of series.setData() to preserve user zoom/viewport state.

  3. CandleStreamChannel.ts: Added mergeCandleData static method and changed cache updates from simple replacement to merge-based, preserving older candles when revisiting intervals (fixes "candles before visible range disappear" bug).

  4. Two new unit test files covering the above logic.

Tag selection rationale:

  • SmokePerps: Directly tests perpetuals functionality. These changes affect the core TradingView chart rendering and candle data streaming within Perps - the primary area of change.
  • SmokeWalletPlatform: Per SmokePerps tag description, "Perps is also a section inside the Trending tab (SmokeWalletPlatform); changes to Perps views affect Trending." The TradingViewChart is a Perps view component.
  • SmokeConfirmations: Per SmokePerps tag description, "When selecting SmokePerps, also select SmokeConfirmations (Add Funds deposits are on-chain transactions)."

No changes to shared components (TabBar, Navigation, Engine, Controllers, or E2E infrastructure), so no broader test coverage is needed beyond the Perps-related tags.

Performance Test Selection:
The changes specifically optimize UI rendering performance in the Perps TradingView chart by switching from full dataset resets (SET_CANDLESTICK_DATA) to incremental updates (UPDATE_LAST_CANDLE) for live ticks. This is a direct rendering performance improvement that @PerformancePreps would validate - it covers perps market loading and position management which includes the TradingView chart rendering.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@gambinish gambinish added this pull request to the merge queue Apr 28, 2026
Merged via the queue into main with commit e7ec5b0 Apr 28, 2026
96 of 102 checks passed
@gambinish gambinish deleted the perps/fix/chart-flicker-2h branch April 28, 2026 21:24
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 28, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.76.0 Issue or pull request that will be included in release 7.76.0 label Apr 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.76.0 Issue or pull request that will be included in release 7.76.0 size-L team-perps Perps team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Chart is flickering, sometimes displaying only 10 candles

3 participants