Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
aeed743
chore: add ohlcv websocket streaming
sahar-fehri May 5, 2026
6b18707
chore: integrate OHLCVService WebSocket streaming into advanced charts
sahar-fehri May 6, 2026
8748a32
fix: add ohlcv latest fallback on disconnect or down
sahar-fehri May 11, 2026
5e5c781
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
sahar-fehri May 11, 2026
6182bb7
fix: todo comment
sahar-fehri May 11, 2026
5786c6c
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
sahar-fehri May 11, 2026
ad5be51
fix: test log
sahar-fehri May 11, 2026
edda0db
fix: cleanup
sahar-fehri May 11, 2026
837b876
fix: lint
sahar-fehri May 11, 2026
caefeb6
fix: ut
sahar-fehri May 12, 2026
88c63a7
fix: fix ut
sahar-fehri May 12, 2026
89f5283
fix: add feature flag to gate WS logic
sahar-fehri May 12, 2026
7664973
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
sahar-fehri May 12, 2026
38cf74e
fix: merge conflict
sahar-fehri May 12, 2026
6754036
fix: fix handling subscription error
sahar-fehri May 12, 2026
d5c404b
fix: FF registration
sahar-fehri May 12, 2026
c49a444
fix: new preview
sahar-fehri May 13, 2026
d6be82e
fix: plug realtime update to price
sahar-fehri May 13, 2026
a24239b
fix: dedupe
sahar-fehri May 13, 2026
1d8190f
fix: fix
sahar-fehri May 13, 2026
f7d859f
fix: immediate poll on error
sahar-fehri May 14, 2026
2ea0f35
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
sahar-fehri May 14, 2026
fd4200d
fix: ut
sahar-fehri May 14, 2026
0e1c567
bump core-backend
bergarces May 14, 2026
88ec55d
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
bergarces May 14, 2026
fe6f560
Merge branch 'main' into chore/ohlcv-ws-streaming-integration
Prithpal-Sooriya May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/scripts/known-feature-flag-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const FILE_SOURCES: Array<{ key: string; file: string; exportName: string }> = [
{ key: 'FULL_PAGE_ACCOUNT_LIST_FLAG_NAME', file: sel('fullPageAccountList'), exportName: 'FULL_PAGE_ACCOUNT_LIST_FLAG_NAME' },
{ key: 'IMPORT_SRP_WORD_SUGGESTION_FLAG_NAME', file: sel('importSrpWordSuggestion'), exportName: 'IMPORT_SRP_WORD_SUGGESTION_FLAG_NAME' },
{ key: 'ASSETS_UNIFY_STATE_FLAG', file: sel('assetsUnifyState'), exportName: 'ASSETS_UNIFY_STATE_FLAG' },
{ key: 'TOKEN_DETAILS_OHLCV_WS_INTEGRATION_FLAG_KEY', file: sel('tokenDetailsOhlcvWsIntegration'), exportName: 'TOKEN_DETAILS_OHLCV_WS_INTEGRATION_FLAG_KEY' },
];

function resolveConstantFromFile(filePath: string, constantName: string): string | undefined {
Expand Down
11 changes: 11 additions & 0 deletions app/components/UI/AssetOverview/Price/Price.advanced.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ jest.mock('../PriceChart/PriceChart.context', () => ({
}),
}));

jest.mock(
'../../../../selectors/featureFlagController/tokenDetailsOhlcvWsIntegration',
() => ({
selectTokenDetailsOhlcvWsEnabled: jest.fn(() => false),
}),
);

