Fix events loading on very fast chains like Avalanche or Gnosis, where web3 provider method 'getBlockNumber' can return not accepted block

This commit is contained in:
Theo 2023-07-18 23:45:12 -07:00
parent 491bcec983
commit 1d60b4016e

@ -2,7 +2,7 @@ import Web3 from 'web3'
import graph from '@/services/graph' import graph from '@/services/graph'
import { download } from '@/store/snark' import { download } from '@/store/snark'
import networkConfig, { enabledChains } from '@/networkConfig' import networkConfig, { enabledChains, blockSyncInterval } from '@/networkConfig'
import InstanceABI from '@/abis/Instance.abi.json' import InstanceABI from '@/abis/Instance.abi.json'
import { CONTRACT_INSTANCES, eventsType, httpConfig } from '@/constants' import { CONTRACT_INSTANCES, eventsType, httpConfig } from '@/constants'
import { sleep, flattenNArray, formatEvents, capitalizeFirstLetter } from '@/utils' import { sleep, flattenNArray, formatEvents, capitalizeFirstLetter } from '@/utils'
@ -178,7 +178,7 @@ class EventService {
return events return events
} }
const blockRange = 4950 const blockRange = Math.floor(blockSyncInterval / 2) - 1
const fromBlock = deployedBlock const fromBlock = deployedBlock
const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock }) const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock })
@ -244,7 +244,7 @@ class EventService {
} }
} }
getPastEvents({ fromBlock, toBlock, type }, shouldRetry = false, i = 0) { getPastEvents({ fromBlock, toBlock, type }, shouldRetry = false, retries = 0) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.contract this.contract
.getPastEvents(capitalizeFirstLetter(type), { .getPastEvents(capitalizeFirstLetter(type), {
@ -253,13 +253,23 @@ class EventService {
}) })
.then((events) => resolve(events)) .then((events) => resolve(events))
.catch((err) => { .catch((err) => {
i = i + 1 retries++
// If provider.getBlockNumber returned last block that isn't accepted (happened on Avalanche/Gnosis),
// get events to last accepted block
if (err.message.includes('after last accepted block')) {
const acceptedBlock = parseInt(err.message.split('after last accepted block ')[1])
toBlock = acceptedBlock
// Retries to 0, because it is not RPC error
retries = 0
}
// maximum 5 second buffer for rate-limiting // maximum 5 second buffer for rate-limiting
if (shouldRetry) { if (shouldRetry) {
const isRetry = i !== 5 const shouldRetryAgain = retries < 5
sleep(1000 * i).then(() => sleep(1000 * retries).then(() =>
this.getPastEvents({ fromBlock, toBlock, type }, isRetry, i) this.getPastEvents({ fromBlock, toBlock, type }, shouldRetryAgain, retries)
.then((events) => resolve(events)) .then((events) => resolve(events))
.catch((_) => resolve(undefined)) .catch((_) => resolve(undefined))
) )
@ -324,19 +334,18 @@ class EventService {
async getBatchEventsFromRpc({ fromBlock, type }) { async getBatchEventsFromRpc({ fromBlock, type }) {
try { try {
const batchSize = 10 const batchSize = 10
const blockRange = 10000
let [events, failed] = [[], []] let [events, failed] = [[], []]
let lastBlock = fromBlock let lastBlock = fromBlock
const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock }) const { blockDifference, currentBlockNumber } = await this.getBlocksDiff({ fromBlock })
const batchDigest = blockDifference === 0 ? 1 : Math.ceil(blockDifference / blockRange) const batchDigest = blockDifference === 0 ? 1 : Math.ceil(blockDifference / blockSyncInterval)
const blockDenom = Math.ceil(blockDifference / batchDigest) const blockDenom = Math.ceil(blockDifference / batchDigest)
const batchCount = Math.ceil(batchDigest / batchSize) const batchCount = Math.ceil(batchDigest / batchSize)
if (fromBlock < currentBlockNumber) { if (fromBlock < currentBlockNumber) {
await this.updateEventProgress(0, type) this.updateEventProgress(0, type)
for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) { for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) {
const isLastBatch = batchIndex === batchCount - 1 const isLastBatch = batchIndex === batchCount - 1
@ -365,7 +374,7 @@ class EventService {
throw new Error('Failed to batch events') throw new Error('Failed to batch events')
} }
} }
await this.updateEventProgress(progressIndex / batchCount, type) this.updateEventProgress(progressIndex / batchCount, type)
} }
return { return {
@ -383,11 +392,10 @@ class EventService {
async getEventsFromRpc({ fromBlock, type }) { async getEventsFromRpc({ fromBlock, type }) {
try { try {
const { blockDifference } = await this.getBlocksDiff({ fromBlock }) const { blockDifference } = await this.getBlocksDiff({ fromBlock })
const blockRange = 10000
let events let events
if (blockDifference < blockRange) { if (blockDifference < blockSyncInterval) {
const rpcEvents = await this.getEventsPartFromRpc({ fromBlock, toBlock: 'latest', type }) const rpcEvents = await this.getEventsPartFromRpc({ fromBlock, toBlock: 'latest', type })
events = rpcEvents?.events || [] events = rpcEvents?.events || []
} else { } else {