Skip to content

Commit

Permalink
Merge pull request #60 from 0xPolygon/fix-invalid-response-err
Browse files Browse the repository at this point in the history
Fix invalid rpc response err handling
  • Loading branch information
nitinmittal23 authored Oct 30, 2024
2 parents b2be5f8 + a3d1a0e commit 2893fb1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 36 deletions.
98 changes: 65 additions & 33 deletions internal/block_getters/block_getter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Block, BlockTransactionObject, Eth, TransactionReceipt } from "web3-eth";
import {
Block,
BlockTransactionObject,
Eth,
TransactionReceipt,
} from "web3-eth";
import { ITransactionReceipt } from "../interfaces/transaction_receipt.js";
import { BlockProducerError } from "../errors/block_producer_error.js";
import { IWeb3Transaction } from "../interfaces/web3_transaction.js";
Expand All @@ -10,14 +15,14 @@ import { Logger } from "../logger/logger.js";

/**
* A wrapper class on web3 block related functions
*
*
* @author - Vibhu Rajeev, Nitin Mittal
*/
export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @param {Eth} eth - Eth module from web3.js
* @param {number} maxRetries - The number of times to retry on errors.
*
*
* @constructor
*/
constructor(protected eth: Eth, protected maxRetries: number = 0) {
Expand All @@ -27,9 +32,9 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @async
* Public method to query block data of a single block
*
*
* @param {number | string} blockNumber - Block number to query the block details for.
*
*
* @returns {Promise<Block>} - Block object
*/
public async getBlock(blockNumber: number | string): Promise<Block> {
Expand All @@ -39,16 +44,22 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @async
* Public method to query block data including transaction receipts of a single block.
*
* @param {number | string} blockNumber - The block number for which block data needs to be retrieved.
*
*
* @param {number | string} blockNumber - The block number for which block data needs to be retrieved.
*
* @returns {Promise<IBlock>} - Block object containing all details including transaction receipts.
*
*
* @throws {Error} - Throws error object on failure.
*/
public async getBlockWithTransactionReceipts(blockNumber: number | string, errorCount: number = 0): Promise<IBlock> {
public async getBlockWithTransactionReceipts(
blockNumber: number | string,
errorCount: number = 0
): Promise<IBlock> {
try {
const block: BlockTransactionObject = await this.eth.getBlock(blockNumber, true);
const block: BlockTransactionObject = await this.eth.getBlock(
blockNumber,
true
);

if (!block) {
throw new BlockProducerError(
Expand All @@ -60,7 +71,9 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
);
}

Logger.debug(`Fetching transaction receipts for the following block ${block.number}`);
Logger.debug(
`Fetching transaction receipts for the following block ${block.number}`
);

const transactions: ITransaction[] = [];

Expand All @@ -73,31 +86,40 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
);
}

return this.formatBlockWithTransactions(
block,
transactions
);
return this.formatBlockWithTransactions(block, transactions);
} catch (error) {
if (!(error instanceof BlockProducerError)) {
throw new BlockProducerError(
"Block producer error",
BlockProducerError.codes.RPC_ERR,
true,
JSON.stringify(error),
"remote"
);
}
if (errorCount > this.maxRetries) {
Logger.info({
location: "block_getter",
function: "getBlockWithTransactionReceipts",
errorCount,
error: JSON.stringify(error)
error: JSON.stringify(error),
});
throw error;
}

return await this.getBlockWithTransactionReceipts(blockNumber, errorCount + 1);
return await this.getBlockWithTransactionReceipts(
blockNumber,
errorCount + 1
);
}
}

/**
* @async
* Public method to query the current block number.
*
*
* @returns {Promise<number>} - the current block.
*
*
* @throws {Error} - Throws error object on failure.
*/
public getLatestBlockNumber(): Promise<number> {
Expand All @@ -106,43 +128,53 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {

/**
* @async
* This internal method retrieves the transaction receipt of the given transaction hash and retries upto retryLimit on failure.
*
* @param {string} transactionHash - The transaction hash for which transaction receipt is to be retrieved.
* @param {number} errorCount - Parameter for the function to know the number of times query has been retried.
* This parameter must ideally not be set by an external call.
*
* @returns {Promise<ITransactionReceipt>} - The transaction receipt of the given transaction hash. On failure throws error object.
*
* This internal method retrieves the transaction receipt of the given transaction hash and retries upto retryLimit on failure.
*
* @param {string} transactionHash - The transaction hash for which transaction receipt is to be retrieved.
* @param {number} errorCount - Parameter for the function to know the number of times query has been retried.
* This parameter must ideally not be set by an external call.
*
* @returns {Promise<ITransactionReceipt>} - The transaction receipt of the given transaction hash. On failure throws error object.
*
* @throws {Error} - Throws error object on failure.
*/
protected async getTransactionReceipt(transactionHash: string, errorCount: number = 0): Promise<ITransactionReceipt> {
protected async getTransactionReceipt(
transactionHash: string,
errorCount: number = 0
): Promise<ITransactionReceipt> {
try {
const transactionReceipt: TransactionReceipt = await this.eth.getTransactionReceipt(transactionHash);
const transactionReceipt: TransactionReceipt =
await this.eth.getTransactionReceipt(transactionHash);

if (transactionReceipt === null) {
throw new BlockProducerError(
"Block producer error",
BlockProducerError.codes.RECEIPT_NOT_FOUND,
false,
true,
`Transaction receipt not found for ${transactionHash}.`,
"remote"
);
}

return this.formatTransactionReceipt(transactionReceipt);
} catch (error) {
if (!(error instanceof BlockProducerError)) {
throw error;
}
if (errorCount > this.maxRetries) {
Logger.info({
location: "block_getter",
function: "getTransactionReceipt",
errorCount,
error: JSON.stringify(error)
error: JSON.stringify(error),
});
throw error;
}

return await this.getTransactionReceipt(transactionHash, errorCount + 1);
return await this.getTransactionReceipt(
transactionHash,
errorCount + 1
);
}
}
}
10 changes: 9 additions & 1 deletion internal/block_subscription/abstract_block_subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,12 @@ export abstract class AbstractBlockSubscription extends Queue<IBlockGetterWorker
if (
this.isReOrgedMissed(promiseResult.block)
) {
throw new Error("Chain re org not handled.");
throw new BlockProducerError(
"Chain reorg encountered",
BlockProducerError.codes.REORG_ENCOUNTERED,
true,
"Chain re org not handled",
"block_subscription");
}

this.observer.next(
Expand All @@ -211,6 +216,9 @@ export abstract class AbstractBlockSubscription extends Queue<IBlockGetterWorker
hash: promiseResult.block.hash
};
} catch (error) {
if (error instanceof BlockProducerError) {
this.observer.error(error);
}
this.fatalError = true;
this.observer.error(
BlockProducerError.createUnknown(error)
Expand Down
4 changes: 3 additions & 1 deletion internal/errors/error_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const codes = {
blockProducer: {
UNKNOWN_ERR: 4000,
RECEIPT_NOT_FOUND: 4001,
OBSERVER_NOT_SET: 4002
OBSERVER_NOT_SET: 4002,
REORG_ENCOUNTERED: 4003,
RPC_ERR: 4004
},

// Event consumer error codes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maticnetwork/chain-indexer-framework",
"version": "1.3.14",
"version": "1.3.15",
"description": "blockchain data indexer",
"type": "module",
"exports": {
Expand Down

0 comments on commit 2893fb1

Please sign in to comment.