15

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!

nikitaeverywhere
  • 307
  • 1
  • 2
  • 9

9 Answers9

9

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

cwatkins
  • 191
  • 1
  • 4
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
kroe
  • 226
  • 3
  • 5
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

mnsx
  • 31
  • 1
  • 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! – nikitaeverywhere Dec 14 '19 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: https://github.com/monosux/ethereum-block-by-date/issues So, I will not forget about this idea :) – mnsx Dec 16 '19 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.

Thomas Jay Rush
  • 9,943
  • 4
  • 31
  • 72
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

rioted
  • 111
  • 3
1

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

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.

ReyHaynes
  • 1,515
  • 7
  • 12
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 &lt;= leftTimestamp) {
    return leftBlockNumber;
}

if (timestamp &gt;= 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 &lt; middleTimestamp) {
        rightBlockNumber = middleBlockNumber;
        rightTimestamp = middleTimestamp;
    } else {
        leftBlockNumber = middleBlockNumber;
        leftTimestamp = middleTimestamp;
    }

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

}

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

kitta
  • 157
  • 7
0

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