Skip to content

Commit

Permalink
improve block frequency updates so we capture more recent history on …
Browse files Browse the repository at this point in the history
…new reloads and also capture important aerodrome epoch blocks
  • Loading branch information
apexearth committed Sep 25, 2024
1 parent e060d60 commit ee6aa47
Showing 1 changed file with 28 additions and 32 deletions.
60 changes: 28 additions & 32 deletions src/utils/blockFrequencyUpdater.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
import utc from 'dayjs/plugin/utc'
import { base } from 'viem/chains'

import { Block, Context } from '@processor'

Expand All @@ -9,6 +10,7 @@ dayjs.extend(utc)

const SECONDS_PER_WEEK = dayjs.duration({ weeks: 1 }).asSeconds()
const SECONDS_PER_DAY = dayjs.duration({ days: 1 }).asSeconds()
const SECONDS_PER_HOUR = dayjs.duration({ hours: 1 }).asSeconds()
const SECONDS_PER_MINUTE = 60

// It's OK that these are only calculated at launch.
Expand All @@ -27,9 +29,9 @@ const getFrequency = (blockRate: number, timestamp: number) => {
} else if (timestamp < oneWeekAgo) {
return (SECONDS_PER_DAY / blockRate / 4) ^ 0 // Older than one week ago
} else if (timestamp < oneDayAgo) {
return (SECONDS_PER_DAY / blockRate / 12) ^ 0 // Older than one day ago
return ((SECONDS_PER_MINUTE * 30) / blockRate) ^ 0 // Older than one day ago
} else if (timestamp < oneHourAgo) {
return ((SECONDS_PER_MINUTE * 30) / blockRate) ^ 0 // Older than one hour ago
return ((SECONDS_PER_MINUTE * 15) / blockRate) ^ 0 // Older than one hour ago
} else if (timestamp < fifteenMinutesAgo) {
return ((SECONDS_PER_MINUTE * 5) / blockRate) ^ 0 // Older than 15 minutes ago
} else {
Expand All @@ -40,46 +42,40 @@ const getFrequency = (blockRate: number, timestamp: number) => {
export const blockFrequencyTracker = (params: { from: number }) => {
return (ctx: Context, block: Block) => {
if (block.header.height < params.from) return
const frequency: number = getFrequency(
ctx.blockRate,
block.header.timestamp,
)
return block.header.height % frequency === 0
const frequency = getFrequency(ctx.blockRate, block.header.timestamp)
return block.header.height % frequency === 0 || isAerodromeImportantBlock(ctx, block)
}
}

export const blockFrequencyUpdater = (params: { from: number }) => {
return async (
ctx: Context,
fn: (ctx: Context, block: Block) => Promise<void>,
) => {
const tracker = blockFrequencyTracker(params)
return async (ctx: Context, fn: (ctx: Context, block: Block) => Promise<void>) => {
if (!ctx.blocks.length) return
if (ctx.blocks[ctx.blocks.length - 1].header.height < params.from) {
// No applicable blocks in current context.
return
}
let frequency: number = getFrequency(
ctx.blockRate,
ctx.blocks[0].header.timestamp,
)
for (
let i = ctx.blocks.findIndex(
(b) =>
b.header.height % frequency === 0 && b.header.height >= params.from,
);
i < ctx.blocks.length;
i += frequency
) {
const block = ctx.blocks[i]
if (!block) break
if (block.header.height % frequency !== 0) {
throw new Error(
'This should never happen. Ensure you are passing all blocks through here.',
)
for (let i = 0; i < ctx.blocks.length; i++) {
if (tracker(ctx, ctx.blocks[i])) {
await fn(ctx, ctx.blocks[i])
}
await fn(ctx, block)
frequency = getFrequency(ctx.blockRate, block.header.timestamp)
i -= ctx.blocks[i].header.height % frequency
}
}
}

// This came around so we can have good historical snapshots of data during Aerodrome epoch flips.
export const isAerodromeImportantBlock = (ctx: Context, block: Block) => {
if (ctx.chain.id !== base.id) return false
if (block.header.height < 17819702) return false
const lastBlockWeek = Math.floor((block.header.timestamp / 1000 - ctx.blockRate) / SECONDS_PER_WEEK)
const blockWeek = Math.floor(block.header.timestamp / 1000 / SECONDS_PER_WEEK)
if (blockWeek !== lastBlockWeek) return true

const nextBlockWeek = Math.floor((block.header.timestamp / 1000 + ctx.blockRate) / SECONDS_PER_WEEK)
if (blockWeek !== nextBlockWeek) return true

const secondOfWeek = Math.floor(block.header.timestamp / 1000) % SECONDS_PER_WEEK
const lastBlockHourOfWeek = Math.floor((secondOfWeek - ctx.blockRate) / SECONDS_PER_HOUR)
const hourOfWeek = Math.floor(secondOfWeek / SECONDS_PER_HOUR)
return lastBlockHourOfWeek === 0 && hourOfWeek === 1
}

0 comments on commit ee6aa47

Please sign in to comment.