Есть ли какой-либо метод (логия) в web3, который позволяет получить номер блока на заданную дату?
В частности, у меня есть две даты в качестве входных данных, и я хочу эффективно получать все события между этими двумя датами. Я знаю, что могу сделать это, имея номера блоков:
contract.Event({}, { fromBlock: 100000, toBlock: 121212 })
Но возможно ли это сделать с помощью Date
s? Спасибо!
Ethfinex только что опубликовал функцию, которая делает именно это.
Это «пиксельное совершенство», но пока он работает очень хорошо, вы даете ему временную метку, и он будет проходить блокчейн в обратном направлении, пока не найдет блок, который очень близок.
Во время моих тестов он всегда находил ближайший блок, возможно, вам придется немного его настроить.
https://github.com/ethfinex/efx-trustless-vol/blob/master/src/lib/getBlockByTime.js
вот некоторые результаты
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
Это старый вопрос, но недавно я написал плагин для такого рода задач. Обычно он делает меньше запросов, чем скрипт Ethfinex (как правило, не всегда 😂).
Взгляните: https://github.com/monosux/ethereum-block-by-date
QuickBlocks имеет программу командной строки под названием «whenBlock», которая принимает либо дату (или отметку времени) и номер блока, который произошел непосредственно перед этим, либо номер блока и возвращает дату и отметку времени этого блока. Вы можете скачать QuickBlocks здесь: http://github.com/Great-Hill-Corporation/quickBlocks .
У DeFiLlama есть новый API, который делает это. https://defillama.com/docs/api
Просто ПОЛУЧИТЕ
https://coins.llama.fi/block/ethereum/1658171864
Вы также можете проверить различные цепи
Не совсем.
Лучше всего взять цикл размера выборки от latest
до latest - {x}
блока и получить скользящее среднее время создания блока. Оттуда вы можете оценить номер блока, чтобы получить время блока, и зацикливаться, пока не пересечете нужное время.
Я создал небольшую функцию для бинарного поиска с использованием 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;
}
}
}
Еще не проверял.
Обновлю код, когда сделаю тест.
ЗитРо