I understand from HIP-415: Introduction Of Blocks, that Hedera now has blocks, and they're based on timestamps of the transactions being grouped together into "record files" which are an artefact of how they are ingested into the Hedera mirror nodes (from the Hedera consensus nodes). Essentially all transactions that are inside the same record file are considered to be in the same block as well, and these blocks are produced approximately every 2 seconds.
Is there a way that I can convert a date (timestamp) into a block number?
My objective is to be able to invoke eth_getBlockByNumber
,
and I need work out the first parameter for that RPC request
based on timestamp.
curl -s -X POST \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"2","method":"eth_getBlockByNumber","params":[MY_BLOCK_NUM, false]}' \
http://localhost:7546
(Need to work out MY_BLOCK_NUM
in the ^ command above.)
For example, here's block 4507206,
which corresponds to the record file 2023-05-10T08_27_52.012122604Z.rcd.gz
,
and contains all transactions between
08:27:52.0121
and 08:27:53.7004
in UTC today.
Suppose I did not know both what the block number was,
or what the record file was.
I only have a single timestamp,
and I want to find the corresponding block number from it.
How can I do this (programmatically)?
First, get the Unix timestamp for the date and time that you need. Use the -u
flag if you want to specify the date/ time in UTC (otherwise default to the timezone on your computer).
TIMESTAMP=$(date -u -j -f "%F %T" "2023-05-10 08:27:52" "+%s")
(Sample result: 1683707272
)
Next, make an API request to the Hedera mirror node API:
/api/v1/blocks
- Responds with a list of blockstimestamp=gte:${TIMESTAMP}
- Use this to specify the timestamp that you have from the previous step. The gte
is a filter to say that you only want block whose timestamp is greater than or equal to the one you have specified.limit=1
and order=asc
- These combine with the above to further sort and filter the query such that it only returns the first block that comes after the specified timestamp.
curl -s "https://testnet.mirrornode.hedera.com/api/v1/blocks?limit=1&order=asc×tamp=gte:${TIMESTAMP}" | jq
We repeat the same command as above, but this time extract the blocknumber out of the full response object using a jq
path.
BLOCKNUM=$( curl -s "https://testnet.mirrornode.hedera.com/api/v1/blocks?limit=1&order=asc×tamp=gte:${TIMESTAMP}" | jq ".blocks[].number" )
(Sample result: 4507206
)
And that's all, you now have your block number!
But let's go one step further to demonstrate that this block number can be used outside of the Hedera mirror node APIs (which are custom, and specific to Hedera).
Let's use this value in JSON-RPC, and obtain the block from there!
Convert that block number to hexadecimal using printf
.
BLOCKNUMHEX=$( printf "0x%x\n" ${BLOCKNUM} )
(Sample result: 0x44c646
)
Make a JSON-RPC request to an instance of hedera-json-rpc-relay
. If you have one running locally, the endpoint is exposed at http://localhost:7546
by default. If you don't have that running, there are other options.
curl -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":"2","method":"eth_getBlockByNumber","params":["'"${BLOCKNUMHEX}"'", false]}' http://localhost:7546 | jq ".result"