/ src / hooks / useNet.ts
useNet.ts
  1  "use client"
  2  import { useState, useEffect, useRef } from 'react'
  3  import { getBlockStream } from '@/services/ws/stream'
  4  import type { StreamingBlock, StreamingStats } from '@/services/ws/stream'
  5  import { getTotalTransactions, getTotalPayloadSize, getSuccessRate } from '@/services/api/discovery'
  6  import { useNetwork } from '@/contexts/networkcontext'
  7  interface Block {
  8    height: number
  9    timestamp: number
 10    transactions: number
 11    hash?: string
 12  }
 13  
 14  interface ChainData {
 15    latestBlock: number
 16    recentBlocks: Block[]
 17    lastUpdated: number
 18    isConnected: boolean
 19    avgBlockTime: number
 20    totalTransactions: number
 21    totalPayloadSize: number
 22    successRate: number
 23  }
 24  
 25  export function useNetData() {
 26    const [chainData, setChainData] = useState<ChainData>(() => ({
 27      latestBlock: 0,
 28      recentBlocks: [],
 29      lastUpdated: 0,
 30      isConnected: false,
 31      avgBlockTime: 0,
 32      totalTransactions: 0,
 33      totalPayloadSize: 0,
 34      successRate: 0
 35    }))
 36    const lastStatsUpdateBlock = useRef(0)
 37    const currentDataNetwork = useRef<NetworkType>('mainnet') // Track which network this data belongs to
 38  
 39    const fetchNetworkStats = async (forNetwork?: NetworkType) => {
 40      try {
 41        const [totalTxns, totalPayload, successRate] = await Promise.all([
 42          getTotalTransactions(),
 43          getTotalPayloadSize(), 
 44          getSuccessRate()
 45        ])
 46        
 47        setChainData(prev => ({
 48          ...prev,
 49          totalTransactions: totalTxns,
 50          totalPayloadSize: totalPayload,
 51          successRate: successRate
 52        }))
 53        
 54        // Track which network this data belongs to
 55        if (forNetwork) {
 56          currentDataNetwork.current = forNetwork;
 57        }
 58      } catch (error) {
 59        // Keep previous values on error
 60      }
 61    }
 62  
 63    useEffect(() => {
 64      const stream = getBlockStream()
 65      
 66      // Listen for network changes
 67      const handleNetworkChange = (event: Event) => {
 68        const customEvent = event as CustomEvent;
 69        const newNetwork = customEvent.detail.network;
 70        console.log('Network changed, reconnecting WebSocket...');
 71        console.log('Refetching stats for network:', newNetwork);
 72        
 73        // Reset to default state while fetching
 74        setChainData({
 75          latestBlock: 0,
 76          recentBlocks: [],
 77          lastUpdated: 0,
 78          isConnected: false,
 79          avgBlockTime: 0,
 80          totalTransactions: 0,
 81          totalPayloadSize: 0,
 82          successRate: 0
 83        });
 84        
 85        // Update which network this data represents
 86        currentDataNetwork.current = newNetwork;
 87        
 88        stream.switchNetwork(newNetwork);
 89        // Immediately refetch stats for the new network
 90        fetchNetworkStats(newNetwork);
 91      };
 92      
 93      if (typeof window !== 'undefined') {
 94        window.addEventListener('network-changed', handleNetworkChange);
 95      }
 96      
 97      const handleBlock = (block: StreamingBlock) => {
 98        const blockData: Block = {
 99          height: block.height,
100          timestamp: block.timestamp,
101          transactions: block.transactions,
102          hash: block.hash
103        }
104        
105        setChainData(prev => ({
106          ...prev,
107          latestBlock: block.height,
108          recentBlocks: [blockData, ...prev.recentBlocks].slice(0, 13),
109          lastUpdated: Date.now(),
110          isConnected: true
111        }))
112  
113        if (block.height - lastStatsUpdateBlock.current >= 5) {
114          lastStatsUpdateBlock.current = block.height
115          fetchNetworkStats(currentDataNetwork.current)
116        }
117      }
118      
119      const handleStats = (stats: StreamingStats) => {
120        setChainData(prev => ({
121          ...prev,
122          avgBlockTime: stats.avgBlockTime,
123          isConnected: true
124        }))
125      }
126      
127      const handleError = () => {
128        setChainData(prev => ({
129          ...prev,
130          isConnected: false
131        }))
132      }
133      
134      stream.onBlock(handleBlock)
135      stream.onStats(handleStats)
136      stream.onError(handleError)
137      
138      const initializeStream = async () => {
139        // Connect to default network (mainnet) initially
140        await stream.connect('mainnet')
141      }
142      
143      initializeStream()
144      
145      return () => {
146        stream.disconnect()
147        if (typeof window !== 'undefined') {
148          window.removeEventListener('network-changed', handleNetworkChange);
149        }
150      }
151    }, [])
152  
153    useEffect(() => {
154      // Initial fetch for default network (mainnet)
155      fetchNetworkStats('mainnet')
156    }, [])
157  
158    return chainData
159  }
160  
161  export function useDualNetworkData() {
162    const { currentNetwork } = useNetwork()
163    const chainData = useNetData()
164    
165    // Always return chainData for the current network
166    // The data is already correct because services are updated before fetching
167    return { 
168      mainnet: currentNetwork === 'mainnet' ? chainData : {
169        latestBlock: 0,
170        recentBlocks: [],
171        lastUpdated: 0,
172        isConnected: false,
173        avgBlockTime: 0,
174        totalTransactions: 0,
175        totalPayloadSize: 0,
176        successRate: 0
177      },
178      testnet: currentNetwork === 'testnet' ? chainData : {
179        latestBlock: 0,
180        recentBlocks: [],
181        lastUpdated: 0,
182        isConnected: false,
183        avgBlockTime: 0,
184        totalTransactions: 0,
185        totalPayloadSize: 0,
186        successRate: 0
187      }
188    }
189  }
190  
191  export function useNetworkData() {
192    return useNetData()
193  }