-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: make get logs type more generic * fix: slightly longer delay to make sure announcements are watched
- Loading branch information
1 parent
b55a867
commit fff75fa
Showing
5 changed files
with
147 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { | ||
type Abi, | ||
type AbiEvent, | ||
type ContractEventName, | ||
type DecodeEventLogReturnType, | ||
type GetEventArgs, | ||
type Log, | ||
type PublicClient, | ||
decodeEventLog | ||
} from 'viem'; | ||
import { getBlockNumber, getLogs } from 'viem/actions'; | ||
|
||
/** | ||
* Parameters for fetching and decoding logs in chunks. | ||
* @template TAbi - The ABI type. | ||
*/ | ||
type FetchLogsParams<TAbi extends Abi> = { | ||
/** An instance of the viem PublicClient. */ | ||
publicClient: PublicClient; | ||
/** The ABI of the contract. */ | ||
abi: TAbi; | ||
/** The name of the event to fetch logs for. */ | ||
eventName: ContractEventName<TAbi>; | ||
/** The address of the contract. */ | ||
address: `0x${string}`; | ||
/** Optional arguments to filter the logs. */ | ||
args?: GetEventArgs<TAbi, ContractEventName<TAbi>>; | ||
/** The starting block number for the fetch. Defaults to 'earliest'. */ | ||
fromBlock?: bigint | 'earliest'; | ||
/** The ending block number for the fetch. Defaults to 'latest'. */ | ||
toBlock?: bigint | 'latest'; | ||
/** The number of blocks to query in each chunk. Defaults to 5000. */ | ||
chunkSize?: number; | ||
}; | ||
|
||
type FetchLogsReturnType<TAbi extends Abi> = Array< | ||
DecodeEventLogReturnType<TAbi, ContractEventName<TAbi>> & Log | ||
>; | ||
|
||
/** | ||
* Fetches and decodes logs in chunks to handle potentially large range queries efficiently. | ||
* | ||
* @template TAbi - The ABI type. | ||
* @param {FetchLogsParams<TAbi>} params - The parameters for fetching logs in chunks. | ||
* @returns {Promise<FetchLogsReturnType>} - A flattened array of all logs fetched in chunks, including decoded event data. | ||
* | ||
* @example | ||
* const logs = await fetchLogsInChunks({ | ||
* publicClient, | ||
* abi: myContractABI, | ||
* eventName: 'Transfer', | ||
* address: '0x...', | ||
* fromBlock: 1000000n, | ||
* toBlock: 2000000n, | ||
* chunkSize: 10000 | ||
* }); | ||
*/ | ||
export const fetchLogsInChunks = async <TAbi extends Abi>({ | ||
publicClient, | ||
abi, | ||
eventName, | ||
address, | ||
args, | ||
fromBlock = 'earliest', | ||
toBlock = 'latest', | ||
chunkSize = 5000 | ||
}: FetchLogsParams<TAbi>): Promise<FetchLogsReturnType<TAbi>> => { | ||
const [start, end] = await Promise.all([ | ||
fromBlock === 'earliest' | ||
? 0n | ||
: typeof fromBlock === 'bigint' | ||
? fromBlock | ||
: getBlockNumber(publicClient), | ||
toBlock === 'latest' ? getBlockNumber(publicClient) : toBlock | ||
]); | ||
|
||
const eventAbi = abi.find( | ||
(item): item is AbiEvent => item.type === 'event' && item.name === eventName | ||
); | ||
|
||
if (!eventAbi) throw new Error(`Event ${eventName} not found in ABI`); | ||
|
||
const allLogs = []; | ||
|
||
for ( | ||
let currentBlock = start; | ||
currentBlock <= end; | ||
currentBlock += BigInt(chunkSize) | ||
) { | ||
const logs = await getLogs(publicClient, { | ||
address, | ||
event: eventAbi, | ||
args, | ||
fromBlock: currentBlock, | ||
toBlock: BigInt( | ||
Math.min(Number(currentBlock) + chunkSize - 1, Number(end)) | ||
), | ||
strict: true | ||
}); | ||
|
||
allLogs.push( | ||
...logs.map(log => ({ | ||
...log, | ||
...decodeEventLog({ | ||
abi, | ||
eventName, | ||
topics: log.topics, | ||
data: log.data | ||
}) | ||
})) | ||
); | ||
} | ||
|
||
return allLogs; | ||
}; |