ethers-opt
Version:
Collection of heavily optimized functions for ethers.js V6
100 lines (91 loc) • 2.73 kB
text/typescript
import {
BaseContract,
ContractEventName,
BlockTag,
Provider,
TopicFilter,
EventFragment,
assert,
EventLog,
UndecodedEventLog,
Log,
} from 'ethers';
import { getSubInfo } from './ethers.js';
/**
* Queries for event logs (optionally decoded) from provider or contract, in an arbitrary block range.
* Supports basic topic and address filtering. If `address === '*'` scans the entire blockchain.
*
* @param args
* - address: Address(es) to filter on (optional).
* - provider: Provider to use (optional).
* - contract: Contract instance for decoding (optional).
* - event: The event signature/name (optional).
* - fromBlock: Start of block range (default: 0).
* - toBlock: End of block range (default: 'latest').
* @returns Array of EventLog, UndecodedEventLog, or Log objects.
*/
export async function multiQueryFilter({
address,
provider,
contract,
event,
fromBlock,
toBlock,
}: {
address?: string | string[];
provider?: Provider;
contract?: BaseContract;
event?: ContractEventName;
fromBlock?: BlockTag;
toBlock?: BlockTag;
}) {
if (!address && contract) {
address = contract.target as string;
} else if (address === '*') {
address = undefined;
}
if (!provider && contract) {
provider = (contract.runner?.provider || contract.runner) as Provider;
}
if (!event) {
event = '*';
}
if (!fromBlock && fromBlock !== 0) {
fromBlock = 0;
}
if (!toBlock && toBlock !== 0) {
toBlock = 'latest';
}
let fragment: EventFragment | null = null,
topics: TopicFilter | null[] = [null];
if (contract) {
({ fragment, topics } = await getSubInfo(contract.interface, event));
}
const filter = {
address,
topics,
fromBlock,
toBlock,
};
assert(provider, 'contract runner does not have a provider', 'UNSUPPORTED_OPERATION', {
operation: 'queryFilter',
});
return (await provider.getLogs(filter)).map((log) => {
let foundFragment = fragment;
if (foundFragment == null && contract) {
try {
foundFragment = contract.interface.getEvent(log.topics[0]);
// eslint-disable-next-line no-empty
} catch {}
}
if (foundFragment && contract) {
try {
return new EventLog(log, contract.interface, foundFragment);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
return new UndecodedEventLog(log, error);
}
}
return new Log(log, provider);
});
}