diff --git a/CHANGELOG.md b/CHANGELOG.md index ec39f42a5..42b9f87ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.2.7] - 2024.2.12 + +### Updated + +- Updated archive condition for evm rpc calls + ## [4.2.6] - 2024.2.12 ### Added diff --git a/README.md b/README.md index f12afce76..db952d7bf 100644 --- a/README.md +++ b/README.md @@ -405,6 +405,28 @@ All RPC calls are implemented in the `tatum.rpc.*` submodule. See the [RPC API Reference](https://docs.tatum.io/docs/rpc-api-reference) for more about supported chains and methods. +### Distinguishing Between Archive and Full Nodes + +When interacting with the blockchain, it's essential to know whether a JSON RPC call requires an archive node or can be serviced by a full node. The distinction hinges on the type of data requested and the historical depth of that data. Here's a breakdown of the conditions under which a call is classified for an archive or a full node: + +#### Archive Node Calls + +Archive nodes store the entire history of the blockchain, including the state of all accounts at every block. Calls that require an archive node typically involve querying historical states. Conditions include: + +1. **Calls to Methods `getCode` or `call`**: Always require an archive node because they may query the state at any block height. + +2. **Calls Including `debug` or `trace` Methods**: These methods require historical data not available on full nodes. + +3. **Parameters Indicating a Specific Block Number**: For following methods, if the call specifies a block number, it requires an archive node. This includes: + - `getStorageAt` with a specific block number. + - `getBalance` with a specific block number. + - `getBlockByNumber` when a block number is specified. + - `getLogs` calls where `fromBlock` or `toBlock` specify a block number other than the latest. + +#### Full Node Calls + +Any other calls not meeting the conditions for archive node calls can be serviced by a full node. These calls typically involve querying the current state of the blockchain. + ### Status Pages This section provides a list of various blockchain network status pages, powered by Tatum. These links direct you to real-time status updates for each network. diff --git a/package.json b/package.json index 897c966d1..bd752c9c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tatumio/tatum", - "version": "4.2.6", + "version": "4.2.7", "description": "Tatum JS SDK", "author": "Tatum", "repository": "https://github.com/tatumio/tatum-js", diff --git a/src/service/rpc/evm/EvmUtils.spec.ts b/src/service/rpc/evm/EvmUtils.spec.ts new file mode 100644 index 000000000..151f0cb3d --- /dev/null +++ b/src/service/rpc/evm/EvmUtils.spec.ts @@ -0,0 +1,42 @@ +import { EvmUtils } from './EvmUtils' + +describe('EvmUtils', () => { + describe('isArchiveMethod', () => { + it.each([ + ['eth_getCode', true], + ['eth_call', true], + ['debug', true], + ['trace', true], + ['getStorageAt', false], + ['eth_call', true], + ['getBalance', false], + ['eth_getCode', true], + ['getBlockByNumber', false], + ['getLogs', false], + ['other', false], + ])('archive method %s -> %s', (method, expected) => { + expect(EvmUtils.isArchiveMethod({ method, id: 2, jsonrpc: 'test' })).toBe(expected) + }) + + it.each([ + ['getStorageAt', [1, 2], false], + ['getStorageAt', [1, 2, 'latest'], false], + ['getStorageAt', [1, 2, 3], true], + ['getStorageAt', [], false], + ['getBalance', [1], false], + ['getBalance', [1, 'latest'], false], + ['getBalance', [1, 2], true], + ['getBalance', [], false], + ['getBlockByNumber', [], false], + ['getBlockByNumber', ['latest'], false], + ['getBlockByNumber', [1], true], + ['getLogs', [1, { fromBlock: 'latest' }], false], + ['getLogs', [1, { fromBlock: 'latest', toBlock: 'latest' }], false], + ['getLogs', [1, { toBlock: 'latest' }], false], + ['getLogs', [1, { toBlock: 1 }], true], + ['getLogs', [1, { fromBlock: 1 }], true], + ])('archive method & param %s -> %s', (method, params, expected) => { + expect(EvmUtils.isArchiveMethod({ method, params, id: 2, jsonrpc: 'test' })).toBe(expected) + }) + }) +}) diff --git a/src/service/rpc/evm/EvmUtils.ts b/src/service/rpc/evm/EvmUtils.ts index a19938910..1410c8956 100644 --- a/src/service/rpc/evm/EvmUtils.ts +++ b/src/service/rpc/evm/EvmUtils.ts @@ -1,47 +1,19 @@ import { JsonRpcCall } from '../../../dto' -export const ARCHIVE_METHODS = [ - // Archival information - 'debug_getBadBlocks', - 'debug_storageRangeAt', - 'debug_traceCall', - 'debug_traceTransaction', - 'debug_traceBlock', - 'debug_traceBlockByHash', - 'debug_traceBlockByNumber', - 'trace_block', - 'trace_call', - 'trace_callMany', - 'trace_rawTransaction', - 'trace_replayBlockTransactions', - - // Network state - 'getBlockByHash', - 'getTransactionByHash', - 'getTransactionReceipt', - 'getUncleCountByBlockHash', - 'getUncleCountByBlockNumber', - 'getBlockTransactionCountByHash', - 'getBlockTransactionCountByNumber', - 'getBlockReceipts', - 'getTransactionByBlockHashAndIndex', - 'getTransactionByBlockNumberAndIndex', - 'getTransactionCount', - 'getProof', -] +export const ARCHIVE_METHODS = ['getCode', 'call'] export const POSSIBLE_ARCHIVE_METHODS = [ - // Network state { method: 'getStorageAt', index: 2 }, - { method: 'call', index: 1 }, { method: 'getBalance', index: 1 }, - { method: 'getCode', index: 1 }, { method: 'getBlockByNumber', index: 0 }, ] export const EvmUtils = { isArchiveMethod(rpc: JsonRpcCall): boolean { - const isArchiveMethod = ARCHIVE_METHODS.find((method) => rpc.method.includes(method)) + const isArchiveMethod = + ARCHIVE_METHODS.find((method) => rpc.method.includes(method)) || + rpc.method?.includes('debug') || + rpc.method?.includes('trace') if (isArchiveMethod) { return true }