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 }