UNPKG

@atomiqlabs/chain-starknet

Version:
115 lines (107 loc) 4.45 kB
import {StarknetModule} from "../StarknetModule"; import {EVENTS_CHUNK} from "starknet"; export type StarknetEvent = { block_hash?: string; block_number?: number; transaction_hash: string; transaction_index?: number; event_index?: number; from_address: string; keys: string[]; data: string[]; } export class StarknetEvents extends StarknetModule { public readonly EVENTS_LIMIT = 100; public readonly FORWARD_BLOCK_RANGE = 2000; /** * Returns the all the events occuring in a block range as identified by the contract and keys * * @param contract * @param keys * @param startBlock * @param endBlock * @param abortSignal */ public async getBlockEvents( contract: string, keys: string[][], startBlock?: number, endBlock: number | null | undefined = startBlock, abortSignal?: AbortSignal ): Promise<StarknetEvent[]> { const events: StarknetEvent[] = []; let result = null; do { result = await this.root.provider.getEvents({ address: contract, from_block: startBlock==null ? "latest" : {block_number: startBlock}, to_block: endBlock==null ? "latest" : {block_number: endBlock}, keys, chunk_size: this.EVENTS_LIMIT, continuation_token: result==null ? undefined : result.continuation_token }); if(abortSignal!=null) abortSignal.throwIfAborted(); events.push(...result.events); } while(result?.continuation_token!=null); return events; } /** * Runs a search backwards in time, processing events from a specific contract and keys * * @param contract * @param keys * @param processor called for every batch of returned signatures, should return a value if the correct signature * was found, or null if the search should continue * @param abortSignal */ public async findInEvents<T>( contract: string, keys: string[][], processor: (signatures: StarknetEvent[]) => Promise<T | null>, abortSignal?: AbortSignal ): Promise<T | null> { const latestBlockNumber = await this.provider.getBlockNumber(); for(let blockNumber = latestBlockNumber; blockNumber >= 0; blockNumber-=this.FORWARD_BLOCK_RANGE) { const eventsResult = await this.getBlockEvents( contract, keys, Math.max(blockNumber-this.FORWARD_BLOCK_RANGE, 0), blockNumber===latestBlockNumber ? null : blockNumber, abortSignal ); const result = await processor(eventsResult.reverse()); if(result!=null) return result; } return null; } /** * Runs a search forwards in time, processing events from a specific contract and keys * * @param contract * @param keys * @param processor called for every batch of returned signatures, should return a value if the correct signature * was found, or null if the search should continue * @param startHeight * @param abortSignal * @param logFetchLimit */ public async findInEventsForward<T>( contract: string, keys: string[][], processor: (signatures: StarknetEvent[]) => Promise<T | null>, startHeight?: number, abortSignal?: AbortSignal, logFetchLimit?: number ): Promise<T | null> { if(logFetchLimit==null || logFetchLimit>this.EVENTS_LIMIT) logFetchLimit = this.EVENTS_LIMIT; let eventsResult: EVENTS_CHUNK | null = null; do { eventsResult = await this.root.provider.getEvents({ address: contract, from_block: startHeight==null ? undefined : {block_number: startHeight}, to_block: "latest", keys, chunk_size: logFetchLimit ?? this.EVENTS_LIMIT, continuation_token: eventsResult==null ? undefined : eventsResult.continuation_token }); if(abortSignal!=null) abortSignal.throwIfAborted(); const result = await processor(eventsResult.events); if(result!=null) return result; } while(eventsResult.continuation_token!=null); return null; } }