Fetch txs required for event logs in historical processing

This commit is contained in:
Nabarun 2023-11-09 16:12:22 +05:30
parent 72ad0596db
commit ad25c4e52d
10 changed files with 190 additions and 156 deletions

View File

@ -32,7 +32,8 @@ import {
Where,
Filter,
OPERATOR_MAP,
ExtraEventData
ExtraEventData,
EthFullTransaction
} from '@cerc-io/util';
import { Context, GraphData, instantiate } from './loader';
@ -155,9 +156,7 @@ export class GraphWatcher {
// Check if block data is already fetched by a previous event in the same block.
if (!this._context.block || this._context.block.blockHash !== block.hash) {
console.time(`time:graph-watcher#handleEvent-getFullBlock-block-${block.number}`);
this._context.block = getFullBlock(extraData.ethFullBlock);
console.timeEnd(`time:graph-watcher#handleEvent-getFullBlock-block-${block.number}`);
}
const blockData = this._context.block;
@ -200,7 +199,7 @@ export class GraphWatcher {
const eventFragment = contractInterface.getEvent(eventSignature);
const tx = await this._getTransactionData(txHash, Number(blockData.blockNumber));
const tx = this._getTransactionData(txHash, extraData.ethFullTransactions);
const data = {
block: blockData,
@ -453,17 +452,14 @@ export class GraphWatcher {
}
}
async _getTransactionData (txHash: string, blockNumber: number): Promise<Transaction> {
_getTransactionData (txHash: string, ethFullTransactions: EthFullTransaction[]): Transaction {
let transaction = this._transactionsMap.get(txHash);
if (transaction) {
return transaction;
}
console.time(`time:graph-watcher#_getTransactionData-getFullTransaction-block-${blockNumber}-tx-${txHash}`);
transaction = await getFullTransaction(this._ethClient, txHash, blockNumber);
console.timeEnd(`time:graph-watcher#_getTransactionData-getFullTransaction-block-${blockNumber}-tx-${txHash}`);
assert(transaction);
transaction = getFullTransaction(txHash, ethFullTransactions);
this._transactionsMap.set(txHash, transaction);
return transaction;

View File

@ -5,7 +5,7 @@
import assert from 'assert';
import { Cache } from '@cerc-io/cache';
import { EthClient as EthClientInterface, FullTransaction } from '@cerc-io/util';
import { EthClient as EthClientInterface, EthFullTransaction } from '@cerc-io/util';
import ethQueries from './eth-queries';
import { padKey } from './utils';
@ -93,7 +93,7 @@ export class EthClient implements EthClientInterface {
async getFullBlocks ({ blockNumber, blockHash }: { blockNumber?: number, blockHash?: string }): Promise<any> {
console.time(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`);
const result = await this._graphqlClient.query(
const { allEthHeaderCids } = await this._graphqlClient.query(
ethQueries.getFullBlocks,
{
blockNumber: blockNumber?.toString(),
@ -102,10 +102,10 @@ export class EthClient implements EthClientInterface {
);
console.timeEnd(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`);
return result;
return allEthHeaderCids.nodes;
}
async getFullTransaction (txHash: string, blockNumber?: number): Promise<FullTransaction> {
async getFullTransaction (txHash: string, blockNumber?: number): Promise<EthFullTransaction> {
console.time(`time:eth-client#getFullTransaction-${JSON.stringify({ txHash, blockNumber })}`);
const result = await this._graphqlClient.query(
ethQueries.getFullTransaction,

View File

@ -6,7 +6,7 @@ import assert from 'assert';
import { errors, providers, utils } from 'ethers';
import { Cache } from '@cerc-io/cache';
import { encodeHeader, escapeHexString, EthClient as EthClientInterface, FullTransaction } from '@cerc-io/util';
import { encodeHeader, escapeHexString, EthClient as EthClientInterface, EthFullTransaction } from '@cerc-io/util';
import { padKey } from '@cerc-io/ipld-eth-client';
export interface Config {
@ -174,40 +174,33 @@ export class EthClient implements EthClientInterface {
const rlpData = encodeHeader(header);
const allEthHeaderCids = {
nodes: [
{
blockNumber: this._provider.formatter.number(rawBlock.number).toString(),
blockHash: this._provider.formatter.hash(rawBlock.hash),
parentHash: this._provider.formatter.hash(rawBlock.parentHash),
timestamp: this._provider.formatter.number(rawBlock.timestamp).toString(),
stateRoot: this._provider.formatter.hash(rawBlock.stateRoot),
td: this._provider.formatter.bigNumber(rawBlock.totalDifficulty).toString(),
txRoot: this._provider.formatter.hash(rawBlock.transactionsRoot),
receiptRoot: this._provider.formatter.hash(rawBlock.receiptsRoot),
uncleRoot: this._provider.formatter.hash(rawBlock.sha3Uncles),
bloom: escapeHexString(this._provider.formatter.hex(rawBlock.logsBloom)),
size: this._provider.formatter.number(rawBlock.size).toString(),
blockByMhKey: {
data: escapeHexString(rlpData)
}
}
]
};
return { allEthHeaderCids };
return [{
blockNumber: this._provider.formatter.number(rawBlock.number).toString(),
blockHash: this._provider.formatter.hash(rawBlock.hash),
parentHash: this._provider.formatter.hash(rawBlock.parentHash),
timestamp: this._provider.formatter.number(rawBlock.timestamp).toString(),
stateRoot: this._provider.formatter.hash(rawBlock.stateRoot),
td: this._provider.formatter.bigNumber(rawBlock.totalDifficulty).toString(),
txRoot: this._provider.formatter.hash(rawBlock.transactionsRoot),
receiptRoot: this._provider.formatter.hash(rawBlock.receiptsRoot),
uncleRoot: this._provider.formatter.hash(rawBlock.sha3Uncles),
bloom: escapeHexString(this._provider.formatter.hex(rawBlock.logsBloom)),
size: this._provider.formatter.number(rawBlock.size).toString(),
blockByMhKey: {
data: escapeHexString(rlpData)
}
}];
}
async getFullTransaction (txHash: string): Promise<FullTransaction> {
async getFullTransaction (txHash: string): Promise<EthFullTransaction> {
console.time(`time:eth-client#getFullTransaction-${JSON.stringify({ txHash })}`);
const tx = await this._provider.getTransaction(txHash);
const txReceipt = await tx.wait();
console.timeEnd(`time:eth-client#getFullTransaction-${JSON.stringify({ txHash })}`);
return {
ethTransactionCidByTxHash: {
txHash: tx.hash,
index: txReceipt.transactionIndex,
index: (tx as any).transactionIndex,
src: tx.from,
dst: tx.to
},

View File

@ -14,8 +14,8 @@ import {
NULL_BLOCK_ERROR
} from './constants';
import { JobQueue } from './job-queue';
import { BlockProgressInterface, IndexerInterface, EventInterface } from './types';
import { EthFullBlock, wait } from './misc';
import { BlockProgressInterface, IndexerInterface, EventInterface, EthFullTransaction, EthFullBlock } from './types';
import { wait } from './misc';
import { OrderDirection } from './database';
import { JobQueueConfig } from './config';
@ -28,6 +28,7 @@ export interface PrefetchedBlock {
block: BlockProgressInterface;
events: DeepPartial<EventInterface>[];
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
}
/**
@ -159,8 +160,8 @@ export const fetchAndSaveFilteredLogsAndBlocks = async (
console.timeEnd('time:common#fetchAndSaveFilteredLogsAndBlocks-fetchAndSaveFilteredEventsAndBlocks');
// Set blocks with events in blockAndEventsMap cache
blocksData.forEach(({ blockProgress, events, ethFullBlock }) => {
blockAndEventsMap.set(blockProgress.blockHash, { block: blockProgress, events, ethFullBlock });
blocksData.forEach(({ blockProgress, events, ethFullBlock, ethFullTransactions }) => {
blockAndEventsMap.set(blockProgress.blockHash, { block: blockProgress, events, ethFullBlock, ethFullTransactions });
});
return blocksData.map(({ blockProgress }) => blockProgress);
@ -183,8 +184,15 @@ export const _prefetchBlocks = async (
);
blocksWithEvents.forEach(({ blockProgress, events }) => {
// TODO: Set ethFullBlock
blockAndEventsMap.set(blockProgress.blockHash, { block: blockProgress, events, ethFullBlock: {} as EthFullBlock });
blockAndEventsMap.set(
blockProgress.blockHash,
{
block: blockProgress,
events,
// TODO: Set ethFullBlock and ethFullTransactions
ethFullBlock: {} as EthFullBlock,
ethFullTransactions: []
});
});
};
@ -289,6 +297,7 @@ export const processBatchEvents = async (
data: {
block: BlockProgressInterface;
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
},
{ eventsInBatch, subgraphEventsOrder }: {
eventsInBatch: number;
@ -324,9 +333,10 @@ export const processBatchEvents = async (
const _processEvents = async (
indexer: IndexerInterface,
{ block, ethFullBlock }: {
{ block, ethFullBlock, ethFullTransactions }: {
block: BlockProgressInterface;
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
},
eventsInBatch: number
): Promise<{ dbBlock: BlockProgressInterface, updatedDbEvents: EventInterface[] }> => {
@ -371,7 +381,7 @@ const _processEvents = async (
updatedDbEvents.push(event);
}
await indexer.processEvent(event, { ethFullBlock });
await indexer.processEvent(event, { ethFullBlock, ethFullTransactions });
}
block.lastProcessedEventIndex = event.index;
@ -388,9 +398,10 @@ const _processEvents = async (
const _processEventsInSubgraphOrder = async (
indexer: IndexerInterface,
{ block, ethFullBlock }: {
{ block, ethFullBlock, ethFullTransactions }: {
block: BlockProgressInterface;
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
},
eventsInBatch: number
): Promise<{ dbBlock: BlockProgressInterface, updatedDbEvents: EventInterface[], isNewContractWatched: boolean }> => {
@ -434,7 +445,7 @@ const _processEventsInSubgraphOrder = async (
// Process known events in a loop
for (const event of watchedContractEvents) {
console.time(`time:common#_processEventsInSubgraphOrder-block-${block.blockNumber}-processEvent-${event.eventName}`);
await indexer.processEvent(event, { ethFullBlock });
await indexer.processEvent(event, { ethFullBlock, ethFullTransactions });
console.timeEnd(`time:common#_processEventsInSubgraphOrder-block-${block.blockNumber}-processEvent-${event.eventName}`);
block.lastProcessedEventIndex = event.index;
@ -483,8 +494,8 @@ const _processEventsInSubgraphOrder = async (
console.time('time:common#processEventsInSubgraphOrder-processing_initially_unwatched_events');
// In the end process events of newly watched contracts
for (const updatedDbEvent of updatedDbEvents) {
console.time(`time:common#processEventsInSubgraphOrder--block-${block.blockNumber}-updated-processEvent-${updatedDbEvent.eventName}`);
await indexer.processEvent(updatedDbEvent, { ethFullBlock });
console.time(`time:common#processEventsInSubgraphOrder-block-${block.blockNumber}-updated-processEvent-${updatedDbEvent.eventName}`);
await indexer.processEvent(updatedDbEvent, { ethFullBlock, ethFullTransactions });
console.timeEnd(`time:common#processEventsInSubgraphOrder-block-${block.blockNumber}-updated-processEvent-${updatedDbEvent.eventName}`);
block.lastProcessedEventIndex = Math.max(block.lastProcessedEventIndex + 1, updatedDbEvent.index);

View File

@ -34,7 +34,7 @@ export interface Transaction {
hash: string;
index: number;
from: string;
to: string;
to?: string;
value: string;
gasLimit: string;
gasPrice?: string;

View File

@ -51,8 +51,9 @@ export const indexBlock = async (
indexer,
{
block: blockProgress,
// TODO: Set ethFullBlock
ethFullBlock: {} as EthFullBlock
// TODO: Set ethFullBlock and ethFullTransactions
ethFullBlock: {} as EthFullBlock,
ethFullTransactions: []
},
{ eventsInBatch, subgraphEventsOrder });
}

View File

@ -24,14 +24,15 @@ import {
StateKind,
EthClient,
ContractJobData,
EventsQueueJobKind
EventsQueueJobKind,
EthFullBlock,
EthFullTransaction
} from './types';
import { UNKNOWN_EVENT_NAME, QUEUE_EVENT_PROCESSING, DIFF_MERGE_BATCH_SIZE } from './constants';
import { JobQueue } from './job-queue';
import { Where, QueryOptions, BlockHeight } from './database';
import { ServerConfig, UpstreamConfig } from './config';
import { createOrUpdateStateData, StateDataMeta } from './state-helper';
import { EthFullBlock } from './misc';
const DEFAULT_MAX_EVENTS_BLOCK_RANGE = 1000;
@ -102,7 +103,8 @@ export type ResultMeta = {
};
export type ExtraEventData = {
ethFullBlock: EthFullBlock
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
}
export class Indexer {
@ -469,7 +471,8 @@ export class Indexer {
): Promise<{
blockProgress: BlockProgressInterface,
events: DeepPartial<EventInterface>[],
ethFullBlock: EthFullBlock
ethFullBlock: EthFullBlock,
ethFullTransactions: EthFullTransaction[]
}[]> {
assert(this._ethClient.getLogsForBlockRange, 'getLogsForBlockRange() not implemented in ethClient');
@ -491,13 +494,7 @@ export class Indexer {
// Fetch blocks with transactions for the logs returned
console.time(`time:indexer#fetchAndSaveFilteredEventsAndBlocks-fetch-blocks-txs-${fromBlock}-${toBlock}`);
const blocksPromises = Array.from(blockLogsMap.keys()).map(async (blockHash) => {
const {
allEthHeaderCids: {
nodes: [
fullBlock
]
}
} = await this._ethClient.getFullBlocks({ blockHash });
const [fullBlock] = await this._ethClient.getFullBlocks({ blockHash });
const block = {
...fullBlock,
@ -508,16 +505,18 @@ export class Indexer {
return { block, fullBlock } as { block: DeepPartial<BlockProgressInterface>; fullBlock: EthFullBlock };
});
const txPromises = txHashes.map(async txHash => {
const {
ethTransactionCidByTxHash: tx
} = await this._ethClient.getFullTransaction(txHash);
return tx;
const ethFullTxPromises = txHashes.map(async txHash => {
return this._ethClient.getFullTransaction(txHash);
});
const blocks = await Promise.all(blocksPromises);
const transactions = await Promise.all(txPromises);
const ethFullTxs = await Promise.all(ethFullTxPromises);
const ethFullTxsMap = ethFullTxs.reduce((acc: Map<string, EthFullTransaction>, ethFullTx) => {
acc.set(ethFullTx.ethTransactionCidByTxHash.txHash, ethFullTx);
return acc;
}, new Map());
console.timeEnd(`time:indexer#fetchAndSaveFilteredEventsAndBlocks-fetch-blocks-txs-${fromBlock}-${toBlock}`);
// Map db ready events according to blockhash
@ -527,10 +526,27 @@ export class Indexer {
assert(blockHash);
const logs = blockLogsMap.get(blockHash) || [];
const events = this.createDbEventsFromLogsAndTxs(blockHash, logs, transactions, parseEventNameAndArgs);
const txHashes = Array.from([
...new Set<string>(logs.map((log: any) => log.transaction.hash))
]);
const blockEthFullTxs = txHashes.map(txHash => ethFullTxsMap.get(txHash)) as EthFullTransaction[];
const events = this.createDbEventsFromLogsAndTxs(
blockHash,
logs,
blockEthFullTxs.map(ethFullTx => ethFullTx?.ethTransactionCidByTxHash),
parseEventNameAndArgs
);
const [blockProgress] = await this.saveBlockWithEvents(block, events);
return { blockProgress, ethFullBlock: fullBlock, events: [] };
return {
blockProgress,
ethFullBlock: fullBlock,
ethFullTransactions: blockEthFullTxs,
block,
events: []
};
});
const blocksWithDbEvents = await Promise.all(blockWithDbEventsPromises);
@ -576,6 +592,7 @@ export class Indexer {
topics
});
// TODO: Use txs from blockEventsMap
const transactionsPromise = this._ethClient.getBlockWithTransactions({ blockHash, blockNumber });
const [

View File

@ -20,8 +20,8 @@ import {
QUEUE_HISTORICAL_PROCESSING
} from './constants';
import { JobQueue } from './job-queue';
import { BlockProgressInterface, ContractJobData, EventInterface, EventsJobData, EventsQueueJobKind, IndexerInterface } from './types';
import { EthFullBlock, wait } from './misc';
import { BlockProgressInterface, ContractJobData, EventInterface, EventsJobData, EventsQueueJobKind, IndexerInterface, EthFullBlock } from './types';
import { wait } from './misc';
import {
createPruningJob,
createHooksJob,
@ -562,8 +562,15 @@ export class JobRunner {
log(`_indexBlock#saveBlockAndFetchEvents: fetched for block: ${blockProgress.blockHash} num events: ${blockProgress.numEvents}`);
console.timeEnd('time:job-runner#_indexBlock-saveBlockAndFetchEvents');
// TODO: Get full block from blockEventsMap
this._blockAndEventsMap.set(blockHash, { block: blockProgress, events: [], ethFullBlock: {} as EthFullBlock });
this._blockAndEventsMap.set(
blockHash,
{
block: blockProgress,
events: [],
// TODO: Get full block and transactions from blockEventsMap
ethFullBlock: {} as EthFullBlock,
ethFullTransactions: []
});
}
}
@ -601,7 +608,7 @@ export class JobRunner {
const prefetchedBlock = this._blockAndEventsMap.get(blockHash);
assert(prefetchedBlock);
const { block, ethFullBlock } = prefetchedBlock;
const { block, ethFullBlock, ethFullTransactions } = prefetchedBlock;
log(`Processing events for block ${block.blockNumber}`);
console.time(`time:job-runner#_processEvents-events-${block.blockNumber}`);
@ -609,7 +616,8 @@ export class JobRunner {
this._indexer,
{
block,
ethFullBlock
ethFullBlock,
ethFullTransactions
},
{
eventsInBatch: this._jobQueueConfig.eventsInBatch,

View File

@ -19,8 +19,9 @@ import { JobQueue } from './job-queue';
import { GraphDecimal } from './graph/graph-decimal';
import * as EthDecoder from './eth';
import { ResultEvent } from './indexer';
import { EventInterface, EthClient } from './types';
import { EventInterface, EthFullBlock, EthFullTransaction } from './types';
import { BlockHeight } from './database';
import { Transaction } from './graph/utils';
const JSONbigNative = JSONbig({ useNativeBigInt: true });
@ -181,25 +182,6 @@ class CustomFormatter extends providers.Formatter {
}
}
export interface EthFullBlock {
id?: string,
cid?: string;
blockNumber: string;
blockHash: string;
parentHash: string;
timestamp: string;
stateRoot: string;
td: string;
txRoot: string;
receiptRoot: string;
uncleRoot: string;
bloom: string;
size: string;
blockByMhKey: {
data: string;
}
}
export const getFullBlock = (ethFullBlock: EthFullBlock): any => {
// Decode the header data.
const header = EthDecoder.decodeHeader(EthDecoder.decodeData(ethFullBlock.blockByMhKey.data));
@ -226,11 +208,14 @@ export const getFullBlock = (ethFullBlock: EthFullBlock): any => {
};
};
export const getFullTransaction = async (ethClient: EthClient, txHash: string, blockNumber: number): Promise<any> => {
export const getFullTransaction = (txHash: string, ethFullTransactions: EthFullTransaction[]): Transaction => {
const ethFullTransaction = ethFullTransactions.find(ethFullTransaction => ethFullTransaction.ethTransactionCidByTxHash.txHash === txHash);
assert(ethFullTransaction);
let {
ethTransactionCidByTxHash: fullTx,
data: txData
} = await ethClient.getFullTransaction(txHash, blockNumber);
} = ethFullTransaction;
// Check if txData does not exist when using ipld-eth-client
if (!txData) {

View File

@ -11,7 +11,6 @@ import { ServerConfig, UpstreamConfig } from './config';
import { Where, QueryOptions, Database } from './database';
import { ValueResult, StateStatus, ExtraEventData } from './indexer';
import { JOB_KIND_CONTRACT, JOB_KIND_EVENTS } from './constants';
import { EthFullBlock } from '.';
export enum StateKind {
Diff = 'diff',
@ -85,6 +84,77 @@ export interface StateInterface {
data: Buffer;
}
export interface EthFullTransaction {
ethTransactionCidByTxHash: {
txHash: string;
index: number;
src: string;
dst?: string;
blockByMhKey?: {
data: string;
}
},
data?: Transaction;
}
export interface EthFullBlock {
id?: string,
cid?: string;
blockNumber: string;
blockHash: string;
parentHash: string;
timestamp: string;
stateRoot: string;
td: string;
txRoot: string;
receiptRoot: string;
uncleRoot: string;
bloom: string;
size: string;
blockByMhKey: {
data: string;
}
}
export interface EthClient {
getStorageAt({ blockHash, contract, slot }: {
blockHash: string;
contract: string;
slot: string;
}): Promise<{
value: string;
proof: {
data: string;
};
}>;
getBlockWithTransactions({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<any>;
getBlocks({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<any>;
getFullBlocks({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<EthFullBlock[]>;
getFullTransaction(txHash: string, blockNumber?: number): Promise<EthFullTransaction>;
getBlockByHash(blockHash?: string): Promise<any>;
getLogs(vars: {
blockHash: string,
blockNumber: string,
addresses?: string[],
topics?: string[][]
}): Promise<any>;
getLogsForBlockRange?: (vars: {
fromBlock?: number,
toBlock?: number,
addresses?: string[],
topics?: string[][]
}) => Promise<any>;
}
export interface IndexerInterface {
readonly serverConfig: ServerConfig
readonly upstreamConfig: UpstreamConfig
@ -104,7 +174,12 @@ export interface IndexerInterface {
getAncestorAtDepth (blockHash: string, depth: number): Promise<string>
fetchEventsAndSaveBlocks (blocks: DeepPartial<BlockProgressInterface>[]): Promise<{ blockProgress: BlockProgressInterface, events: DeepPartial<EventInterface>[] }[]>
saveBlockAndFetchEvents (block: DeepPartial<BlockProgressInterface>): Promise<[BlockProgressInterface, DeepPartial<EventInterface>[]]>
fetchAndSaveFilteredEventsAndBlocks (startBlock: number, endBlock: number): Promise<{ blockProgress: BlockProgressInterface, events: DeepPartial<EventInterface>[], ethFullBlock: EthFullBlock }[]>
fetchAndSaveFilteredEventsAndBlocks (startBlock: number, endBlock: number): Promise<{
blockProgress: BlockProgressInterface,
events: DeepPartial<EventInterface>[],
ethFullBlock: EthFullBlock,
ethFullTransactions: EthFullTransaction[]
}[]>
fetchEventsForContracts (blockHash: string, blockNumber: number, addresses: string[]): Promise<DeepPartial<EventInterface>[]>
removeUnknownEvents (block: BlockProgressInterface): Promise<void>
updateBlockProgress (block: BlockProgressInterface, lastProcessedEventIndex: number): Promise<BlockProgressInterface>
@ -205,58 +280,6 @@ export interface GraphWatcherInterface {
setIndexer (indexer: IndexerInterface): void;
}
export interface FullTransaction {
ethTransactionCidByTxHash: {
txHash: string;
index: number;
src: string;
dst?: string;
blockByMhKey?: {
data: string;
}
},
data?: Transaction;
}
export interface EthClient {
getStorageAt({ blockHash, contract, slot }: {
blockHash: string;
contract: string;
slot: string;
}): Promise<{
value: string;
proof: {
data: string;
};
}>;
getBlockWithTransactions({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<any>;
getBlocks({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<any>;
getFullBlocks({ blockNumber, blockHash }: {
blockNumber?: number;
blockHash?: string;
}): Promise<any>;
getFullTransaction(txHash: string, blockNumber?: number): Promise<FullTransaction>;
getBlockByHash(blockHash?: string): Promise<any>;
getLogs(vars: {
blockHash: string,
blockNumber: string,
addresses?: string[],
topics?: string[][]
}): Promise<any>;
getLogsForBlockRange?: (vars: {
fromBlock?: number,
toBlock?: number,
addresses?: string[],
topics?: string[][]
}) => Promise<any>;
}
export type Clients = {
ethClient: EthClient;
[key: string]: any;