Skip to content

FEDEV-3973: WebSocket price and candle streaming to the trading UI#2613

Open
divhead wants to merge 1 commit into
releasefrom
phase-2-ws-prices-2
Open

FEDEV-3973: WebSocket price and candle streaming to the trading UI#2613
divhead wants to merge 1 commit into
releasefrom
phase-2-ws-prices-2

Conversation

@divhead

@divhead divhead commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Phase 2 (FEDEV-3973): stream prices and live candles into the UI and SDK, behind off-by-default flags with the existing REST/poll as fallback.

  • sdk: WsStreamClient transport (isomorphic-ws, reconnect+backoff, snapshot- then-stream); v2 watchTokenPrices / watchCandles raw Subscriptions and a fetchTokenPrices REST snapshot, all serving normalized TokenPricesData over one shared connection
  • prices: useTokenRecentPricesRequest overlays the WS set behind the abWebsocket flag, throttled, with an originTs staleness fallback to the REST poll; useWsPriceOverlay emits freshness metrics
  • candles: DataFeed streams the forming bar into TradingView behind wsCandles; the poll stays the backstop and a monotonic onTick guard prevents rollover rewrites
  • fix weekly/monthly CHART_PERIODS NaN and guard empty stream frames; unit + e2e tests

Phase 2 (FEDEV-3973): stream prices and live candles into the UI and SDK,
behind off-by-default flags with the existing REST/poll as fallback.

- sdk: WsStreamClient transport (isomorphic-ws, reconnect+backoff, snapshot-
  then-stream); v2 watchTokenPrices / watchCandles raw Subscriptions and a
  fetchTokenPrices REST snapshot, all serving normalized TokenPricesData over
  one shared connection
- prices: useTokenRecentPricesRequest overlays the WS set behind the abWebsocket
  flag, throttled, with an originTs staleness fallback to the REST poll;
  useWsPriceOverlay emits freshness metrics
- candles: DataFeed streams the forming bar into TradingView behind wsCandles;
  the poll stays the backstop and a monotonic onTick guard prevents rollover
  rewrites
- fix weekly/monthly CHART_PERIODS NaN and guard empty stream frames; unit +
  e2e tests
@divhead divhead changed the title WebSocket price and candle streaming to the trading UI FEDEV-3973: WebSocket price and candle streaming to the trading UI Jul 2, 2026

@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 2 potential issues.

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit 1ca4a55. Configure here.

pricesData: data?.pricesData,
updatedAt: data?.updatedAt,
pricesData: wsFresh ? wsPrices : data?.pricesData,
updatedAt: wsFresh ? wsOriginTs : data?.updatedAt,

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.

Native token missing WS prices

Medium Severity

When the WebSocket overlay is active, pricesData is taken straight from the stream snapshot. The REST fetcher still mirrors wrapped-token prices onto NATIVE_TOKEN_ADDRESS, but that step never runs on the WS path, so native-token rows can lose prices while the flag is on.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1ca4a55. Configure here.

reconnectMaxMs: this.reconnectMaxMs,
});
}
return this._streamClient;

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.

Stream URL ignores API failover

Medium Severity

getStreamClient builds the WebSocket URL once from this.ctx.api.url or streamUrlOverride and caches _streamClient. With HttpClientWithFallback, HTTP can rotate primaries after failures while the stream stays on the first host, so REST and live prices can diverge after failover.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1ca4a55. Configure here.

Comment thread sdk/src/utils/stream/__tests__/stream.e2e.spec.ts

const marketsInfo = useMarketsInfoRequest(chainId, { tokensData: tokensDataResult.tokensData });

useWsPriceOverlay(chainId);

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.

Please check that useWsPriceOverlay does not cause rerender storm

Comment on lines +176 to +177
pricesData: wsFresh ? wsPrices : data?.pricesData,
updatedAt: wsFresh ? wsOriginTs : data?.updatedAt,

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.

Could we merge prices in case API misses some?

"apiMarkets",
"apiPositions",
"apiOrders",
"wsPrices",

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.

should not we add wsCandles as well?

updatedAt: data?.updatedAt,
pricesData: wsFresh ? wsPrices : data?.pricesData,
updatedAt: wsFresh ? wsOriginTs : data?.updatedAt,
error,

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.

Error should also be selected based on ws/http data

Comment on lines +70 to +74
emitMetricTiming<WsPriceInterArrivalTiming>({
event: "wsPrices.interArrival",
time: now - lastFrameAtRef.current,
data: { chainId },
});

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.

should we also subsample these metrics?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants