@@ -18,29 +18,44 @@ import { PROOF_SIZE_MB, MB_TO_GAS, GAS_TO_MGAS } from './constants';
1818
1919const ALPHA = 0.3 ;
2020const TARGET_WINDOW_SIZE = 30000 ; // 30s
21- const MAX_BLOCKS_STORE = 2000 ;
21+ const MAX_BLOCKS_STORE = 1000 ;
22+
23+ type RelayType = 'Polkadot' | 'Kusama' ;
24+
25+ interface BlockRecord {
26+ chainKey : string ;
27+ blockNumber : number ;
28+ timestamp : number ;
29+ extrinsics : number ;
30+ proofSize : number ;
31+ }
2232
23- // standard ema
2433function calculateEma ( oldValue : number , newValue : number ) {
2534 return ALPHA * newValue + ( 1 - ALPHA ) * oldValue ;
2635}
2736
28- // compute rolling tps, mbs, gas from blocks in the last 30s
29- function calculateRollingMetrics (
30- blocks : Array < { blockNumber : number ; timestamp : number ; extrinsics : number ; proofSize : number } >
31- ) {
32- if ( blocks . length < 2 ) return { tps : 0 , mbs : 0 , gas : 0 } ;
37+ // compute rolling tps, mbs, gas from last 30s
38+ function calculateRollingMetrics ( blocks : BlockRecord [ ] ) {
39+ if ( blocks . length < 2 ) {
40+ // console.log('debug: not enough blocks to calc rolling metrics -> returning 0');
41+ return { tps : 0 , mbs : 0 , gas : 0 } ;
42+ }
3343
3444 const now = Date . now ( ) ;
3545 const cutoff = now - TARGET_WINDOW_SIZE ;
3646 const relevant = blocks . filter ( b => b . timestamp >= cutoff ) ;
37- if ( relevant . length === 0 ) return { tps : 0 , mbs : 0 , gas : 0 } ;
47+ if ( relevant . length === 0 ) {
48+ // console.log('debug: no blocks in last 30s -> returning 0');
49+ return { tps : 0 , mbs : 0 , gas : 0 } ;
50+ }
3851
3952 relevant . sort ( ( a , b ) => a . timestamp - b . timestamp ) ;
4053 const timeWindow = relevant [ relevant . length - 1 ] . timestamp - relevant [ 0 ] . timestamp ;
41- if ( timeWindow <= 0 ) return { tps : 0 , mbs : 0 , gas : 0 } ;
54+ if ( timeWindow <= 0 ) {
55+ // console.log('debug: timeWindow <= 0, weird data -> returning 0');
56+ return { tps : 0 , mbs : 0 , gas : 0 } ;
57+ }
4258
43- // adjust extrinsics with -2 offset if desired
4459 const sumExtrinsics = relevant . reduce ( ( acc , b ) => acc + Math . max ( 0 , b . extrinsics - 2 ) , 0 ) ;
4560 const sumProofSize = relevant . reduce ( ( acc , b ) => acc + b . proofSize , 0 ) ;
4661
@@ -51,70 +66,67 @@ function calculateRollingMetrics(
5166 return { tps, mbs, gas } ;
5267}
5368
54- interface BlockRecord {
55- chainKey : string ;
56- blockNumber : number ;
57- timestamp : number ;
58- extrinsics : number ;
59- proofSize : number ;
60- }
61-
6269const App : React . FC = ( ) => {
63- const [ selectedRelay , setSelectedRelay ] = useState < 'Polkadot' | 'Kusama' > ( 'Polkadot' ) ;
70+ // user picks polkadot or kusama
71+ const [ selectedRelay , setSelectedRelay ] = useState < RelayType > ( 'Polkadot' ) ;
6472
65- // data feed
6673 const consumptionData = useWeightConsumption ( 'https://stream.freeside.network/events' ) ;
6774
68- // figure out which chains we're interested in
75+ // separate chain arrays for polkadot vs. kusama
76+ // do the same for blockNumber dedupe
77+ const blocksByRelayRef = useRef < { Polkadot : BlockRecord [ ] ; Kusama : BlockRecord [ ] } > ( {
78+ Polkadot : [ ] ,
79+ Kusama : [ ] ,
80+ } ) ;
81+
82+ const lastBlockNumberByRelayRef = useRef < {
83+ Polkadot : Record < string , number > ;
84+ Kusama : Record < string , number > ;
85+ } > ( {
86+ Polkadot : { } ,
87+ Kusama : { } ,
88+ } ) ;
89+
90+ // rolling totals for whichever relay is selected
91+ //const [rollingTps, setRollingTps] = useState(0);
92+ const [ rollingTpsEma , setRollingTpsEma ] = useState ( 0 ) ;
93+ //const [rollingMbs, setRollingMbs] = useState(0);
94+ const [ rollingMbsEma , setRollingMbsEma ] = useState ( 0 ) ;
95+ //const [rollingGas, setRollingGas] = useState(0);
96+ const [ rollingGasEma , setRollingGasEma ] = useState ( 0 ) ;
97+
98+ // figure out chain lists
6999 const chainNames = selectedRelay === 'Polkadot' ? polkadotChainNames : kusamaChainNames ;
70100 const paraIdToChainName =
71101 selectedRelay === 'Polkadot' ? polkadotParaIdToChainName : kusamaParaIdToChainName ;
72102
73- // gather the "weightData" for all chains (just the mandatory + total_proof_size, for example)
103+ // gather "weightData" for chain table
74104 const weightData : Record < PolkadotChainName | KusamaChainName , number > = chainNames . reduce (
75105 ( acc , chain ) => {
76- const paraId = Object . keys ( paraIdToChainName ) . find (
77- ( key ) => paraIdToChainName [ Number ( key ) ] === chain
78- ) ;
106+ const paraId = Object . keys ( paraIdToChainName ) . find ( k => paraIdToChainName [ Number ( k ) ] === chain ) ;
79107 if ( paraId ) {
80108 const key = `${ selectedRelay } -${ paraId } ` ;
81109 const chainData = consumptionData [ key ] ?. current ;
82110 if ( chainData ) {
83- // example: combine mandatory + total_proof_size
84111 const mandatorySize = chainData . ref_time ?. mandatory ?? 0 ;
85112 const totalSize = chainData . total_proof_size ?? 0 ;
86- const combinedProof = mandatorySize + totalSize ;
87- return { ... acc , [ chain ] : combinedProof } ;
113+ const totalProof = mandatorySize + totalSize ;
114+ acc [ chain ] = totalProof ;
88115 }
89116 }
90117 return acc ;
91118 } ,
92119 { } as Record < PolkadotChainName | KusamaChainName , number >
93120 ) ;
94121
95- // store rolling metrics
96- //const [rollingTps, setRollingTps] = useState(0);
97- const [ rollingTpsEma , setRollingTpsEma ] = useState ( 0 ) ;
98-
99- //const [rollingMbs, setRollingMbs] = useState(0);
100- const [ rollingMbsEma , setRollingMbsEma ] = useState ( 0 ) ;
101-
102- //const [rollingGas, setRollingGas] = useState(0);
103- const [ rollingGasEma , setRollingGasEma ] = useState ( 0 ) ;
104-
105- // dedup blocks
106- const blocksRef = useRef < BlockRecord [ ] > ( [ ] ) ;
107- const lastBlockNumberByChain = useRef < Record < string , number > > ( { } ) ;
108-
109- // we also want the immediate (non-ema) relay data
122+ // immediate (non-ema) relay stats for whichever relay is selected
110123 let weightRelay = 0 ;
111124 let tpsRelay = 0 ;
112125 let gasRelay = 0 ;
113126
114- // figure out the relay chain's data
115127 const relayChainName = selectedRelay === 'Polkadot' ? 'Polkadot' : 'Kusama' ;
116128 const relayParaId = Object . keys ( paraIdToChainName ) . find (
117- ( k ) => paraIdToChainName [ Number ( k ) ] === relayChainName
129+ k => paraIdToChainName [ Number ( k ) ] === relayChainName
118130 ) ;
119131 if ( relayParaId ) {
120132 const relayKey = `${ selectedRelay } -${ relayParaId } ` ;
@@ -125,67 +137,96 @@ const App: React.FC = () => {
125137 const totalSize = relayData . total_proof_size ?? 0 ;
126138 weightRelay = mandatorySize + totalSize ;
127139 tpsRelay = ( relayData . extrinsics_num ?? 0 ) / blockTime ;
128-
129140 const chainMbs = ( weightRelay * PROOF_SIZE_MB ) / blockTime ;
130141 gasRelay = chainMbs * ( MB_TO_GAS / PROOF_SIZE_MB / GAS_TO_MGAS ) ;
131142 }
132143 }
133144
134145 useEffect ( ( ) => {
135- const newBlocks : BlockRecord [ ] = [ ] ;
146+ // console.log('debug: consumptionData or selectedRelay changed -> updating polkadot + kusama blocks') ;
136147
137- chainNames . forEach ( ( chain ) => {
138- const paraId = Object . keys ( paraIdToChainName ) . find (
139- ( key ) => paraIdToChainName [ Number ( key ) ] === chain
148+ // step 1: process polkadot chain data
149+ polkadotChainNames . forEach ( chain => {
150+ const paraId = Object . keys ( polkadotParaIdToChainName ) . find (
151+ k => polkadotParaIdToChainName [ Number ( k ) ] === chain
140152 ) ;
141153 if ( ! paraId ) return ;
142- const key = `${ selectedRelay } -${ paraId } ` ;
154+ const key = `Polkadot -${ paraId } ` ;
143155 const chainData = consumptionData [ key ] ?. current ;
144156 if ( ! chainData ) return ;
145157
146158 const blockNum = chainData . block_number ;
147159 const ts = chainData . timestamp ;
148- // only add if we haven't seen this block_number before for this chain
149- if (
150- typeof blockNum === 'number' &&
151- ts &&
152- ( lastBlockNumberByChain . current [ key ] === undefined ||
153- blockNum > lastBlockNumberByChain . current [ key ] )
154- ) {
155- lastBlockNumberByChain . current [ key ] = blockNum ;
156-
157- // combine mandatory + total_proof_size
160+ const lastSeen = lastBlockNumberByRelayRef . current [ 'Polkadot' ] [ key ] ;
161+
162+ if ( typeof blockNum === 'number' && ts && ( lastSeen === undefined || blockNum > lastSeen ) ) {
163+ lastBlockNumberByRelayRef . current [ 'Polkadot' ] [ key ] = blockNum ;
158164 const mandatorySize = chainData . ref_time ?. mandatory ?? 0 ;
159165 const totalSize = chainData . total_proof_size ?? 0 ;
160166 const totalProof = mandatorySize + totalSize ;
161167
162- newBlocks . push ( {
163- chainKey : key ,
164- blockNumber : blockNum ,
165- timestamp : ts ,
166- extrinsics : chainData . extrinsics_num ?? 0 ,
167- proofSize : totalProof ,
168- } ) ;
168+ blocksByRelayRef . current [ 'Polkadot' ] = [
169+ ...blocksByRelayRef . current [ 'Polkadot' ] ,
170+ {
171+ chainKey : key ,
172+ blockNumber : blockNum ,
173+ timestamp : ts ,
174+ extrinsics : chainData . extrinsics_num ?? 0 ,
175+ proofSize : totalProof ,
176+ } ,
177+ ] . slice ( - MAX_BLOCKS_STORE ) ;
178+
169179 }
170180 } ) ;
171181
172- // if we actually have new blocks, compute rolling metrics
173- if ( newBlocks . length > 0 ) {
174- // add them, prune old
175- blocksRef . current = [ ...blocksRef . current , ...newBlocks ] . slice ( - MAX_BLOCKS_STORE ) ;
182+ // step 2: process kusama chain data
183+ kusamaChainNames . forEach ( chain => {
184+ const paraId = Object . keys ( kusamaParaIdToChainName ) . find (
185+ k => kusamaParaIdToChainName [ Number ( k ) ] === chain
186+ ) ;
187+ if ( ! paraId ) return ;
188+ const key = `Kusama-${ paraId } ` ;
189+ const chainData = consumptionData [ key ] ?. current ;
190+ if ( ! chainData ) return ;
191+
192+ const blockNum = chainData . block_number ;
193+ const ts = chainData . timestamp ;
194+ const lastSeen = lastBlockNumberByRelayRef . current [ 'Kusama' ] [ key ] ;
195+
196+ if ( typeof blockNum === 'number' && ts && ( lastSeen === undefined || blockNum > lastSeen ) ) {
197+ lastBlockNumberByRelayRef . current [ 'Kusama' ] [ key ] = blockNum ;
198+ const mandatorySize = chainData . ref_time ?. mandatory ?? 0 ;
199+ const totalSize = chainData . total_proof_size ?? 0 ;
200+ const totalProof = mandatorySize + totalSize ;
201+
202+ blocksByRelayRef . current [ 'Kusama' ] = [
203+ ...blocksByRelayRef . current [ 'Kusama' ] ,
204+ {
205+ chainKey : key ,
206+ blockNumber : blockNum ,
207+ timestamp : ts ,
208+ extrinsics : chainData . extrinsics_num ?? 0 ,
209+ proofSize : totalProof ,
210+ } ,
211+ ] . slice ( - MAX_BLOCKS_STORE ) ;
176212
177- const { tps, mbs, gas } = calculateRollingMetrics ( blocksRef . current ) ;
213+ }
214+ } ) ;
178215
179- //setRollingTps(tps);
180- setRollingTpsEma ( ( prev ) => calculateEma ( prev || tps , tps ) ) ;
216+ // step 3: compute rolling metrics for whichever relay is selected
217+ const blocks = blocksByRelayRef . current [ selectedRelay ] || [ ] ;
218+ // console.log(`debug: computing rolling metrics for ${selectedRelay}, block array length = ${blocks.length}`);
181219
182- //setRollingMbs(mbs);
183- setRollingMbsEma ( ( prev ) => calculateEma ( prev || mbs , mbs ) ) ;
220+ const { tps, mbs, gas } = calculateRollingMetrics ( blocks ) ;
221+ // setRollingTps(tps);
222+ setRollingTpsEma ( prev => calculateEma ( prev || tps , tps ) ) ;
223+ // setRollingMbs(mbs);
224+ setRollingMbsEma ( prev => calculateEma ( prev || mbs , mbs ) ) ;
225+ // setRollingGas(gas);
226+ setRollingGasEma ( prev => calculateEma ( prev || gas , gas ) ) ;
184227
185- // setRollingGas(gas);
186- setRollingGasEma ( ( prev ) => calculateEma ( prev || gas , gas ) ) ;
187- }
188- } , [ consumptionData , chainNames , paraIdToChainName , selectedRelay ] ) ;
228+ // console.log('debug: set new rolling metrics ->', { tps, mbs, gas });
229+ } , [ consumptionData , selectedRelay ] ) ;
189230
190231 return (
191232 < div className = "app-container" >
@@ -200,15 +241,9 @@ const App: React.FC = () => {
200241 < RelaySelector selectedRelay = { selectedRelay } onRelayChange = { setSelectedRelay } />
201242
202243 < MetricsTotal
203- // the rolling 30s metrics
204- // rollingTps={rollingTps.toFixed(2)}
205244 totalTps = { rollingTpsEma . toFixed ( 2 ) }
206- // rollingMbs={rollingMbs.toFixed(2)}
207245 totalMbs = { rollingMbsEma . toFixed ( 2 ) }
208- // rollingGas={rollingGas.toFixed(2)}
209246 totalGas = { rollingGasEma . toFixed ( 2 ) }
210-
211- // immediate relay chain-only stats (non-ema)
212247 tpsRelay = { tpsRelay }
213248 weightRelay = { weightRelay }
214249 gasRelay = { gasRelay }
@@ -220,7 +255,6 @@ const App: React.FC = () => {
220255 chains = { chainNames }
221256 selectedRelay = { selectedRelay }
222257 paraIdToChainName = { paraIdToChainName }
223- // pass in weightData for chain usage
224258 weightData = { weightData }
225259 />
226260 </ div >
0 commit comments