16

Is there any method(ology) in web3 which allows to get the block number at a given date?

In particular, I have two dates as an input and I want to effectively get all events between those two dates. I know that I can do this by having block numbers:

contract.Event({}, { fromBlock: 100000, toBlock: 121212 })

But is it possible to do so with Dates? Thanks!

9 Answers 9

7

Ethfinex just published a function that does exactly that.

It's to "pixel perfect" but it's working really well so far, you give it a timestamp and it will walk the blockchain backwards until it finds a block that is very close.

During my tests it always found the nearest block, you might need to tweak it a little bit more.

https://github.com/ethfinex/efx-trustless-vol/blob/master/src/lib/getBlockByTime.js

here are some results

tgt timestamp   -> 1545523200
tgt date        -> 2018-12-23T00:00:00Z

block timestamp -> 1545523212
block date      -> 2018-12-23T00:00:12Z

requests made   -> 3

tgt timestamp   -> 1545609600
tgt date        -> 2018-12-24T00:00:00Z

block timestamp -> 1545609592
block date      -> 2018-12-23T23:59:52Z

requests made   -> 4
1
  • Thank you, this is the closest answer to what I've been looking for. Commented Dec 14, 2019 at 10:45
11

DeFiLlama has a new API that does this. https://defillama.com/docs/api

Just GET

https://coins.llama.fi/block/ethereum/1658171864

You can also check different chains

3

This is an old question, but recently I wrote a plugin for this kind of task. Usually, it makes fewer requests than Ethfinex's script does (usually, not always 😂).

Take a look: https://github.com/monosux/ethereum-block-by-date

2
  • 1
    Great work! It would be even greater if you could avoid using moment.js as a dependency (it's a really heavy module). Thanks! Commented Dec 14, 2019 at 10:44
  • Thanks :) Yeah, you are right, moment is heavy. I used it since I already had it in my project's dependencies. I think I can rewrite code to use moment as optional dependence or do not use moment at all. It will be cool if you create an issue in the repo: github.com/monosux/ethereum-block-by-date/issues So, I will not forget about this idea :)
    – mnsx
    Commented Dec 16, 2019 at 17:35
2

QuickBlocks has a command line program called 'whenBlock' that takes either a date (or timestamp) and takes the block number that occurred just prior, or a block number and returns the date and timestamp of that block. You can download QuickBlocks here: http://github.com/Great-Hill-Corporation/quickBlocks.

1

Not really.

Your best bet is to take a sample size loop from latest to latest - {x} block and get the moving average of block time creation. From there you can estimate a block number to get the block time from and loop until you cross the time you need.

1

Moralis have an API endpoint just for that, so if you already happen to use their API, there's no need to add another dependency.

https://docs.moralis.io/web3-data-api/evm/reference/get-date-to-block?chain=eth

1

Old question, new answer: findblock API provides you with two endpoints that can do just that

0

I've created a little function to do a binary search using ether.js.

export async function getBlockNumberByTimestamp(
    provider: JsonRpcProvider,
    timestamp: number
): Promise<number> {
    const getBlockTime = async (blockNumber: number) => (await provider.getBlock(blockNumber)).timestamp;
    
    let leftBlockNumber = 0;
    let leftTimestamp = await getBlockTime(leftBlockNumber);
    let rightBlockNumber = await provider.getBlockNumber();
    let rightTimestamp = await getBlockTime(rightBlockNumber);
    
    if (timestamp <= leftTimestamp) {
        return leftBlockNumber;
    }
    
    if (timestamp >= rightTimestamp) {
        return rightBlockNumber;
    }
    
    // eslint-disable-next-line no-constant-condition
    while (true) {
        const middleBlockNumber = leftBlockNumber + Math.floor((rightBlockNumber - leftBlockNumber) / 2);
        const middleTimestamp = await getBlockTime(rightBlockNumber);
        if (timestamp === middleTimestamp) {
            return middleBlockNumber;
        } else if (timestamp < middleTimestamp) {
            rightBlockNumber = middleBlockNumber;
            rightTimestamp = middleTimestamp;
        } else {
            leftBlockNumber = middleBlockNumber;
            leftTimestamp = middleTimestamp;
        }

        if (rightBlockNumber - leftBlockNumber <= 1) {
            return leftBlockNumber;
        }
    }
}

Didn't test it yet.
Will update the code when I have done the test.

0

You can use the https://chaintime.xyz to check the timestamp of a given block number on different chains.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.