Skip to content

Commit e753f61

Browse files
committed
fix
1 parent a793420 commit e753f61

File tree

2 files changed

+61
-59
lines changed

2 files changed

+61
-59
lines changed

components/CandlestickChart.tsx

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
PERIOD_BUTTONS,
1414
PERIOD_CONFIG,
1515
} from '@/lib/constants';
16-
import { convertOHLCData, convertOHLCToCandlestickData } from '@/lib/utils';
16+
import { convertOHLCData } from '@/lib/utils';
1717
const { getCoinOHLC } = await import('@/lib/coingecko.actions');
1818

1919
export default function CandlestickChart({
@@ -95,31 +95,50 @@ export default function CandlestickChart({
9595
useEffect(() => {
9696
if (!candleSeriesRef.current) return;
9797

98-
// Convert timestamps from milliseconds to seconds while keeping full OHLC structure
99-
const convertedToSeconds = ohlcData.map((item) => [
100-
Math.floor(item[0] / 1000), // timestamp in seconds
101-
item[1], // open
102-
item[2], // high
103-
item[3], // low
104-
item[4], // close
105-
] as OHLCData);
106-
console.log('==== Updating convertedToSeconds:', convertedToSeconds);
107-
108-
const merged = liveOhlcv
109-
? [...convertedToSeconds, liveOhlcv]
110-
: [...convertedToSeconds];
111-
112-
console.log('==== Updating merged:', merged);
113-
// Sort ascending by time
98+
// Convert timestamps from milliseconds to seconds
99+
const convertedToSeconds = ohlcData.map(
100+
(item) =>
101+
[
102+
Math.floor(item[0] / 1000), // timestamp in seconds
103+
item[1], // open
104+
item[2], // high
105+
item[3], // low
106+
item[4], // close
107+
] as OHLCData
108+
);
109+
110+
let merged: OHLCData[];
111+
112+
if (liveOhlcv) {
113+
const liveTimestamp = liveOhlcv[0];
114+
115+
// Check if we need to update an existing candle or add a new one
116+
const lastHistoricalCandle =
117+
convertedToSeconds[convertedToSeconds.length - 1];
118+
119+
if (lastHistoricalCandle && lastHistoricalCandle[0] === liveTimestamp) {
120+
// Update the last candle with live data
121+
merged = [...convertedToSeconds.slice(0, -1), liveOhlcv];
122+
} else {
123+
// Append new live candle
124+
merged = [...convertedToSeconds, liveOhlcv];
125+
}
126+
} else {
127+
merged = convertedToSeconds;
128+
}
129+
130+
// Sort ascending by time (in case of any ordering issues)
114131
merged.sort((a, b) => a[0] - b[0]);
115132

116133
const converted = convertOHLCData(merged);
117134

118-
console.log('==== Updating Candlestick Data:', converted);
119-
120135
candleSeriesRef.current.setData(converted);
121-
chartRef.current?.timeScale().fitContent();
122-
}, [ohlcData, liveOhlcv, period]);
136+
137+
// Only fit content on initial load or period change, not on live updates
138+
if (!liveOhlcv || mode === 'historical') {
139+
chartRef.current?.timeScale().fitContent();
140+
}
141+
}, [ohlcData, liveOhlcv, period, mode]);
123142

124143
return (
125144
<div className='candlestick-container'>

hooks/useCoinGeckoWebSocket.ts

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,11 @@ export function useCoinGeckoWebSocket({
1313

1414
const [price, setPrice] = useState<ExtendedPriceData | null>(null);
1515
const [trades, setTrades] = useState<TradeData[]>([]);
16-
// const [ohlcv, setOhlcv] = useState<OHLCData[]>(
17-
// coinOHLCData.map((c) => [
18-
// Math.floor(c[0] / 1000), // normalize ms → seconds
19-
// c[1],
20-
// c[2],
21-
// c[3],
22-
// c[4],
23-
// ])
24-
// );
25-
const [ohlcv, setOhlcv] = useState<OHLCData | null>( null)
26-
16+
const [ohlcv, setOhlcv] = useState<OHLCData | null>(null);
17+
const lastOhlcvTimestamp = useRef<number>(0);
2718

2819
const [isWsReady, setIsWsReady] = useState(false);
2920

30-
// Track where historical data ends and live data begins
31-
// const historicalDataLength = useRef(ohlcv.length);
32-
3321
const handleMessage = useCallback((event: MessageEvent) => {
3422
const ws = wsRef.current;
3523
const msg: WebSocketMessage = JSON.parse(event.data);
@@ -69,18 +57,21 @@ export function useCoinGeckoWebSocket({
6957

7058
setTrades((prev) => [newTrade, ...prev].slice(0, 10));
7159
}
72-
console.log('==== Message:', msg);
73-
// G3: OHLCV updates — simple append
74-
if (msg.ch === 'G3') {
75-
76-
setOhlcv([
77-
msg.t || 0, // seconds
78-
Number(msg.o ?? 0),
79-
Number(msg.h ?? 0),
80-
Number(msg.l ?? 0),
81-
Number(msg.c ?? 0),
82-
]);
83-
}
60+
// G3: OHLCV updates
61+
if (msg.ch === 'G3') {
62+
const timestamp = msg.t || 0; // already in seconds
63+
const newCandle: OHLCData = [
64+
timestamp,
65+
Number(msg.o ?? 0),
66+
Number(msg.h ?? 0),
67+
Number(msg.l ?? 0),
68+
Number(msg.c ?? 0),
69+
];
70+
71+
// Always update with the latest candle - chart will handle deduplication
72+
setOhlcv(newCandle);
73+
lastOhlcvTimestamp.current = timestamp;
74+
}
8475
}, []);
8576

8677
// WebSocket connection
@@ -100,7 +91,7 @@ if (msg.ch === 'G3') {
10091
(channel: string, data?: Record<string, any>) => {
10192
const ws = wsRef.current;
10293
if (!ws || !isWsReady || subscribed.current.has(channel)) return;
103-
console.log('==== Subscribing to channel:', channel, data);
94+
10495
ws.send(
10596
JSON.stringify({
10697
command: 'subscribe',
@@ -143,19 +134,11 @@ console.log('==== Subscribing to channel:', channel, data);
143134
(async () => {
144135
if (!active) return;
145136

146-
// Reset state and normalize historical data
137+
// Reset state
147138
setPrice(null);
148139
setTrades([]);
149-
// setOhlcv(
150-
// coinOHLCData.map((c) => [
151-
// Math.floor(c[0] / 1000),
152-
// c[1],
153-
// c[2],
154-
// c[3],
155-
// c[4],
156-
// ])
157-
// );
158-
// historicalDataLength.current = coinOHLCData.length;
140+
setOhlcv(null);
141+
lastOhlcvTimestamp.current = 0;
159142

160143
unsubscribeAll();
161144

0 commit comments

Comments
 (0)