diff --git a/packages/client/src/rpc/modules/eth.ts b/packages/client/src/rpc/modules/eth.ts index 7acd32f8571..9f5e60a06a8 100644 --- a/packages/client/src/rpc/modules/eth.ts +++ b/packages/client/src/rpc/modules/eth.ts @@ -100,6 +100,7 @@ type JSONRPCLog = { transactionHash: string | null // DATA, 32 Bytes - hash of the transactions this log was created from. null when it's pending. blockHash: string | null // DATA, 32 Bytes - hash of the block where this log was in. null when it's pending. blockNumber: string | null // QUANTITY - the block number where this log was in. null when it's pending. + blockTimestamp: string | null // QUANTITY - the block timestamp where this log was in. null when it's pending. address: string // DATA, 20 Bytes - address from which this log originated. data: string // DATA - contains one or more 32 Bytes non-indexed arguments of the log. topics: string[] // Array of DATA - Array of 0 to 4 32 Bytes DATA of indexed log arguments. @@ -174,6 +175,7 @@ const toJSONRPCLog = async ( transactionHash: tx !== undefined ? bytesToHex(tx.hash()) : null, blockHash: block ? bytesToHex(block.hash()) : null, blockNumber: block ? bigIntToHex(block.header.number) : null, + blockTimestamp: block ? bigIntToHex(block.header.timestamp) : null, address: bytesToHex(log[0]), topics: log[1].map(bytesToHex), data: bytesToHex(log[2]), diff --git a/packages/client/test/rpc/eth/getLogs.spec.ts b/packages/client/test/rpc/eth/getLogs.spec.ts index a8f81e35681..088cc826b64 100644 --- a/packages/client/test/rpc/eth/getLogs.spec.ts +++ b/packages/client/test/rpc/eth/getLogs.spec.ts @@ -1,5 +1,11 @@ import { createLegacyTx } from '@ethereumjs/tx' -import { bytesToHex, createContractAddress, hexToBytes } from '@ethereumjs/util' +import { + bigIntToHex, + bytesToHex, + createContractAddress, + hexToBigInt, + hexToBytes, +} from '@ethereumjs/util' import { assert, describe, it } from 'vitest' import { INVALID_PARAMS } from '../../../src/rpc/error-code.ts' @@ -75,7 +81,7 @@ describe(method, async () => { { common }, ).sign(dummy.privKey) - await runBlockWithTxs(chain, execution, [tx1, tx2, tx3, tx4]) + let block = await runBlockWithTxs(chain, execution, [tx1, tx2, tx3, tx4]) // compare the logs let res = await rpc.request(method, [{ fromBlock: 'earliest', toBlock: 'latest' }]) @@ -100,6 +106,12 @@ describe(method, async () => { assert.fail(`should return the correct logs (fromBlock/toBlock as 'earliest' and 'latest')`) } + assert.strictEqual( + hexToBigInt(res.result[0].blockTimestamp), + block.header.timestamp, + `should return the correct blockTimestamp (fromBlock/toBlock as 'earliest' and 'latest')`, + ) + // get the logs using fromBlock/toBlock as numbers res = await rpc.request(method, [{ fromBlock: '0x0', toBlock: '0x1' }]) assert.strictEqual( @@ -206,6 +218,40 @@ describe(method, async () => { 20, 'should return the correct logs (filter by blockHash)', ) + + // test adding more logs and checking timestamps against multiple blocks + const tx5 = createLegacyTx( + { + ...txData, + data, + to: contractAddr1, + nonce: 4, + }, + { common }, + ).sign(dummy.privKey) + const tx6 = createLegacyTx( + { + ...txData, + data, + to: contractAddr2, + nonce: 5, + }, + { common }, + ).sign(dummy.privKey) + + const block1Timestamp = bigIntToHex(block.header.timestamp) + block = await runBlockWithTxs(chain, execution, [tx5, tx6]) + const block2Timestamp = bigIntToHex(block.header.timestamp) + + res = await rpc.request(method, [{ fromBlock: 'earliest', toBlock: 'latest' }]) + const block1Logs: any[] = res.result.filter((log: any) => log.blockNumber === '0x1') + const block2Logs: any[] = res.result.filter((log: any) => log.blockNumber === '0x2') + + assert.isTrue( + block1Logs.every((log) => log.blockTimestamp === block1Timestamp) && + block2Logs.every((log) => log.blockTimestamp === block2Timestamp), + 'should return the correct log timestamps across multiple blocks', + ) }) it('call with invalid params', async () => {