@@ -13,7 +13,7 @@ import { useEffect, useRef, useState, useCallback } from 'react';
1313import CoinHeader from './CoinHeader' ;
1414import { Separator } from './ui/separator' ;
1515import CandlestickChart from './CandlestickChart' ;
16- import { timeAgo } from '@/lib/utils' ;
16+ import { formatPrice , formatTime , timeAgo } from '@/lib/utils' ;
1717
1818const WS_BASE = `${ process . env . NEXT_PUBLIC_COINGECKO_WEBSOCKET_URL } ?x_cg_pro_api_key=${ process . env . NEXT_PUBLIC_COINGECKO_API_KEY } ` ;
1919
@@ -22,22 +22,19 @@ export default function LiveDataWrapper({
2222 pool,
2323 coin,
2424 coinOHLCData,
25+ children,
2526} : LiveDataProps ) {
2627 const wsRef = useRef < WebSocket | null > ( null ) ;
2728 const subscribed = useRef < Set < string > > ( new Set ( ) ) ;
2829
2930 const [ price , setPrice ] = useState < ExtendedPriceData | null > ( null ) ;
30- const [ trades , setTrades ] = useState < TradeData [ ] | null > ( null ) ;
31+ const [ trades , setTrades ] = useState < TradeData [ ] > ( [ ] ) ;
3132 const [ ohlcv , setOhlcv ] = useState < OHLCData [ ] > ( coinOHLCData ) ;
3233 const [ isWsReady , setIsWsReady ] = useState ( false ) ;
3334
3435 // Track where historical data ends and live data begins
3536 const historicalDataLength = useRef ( coinOHLCData . length ) ;
3637
37- console . log ( 'price' , price ) ;
38- console . log ( 'trades' , trades ) ;
39- console . log ( 'ohlcv' , ohlcv ) ;
40-
4138 const handleMessage = useCallback ( ( event : MessageEvent ) => {
4239 const ws = wsRef . current ;
4340 const msg : WebSocketMessage = JSON . parse ( event . data ) ;
@@ -66,15 +63,19 @@ export default function LiveDataWrapper({
6663 }
6764
6865 if ( msg . c === 'G2' ) {
69- setTrades ( [
70- {
71- price : msg . pu ,
72- value : msg . vo ,
73- timestamp : msg . t ,
74- type : msg . ty ,
75- amount : msg . to ,
76- } ,
77- ] ) ;
66+ const newTrade : TradeData = {
67+ price : msg . pu ,
68+ value : msg . vo ,
69+ timestamp : ( msg . t ?? 0 ) * 1000 , // Convert to milliseconds
70+ type : msg . ty ,
71+ amount : msg . to ,
72+ } ;
73+
74+ setTrades ( ( prev ) => {
75+ // Prepend new trade to beginning (most recent first)
76+ const allTrades = [ newTrade , ...prev ] ;
77+ return allTrades . slice ( 0 , 10 ) ;
78+ } ) ;
7879 }
7980
8081 if ( msg . ch === 'G3' ) {
@@ -161,8 +162,8 @@ export default function LiveDataWrapper({
161162 let active = true ;
162163 ( async ( ) => {
163164 setPrice ( null ) ;
164- setTrades ( null ) ;
165- // Reset to historical data only (clear live data)
165+ // Reset to empty (clear live data)
166+ setTrades ( [ ] ) ;
166167 setOhlcv ( coinOHLCData ) ;
167168 historicalDataLength . current = coinOHLCData . length ;
168169
@@ -216,39 +217,59 @@ export default function LiveDataWrapper({
216217 < Separator className = 'my-8 bg-purple-600' />
217218
218219 { /* Recent Trades */ }
219- < div className = 'w-full mt -8 space-y-4' >
220+ < div className = 'w-full my -8 space-y-4' >
220221 < h4 className = 'text-2xl' > Recent Trades</ h4 >
221- < Table className = 'bg-dark-500 rounded-xl' >
222- < TableHeader className = 'text-purple-100' >
223- < TableRow className = 'hover:bg-transparent' >
224- < TableHead className = 'pl-5 py-5 text-purple-100' >
225- Amount
226- </ TableHead >
227- < TableHead className = 'text-purple-100' > Price</ TableHead >
228- < TableHead className = 'pr-8 text-purple-100' > Value</ TableHead >
229- < TableHead className = 'pr-8 text-purple-100' > Buy/Sell</ TableHead >
230- < TableHead className = 'pr-8 text-purple-100' > Time</ TableHead >
231- </ TableRow >
232- </ TableHeader >
233- < TableBody >
234- { trades ?. map ( ( trade , index ) => (
235- < TableRow key = { index } >
236- < TableCell className = 'pl-5 py-4 font-medium' >
237- { trade . amount }
238- </ TableCell >
239- < TableCell className = 'font-medium' > { trade . price } </ TableCell >
240- < TableCell className = 'font-medium' > { trade . value } </ TableCell >
241- < TableCell className = 'font-medium' >
242- { trade . type === 'b' ? 'Buy' : 'Sell' }
243- </ TableCell >
244- < TableCell className = 'pr-5' >
245- { trade . timestamp && timeAgo ( trade . timestamp ) }
246- </ TableCell >
247- </ TableRow >
248- ) ) }
249- </ TableBody >
250- </ Table >
222+ < div className = 'custom-scrollbar bg-dark-500 rounded-xl overflow-hidden' >
223+ { trades . length > 0 ? (
224+ < Table className = 'bg-dark-500' >
225+ < TableHeader className = 'text-purple-100' >
226+ < TableRow className = 'hover:bg-transparent' >
227+ < TableHead className = 'pl-5 text-purple-100' > Price</ TableHead >
228+ < TableHead className = 'py-5 text-purple-100' > Amount</ TableHead >
229+ < TableHead className = 'pr-8 text-purple-100' > Value</ TableHead >
230+ < TableHead className = 'pr-8 text-purple-100' >
231+ Buy/Sell
232+ </ TableHead >
233+ < TableHead className = 'pr-8 text-purple-100' > Time</ TableHead >
234+ </ TableRow >
235+ </ TableHeader >
236+ < TableBody >
237+ { trades ?. map ( ( trade , index ) => (
238+ < TableRow key = { index } >
239+ < TableCell className = 'pl-5 py-5 font-medium' >
240+ { trade . price ? formatPrice ( trade . price ) : '-' }
241+ </ TableCell >
242+ < TableCell className = 'py-4 font-medium' >
243+ { trade . amount ?. toFixed ( 4 ) ?? '-' }
244+ </ TableCell >
245+ < TableCell className = 'font-medium' >
246+ { trade . value ? formatPrice ( trade . value ) : '-' }
247+ </ TableCell >
248+ < TableCell className = 'font-medium' >
249+ < span
250+ className = {
251+ trade . type === 'b' ? 'text-green-500' : 'text-red-500'
252+ }
253+ >
254+ { trade . type === 'b' ? 'Buy' : 'Sell' }
255+ </ span >
256+ </ TableCell >
257+ < TableCell className = 'pr-5' >
258+ { trade . timestamp ? timeAgo ( trade . timestamp ) : '-' }
259+ </ TableCell >
260+ </ TableRow >
261+ ) ) }
262+ </ TableBody >
263+ </ Table >
264+ ) : (
265+ < div className = 'text-center p-10 text-purple-100/50' >
266+ No recent trades
267+ </ div >
268+ ) }
269+ </ div >
251270 </ div >
271+
272+ { children }
252273 </ section >
253274 ) ;
254275}
0 commit comments