UNPKG

@vechain/sdk-network

Version:

This module serves as the standard interface connecting decentralized applications (dApps) and users to the VeChainThor blockchain

191 lines (166 loc) 7.09 kB
import { type ABIEvent, Hex } from '@vechain/sdk-core'; import { InvalidAbiItem } from '@vechain/sdk-errors'; import { thorest } from '../../utils/thorest/thorest'; import { type EventLogs, type FilterEventLogsOptions, type FilterRawEventLogsOptions, type FilterTransferLogsOptions, type TransferLogs } from './types'; import { HttpMethod } from '../../http'; import { type BlocksModule } from '../blocks'; /** * The `LogsClient` class provides methods to interact with log-related endpoints * of the VeChainThor blockchain. It allows filtering event and transfer logs. */ class LogsModule { readonly blocksModule: BlocksModule; constructor(blocksModule: BlocksModule) { this.blocksModule = blocksModule; } /** * Filters event logs based on the provided criteria. Raw event logs are not decoded. * * @param filterOptions - An object specifying filtering criteria for event logs. * @returns A promise that resolves to filtered event logs. */ public async filterRawEventLogs( filterOptions: FilterRawEventLogsOptions ): Promise<EventLogs[]> { return (await this.blocksModule.httpClient.http( HttpMethod.POST, thorest.logs.post.EVENT_LOGS(), { query: {}, body: filterOptions, headers: {} } )) as EventLogs[]; } /** * Filters event logs based on the provided criteria and decodes them using the provided ABI items. * The decoded data is added to the event logs as a new property. * @param filterOptions - An object specifying filtering criteria for event logs. */ public async filterEventLogs( filterOptions: FilterEventLogsOptions ): Promise<EventLogs[]> { // Extract raw event logs and ABI items from filter options const eventAbis = filterOptions.criteriaSet?.map((c) => c.eventAbi); const eventLogs = await this.getRawEventLogs(filterOptions); const result: EventLogs[] = []; if (eventAbis !== undefined) { const uniqueEventAbis = this.removeDuplicatedAbis(eventAbis); eventLogs.forEach((log) => { const eventAbi = uniqueEventAbis.get(log.topics[0]); if (eventAbi === undefined || eventAbi === null) { throw new InvalidAbiItem( 'LogsModule.filterEventLogs', 'Topic not found in the provided ABIs.', { type: 'event', value: log.topics[0] } ); } log.decodedData = eventAbi.decodeEventLogAsArray({ data: Hex.of(log.data), topics: log.topics.map((topic) => Hex.of(topic)) }); result.push(log); }); } return result; } /** * Filters event logs based on the provided criteria and decodes them using the provided ABI items. * The decoded data is added to the event logs as a new property. * The result is an array of event logs grouped by the event topic hash. * @param filterOptions * @returns A promise that resolves to an array of event logs grouped by event. */ public async filterGroupedEventLogs( filterOptions: FilterEventLogsOptions ): Promise<EventLogs[][]> { // Extract raw event logs and ABI items from filter options const eventAbis = filterOptions.criteriaSet?.map((c) => c.eventAbi); const eventLogs = await this.getRawEventLogs(filterOptions); const result = new Map<string, EventLogs[]>(); if (eventAbis !== undefined) { const uniqueEventAbis = this.removeDuplicatedAbis(eventAbis); // Initialize the result map with empty arrays for each unique ABI item uniqueEventAbis.forEach((f) => result.set(f.signatureHash, [])); eventLogs.forEach((log) => { const eventAbi = uniqueEventAbis.get(log.topics[0]); if (eventAbi === undefined || eventAbi === null) { throw new InvalidAbiItem( 'LogsModule.filterGroupedEventLogs', 'Topic not found in the provided ABIs.', { type: 'event', value: log.topics[0] } ); } log.decodedData = eventAbi.decodeEventLogAsArray({ data: Hex.of(log.data), topics: log.topics.map((topic) => Hex.of(topic)) }); result.get(log.topics[0])?.push(log); }); } return Array.from(result.values()); } /** * Filters event logs based on the provided criteria without decoding them. * @param filterOptions - An object specifying filtering criteria for event logs. * @private Returns a promise that resolves to filtered non decoded event logs. */ private async getRawEventLogs( filterOptions: FilterEventLogsOptions ): Promise<EventLogs[]> { const criteriaSet = filterOptions.criteriaSet?.map((c) => c.criteria); // Create new filter options with the criteria set const filterRawEventLogsOptions: FilterRawEventLogsOptions = { range: filterOptions.range ?? { unit: 'block', from: 0, to: (await this.blocksModule.getBestBlockCompressed())?.number }, criteriaSet, options: filterOptions.options, order: filterOptions.order ?? 'asc' }; // Filter event logs based on the provided criteria return await this.filterRawEventLogs(filterRawEventLogsOptions); } /** * Removes duplicated ABI items from the provided array. ABI items are considered duplicated if they have the same topic hash. * @param eventAbis - An array of event ABI items. * @private Returns a map of unique ABI items. */ private removeDuplicatedAbis(eventAbis: ABIEvent[]): Map<string, ABIEvent> { const uniqueEventAbis = new Map<string, ABIEvent>(); eventAbis.forEach((obj) => { if (!uniqueEventAbis.has(obj.signatureHash)) { uniqueEventAbis.set(obj.signatureHash, obj); } }); return uniqueEventAbis; } /** * Filters transfer logs based on the provided criteria. * * @param filterOptions - An object specifying filtering criteria for transfer logs. * @returns A promise that resolves to filtered transfer logs. */ public async filterTransferLogs( filterOptions: FilterTransferLogsOptions ): Promise<TransferLogs[]> { return (await this.blocksModule.httpClient.http( HttpMethod.POST, thorest.logs.post.TRANSFER_LOGS(), { query: {}, body: filterOptions, headers: {} } )) as TransferLogs[]; } } export { LogsModule };