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 } }