1
1
import { useQuery } from "@tanstack/react-query" ;
2
-
3
2
import { useGraphqlBatcher } from "context/GraphqlBatcher" ;
4
3
import { isUndefined } from "utils/index" ;
5
-
6
4
import { graphql } from "src/graphql" ;
7
5
import { HomePageBlockQuery } from "src/graphql/graphql" ;
8
- import useGenesisBlock from "../useGenesisBlock" ;
9
- export type { HomePageBlockQuery } ;
10
6
11
7
const homePageBlockQuery = graphql ( `
12
- query HomePageBlock($blockNumber: Int ) {
13
- presentCourts: courts(orderBy: id, orderDirection: asc) {
8
+ query HomePageBlock($pastTimestamp: BigInt ) {
9
+ presentCourts: courts(orderBy: id, orderDirection: asc, first: 1000 ) {
14
10
id
15
11
parent {
16
12
id
@@ -21,21 +17,25 @@ const homePageBlockQuery = graphql(`
21
17
feeForJuror
22
18
effectiveStake
23
19
}
24
- pastCourts: courts(orderBy: id, orderDirection: asc, block: { number: $blockNumber }) {
25
- id
26
- parent {
20
+ pastCourts: courtCounters(
21
+ where: { timestamp_lte: $pastTimestamp }
22
+ orderBy: timestamp
23
+ orderDirection: desc
24
+ first: 1000
25
+ ) {
26
+ court {
27
27
id
28
28
}
29
- name
30
29
numberDisputes
31
30
numberVotes
32
- feeForJuror
33
31
effectiveStake
32
+ timestamp
34
33
}
35
34
}
36
35
` ) ;
37
36
38
37
type Court = HomePageBlockQuery [ "presentCourts" ] [ number ] ;
38
+ type CourtCounter = HomePageBlockQuery [ "pastCourts" ] [ number ] ;
39
39
type CourtWithTree = Court & {
40
40
numberDisputes : number ;
41
41
numberVotes : number ;
@@ -58,66 +58,62 @@ export type HomePageBlockStats = {
58
58
courts : CourtWithTree [ ] ;
59
59
} ;
60
60
61
- export const useHomePageBlockQuery = ( blockNumber : number | undefined , allTime : boolean ) => {
62
- const genesisBlock = useGenesisBlock ( ) ;
63
- const isEnabled = ! isUndefined ( blockNumber ) || allTime || ! isUndefined ( genesisBlock ) ;
64
- const { graphqlBatcher } = useGraphqlBatcher ( ) ;
65
-
66
- return useQuery < HomePageBlockStats > ( {
67
- queryKey : [ `homePageBlockQuery${ blockNumber } -${ allTime } ` ] ,
68
- enabled : isEnabled ,
69
- staleTime : Infinity ,
70
- queryFn : async ( ) => {
71
- const targetBlock = Math . max ( blockNumber ! , genesisBlock ! ) ;
72
- const data = await graphqlBatcher . fetch ( {
73
- id : crypto . randomUUID ( ) ,
74
- document : homePageBlockQuery ,
75
- variables : { blockNumber : targetBlock } ,
76
- } ) ;
77
-
78
- return processData ( data , allTime ) ;
79
- } ,
80
- } ) ;
81
- } ;
61
+ const getCourtMostDisputes = ( courts : CourtWithTree [ ] ) =>
62
+ courts . toSorted ( ( a , b ) => b . numberDisputes - a . numberDisputes ) [ 0 ] ;
63
+ const getCourtBestDrawingChances = ( courts : CourtWithTree [ ] ) =>
64
+ courts . toSorted ( ( a , b ) => b . treeVotesPerPnk - a . treeVotesPerPnk ) [ 0 ] ;
65
+ const getBestExpectedRewardCourt = ( courts : CourtWithTree [ ] ) =>
66
+ courts . toSorted ( ( a , b ) => b . treeExpectedRewardPerPnk - a . treeExpectedRewardPerPnk ) [ 0 ] ;
82
67
83
68
const processData = ( data : HomePageBlockQuery , allTime : boolean ) => {
84
- const presentCourts = data . presentCourts ;
69
+ const presentCourts = [ ... data . presentCourts ] . sort ( ( a , b ) => Number ( a . id ) - Number ( b . id ) ) ;
85
70
const pastCourts = data . pastCourts ;
86
- const processedCourts : CourtWithTree [ ] = Array ( presentCourts . length ) ;
87
- const processed = new Set ( ) ;
88
-
89
- const processCourt = ( id : number ) : CourtWithTree => {
90
- if ( processed . has ( id ) ) return processedCourts [ id ] ;
91
-
92
- processed . add ( id ) ;
93
- const court =
94
- ! allTime && id < data . pastCourts . length
95
- ? addTreeValuesWithDiff ( presentCourts [ id ] , pastCourts [ id ] )
96
- : addTreeValues ( presentCourts [ id ] ) ;
97
- const parentIndex = court . parent ? Number ( court . parent . id ) - 1 : 0 ;
98
-
99
- if ( id === parentIndex ) {
100
- processedCourts [ id ] = court ;
101
- return court ;
71
+
72
+ const presentCourtsMap = new Map ( presentCourts . map ( ( c ) => [ c . id , c ] ) ) ;
73
+ const pastCourtsMap = new Map < string , CourtCounter > ( ) ;
74
+ if ( ! allTime ) {
75
+ for ( const pastCourt of pastCourts ) {
76
+ const courtId = pastCourt . court . id ;
77
+ if ( ! pastCourtsMap . has ( courtId ) ) {
78
+ pastCourtsMap . set ( courtId , pastCourt ) ;
79
+ }
80
+ }
81
+ }
82
+
83
+ const processedCourtsMap = new Map < string , CourtWithTree > ( ) ;
84
+ const processCourt = ( courtId : string ) : CourtWithTree => {
85
+ if ( processedCourtsMap . has ( courtId ) ) return processedCourtsMap . get ( courtId ) ! ;
86
+
87
+ const court = presentCourtsMap . get ( courtId ) ! ;
88
+ const pastCourt = pastCourtsMap . get ( courtId ) ;
89
+
90
+ const courtWithTree = ! allTime && pastCourt ? addTreeValuesWithDiff ( court , pastCourt ) : addTreeValues ( court ) ;
91
+
92
+ const parentId = court . parent ?. id ;
93
+ if ( ! parentId || courtId === parentId ) {
94
+ processedCourtsMap . set ( courtId , courtWithTree ) ;
95
+ return courtWithTree ;
102
96
}
103
97
104
- processedCourts [ id ] = {
105
- ...court ,
106
- treeNumberDisputes : court . treeNumberDisputes + processCourt ( parentIndex ) . treeNumberDisputes ,
107
- treeNumberVotes : court . treeNumberVotes + processCourt ( parentIndex ) . treeNumberVotes ,
108
- treeVotesPerPnk : court . treeVotesPerPnk + processCourt ( parentIndex ) . treeVotesPerPnk ,
109
- treeDisputesPerPnk : court . treeDisputesPerPnk + processCourt ( parentIndex ) . treeDisputesPerPnk ,
110
- treeExpectedRewardPerPnk : court . treeExpectedRewardPerPnk + processCourt ( parentIndex ) . treeExpectedRewardPerPnk ,
98
+ const parentCourt = processCourt ( parentId ) ;
99
+ const fullTreeCourt : CourtWithTree = {
100
+ ...courtWithTree ,
101
+ treeNumberDisputes : courtWithTree . treeNumberDisputes + parentCourt . treeNumberDisputes ,
102
+ treeNumberVotes : courtWithTree . treeNumberVotes + parentCourt . treeNumberVotes ,
103
+ treeVotesPerPnk : courtWithTree . treeVotesPerPnk + parentCourt . treeVotesPerPnk ,
104
+ treeDisputesPerPnk : courtWithTree . treeDisputesPerPnk + parentCourt . treeDisputesPerPnk ,
105
+ treeExpectedRewardPerPnk : courtWithTree . treeExpectedRewardPerPnk + parentCourt . treeExpectedRewardPerPnk ,
111
106
} ;
112
107
113
- return processedCourts [ id ] ;
108
+ processedCourtsMap . set ( courtId , fullTreeCourt ) ;
109
+ return fullTreeCourt ;
114
110
} ;
115
111
116
112
for ( const court of presentCourts . toReversed ( ) ) {
117
- processCourt ( Number ( court . id ) - 1 ) ;
113
+ processCourt ( court . id ) ;
118
114
}
119
115
120
- processedCourts . reverse ( ) ;
116
+ const processedCourts = [ ... processedCourtsMap . values ( ) ] . sort ( ( a , b ) => Number ( a . id ) - Number ( b . id ) ) ;
121
117
122
118
return {
123
119
mostDisputedCourt : getCourtMostDisputes ( processedCourts ) ,
@@ -148,21 +144,41 @@ const addTreeValues = (court: Court): CourtWithTree => {
148
144
} ;
149
145
} ;
150
146
151
- const addTreeValuesWithDiff = ( presentCourt : Court , pastCourt : Court ) : CourtWithTree => {
147
+ const addTreeValuesWithDiff = ( presentCourt : Court , pastCourt : CourtCounter | undefined ) : CourtWithTree => {
152
148
const presentCourtWithTree = addTreeValues ( presentCourt ) ;
153
- const pastCourtWithTree = addTreeValues ( pastCourt ) ;
154
- const diffNumberVotes = presentCourtWithTree . numberVotes - pastCourtWithTree . numberVotes ;
155
- const diffNumberDisputes = presentCourtWithTree . numberDisputes - pastCourtWithTree . numberDisputes ;
156
- const avgEffectiveStake = ( presentCourtWithTree . effectiveStake + pastCourtWithTree . effectiveStake ) / 2n ;
149
+
150
+ if ( ! pastCourt ) {
151
+ console . warn ( `Missing snapshot for court ${ presentCourt . id } , falling back to live` ) ;
152
+ return presentCourtWithTree ;
153
+ }
154
+
155
+ const pastNumberVotes = Number ( pastCourt . numberVotes ) ;
156
+ const pastNumberDisputes = Number ( pastCourt . numberDisputes ) ;
157
+ const pastEffectiveStake = BigInt ( pastCourt . effectiveStake ) ;
158
+
159
+ const diffNumberVotes = presentCourtWithTree . numberVotes - pastNumberVotes ;
160
+ const diffNumberDisputes = presentCourtWithTree . numberDisputes - pastNumberDisputes ;
161
+
162
+ const hasLiveActivity = presentCourtWithTree . numberDisputes > 0 || presentCourtWithTree . numberVotes > 0 ;
163
+ const hasSnapshotActivity = diffNumberDisputes > 0 || diffNumberVotes > 0 ;
164
+
165
+ if ( ! hasSnapshotActivity && hasLiveActivity ) {
166
+ console . warn ( `Snapshot shows no delta for court ${ presentCourt . id } , using live` ) ;
167
+ return presentCourtWithTree ;
168
+ }
169
+
170
+ const avgEffectiveStake = ( presentCourtWithTree . effectiveStake + pastEffectiveStake ) / 2n ;
157
171
const votesPerPnk = diffNumberVotes / ( Number ( avgEffectiveStake ) / 1e18 ) || 0 ;
158
172
const disputesPerPnk = diffNumberDisputes / ( Number ( avgEffectiveStake ) / 1e18 ) || 0 ;
159
173
const expectedRewardPerPnk = votesPerPnk * ( Number ( presentCourt . feeForJuror ) / 1e18 ) ;
174
+
160
175
return {
161
176
...presentCourt ,
162
- numberDisputes : presentCourtWithTree . numberDisputes - pastCourtWithTree . numberDisputes ,
163
- treeNumberDisputes : presentCourtWithTree . treeNumberDisputes - pastCourtWithTree . treeNumberDisputes ,
177
+ numberDisputes : diffNumberDisputes ,
178
+ treeNumberDisputes : diffNumberDisputes ,
164
179
numberVotes : diffNumberVotes ,
165
- treeNumberVotes : presentCourtWithTree . treeNumberVotes - pastCourtWithTree . treeNumberVotes ,
180
+ treeNumberVotes : diffNumberVotes ,
181
+ feeForJuror : presentCourtWithTree . feeForJuror ,
166
182
effectiveStake : avgEffectiveStake ,
167
183
votesPerPnk,
168
184
treeVotesPerPnk : votesPerPnk ,
@@ -173,9 +189,21 @@ const addTreeValuesWithDiff = (presentCourt: Court, pastCourt: Court): CourtWith
173
189
} ;
174
190
} ;
175
191
176
- const getCourtMostDisputes = ( courts : CourtWithTree [ ] ) =>
177
- courts . toSorted ( ( a : CourtWithTree , b : CourtWithTree ) => b . numberDisputes - a . numberDisputes ) [ 0 ] ;
178
- const getCourtBestDrawingChances = ( courts : CourtWithTree [ ] ) =>
179
- courts . toSorted ( ( a , b ) => b . treeVotesPerPnk - a . treeVotesPerPnk ) [ 0 ] ;
180
- const getBestExpectedRewardCourt = ( courts : CourtWithTree [ ] ) =>
181
- courts . toSorted ( ( a , b ) => b . treeExpectedRewardPerPnk - a . treeExpectedRewardPerPnk ) [ 0 ] ;
192
+ export const useHomePageBlockQuery = ( pastTimestamp : bigint | undefined , allTime : boolean ) => {
193
+ const { graphqlBatcher } = useGraphqlBatcher ( ) ;
194
+ const isEnabled = ! isUndefined ( pastTimestamp ) || allTime ;
195
+
196
+ return useQuery < HomePageBlockStats > ( {
197
+ queryKey : [ `homePageBlockQuery${ pastTimestamp ?. toString ( ) } -${ allTime } ` ] ,
198
+ enabled : isEnabled ,
199
+ staleTime : Infinity ,
200
+ queryFn : async ( ) => {
201
+ const data = await graphqlBatcher . fetch ( {
202
+ id : crypto . randomUUID ( ) ,
203
+ document : homePageBlockQuery ,
204
+ variables : { pastTimestamp : allTime ? "0" : pastTimestamp ?. toString ( ) } ,
205
+ } ) ;
206
+ return processData ( data , allTime ) ;
207
+ } ,
208
+ } ) ;
209
+ } ;
0 commit comments