import { ethers } from "ethers"; import { EvmLog, EvmTopicFilter } from "../../entities"; /** * Handling means mapping and forward to a given target. * As of today, only one type of event can be handled per each instance. */ export class HandleEvmLogs { cfg: HandleEvmLogsConfig; mapper: (log: EvmLog, parsedArgs: ReadonlyArray) => T; target: (parsed: T[]) => Promise; constructor( cfg: HandleEvmLogsConfig, mapper: (log: EvmLog, args: ReadonlyArray) => T, target: (parsed: T[]) => Promise ) { this.cfg = this.normalizeCfg(cfg); this.mapper = mapper; this.target = target; } public async handle(logs: EvmLog[]): Promise { const mappedItems = logs .filter( (log) => this.cfg.filter.addresses.includes(log.address.toLowerCase()) && this.cfg.filter.topics.includes(log.topics[0].toLowerCase()) ) .map((log) => { const iface = new ethers.utils.Interface([this.cfg.abi]); const parsedLog = iface.parseLog(log); return this.mapper(log, parsedLog.args); }); await this.target(mappedItems); // TODO: return a result specifying failures if any return mappedItems; } private normalizeCfg(cfg: HandleEvmLogsConfig): HandleEvmLogsConfig { return { filter: { addresses: cfg.filter.addresses.map((addr) => addr.toLowerCase()), topics: cfg.filter.topics.map((topic) => topic.toLowerCase()), }, abi: cfg.abi, }; } } export type HandleEvmLogsConfig = { filter: EvmTopicFilter; abi: string; };