From 85db7f9cfc7a0bab5f28157d61ac614c17ee0a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83t=C4=83lin=20Iordache?= <47974519+catalin-iordache@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:18:53 +0300 Subject: [PATCH 1/5] Refactor transaction processing to improve shard block fetching - Introduced a new method `fetchNextShardBlock` to encapsulate the logic for fetching the next shard block, improving code readability and maintainability. - Replaced the previous inline logic with a Promise.all call to fetch shard blocks concurrently, enhancing performance. - Retained existing logging for debugging purposes while streamlining nonce handling logic. --- src/transaction.processor.ts | 73 ++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/src/transaction.processor.ts b/src/transaction.processor.ts index 91739b1..b555e03 100644 --- a/src/transaction.processor.ts +++ b/src/transaction.processor.ts @@ -70,40 +70,21 @@ export class TransactionProcessor { do { reachedTip = true; - for (const shardId of this.shardIds) { - const currentNonce = currentNonces[shardId]; - let lastProcessedNonce = await this.getLastProcessedNonceOrCurrent(shardId, currentNonce); + const shardBlocks = await Promise.all( + this.shardIds.map(shardId => this.fetchNextShardBlock(shardId, currentNonces[shardId], options)), + ); - this.logMessage(LogTopic.Debug, `shardId: ${shardId}, currentNonce: ${currentNonce}, lastProcessedNonce: ${lastProcessedNonce}`); - - if (lastProcessedNonce === currentNonce) { - this.logMessage(LogTopic.Debug, 'lastProcessedNonce === currentNonce'); + for (const shardBlock of shardBlocks) { + if (shardBlock === undefined) { continue; } - // this is to handle the situation where the current nonce is reset - // (e.g. devnet/testnet reset where the nonces start again from zero) - if (lastProcessedNonce > currentNonce + NETWORK_RESET_NONCE_THRESHOLD) { - this.logMessage(LogTopic.Debug, `Detected network reset. Setting last processed nonce to ${currentNonce} for shard ${shardId}`); - lastProcessedNonce = currentNonce; - } - - if (lastProcessedNonce > currentNonce) { - this.logMessage(LogTopic.Debug, 'lastProcessedNonce > currentNonce'); - continue; - } - - if (options.maxLookBehind && currentNonce - lastProcessedNonce > options.maxLookBehind) { - lastProcessedNonce = currentNonce - options.maxLookBehind; - } + const { shardId, currentNonce, lastProcessedNonce, nonce, transactionsResult } = shardBlock; if (!startLastProcessedNonces[shardId]) { startLastProcessedNonces[shardId] = lastProcessedNonce; } - const nonce = lastProcessedNonce + 1; - - const transactionsResult = await this.getShardTransactions(shardId, nonce); if (transactionsResult === undefined) { this.logMessage(LogTopic.Debug, 'transactionsResult === undefined'); continue; @@ -343,6 +324,48 @@ export class TransactionProcessor { return crossShardTransactions; } + private async fetchNextShardBlock( + shardId: number, + currentNonce: number, + options: TransactionProcessorOptions, + ): Promise<{ + shardId: number; + currentNonce: number; + lastProcessedNonce: number; + nonce: number; + transactionsResult: { blockHash: string, transactions: ShardTransaction[] } | undefined; + } | undefined> { + let lastProcessedNonce = await this.getLastProcessedNonceOrCurrent(shardId, currentNonce); + + this.logMessage(LogTopic.Debug, `shardId: ${shardId}, currentNonce: ${currentNonce}, lastProcessedNonce: ${lastProcessedNonce}`); + + if (lastProcessedNonce === currentNonce) { + this.logMessage(LogTopic.Debug, 'lastProcessedNonce === currentNonce'); + return undefined; + } + + // this is to handle the situation where the current nonce is reset + // (e.g. devnet/testnet reset where the nonces start again from zero) + if (lastProcessedNonce > currentNonce + NETWORK_RESET_NONCE_THRESHOLD) { + this.logMessage(LogTopic.Debug, `Detected network reset. Setting last processed nonce to ${currentNonce} for shard ${shardId}`); + lastProcessedNonce = currentNonce; + } + + if (lastProcessedNonce > currentNonce) { + this.logMessage(LogTopic.Debug, 'lastProcessedNonce > currentNonce'); + return undefined; + } + + if (options.maxLookBehind && currentNonce - lastProcessedNonce > options.maxLookBehind) { + lastProcessedNonce = currentNonce - options.maxLookBehind; + } + + const nonce = lastProcessedNonce + 1; + const transactionsResult = await this.getShardTransactions(shardId, nonce); + + return { shardId, currentNonce, lastProcessedNonce, nonce, transactionsResult }; + } + private async getShardTransactions(shardId: number, nonce: number): Promise<{ blockHash: string, transactions: ShardTransaction[] } | undefined> { const result = await this.gatewayGet(`block/${shardId}/by-nonce/${nonce}?withTxs=true`); From 10dee8bc0c3935527cddc0426593eef711e0fa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83t=C4=83lin=20Iordache?= <47974519+catalin-iordache@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:23:39 +0300 Subject: [PATCH 2/5] Bump version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a1ee899..097f998 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-transaction-processor", - "version": "0.1.35", + "version": "0.2.0", "description": "Real-time transaction processor", "main": "lib/transaction.processor.js", "types": "lib/transaction.processor.d.ts", @@ -33,4 +33,4 @@ "dependencies": { "axios": "^1.7.4" } -} \ No newline at end of file +} From c6de513df5691d826b1287e4e940bf3e4d6a84f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83t=C4=83lin=20Iordache?= <47974519+catalin-iordache@users.noreply.github.com> Date: Thu, 10 Sep 2026 12:28:39 +0300 Subject: [PATCH 3/5] Fixes --- src/transaction.processor.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/transaction.processor.ts b/src/transaction.processor.ts index b555e03..b0d33e0 100644 --- a/src/transaction.processor.ts +++ b/src/transaction.processor.ts @@ -75,7 +75,7 @@ export class TransactionProcessor { ); for (const shardBlock of shardBlocks) { - if (shardBlock === undefined) { + if (shardBlock == null) { continue; } @@ -85,8 +85,8 @@ export class TransactionProcessor { startLastProcessedNonces[shardId] = lastProcessedNonce; } - if (transactionsResult === undefined) { - this.logMessage(LogTopic.Debug, 'transactionsResult === undefined'); + if (transactionsResult == null) { + this.logMessage(LogTopic.Debug, 'transactionsResult is null'); continue; } @@ -205,8 +205,8 @@ export class TransactionProcessor { const nonce = lastProcessedNonce + 1; const transactionsResult = await this.getHyperblockTransactions(nonce); - if (transactionsResult === undefined) { - this.logMessage(LogTopic.Debug, 'transactionsResult === undefined'); + if (transactionsResult == null) { + this.logMessage(LogTopic.Debug, 'transactionsResult is null'); continue; } From 30b927df9404ce6aab5ec0a10bdb0093d997f8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83t=C4=83lin=20Iordache?= <47974519+catalin-iordache@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:36:35 +0300 Subject: [PATCH 4/5] Fixes --- src/transaction.processor.ts | 13 +++++++++++-- tsconfig.json | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/transaction.processor.ts b/src/transaction.processor.ts index b0d33e0..9be7cd9 100644 --- a/src/transaction.processor.ts +++ b/src/transaction.processor.ts @@ -70,11 +70,20 @@ export class TransactionProcessor { do { reachedTip = true; - const shardBlocks = await Promise.all( + const shardBlockResults = await Promise.allSettled( this.shardIds.map(shardId => this.fetchNextShardBlock(shardId, currentNonces[shardId], options)), ); - for (const shardBlock of shardBlocks) { + for (const [index, result] of shardBlockResults.entries()) { + if (result.status === 'rejected') { + const shardId = this.shardIds[index]; + const reason = result.reason instanceof Error ? result.reason.message : String(result.reason); + this.logMessage(LogTopic.Error, `Failed to fetch next shard block for shardId ${shardId}: ${reason}`); + reachedTip = false; + continue; + } + + const shardBlock = result.value; if (shardBlock == null) { continue; } diff --git a/tsconfig.json b/tsconfig.json index 4dc02af..e352038 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "target": "es2015", + "lib": ["es2020"], "module": "commonjs", "declaration": true, "outDir": "./lib", From 366000b131f0e3f6c432ca13d29c507f02601f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83t=C4=83lin=20Iordache?= <47974519+catalin-iordache@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:47:37 +0300 Subject: [PATCH 5/5] Fix version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 097f998..cea9f88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-transaction-processor", - "version": "0.2.0", + "version": "0.1.36", "description": "Real-time transaction processor", "main": "lib/transaction.processor.js", "types": "lib/transaction.processor.d.ts",