UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

107 lines 4.54 kB
import { z } from 'zod'; import { rootLogger } from '@hyperlane-xyz/utils'; import { getContractDeploymentTransaction, getLogsFromEtherscanLikeExplorerAPI, } from '../../block-explorer/etherscan.js'; import { assertIsContractAddress } from '../../contracts/contracts.js'; import { ZBytes32String, ZHash, ZUint } from '../../metadata/customZodTypes.js'; import { getContractCreationBlockFromRpc, getLogsFromRpc } from './utils.js'; export const GetLogByTopicOptionsSchema = z.object({ eventTopic: ZBytes32String, contractAddress: ZHash, fromBlock: ZUint.optional(), toBlock: ZUint.optional(), }); export const RequiredGetLogByTopicOptionsSchema = GetLogByTopicOptionsSchema.required(); export class EvmEtherscanLikeEventLogsReader { chain; config; multiProvider; constructor(chain, config, multiProvider) { this.chain = chain; this.config = config; this.multiProvider = multiProvider; } async getContractDeploymentBlockNumber(address) { const contractDeploymentTx = await getContractDeploymentTransaction({ apiUrl: this.config.apiUrl, apiKey: this.config.apiKey }, { contractAddress: address }); const deploymentTransactionReceipt = await this.multiProvider .getProvider(this.chain) .getTransactionReceipt(contractDeploymentTx.txHash); return deploymentTransactionReceipt.blockNumber; } async getContractLogs(options) { const parsedOptions = RequiredGetLogByTopicOptionsSchema.parse(options); return getLogsFromEtherscanLikeExplorerAPI({ apiUrl: this.config.apiUrl, apiKey: this.config.apiKey, }, { address: parsedOptions.contractAddress, fromBlock: parsedOptions.fromBlock, toBlock: parsedOptions.toBlock, topic0: parsedOptions.eventTopic, }); } } export class EvmRpcEventLogsReader { chain; config; multiProvider; constructor(chain, config, multiProvider) { this.chain = chain; this.config = config; this.multiProvider = multiProvider; } getContractDeploymentBlockNumber(address) { return getContractCreationBlockFromRpc(this.chain, address, this.multiProvider); } getContractLogs(options) { const parsedOptions = RequiredGetLogByTopicOptionsSchema.parse(options); return getLogsFromRpc({ chain: this.chain, contractAddress: parsedOptions.contractAddress, topic: parsedOptions.eventTopic, fromBlock: parsedOptions.fromBlock, toBlock: parsedOptions.toBlock, multiProvider: this.multiProvider, range: this.config.paginationBlockRange, }); } } export class EvmEventLogsReader { config; multiProvider; logReaderStrategy; logger; constructor(config, multiProvider, logReaderStrategy, logger) { this.config = config; this.multiProvider = multiProvider; this.logReaderStrategy = logReaderStrategy; this.logger = logger; } static fromConfig(config, multiProvider, logger = rootLogger.child({ module: EvmEventLogsReader.name, })) { const explorer = multiProvider.tryGetEvmExplorerMetadata(config.chain); let logReaderStrategy; if (explorer && !config.useRPC) { logReaderStrategy = new EvmEtherscanLikeEventLogsReader(config.chain, explorer, multiProvider); } else { logReaderStrategy = new EvmRpcEventLogsReader(config.chain, { paginationBlockRange: config.paginationBlockRange }, multiProvider); } return new EvmEventLogsReader(config, multiProvider, logReaderStrategy, logger); } async getLogsByTopic(options) { const parsedOptions = GetLogByTopicOptionsSchema.parse(options); const provider = this.multiProvider.getProvider(this.config.chain); await assertIsContractAddress(this.multiProvider, this.config.chain, options.contractAddress); const fromBlock = parsedOptions.fromBlock ?? (await this.logReaderStrategy.getContractDeploymentBlockNumber(parsedOptions.contractAddress)); const toBlock = parsedOptions.toBlock ?? (await provider.getBlockNumber()); return this.logReaderStrategy.getContractLogs({ contractAddress: parsedOptions.contractAddress, eventTopic: parsedOptions.eventTopic, fromBlock, toBlock, }); } } //# sourceMappingURL=EvmEventLogsReader.js.map