From 4f5d056cb0e9b2d915d24616af90a5249a7e6d20 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Tue, 18 Nov 2025 16:38:44 +0100 Subject: [PATCH 1/7] HEAD From 5eeff2c7f7ed0d99c65f764a59652c625bb54789 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Tue, 18 Nov 2025 16:40:11 +0100 Subject: [PATCH 2/7] HEAD From 1e8c740e656357b4e06294aab3645a333694317d Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Tue, 18 Nov 2025 16:52:11 +0100 Subject: [PATCH 3/7] refactor: extract generic event processing utilities and add FallbackHyperEVMFlowCompleted tracking - Extract `getEventsFromTransactionReceipts` and `formatAndSaveEvents` into reusable generic utilities in `eventProcessing.ts` - Refactor `hyperEvmExecutor.ts` to export formatting functions instead of processing logic - Add `FallbackHyperEVMFlowCompleted` event tracking to OFT indexer alongside existing `SimpleTransferFlowCompleted` events - Replace duplicate event extraction methods in `CCTPIndexerDataHandler` with generic utilities - Update `EventDecoder` methods to use static references for consistency - Add integration test coverage for `FallbackHyperEVMFlowCompleted` event processing --- .../service/CCTPIndexerDataHandler.ts | 152 +++++------------- .../service/OFTIndexerDataHandler.ts | 87 ++++++---- .../data-indexing/service/eventProcessing.ts | 93 +++++++++++ .../data-indexing/service/hyperEvmExecutor.ts | 143 +++++++--------- .../OFTIndexerDataHandler.integration.test.ts | 37 +++++ packages/indexer/src/web3/EventDecoder.ts | 24 ++- 6 files changed, 288 insertions(+), 248 deletions(-) create mode 100644 packages/indexer/src/data-indexing/service/eventProcessing.ts diff --git a/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts b/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts index be44be7b..7369c509 100644 --- a/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts +++ b/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts @@ -42,9 +42,13 @@ import { } from "../adapter/cctp-v2/service"; import { entities, SaveQueryResult } from "@repo/indexer-database"; import { - formatAndSaveSimpleTransferFlowCompletedEvents, - getSimpleTransferFlowCompletedEventsFromTransactionReceipts, + formatFallbackHyperEVMFlowCompletedEvent, + formatSimpleTransferFlowCompletedEvent, } from "./hyperEvmExecutor"; +import { + formatAndSaveEvents, + getEventsFromTransactionReceipts, +} from "./eventProcessing"; export type EvmBurnEventsPair = { depositForBurn: DepositForBurnEvent; @@ -250,16 +254,17 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { ), ]); - const messageSentEvents = this.getMessageSentEventsFromTransactionReceipts( + const messageSentEvents = getEventsFromTransactionReceipts( filteredDepositForBurnTxReceipts, messageTransmitterAddress, + EventDecoder.decodeCCTPMessageSentEvents, ); - const mintAndWithdrawEvents = - this.getMintAndWithdrawEventsFromTransactionReceipts( - filteredMessageReceivedTxReceipts, - tokenMessengerAddress, - ); + const mintAndWithdrawEvents = getEventsFromTransactionReceipts( + filteredMessageReceivedTxReceipts, + tokenMessengerAddress, + EventDecoder.decodeCCTPMintAndWithdrawEvents, + ); const burnEvents = await this.matchDepositForBurnWithMessageSentEvents( filteredDepositForBurnEvents, @@ -290,30 +295,30 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { let simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[] = []; if (hyperEvmExecutorAddress) { - simpleTransferFlowCompletedEvents = - getSimpleTransferFlowCompletedEventsFromTransactionReceipts( - filteredMessageReceivedTxReceipts, - hyperEvmExecutorAddress, - ); + simpleTransferFlowCompletedEvents = getEventsFromTransactionReceipts( + filteredMessageReceivedTxReceipts, + hyperEvmExecutorAddress, + EventDecoder.decodeSimpleTransferFlowCompletedEvents, + ); } let arbitraryActionsExecutedEvents: ArbitraryActionsExecutedLog[] = []; if (arbitraryEvmFlowExecutorAddress) { - arbitraryActionsExecutedEvents = - this.getArbitraryActionsExecutedEventsFromTransactionReceipts( - filteredMessageReceivedTxReceipts, - arbitraryEvmFlowExecutorAddress, - ); + arbitraryActionsExecutedEvents = getEventsFromTransactionReceipts( + filteredMessageReceivedTxReceipts, + arbitraryEvmFlowExecutorAddress, + EventDecoder.decodeArbitraryActionsExecutedEvents, + ); } let fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[] = []; if (arbitraryEvmFlowExecutorAddress) { - fallbackHyperEVMFlowCompletedEvents = - this.getFallbackHyperEVMFlowCompletedEventsFromTransactionReceipts( - filteredMessageReceivedTxReceipts, - arbitraryEvmFlowExecutorAddress, - ); + fallbackHyperEVMFlowCompletedEvents = getEventsFromTransactionReceipts( + filteredMessageReceivedTxReceipts, + arbitraryEvmFlowExecutorAddress, + EventDecoder.decodeFallbackHyperEVMFlowCompletedEvents, + ); } this.runChecks(burnEvents, mintEvents); @@ -416,52 +421,6 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { } } - private getMessageSentEventsFromTransactionReceipts( - transactionReceipts: Record, - messageTransmitterAddress: string, - ) { - const events: MessageSentLog[] = []; - - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const messageSentEvents: MessageSentLog[] = - EventDecoder.decodeCCTPMessageSentEvents( - transactionReceipt, - messageTransmitterAddress, - ); - if (messageSentEvents.length > 0) { - events.push(...messageSentEvents); - } - } - - return events; - } - - private getMintAndWithdrawEventsFromTransactionReceipts( - transactionReceipts: Record, - tokenMessengerAddress: string, - ) { - const events: MintAndWithdrawLog[] = []; - - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const mintAndWithdrawEvents: MintAndWithdrawLog[] = - EventDecoder.decodeCCTPMintAndWithdrawEvents( - transactionReceipt, - tokenMessengerAddress, - ); - if (mintAndWithdrawEvents.length > 0) { - events.push(...mintAndWithdrawEvents); - } - } - - return events; - } - private getSponsoredDepositForBurnEventsFromTransactionReceipts( transactionReceipts: Record, sponsoredCCTPSrcPeripheryAddress: string, @@ -520,50 +479,6 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { return events; } - private getArbitraryActionsExecutedEventsFromTransactionReceipts( - transactionReceipts: Record, - arbitraryEvmFlowExecutorAddress: string, - ) { - const events: ArbitraryActionsExecutedLog[] = []; - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const arbitraryActionsExecutedEvents: ArbitraryActionsExecutedLog[] = - EventDecoder.decodeArbitraryActionsExecutedEvents( - transactionReceipt, - arbitraryEvmFlowExecutorAddress, - ); - if (arbitraryActionsExecutedEvents.length > 0) { - events.push(...arbitraryActionsExecutedEvents); - } - } - - return events; - } - - private getFallbackHyperEVMFlowCompletedEventsFromTransactionReceipts( - transactionReceipts: Record, - arbitraryEvmFlowExecutorAddress: string, - ) { - const events: FallbackHyperEVMFlowCompletedLog[] = []; - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[] = - EventDecoder.decodeFallbackHyperEVMFlowCompletedEvents( - transactionReceipt, - arbitraryEvmFlowExecutorAddress, - ); - if (fallbackHyperEVMFlowCompletedEvents.length > 0) { - events.push(...fallbackHyperEVMFlowCompletedEvents); - } - } - - return events; - } - private async getTransactionsReceipts(uniqueTransactionHashes: string[]) { const transactionReceipts = await Promise.all( uniqueTransactionHashes.map(async (txHash) => { @@ -665,12 +580,15 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { this.chainId, blocksTimestamps, ), - formatAndSaveSimpleTransferFlowCompletedEvents( + formatAndSaveEvents( this.cctpRepository, simpleTransferFlowCompletedEvents, lastFinalisedBlock, this.chainId, blocksTimestamps, + formatSimpleTransferFlowCompletedEvent, + entities.SimpleTransferFlowCompleted, + ["chainId", "blockNumber", "transactionHash", "logIndex"], ), this.cctpRepository.formatAndSaveArbitraryActionsExecutedEvents( arbitraryActionsExecutedEvents, @@ -678,11 +596,15 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { this.chainId, blocksTimestamps, ), - this.cctpRepository.formatAndSaveFallbackHyperEVMFlowCompletedEvents( + formatAndSaveEvents( + this.cctpRepository, fallbackHyperEVMFlowCompletedEvents, lastFinalisedBlock, this.chainId, blocksTimestamps, + formatFallbackHyperEVMFlowCompletedEvent, + entities.FallbackHyperEVMFlowCompleted, + ["chainId", "blockNumber", "transactionHash", "logIndex"], ), ]); diff --git a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts index b6b70fe3..02fc6de0 100644 --- a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts +++ b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts @@ -6,6 +6,7 @@ import { entities, SaveQueryResult } from "@repo/indexer-database"; import { BlockRange, + FallbackHyperEVMFlowCompletedLog, HYPERCORE_FLOW_EXECUTOR_ADDRESS, SimpleTransferFlowCompletedLog, ENDPOINT_V2_ADDRESS, @@ -26,8 +27,12 @@ import { import { EventDecoder } from "../../web3/EventDecoder"; import { fetchEvents } from "../../utils/contractUtils"; import { - formatAndSaveSimpleTransferFlowCompletedEvents, - getSimpleTransferFlowCompletedEventsFromTransactionReceipts, + formatAndSaveEvents, + getEventsFromTransactionReceipts, +} from "./eventProcessing"; +import { + formatFallbackHyperEVMFlowCompletedEvent, + formatSimpleTransferFlowCompletedEvent, } from "./hyperEvmExecutor"; export type FetchEventsResult = { @@ -35,6 +40,7 @@ export type FetchEventsResult = { oftReceivedEvents: OFTReceivedEvent[]; sponsoredOFTSendEvents: SponsoredOFTSendLog[]; simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[]; + fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[]; blocks: Record; }; export type StoreEventsResult = { @@ -42,6 +48,7 @@ export type StoreEventsResult = { oftReceivedEvents: SaveQueryResult[]; sponsoredOFTSendEvents: SaveQueryResult[]; simpleTransferFlowCompletedEvents: SaveQueryResult[]; + fallbackHyperEVMFlowCompletedEvents: SaveQueryResult[]; }; const SWAP_API_CALLDATA_MARKER = "73c0de"; @@ -166,14 +173,16 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { let sponsoredOFTSendEvents: SponsoredOFTSendLog[] = []; if (sponsoredOFTSrcPeripheryAddress) { - sponsoredOFTSendEvents = - this.getSponsoredOFTSendEventsFromTransactionReceipts( - filteredOftSentTransactionReceipts, - sponsoredOFTSrcPeripheryAddress, - ); + sponsoredOFTSendEvents = getEventsFromTransactionReceipts( + filteredOftSentTransactionReceipts, + sponsoredOFTSrcPeripheryAddress, + EventDecoder.decodeOFTSponsoredSendEvents, + ); } - const simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[] = + let simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[] = + []; + let fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[] = []; if (endpointAddress) { const composeDeliveredEvents = await fetchEvents( @@ -188,13 +197,27 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { const transactionReceipts = await this.getTransactionsReceipts( composeDeliveredEvents.map((event) => event.transactionHash), ); - const events = - getSimpleTransferFlowCompletedEventsFromTransactionReceipts( + simpleTransferFlowCompletedEvents = getEventsFromTransactionReceipts( + transactionReceipts, + hypercoreFlowExecutorAddress, + EventDecoder.decodeSimpleTransferFlowCompletedEvents, + ); + blockHashes.push( + ...simpleTransferFlowCompletedEvents.map( + (event) => event.blockHash, + ), + ); + fallbackHyperEVMFlowCompletedEvents = + getEventsFromTransactionReceipts( transactionReceipts, hypercoreFlowExecutorAddress, + EventDecoder.decodeFallbackHyperEVMFlowCompletedEvents, ); - simpleTransferFlowCompletedEvents.push(...events); - blockHashes.push(...events.map((event) => event.blockHash)); + blockHashes.push( + ...fallbackHyperEVMFlowCompletedEvents.map( + (event) => event.blockHash, + ), + ); } } } @@ -217,6 +240,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { oftReceivedEvents: filteredOftReceivedEvents, sponsoredOFTSendEvents, simpleTransferFlowCompletedEvents, + fallbackHyperEVMFlowCompletedEvents, blocks, }; } @@ -232,6 +256,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { oftSentEvents, sponsoredOFTSendEvents, simpleTransferFlowCompletedEvents, + fallbackHyperEVMFlowCompletedEvents, } = events; const blocksTimestamps = this.getBlocksTimestamps(blocks); const [ @@ -239,6 +264,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { savedOftReceivedEvents, savedSponsoredOFTSendEvents, savedSimpleTransferFlowCompletedEvents, + savedFallbackHyperEVMFlowCompletedEvents, ] = await Promise.all([ this.oftRepository.formatAndSaveOftSentEvents( oftSentEvents, @@ -260,12 +286,25 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { this.chainId, blocksTimestamps, ), - formatAndSaveSimpleTransferFlowCompletedEvents( + formatAndSaveEvents( this.oftRepository, simpleTransferFlowCompletedEvents, lastFinalisedBlock, this.chainId, blocksTimestamps, + formatSimpleTransferFlowCompletedEvent, + entities.SimpleTransferFlowCompleted, + ["chainId", "blockNumber", "transactionHash", "logIndex"], + ), + formatAndSaveEvents( + this.oftRepository, + fallbackHyperEVMFlowCompletedEvents, + lastFinalisedBlock, + this.chainId, + blocksTimestamps, + formatFallbackHyperEVMFlowCompletedEvent, + entities.FallbackHyperEVMFlowCompleted, + ["chainId", "blockNumber", "transactionHash", "logIndex"], ), ]); @@ -274,6 +313,8 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { oftReceivedEvents: savedOftReceivedEvents, sponsoredOFTSendEvents: savedSponsoredOFTSendEvents, simpleTransferFlowCompletedEvents: savedSimpleTransferFlowCompletedEvents, + fallbackHyperEVMFlowCompletedEvents: + savedFallbackHyperEVMFlowCompletedEvents, }; } @@ -309,26 +350,6 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { return transactionReceiptsMap; } - private getSponsoredOFTSendEventsFromTransactionReceipts( - transactionReceipts: Record, - sponsoredOFTSrcPeripheryAddress: string, - ) { - const events: SponsoredOFTSendLog[] = []; - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const sponsoredOFTSendEvents = EventDecoder.decodeOFTSponsoredSendEvents( - transactionReceipt, - sponsoredOFTSrcPeripheryAddress, - ); - if (sponsoredOFTSendEvents.length > 0) { - events.push(...sponsoredOFTSendEvents); - } - } - return events; - } - private async filterTransactionsForSupportedEndpointIds( oftReceivedEvents: OFTReceivedEvent[], ) { diff --git a/packages/indexer/src/data-indexing/service/eventProcessing.ts b/packages/indexer/src/data-indexing/service/eventProcessing.ts new file mode 100644 index 00000000..11aa14ca --- /dev/null +++ b/packages/indexer/src/data-indexing/service/eventProcessing.ts @@ -0,0 +1,93 @@ +import { SaveQueryResult } from "@repo/indexer-database"; +import * as across from "@across-protocol/sdk"; +import { utils } from "@repo/indexer-database"; +import { ObjectLiteral } from "typeorm"; +import { providers } from "ethers"; + +/** + * Formats and saves a batch of blockchain events to the database using a provided formatting function. + * This generic function is designed to handle different types of events by accepting a specific formatting function for each event type. + * It maps the raw event data to the database entity format, marks them as finalized if they are within the finalized block range, + * and then saves them to the database in batches. + * + * @param repository The repository for database operations, specifically for saving blockchain events. + * @param events An array of events to be processed. + * @param lastFinalisedBlock The last block number that is considered finalized. + * @param chainId The ID of the chain where these events were emitted. + * @param blockDates A record mapping block numbers to their corresponding `Date` objects. + * @param formatEvent A function that takes an event and returns a partial entity. + * @param entity The entity to save the events to. + * @param primaryKeyColumns The primary key columns of the entity. + * @param chunkSize The number of events to save in a single batch. Defaults to 100. + * @returns A promise that resolves to an array of `SaveQueryResult` for the saved events. + */ +export async function formatAndSaveEvents( + repository: utils.BlockchainEventRepository, + events: T[], + lastFinalisedBlock: number, + chainId: number, + blockDates: Record, + formatEvent: ( + event: T, + finalised: boolean, + blockTimestamp: Date, + chainId: number, + ) => Partial, + entity: new () => TEntity, + primaryKeyColumns: (keyof TEntity)[], + chunkSize = 100, +): Promise[]> { + const formattedEvents = events.map((event: any) => { + const finalised = event.blockNumber <= lastFinalisedBlock; + const blockTimestamp = blockDates[event.blockNumber]!; + return formatEvent(event, finalised, blockTimestamp, chainId); + }); + + const chunkedEvents = across.utils.chunk(formattedEvents, chunkSize); + const savedEvents = await Promise.all( + chunkedEvents.map((eventsChunk) => + repository.saveAndHandleFinalisationBatch( + entity, + eventsChunk, + primaryKeyColumns as string[], + [], + ), + ), + ); + const result = savedEvents.flat(); + return result; +} + +/** + * Decodes and extracts events from a collection of transaction receipts using a provided decoding function. + * This generic function iterates over transaction receipts, decodes logs, and filters for events + * emitted by a specified contract address. + * + * @param transactionReceipts A record of transaction receipts, indexed by their transaction hash. + * @param contractAddress The address of the contract to filter events from. + * @param decodeEvents A function that takes a transaction receipt and contract address and returns an array of decoded events. + * @returns An array of decoded event objects. + */ +export function getEventsFromTransactionReceipts( + transactionReceipts: Record, + contractAddress: string, + decodeEvents: ( + receipt: providers.TransactionReceipt, + contractAddress?: string, + ) => T[], +): T[] { + const events: T[] = []; + for (const txHash of Object.keys(transactionReceipts)) { + const transactionReceipt = transactionReceipts[ + txHash + ] as providers.TransactionReceipt; + const decodedEvents: T[] = decodeEvents( + transactionReceipt, + contractAddress, + ); + if (decodedEvents.length > 0) { + events.push(...decodedEvents); + } + } + return events; +} diff --git a/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts b/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts index 20f9b2bf..ab7450a1 100644 --- a/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts +++ b/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts @@ -1,92 +1,65 @@ -import { ethers, providers } from "ethers"; -import { SimpleTransferFlowCompletedLog } from "../model"; -import { EventDecoder } from "../../web3/EventDecoder"; -import { entities, SaveQueryResult } from "@repo/indexer-database"; -import * as across from "@across-protocol/sdk"; -import { BlockchainEventRepository } from "../../../../indexer-database/dist/src/utils"; +import { + FallbackHyperEVMFlowCompletedLog, + SimpleTransferFlowCompletedLog, +} from "../model"; +import { entities } from "@repo/indexer-database"; /** - * Decodes and extracts `SimpleTransferFlowCompleted` events from a collection of transaction receipts. - * This function iterates over transaction receipts, decodes logs, and filters for `SimpleTransferFlowCompleted` events - * emitted by a specified HyperEVM executor contract. - * - * @param transactionReceipts A record of transaction receipts, indexed by their transaction hash. - * @param hyperEvmExecutorAddress The address of the HyperEVM executor contract to filter events from. - * @returns An array of decoded `SimpleTransferFlowCompletedLog` objects. + * @constant formatSimpleTransferFlowCompletedEvent + * Formats a `SimpleTransferFlowCompletedLog` event into a partial `SimpleTransferFlowCompleted` entity. + * @param event The `SimpleTransferFlowCompletedLog` event to format. + * @param finalised A boolean indicating if the event is finalized. + * @param blockTimestamp The timestamp of the block where the event was emitted. + * @param chainId The ID of the chain where the event was emitted. + * @returns A partial `SimpleTransferFlowCompleted` entity. */ -export function getSimpleTransferFlowCompletedEventsFromTransactionReceipts( - transactionReceipts: Record, - hyperEvmExecutorAddress: string, -) { - const events: SimpleTransferFlowCompletedLog[] = []; - for (const txHash of Object.keys(transactionReceipts)) { - const transactionReceipt = transactionReceipts[ - txHash - ] as providers.TransactionReceipt; - const simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[] = - EventDecoder.decodeSimpleTransferFlowCompletedEvents( - transactionReceipt, - hyperEvmExecutorAddress, - ); - if (simpleTransferFlowCompletedEvents.length > 0) { - events.push(...simpleTransferFlowCompletedEvents); - } - } - - return events; -} +export const formatSimpleTransferFlowCompletedEvent = ( + event: SimpleTransferFlowCompletedLog, + finalised: boolean, + blockTimestamp: Date, + chainId: number, +): Partial => ({ + blockNumber: event.blockNumber, + logIndex: event.logIndex, + transactionHash: event.transactionHash, + transactionIndex: event.transactionIndex, + blockTimestamp: blockTimestamp, + chainId: chainId.toString(), + quoteNonce: event.args.quoteNonce, + finalRecipient: event.args.finalRecipient, + finalToken: event.args.finalToken.toString(), + evmAmountIn: event.args.evmAmountIn.toString(), + bridgingFeesIncurred: event.args.bridgingFeesIncurred.toString(), + evmAmountSponsored: event.args.evmAmountSponsored.toString(), + finalised, +}); /** - * Formats and saves `SimpleTransferFlowCompleted` events to the database. - * This function maps the raw event data to the database entity format, marks them as finalized if they are within the finalized block range, - * and then saves them to the database in batches. - * - * @param repository The repository for database operations, specifically for saving blockchain events. - * @param simpleTransferFlowCompletedEvents An array of `SimpleTransferFlowCompletedLog` events to be processed. - * @param lastFinalisedBlock The last block number that is considered finalized. - * @param chainId The ID of the chain where these events were emitted. - * @param blockDates A record mapping block numbers to their corresponding `Date` objects. - * @param chunkSize The number of events to save in a single batch. Defaults to 100. - * @returns A promise that resolves to an array of `SaveQueryResult` for the saved events. + * @constant formatFallbackHyperEVMFlowCompletedEvent + * Formats a `FallbackHyperEVMFlowCompletedLog` event into a partial `FallbackHyperEVMFlowCompleted` entity. + * @param event The `FallbackHyperEVMFlowCompletedLog` event to format. + * @param finalised A boolean indicating if the event is finalized. + * @param blockTimestamp The timestamp of the block where the event was emitted. + * @param chainId The ID of the chain where the event was emitted. + * @returns A partial `FallbackHyperEVMFlowCompleted` entity. */ -export async function formatAndSaveSimpleTransferFlowCompletedEvents( - repository: BlockchainEventRepository, - simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[], - lastFinalisedBlock: number, +export const formatFallbackHyperEVMFlowCompletedEvent = ( + event: FallbackHyperEVMFlowCompletedLog, + finalised: boolean, + blockTimestamp: Date, chainId: number, - blockDates: Record, - chunkSize = 100, -) { - const formattedEvents: Partial[] = - simpleTransferFlowCompletedEvents.map((event) => { - return { - blockNumber: event.blockNumber, - logIndex: event.logIndex, - transactionHash: event.transactionHash, - transactionIndex: event.transactionIndex, - blockTimestamp: blockDates[event.blockNumber]!, - chainId: chainId.toString(), - quoteNonce: event.args.quoteNonce, - finalRecipient: event.args.finalRecipient, - finalToken: event.args.finalToken.toString(), - evmAmountIn: event.args.evmAmountIn.toString(), - bridgingFeesIncurred: event.args.bridgingFeesIncurred.toString(), - evmAmountSponsored: event.args.evmAmountSponsored.toString(), - finalised: event.blockNumber <= lastFinalisedBlock, - }; - }); - - const chunkedEvents = across.utils.chunk(formattedEvents, chunkSize); - const savedEvents = await Promise.all( - chunkedEvents.map((eventsChunk) => - repository.saveAndHandleFinalisationBatch( - entities.SimpleTransferFlowCompleted, - eventsChunk, - ["chainId", "blockNumber", "transactionHash", "logIndex"], - [], - ), - ), - ); - const result = savedEvents.flat(); - return result; -} +): Partial => ({ + blockNumber: event.blockNumber, + logIndex: event.logIndex, + transactionHash: event.transactionHash, + transactionIndex: event.transactionIndex, + blockTimestamp: blockTimestamp, + chainId: chainId.toString(), + quoteNonce: event.args.quoteNonce, + finalRecipient: event.args.finalRecipient, + finalToken: event.args.finalToken.toString(), + evmAmountIn: event.args.evmAmountIn.toString(), + bridgingFeesIncurred: event.args.bridgingFeesIncurred.toString(), + evmAmountSponsored: event.args.evmAmountSponsored.toString(), + finalised, +}); diff --git a/packages/indexer/src/data-indexing/tests/OFTIndexerDataHandler.integration.test.ts b/packages/indexer/src/data-indexing/tests/OFTIndexerDataHandler.integration.test.ts index cb50353f..74b887e3 100644 --- a/packages/indexer/src/data-indexing/tests/OFTIndexerDataHandler.integration.test.ts +++ b/packages/indexer/src/data-indexing/tests/OFTIndexerDataHandler.integration.test.ts @@ -110,4 +110,41 @@ describe("OFTIndexerDataHandler", () => { expect(savedEvent!.bridgingFeesIncurred.toString()).to.equal("0"); expect(savedEvent!.evmAmountSponsored.toString()).to.equal("0"); }).timeout(20000); + + it("should process a block range and store FallbackHyperEVMFlowCompleted event for OFT", async () => { + const transactionHash = + "0x05ccdbd44e8ffbed8f057762f40dee73fb218049347705d88f839dfe3c368c52"; + const blockNumber = 17917691; + const blockRange: BlockRange = { + from: blockNumber, + to: blockNumber, + }; + setupTestForChainId(CHAIN_IDs.HYPEREVM); + // We need to stub the filterTransactionsFromSwapApi method to avoid filtering out our test transaction + sinon.stub(handler as any, "filterTransactionsFromSwapApi").resolvesArg(1); + await handler.processBlockRange(blockRange, blockNumber - 1); + + const fallbackHyperEVMFlowCompletedRepo = dataSource.getRepository( + entities.FallbackHyperEVMFlowCompleted, + ); + const savedEvent = await fallbackHyperEVMFlowCompletedRepo.findOne({ + where: { transactionHash: transactionHash }, + }); + + expect(savedEvent).to.exist; + expect(savedEvent!.transactionHash).to.equal(transactionHash); + expect(savedEvent!.blockNumber).to.equal(blockNumber); + expect(savedEvent!.quoteNonce).to.equal( + "0x0000000000000000000000000000000000000000000000000000000069041bd4", + ); + expect(savedEvent!.finalRecipient).to.equal( + "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", + ); + expect(savedEvent!.finalToken).to.equal( + "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb", + ); + expect(savedEvent!.evmAmountIn.toString()).to.equal("1005000"); + expect(savedEvent!.bridgingFeesIncurred.toString()).to.equal("0"); + expect(savedEvent!.evmAmountSponsored.toString()).to.equal("0"); + }).timeout(20000); }); diff --git a/packages/indexer/src/web3/EventDecoder.ts b/packages/indexer/src/web3/EventDecoder.ts index c84684d8..b400c0a1 100644 --- a/packages/indexer/src/web3/EventDecoder.ts +++ b/packages/indexer/src/web3/EventDecoder.ts @@ -102,7 +102,7 @@ export class EventDecoder { const eventTopic = "0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036"; const eventAbi = ["event MessageSent (bytes message)"]; - let events: MessageSentLog[] = this.decodeTransactionReceiptLogs( + let events: MessageSentLog[] = EventDecoder.decodeTransactionReceiptLogs( receipt, eventTopic, eventAbi, @@ -123,11 +123,8 @@ export class EventDecoder { const eventAbi = [ "event MintAndWithdraw(address indexed mintRecipient, uint256 amount, address indexed mintToken, uint256 feeCollected)", ]; - let events: MintAndWithdrawLog[] = this.decodeTransactionReceiptLogs( - receipt, - eventTopic, - eventAbi, - ); + let events: MintAndWithdrawLog[] = + EventDecoder.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); if (contractAddress) { events = events.filter((event) => event.address === contractAddress); } @@ -148,7 +145,7 @@ export class EventDecoder { ]; let events: SponsoredDepositForBurnLog[] = - this.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); + EventDecoder.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); if (contractAddress) { events = events.filter((event) => event.address === contractAddress); } @@ -167,11 +164,8 @@ export class EventDecoder { "event SponsoredOFTSend(bytes32 indexed quoteNonce, address indexed originSender, bytes32 indexed finalRecipient, bytes32 destinationHandler, uint256 quoteDeadline, uint256 maxBpsToSponsor, uint256 maxUserSlippageBps, bytes32 finalToken, bytes sig)", ]; - let events: SponsoredOFTSendLog[] = this.decodeTransactionReceiptLogs( - receipt, - eventTopic, - eventAbi, - ); + let events: SponsoredOFTSendLog[] = + EventDecoder.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); if (contractAddress) { events = events.filter((event) => event.address === contractAddress); } @@ -200,7 +194,7 @@ export class EventDecoder { "event SimpleTransferFlowCompleted(bytes32 indexed quoteNonce,address indexed finalRecipient,address indexed finalToken,uint256 evmAmountIn,uint256 bridgingFeesIncurred,uint256 evmAmountSponsored)", ]; let events: SimpleTransferFlowCompletedLog[] = - this.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); + EventDecoder.decodeTransactionReceiptLogs(receipt, eventTopic, eventAbi); if (contractAddress) { events = events.filter((event) => event.address === contractAddress); } @@ -217,7 +211,7 @@ export class EventDecoder { const eventAbi = [ "event ArbitraryActionsExecuted(bytes32 indexed quoteNonce, address indexed initialToken, uint256 initialAmount, address indexed finalToken, uint256 finalAmount)", ]; - let events: any[] = this.decodeTransactionReceiptLogs( + let events: any[] = EventDecoder.decodeTransactionReceiptLogs( receipt, eventTopic, eventAbi, @@ -238,7 +232,7 @@ export class EventDecoder { const eventAbi = [ "event FallbackHyperEVMFlowCompleted(bytes32 indexed quoteNonce, address indexed finalRecipient, address indexed finalToken, uint256 evmAmountIn, uint256 bridgingFeesIncurred, uint256 evmAmountSponsored)", ]; - let events: any[] = this.decodeTransactionReceiptLogs( + let events: any[] = EventDecoder.decodeTransactionReceiptLogs( receipt, eventTopic, eventAbi, From 2b62a020c816f32204a327da1c2d44d3ae3f79f2 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Wed, 19 Nov 2025 11:04:56 +0100 Subject: [PATCH 4/7] Refactor block hash collection and extract primary key columns in indexer data handlers --- .../data-indexing/service/CCTPIndexerDataHandler.ts | 11 ++++++++--- .../data-indexing/service/OFTIndexerDataHandler.ts | 7 ++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts b/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts index 78d01a22..adbfb935 100644 --- a/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts +++ b/packages/indexer/src/data-indexing/service/CCTPIndexerDataHandler.ts @@ -547,7 +547,12 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { const chainAgnosticSponsoredBurnEvents = sponsoredBurnEvents.map((event) => this.convertSponsoredDepositForBurnToChainAgnostic(event), ); - + const primaryKeyColumns = [ + "chainId", + "blockNumber", + "transactionHash", + "logIndex", + ]; const [ savedBurnEvents, savedMintEvents, @@ -582,7 +587,7 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { blocksTimestamps, formatSimpleTransferFlowCompletedEvent, entities.SimpleTransferFlowCompleted, - ["chainId", "blockNumber", "transactionHash", "logIndex"], + primaryKeyColumns as (keyof entities.SimpleTransferFlowCompleted)[], ), this.cctpRepository.formatAndSaveArbitraryActionsExecutedEvents( arbitraryActionsExecutedEvents, @@ -598,7 +603,7 @@ export class CCTPIndexerDataHandler implements IndexerDataHandler { blocksTimestamps, formatFallbackHyperEVMFlowCompletedEvent, entities.FallbackHyperEVMFlowCompleted, - ["chainId", "blockNumber", "transactionHash", "logIndex"], + primaryKeyColumns as (keyof entities.FallbackHyperEVMFlowCompleted)[], ), ]); diff --git a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts index f9544a9c..0637a146 100644 --- a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts +++ b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts @@ -161,8 +161,6 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { oftSentTransactions, oftSentEvents, ); - blockHashes.push(...filteredOftSentEvents.map((event) => event.blockHash)); - const filteredOftReceivedEvents = await this.filterTransactionsForSupportedEndpointIds(oftReceivedEvents); const filteredOftSentTransactionReceipts = @@ -170,6 +168,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { ...new Set(filteredOftSentEvents.map((event) => event.transactionHash)), ]); blockHashes.push( + ...filteredOftSentEvents.map((event) => event.blockHash), ...filteredOftReceivedEvents.map((event) => event.blockHash), ); @@ -203,15 +202,13 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { hypercoreFlowExecutorAddress, EventDecoder.decodeSimpleTransferFlowCompletedEvents, ); - blockHashes.push( - ...simpleTransferFlowCompletedEvents.map((event) => event.blockHash), - ); fallbackHyperEVMFlowCompletedEvents = getEventsFromTransactionReceipts( transactionReceipts, hypercoreFlowExecutorAddress, EventDecoder.decodeFallbackHyperEVMFlowCompletedEvents, ); blockHashes.push( + ...simpleTransferFlowCompletedEvents.map((event) => event.blockHash), ...fallbackHyperEVMFlowCompletedEvents.map( (event) => event.blockHash, ), From bed7ee08df639ae2a1340fc2f8eff23c6e039af8 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Wed, 19 Nov 2025 12:52:54 +0100 Subject: [PATCH 5/7] update delete function --- packages/indexer/src/database/OftRepository.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/indexer/src/database/OftRepository.ts b/packages/indexer/src/database/OftRepository.ts index df2c57b7..ed02b120 100644 --- a/packages/indexer/src/database/OftRepository.ts +++ b/packages/indexer/src/database/OftRepository.ts @@ -38,6 +38,12 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { lastFinalisedBlock, entities.OFTReceived, ), + this.deleteUnfinalisedEvents( + chainId, + chainIdColumn, + lastFinalisedBlock, + entities.FallbackHyperEVMFlowCompleted, + ), ]); return { From 7972caa31f8c1c482634a4bbce98db9d8a9b944d Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Wed, 19 Nov 2025 12:59:35 +0100 Subject: [PATCH 6/7] update delete function --- packages/indexer/src/database/OftRepository.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/indexer/src/database/OftRepository.ts b/packages/indexer/src/database/OftRepository.ts index 50c53cca..7c4b5a5b 100644 --- a/packages/indexer/src/database/OftRepository.ts +++ b/packages/indexer/src/database/OftRepository.ts @@ -29,6 +29,7 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { oftSentEvents, oftReceivedEvents, simpleTransferFlowCompletedEvents, + fallbackHyperEVMFlowCompletedEvents, ] = await Promise.all([ this.deleteUnfinalisedEvents( chainId, @@ -60,6 +61,7 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { oftSentEvents, oftReceivedEvents, simpleTransferFlowCompletedEvents, + fallbackHyperEVMFlowCompletedEvents, }; } From 1e1cf24c139f16f301b2b9403854a97d42357f46 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:34:43 +0100 Subject: [PATCH 7/7] feat: Add ArbitraryActionsExecuted event tracking to OFT indexer (#438) --- .../service/OFTIndexerDataHandler.ts | 35 +++++++++++++++++-- .../data-indexing/service/hyperEvmExecutor.ts | 30 ++++++++++++++++ .../indexer/src/database/OftRepository.ts | 8 +++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts index 14518bb7..36b2e8d8 100644 --- a/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts +++ b/packages/indexer/src/data-indexing/service/OFTIndexerDataHandler.ts @@ -5,6 +5,7 @@ import * as across from "@across-protocol/sdk"; import { entities, SaveQueryResult } from "@repo/indexer-database"; import { + ArbitraryActionsExecutedLog, BlockRange, FallbackHyperEVMFlowCompletedLog, SimpleTransferFlowCompletedLog, @@ -29,6 +30,7 @@ import { getEventsFromTransactionReceipts, } from "./eventProcessing"; import { + formatArbitraryActionsExecutedEvent, formatFallbackHyperEVMFlowCompletedEvent, formatSimpleTransferFlowCompletedEvent, } from "./hyperEvmExecutor"; @@ -40,6 +42,7 @@ export type FetchEventsResult = { sponsoredOFTSendEvents: SponsoredOFTSendLog[]; simpleTransferFlowCompletedEvents: SimpleTransferFlowCompletedLog[]; fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[]; + arbitraryActionsExecutedEvents: ArbitraryActionsExecutedLog[]; blocks: Record; }; export type StoreEventsResult = { @@ -48,6 +51,7 @@ export type StoreEventsResult = { sponsoredOFTSendEvents: SaveQueryResult[]; simpleTransferFlowCompletedEvents: SaveQueryResult[]; fallbackHyperEVMFlowCompletedEvents: SaveQueryResult[]; + arbitraryActionsExecutedEvents: SaveQueryResult[]; }; // Taken from https://hyperevmscan.io/tx/0xf72cfb2c0a9f781057cd4f7beca6fc6bd9290f1d73adef1142b8ac1b0ed7186c#eventlog#37 @@ -191,6 +195,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { []; let fallbackHyperEVMFlowCompletedEvents: FallbackHyperEVMFlowCompletedLog[] = []; + let arbitraryActionsExecutedEvents: ArbitraryActionsExecutedLog[] = []; const composeDeliveredEvents = await fetchEvents( this.provider, ENDPOINT_V2_ADDRESS, @@ -213,11 +218,17 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { dstOftHandlerAddress, EventDecoder.decodeFallbackHyperEVMFlowCompletedEvents, ); + arbitraryActionsExecutedEvents = getEventsFromTransactionReceipts( + transactionReceipts, + dstOftHandlerAddress, + EventDecoder.decodeArbitraryActionsExecutedEvents, + ); blockHashes.push( ...simpleTransferFlowCompletedEvents.map((event) => event.blockHash), ...fallbackHyperEVMFlowCompletedEvents.map( (event) => event.blockHash, ), + ...arbitraryActionsExecutedEvents.map((event) => event.blockHash), ); } } @@ -241,6 +252,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { sponsoredOFTSendEvents, simpleTransferFlowCompletedEvents, fallbackHyperEVMFlowCompletedEvents, + arbitraryActionsExecutedEvents, blocks, }; } @@ -257,14 +269,22 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { sponsoredOFTSendEvents, simpleTransferFlowCompletedEvents, fallbackHyperEVMFlowCompletedEvents, + arbitraryActionsExecutedEvents, } = events; const blocksTimestamps = this.getBlocksTimestamps(blocks); + const primaryKeyColumns = [ + "chainId", + "blockNumber", + "transactionHash", + "logIndex", + ]; const [ savedOftSentEvents, savedOftReceivedEvents, savedSponsoredOFTSendEvents, savedSimpleTransferFlowCompletedEvents, savedFallbackHyperEVMFlowCompletedEvents, + savedArbitraryActionsExecutedEvents, ] = await Promise.all([ this.oftRepository.formatAndSaveOftSentEvents( oftSentEvents, @@ -294,7 +314,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { blocksTimestamps, formatSimpleTransferFlowCompletedEvent, entities.SimpleTransferFlowCompleted, - ["chainId", "blockNumber", "transactionHash", "logIndex"], + primaryKeyColumns as (keyof entities.SimpleTransferFlowCompleted)[], ), formatAndSaveEvents( this.oftRepository, @@ -304,7 +324,17 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { blocksTimestamps, formatFallbackHyperEVMFlowCompletedEvent, entities.FallbackHyperEVMFlowCompleted, - ["chainId", "blockNumber", "transactionHash", "logIndex"], + primaryKeyColumns as (keyof entities.FallbackHyperEVMFlowCompleted)[], + ), + formatAndSaveEvents( + this.oftRepository, + arbitraryActionsExecutedEvents, + lastFinalisedBlock, + this.chainId, + blocksTimestamps, + formatArbitraryActionsExecutedEvent, + entities.ArbitraryActionsExecuted, + primaryKeyColumns as (keyof entities.ArbitraryActionsExecuted)[], ), ]); @@ -315,6 +345,7 @@ export class OFTIndexerDataHandler implements IndexerDataHandler { simpleTransferFlowCompletedEvents: savedSimpleTransferFlowCompletedEvents, fallbackHyperEVMFlowCompletedEvents: savedFallbackHyperEVMFlowCompletedEvents, + arbitraryActionsExecutedEvents: savedArbitraryActionsExecutedEvents, }; } diff --git a/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts b/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts index ab7450a1..6df8df39 100644 --- a/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts +++ b/packages/indexer/src/data-indexing/service/hyperEvmExecutor.ts @@ -1,4 +1,5 @@ import { + ArbitraryActionsExecutedLog, FallbackHyperEVMFlowCompletedLog, SimpleTransferFlowCompletedLog, } from "../model"; @@ -34,6 +35,35 @@ export const formatSimpleTransferFlowCompletedEvent = ( finalised, }); +/** + * @constant formatArbitraryActionsExecutedEvent + * Formats an `ArbitraryActionsExecutedLog` event into a partial `ArbitraryActionsExecuted` entity. + * @param event The `ArbitraryActionsExecutedLog` event to format. + * @param finalised A boolean indicating if the event is finalized. + * @param blockTimestamp The timestamp of the block where the event was emitted. + * @param chainId The ID of the chain where the event was emitted. + * @returns A partial `ArbitraryActionsExecuted` entity. + */ +export const formatArbitraryActionsExecutedEvent = ( + event: ArbitraryActionsExecutedLog, + finalised: boolean, + blockTimestamp: Date, + chainId: number, +): Partial => ({ + blockNumber: event.blockNumber, + logIndex: event.logIndex, + transactionHash: event.transactionHash, + transactionIndex: event.transactionIndex, + blockTimestamp: blockTimestamp, + chainId: chainId.toString(), + quoteNonce: event.args.quoteNonce, + initialToken: event.args.initialToken, + initialAmount: event.args.initialAmount.toString(), + finalToken: event.args.finalToken, + finalAmount: event.args.finalAmount.toString(), + finalised, +}); + /** * @constant formatFallbackHyperEVMFlowCompletedEvent * Formats a `FallbackHyperEVMFlowCompletedLog` event into a partial `FallbackHyperEVMFlowCompleted` entity. diff --git a/packages/indexer/src/database/OftRepository.ts b/packages/indexer/src/database/OftRepository.ts index 7c4b5a5b..e7079a02 100644 --- a/packages/indexer/src/database/OftRepository.ts +++ b/packages/indexer/src/database/OftRepository.ts @@ -30,6 +30,7 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { oftReceivedEvents, simpleTransferFlowCompletedEvents, fallbackHyperEVMFlowCompletedEvents, + arbitraryActionsExecutedEvents, ] = await Promise.all([ this.deleteUnfinalisedEvents( chainId, @@ -55,6 +56,12 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { lastFinalisedBlock, entities.FallbackHyperEVMFlowCompleted, ), + this.deleteUnfinalisedEvents( + chainId, + chainIdColumn, + lastFinalisedBlock, + entities.ArbitraryActionsExecuted, + ), ]); return { @@ -62,6 +69,7 @@ export class OftRepository extends dbUtils.BlockchainEventRepository { oftReceivedEvents, simpleTransferFlowCompletedEvents, fallbackHyperEVMFlowCompletedEvents, + arbitraryActionsExecutedEvents, }; }