@@ -53,6 +53,23 @@ async function getRPCLatestBlock(url) {
53
53
}
54
54
}
55
55
56
+ async function getBlockIngestorLatestBlock ( url ) {
57
+ const res = await fetch ( url , {
58
+ method : 'POST' ,
59
+ headers : {
60
+ 'Content-Type' : 'application/json' ,
61
+ } ,
62
+ body : JSON . stringify ( {
63
+ "query" : "query test {\n getIngestorStats(id: \"STATS\") {\n value\n }\n}\n" ,
64
+ "variables" : { } ,
65
+ "operationName" : "test"
66
+ } )
67
+ } ) ;
68
+ const output = await res . json ( )
69
+ const stats = JSON . parse ( output . data . getIngestorStats . value ) ;
70
+ return parseInt ( stats . lastBlockNumber , 10 ) ;
71
+ }
72
+
56
73
async function getBlockscoutLatestBlock ( ) {
57
74
try {
58
75
const blockScoutBlock = await fetch ( "https://blockscout.com/xdai/mainnet/api?module=block&action=eth_block_number" )
@@ -74,7 +91,7 @@ async function getBalance(account, url) {
74
91
body : JSON . stringify ( {
75
92
"jsonrpc" :"2.0" ,
76
93
"method" :"eth_getBalance" ,
77
- "params" :[ account ] ,
94
+ "params" :[ account , "latest" ] ,
78
95
"id" :1
79
96
} )
80
97
} )
@@ -112,8 +129,8 @@ module.exports = robot => {
112
129
return "🔴" ;
113
130
}
114
131
115
- async function getMessage ( ) {
116
- let message = ""
132
+ async function getMessageGnosis ( ) {
133
+ let message = "**On Gnosis:**\n "
117
134
// Get latest block from graph
118
135
const graphNumberRes = getGraphLatestBlock ( "https://xdai.colony.io/graph/subgraphs/name/joinColony/subgraph" )
119
136
@@ -250,6 +267,77 @@ module.exports = robot => {
250
267
return message
251
268
}
252
269
270
+ async function getArbitrumMessage ( ) {
271
+
272
+ const ARBITRUM_MINER_ADDRESS = "0xd090822a84e037Acc8a169C54a5943FF9fB82236"
273
+ const ARBITRUM_BROADCASTER_ADDRESS = "0xf4ab92A14c7CBc232E8293C59DfFbd98Fbdf9b3E"
274
+ const ARBITRUM_NETWORK_ADDRESS = "0xcccccdcc0ccf6c708d860e19353c5f9a49accccc"
275
+ const ARBITRUM_GRAPH_URL = "https://arbitrum.colony.io/auth-proxy/graphql"
276
+ const ourRPC = process . env . ARBITRUM_RPC
277
+ const publicRPC = process . env . ARBITRUM_PUBLIC_RPC
278
+
279
+
280
+ // Get latest block from our RPC
281
+ const ourRpcPromise = getRPCLatestBlock ( ourRPC ) ;
282
+
283
+ // Get latest block from another RPC
284
+ const publicRPCPromise = getRPCLatestBlock ( publicRPC ) ;
285
+
286
+ // Get latest block from block ingestor
287
+ const blockIngestorNumberPromise = getBlockIngestorLatestBlock ( ARBITRUM_GRAPH_URL ) ;
288
+
289
+ // Get balance of miner
290
+ const balancePromise = await getBalance ( ARBITRUM_MINER_ADDRESS , ourRPC )
291
+
292
+ // Get balance of MTX Broadcaster
293
+ const mtxBalancePromise = await getBalance ( ARBITRUM_BROADCASTER_ADDRESS , ourRPC )
294
+
295
+ const [ ourRpcBlock , publicRpcBlock , ingestorNumber , minerBalance , mtxBalance ] = await Promise . all ( [ ourRpcPromise , publicRPCPromise , blockIngestorNumberPromise , balancePromise , mtxBalancePromise ] )
296
+
297
+ // Get time since last mining cycle completed
298
+ // Get reputation mining cycle status
299
+ let secondsSinceOpen = - 1 ;
300
+ let nSubmitted = - 1 ;
301
+ try {
302
+ let provider ;
303
+ // Use our RPC if okay
304
+ if ( ourRpcBlock > 0 ) {
305
+ provider = new ethers . providers . JsonRpcProvider ( ourRPC )
306
+ } else {
307
+ provider = new ethers . providers . JsonRpcProvider ( publicRPC ) ;
308
+ }
309
+
310
+ const cn = new ethers . Contract ( ARBITRUM_NETWORK_ADDRESS , networkABI , provider )
311
+ const miningAddress = await cn . getReputationMiningCycle ( true ) ;
312
+
313
+ const rm = new ethers . Contract ( miningAddress , miningABI , provider ) ;
314
+ const openTimestamp = await rm . getReputationMiningWindowOpenTimestamp ( ) ;
315
+ secondsSinceOpen = Math . floor ( Date . now ( ) / 1000 ) - openTimestamp ;
316
+
317
+ nSubmitted = await rm . getNUniqueSubmittedHashes ( ) ;
318
+ } catch ( err ) {
319
+ // Use default values for anything not set
320
+ }
321
+
322
+ let message = "**On Arbitrum:**\n"
323
+ message += `Public RPC latest block: ${ publicRpcBlock } \n`
324
+ const rpcDiscrepancy = Math . abs ( ourRpcBlock - publicRpcBlock )
325
+ message += `${ status ( rpcDiscrepancy , 60 , 120 ) } Our RPC latest block: ${ ourRpcBlock } \n`
326
+ message += `${ status ( ingestorNumber - ourRpcBlock , 25 * GRAPH_LAG_INCIDENT / 2 , 25 * GRAPH_LAG_INCIDENT ) } Our ingestor latest block: ${ ingestorNumber } \n`
327
+ message += `${ status ( - minerBalance , - 0.05 , - 0.01 ) } Miner balance (\`${ ARBITRUM_MINER_ADDRESS . slice ( 0 , 6 ) } ...${ ARBITRUM_MINER_ADDRESS . slice ( - 4 ) } \`): ${ minerBalance } \n`
328
+ message += `${ status ( - mtxBalance , - 0.1 , - 0.01 ) } Metatx broadcaster balance (\`${ ARBITRUM_BROADCASTER_ADDRESS . slice ( 0 , 6 ) } ...${ ARBITRUM_BROADCASTER_ADDRESS . slice ( - 4 ) } \`): ${ mtxBalance } \n`
329
+ message += `${ status ( secondsSinceOpen , 3600 , 4500 ) } Time since last mining cycle completed: ${ ( secondsSinceOpen / 60 ) . toFixed ( 0 ) } minutes\n`
330
+ message += `${ status ( nSubmitted , 2 , 10000 ) } ${ nSubmitted } unique submissions so far this cycle\n`
331
+ return message ;
332
+ }
333
+
334
+ async function getMessage ( ) {
335
+ const gnosisMessage = await getMessageGnosis ( ) ;
336
+ const arbitrumMessage = await getArbitrumMessage ( ) ;
337
+ return arbitrumMessage + "\n" + gnosisMessage ;
338
+ }
339
+
340
+
253
341
robot . hear ( / ^ ! s t a t u s $ / , async ( ) => {
254
342
const message = await getMessage ( ) ;
255
343
channel . send ( message )
@@ -276,6 +364,17 @@ module.exports = robot => {
276
364
}
277
365
}
278
366
367
+ async function checkStatusArbitrum ( ) {
368
+ const message = await getArbitrumMessage ( ) ;
369
+ if ( message . indexOf ( "🔴 Our graph latest block" ) != - 1 && ! ongoingGraphIncident ) {
370
+ ongoingGraphIncident = true ;
371
+ channel . send ( "There appears to be an incident with the graph. \n" + message )
372
+ } else if ( message . indexOf ( "🔴" ) != - 1 && ! ongoingGenericIncident && ! ongoingGraphIncident ) {
373
+ ongoingGenericIncident = true ;
374
+ channel . send ( "There appears to be a generic incident. \n" + message )
375
+ }
376
+ }
377
+
279
378
const setupCronJob = ( ) => {
280
379
const job = new CronJob ( {
281
380
// Every minute
@@ -288,6 +387,20 @@ module.exports = robot => {
288
387
timeZone : 'Pacific/Niue'
289
388
} )
290
389
job . start ( )
390
+
391
+
392
+ const arbitrumJob = new CronJob ( {
393
+ // Every minute
394
+ cronTime : '00 * * * * *' ,
395
+ onTick : ( ) => {
396
+ checkStatusArbitrum ( )
397
+ } ,
398
+ start : true ,
399
+ // Last time zone of the day (UTC-11)
400
+ timeZone : 'Pacific/Niue'
401
+ } )
402
+ arbitrumJob . start ( )
403
+
291
404
}
292
405
setupCronJob ( )
293
406
}
0 commit comments