useOrderbook.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. 'use client';
  2. import { useEffect, useState, useCallback } from 'react';
  3. import { useSignalRContext } from '@/contexts/signalrProvider';
  4. import { fetchApi } from '@/lib/utils/client';
  5. import type { OrderbookData, OrderbookRestData } from '@/types/crypto';
  6. export default function useOrderbook(market: string) {
  7. const { cryptoConnection, cryptoConnected } = useSignalRContext();
  8. const [orderbook, setOrderbook] = useState<OrderbookData | null>(null);
  9. // REST 초기 로드
  10. useEffect(() => {
  11. if (!market) {
  12. return;
  13. }
  14. const load = async () => {
  15. try {
  16. const res = await fetchApi<OrderbookRestData>(`/api/crypto/${market}/orderbook`);
  17. if (res.success && res.data) {
  18. setOrderbook({
  19. market,
  20. symbol: market.split('-')[1] || '',
  21. totalAskSize: res.data.totalAskSize,
  22. totalBidSize: res.data.totalBidSize,
  23. units: res.data.units,
  24. timestamp: res.data.timestamp,
  25. level: res.data.level,
  26. streamType: 'SNAPSHOT',
  27. });
  28. }
  29. } catch (error) {
  30. console.error('Failed to load orderbook:', error);
  31. }
  32. };
  33. load();
  34. }, [market]);
  35. // SignalR 실시간 업데이트
  36. const handleOrderbook = useCallback((data: OrderbookData) => {
  37. if (data.market === market) {
  38. setOrderbook(data);
  39. }
  40. }, [market]);
  41. useEffect(() => {
  42. if (!cryptoConnection || !cryptoConnected) {
  43. return;
  44. }
  45. cryptoConnection.on('ReceiveOrderbook', handleOrderbook);
  46. return () => {
  47. cryptoConnection.off('ReceiveOrderbook', handleOrderbook);
  48. };
  49. }, [cryptoConnection, cryptoConnected, handleOrderbook]);
  50. return orderbook;
  51. }