1
1
import dayjs from 'dayjs'
2
2
import duration from 'dayjs/plugin/duration'
3
3
import utc from 'dayjs/plugin/utc'
4
+ import { base } from 'viem/chains'
4
5
5
6
import { Block , Context } from '@processor'
6
7
@@ -9,6 +10,7 @@ dayjs.extend(utc)
9
10
10
11
const SECONDS_PER_WEEK = dayjs . duration ( { weeks : 1 } ) . asSeconds ( )
11
12
const SECONDS_PER_DAY = dayjs . duration ( { days : 1 } ) . asSeconds ( )
13
+ const SECONDS_PER_HOUR = dayjs . duration ( { hours : 1 } ) . asSeconds ( )
12
14
const SECONDS_PER_MINUTE = 60
13
15
14
16
// It's OK that these are only calculated at launch.
@@ -27,9 +29,9 @@ const getFrequency = (blockRate: number, timestamp: number) => {
27
29
} else if ( timestamp < oneWeekAgo ) {
28
30
return ( SECONDS_PER_DAY / blockRate / 4 ) ^ 0 // Older than one week ago
29
31
} else if ( timestamp < oneDayAgo ) {
30
- return ( SECONDS_PER_DAY / blockRate / 12 ) ^ 0 // Older than one day ago
32
+ return ( ( SECONDS_PER_MINUTE * 30 ) / blockRate ) ^ 0 // Older than one day ago
31
33
} else if ( timestamp < oneHourAgo ) {
32
- return ( ( SECONDS_PER_MINUTE * 30 ) / blockRate ) ^ 0 // Older than one hour ago
34
+ return ( ( SECONDS_PER_MINUTE * 15 ) / blockRate ) ^ 0 // Older than one hour ago
33
35
} else if ( timestamp < fifteenMinutesAgo ) {
34
36
return ( ( SECONDS_PER_MINUTE * 5 ) / blockRate ) ^ 0 // Older than 15 minutes ago
35
37
} else {
@@ -40,46 +42,40 @@ const getFrequency = (blockRate: number, timestamp: number) => {
40
42
export const blockFrequencyTracker = ( params : { from : number } ) => {
41
43
return ( ctx : Context , block : Block ) => {
42
44
if ( block . header . height < params . from ) return
43
- const frequency : number = getFrequency (
44
- ctx . blockRate ,
45
- block . header . timestamp ,
46
- )
47
- return block . header . height % frequency === 0
45
+ const frequency = getFrequency ( ctx . blockRate , block . header . timestamp )
46
+ return block . header . height % frequency === 0 || isAerodromeImportantBlock ( ctx , block )
48
47
}
49
48
}
50
49
51
50
export const blockFrequencyUpdater = ( params : { from : number } ) => {
52
- return async (
53
- ctx : Context ,
54
- fn : ( ctx : Context , block : Block ) => Promise < void > ,
55
- ) => {
51
+ const tracker = blockFrequencyTracker ( params )
52
+ return async ( ctx : Context , fn : ( ctx : Context , block : Block ) => Promise < void > ) => {
56
53
if ( ! ctx . blocks . length ) return
57
54
if ( ctx . blocks [ ctx . blocks . length - 1 ] . header . height < params . from ) {
58
55
// No applicable blocks in current context.
59
56
return
60
57
}
61
- let frequency : number = getFrequency (
62
- ctx . blockRate ,
63
- ctx . blocks [ 0 ] . header . timestamp ,
64
- )
65
- for (
66
- let i = ctx . blocks . findIndex (
67
- ( b ) =>
68
- b . header . height % frequency === 0 && b . header . height >= params . from ,
69
- ) ;
70
- i < ctx . blocks . length ;
71
- i += frequency
72
- ) {
73
- const block = ctx . blocks [ i ]
74
- if ( ! block ) break
75
- if ( block . header . height % frequency !== 0 ) {
76
- throw new Error (
77
- 'This should never happen. Ensure you are passing all blocks through here.' ,
78
- )
58
+ for ( let i = 0 ; i < ctx . blocks . length ; i ++ ) {
59
+ if ( tracker ( ctx , ctx . blocks [ i ] ) ) {
60
+ await fn ( ctx , ctx . blocks [ i ] )
79
61
}
80
- await fn ( ctx , block )
81
- frequency = getFrequency ( ctx . blockRate , block . header . timestamp )
82
- i -= ctx . blocks [ i ] . header . height % frequency
83
62
}
84
63
}
85
64
}
65
+
66
+ // This came around so we can have good historical snapshots of data during Aerodrome epoch flips.
67
+ export const isAerodromeImportantBlock = ( ctx : Context , block : Block ) => {
68
+ if ( ctx . chain . id !== base . id ) return false
69
+ if ( block . header . height < 17819702 ) return false
70
+ const lastBlockWeek = Math . floor ( ( block . header . timestamp / 1000 - ctx . blockRate ) / SECONDS_PER_WEEK )
71
+ const blockWeek = Math . floor ( block . header . timestamp / 1000 / SECONDS_PER_WEEK )
72
+ if ( blockWeek !== lastBlockWeek ) return true
73
+
74
+ const nextBlockWeek = Math . floor ( ( block . header . timestamp / 1000 + ctx . blockRate ) / SECONDS_PER_WEEK )
75
+ if ( blockWeek !== nextBlockWeek ) return true
76
+
77
+ const secondOfWeek = Math . floor ( block . header . timestamp / 1000 ) % SECONDS_PER_WEEK
78
+ const lastBlockHourOfWeek = Math . floor ( ( secondOfWeek - ctx . blockRate ) / SECONDS_PER_HOUR )
79
+ const hourOfWeek = Math . floor ( secondOfWeek / SECONDS_PER_HOUR )
80
+ return lastBlockHourOfWeek === 0 && hourOfWeek === 1
81
+ }
0 commit comments