jest.mock('react-redux', () => {
const actual = jest.requireActual('react-redux');
return {
Expand Down Expand Up @@ -89,6 +96,10 @@ jest.mock('../../Charts/AdvancedChart/useOHLCVChart', () => ({
useOHLCVChart: (...args: unknown[]) => mockUseOHLCVChart(...args),
}));

jest.mock('../../Charts/AdvancedChart/useOHLCVRealtime', () => ({
useOHLCVRealtime: () => ({ latestBar: null }),
}));

jest.mock('../../Charts/AdvancedChart/TimeRangeSelector', () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const { View, Pressable, Text } = require('react-native');
Expand Down
48 changes: 48 additions & 0 deletions app/components/UI/AssetOverview/Price/Price.advanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import TimeRangeSelector, {
type TimeRange,
} from '../../Charts/AdvancedChart/TimeRangeSelector';
import { useOHLCVChart } from '../../Charts/AdvancedChart/useOHLCVChart';
import { useOHLCVRealtime } from '../../Charts/AdvancedChart/useOHLCVRealtime';
import { OHLCVBar } from '../../Charts/AdvancedChart/OHLCVBar/OHLCVBar';
import {
Box,
Expand All @@ -62,9 +63,23 @@ import {
TraceName,
TraceOperation,
} from '../../../../util/trace';
import { selectTokenDetailsOhlcvWsEnabled } from '../../../../selectors/featureFlagController/tokenDetailsOhlcvWsIntegration';

const EMPTY_INDICATORS: IndicatorType[] = [];

/**
* Maps UI time-range selections to the WebSocket candle interval used by
* OHLCVService. These match the default intervals the REST OHLCV API returns
* for each timePeriod.
*/
const WS_INTERVAL_BY_TIME_RANGE: Record<TimeRange, string> = {
'1H': '1m',
'1D': '15m',
'1W': '1h',
'1M': '1d',
'1Y': '1d',
};

const TIME_RANGE_LABELS: Record<TimeRange, string> = {
'1H': 'asset_overview.chart_time_period.1h',
'1D': 'asset_overview.chart_time_period.1d',
Expand Down Expand Up @@ -134,6 +149,7 @@ const PriceAdvanced = ({
const { trackEvent, createEventBuilder } = useAnalytics();
const [timeRange, setTimeRange] = useState<TimeRange>('1D');
const chartType = useSelector(selectTokenOverviewChartType);
const isOhlcvWsEnabled = useSelector(selectTokenDetailsOhlcvWsEnabled);
const [crosshairData, setCrosshairData] = useState<CrosshairData | null>(
null,
);
Expand Down Expand Up @@ -293,6 +309,37 @@ const PriceAdvanced = ({
vsCurrency: currentCurrency,
});

const wsInterval = WS_INTERVAL_BY_TIME_RANGE[timeRange];
const wsEnabled =
isOhlcvWsEnabled &&
!chartLoading &&
ohlcvData.length >= CHART_DATA_THRESHOLD &&
!hasEmptyData &&
!chartError;

const { latestBar } = useOHLCVRealtime({
assetId,
interval: wsInterval,
currency: currentCurrency,
timePeriod: timeRange.toLowerCase(),
enabled: wsEnabled,
});

// TradingView Advanced Charts Bar.time expects milliseconds
// https://www.tradingview.com/charting-library-docs/latest/api/interfaces/Datafeed.Bar/
// OHLCVService delivers bars with `timestamp` in Unix seconds — multiply by 1000
const realtimeBar = useMemo(() => {
if (!latestBar) return undefined;
return {
time: latestBar.timestamp * 1000,
open: latestBar.open,
high: latestBar.high,
low: latestBar.low,
close: latestBar.close,
volume: latestBar.volume,
};
}, [latestBar]);
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

const ohlcvPagination = useMemo(
() => ({
nextCursor,
Expand Down Expand Up @@ -554,6 +601,7 @@ const PriceAdvanced = ({
<AdvancedChart
ohlcvData={ohlcvData}
ohlcvSeriesKey={ohlcvSeriesKey}
realtimeBar={realtimeBar}
height={CHART_HEIGHT}
showVolume={chartType === ChartType.Candles}
volumeOverlay
Expand Down
4 changes: 4 additions & 0 deletions app/components/UI/AssetOverview/Price/Price.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ jest.mock('../../Charts/AdvancedChart/useOHLCVChart', () => ({
useOHLCVChart: (...args: unknown[]) => mockUseOHLCVChart(...args),
}));

jest.mock('../../Charts/AdvancedChart/useOHLCVRealtime', () => ({
useOHLCVRealtime: () => ({ latestBar: null }),
}));

jest.mock('../PriceChart/PriceChart', () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const { View } = require('react-native');
Expand Down
Loading
Loading