site-activity-chain/src/service/block.sync.service.ts
2024-01-17 19:19:02 +08:00

81 lines
2.5 KiB
TypeScript

import { IChain } from 'chain/allchain'
import { retryEthBlockNumber } from 'chain/chain.api'
import { IScriptionCfg } from 'interface/IScriptionCfg'
import logger from 'logger/logger'
import { RedisClient } from 'redis/RedisClient'
import { getPastBlocksIter } from 'utils/block.util'
import { formatDate } from 'utils/date.util'
export class BlockSyncSvr {
chainCfg: IChain
scriptionCfgs: IScriptionCfg[] = []
fromBlock: number = Number.MAX_SAFE_INTEGER
batchCount: number = 0
redisKey = ''
rpc = ''
constructor(_chainCfg: IChain, _scriptionCfgs: IScriptionCfg[]) {
this.chainCfg = _chainCfg
this.scriptionCfgs = _scriptionCfgs
this.rpc = _chainCfg.rpc.split('|')[0]
for (let cfg of _scriptionCfgs) {
this.fromBlock = Math.min(this.fromBlock, cfg.fromBlock)
if (cfg.rpc) {
this.rpc = cfg.rpc
}
}
this.redisKey = `blocknum_${this.chainCfg.id}`
}
async execute() {
let currentBlock = await retryEthBlockNumber(this.rpc)
let blockStr = await new RedisClient().get(this.redisKey)
if (blockStr) {
this.fromBlock = Math.max(parseInt(blockStr), this.fromBlock)
}
this.batchCount = parseInt(currentBlock.result, 16) - this.fromBlock
if (this.batchCount <= 0) {
return
}
let blocks = getPastBlocksIter({
chainId: this.chainCfg.id,
rpc: this.rpc,
fromBlock: this.fromBlock,
amount: this.batchCount,
})
await this.processBlockDatas(blocks)
}
async processBlockDatas(iterator: any) {
let count = 0
for (const getPastBlockPromise of iterator) {
const blocks = await getPastBlockPromise
for (const block of blocks) {
// await BlockData.saveBlock(block)
count++
if (!block.transactions || block.transactions.length === 0) {
continue
}
for (let i = 0; i < block.transactions.length; i++) {
const tx = block.transactions[i]
if (block.timestamp) {
tx.blockTime = parseInt(block.timestamp, 16)
tx.dateTag = formatDate(new Date(tx.blockTime * 1000))
}
for (let j = 0; j < this.scriptionCfgs.length; j++) {
const cfg = this.scriptionCfgs[j]
if (cfg.filter && cfg.filter(tx)) {
try {
await cfg.process(tx)
} catch (err) {
logger.error('process tx error: ', err.message || err)
}
}
}
}
}
}
return count
}
}