adds a new overload of queryPastEvents allowing to query past events based on timestamp in the past

This commit is contained in:
Marcin Czenko 2024-09-26 16:22:50 +02:00
parent d47ce38894
commit 68cfce6363
No known key found for this signature in database
GPG Key ID: 33DEA0C8E30937C0
2 changed files with 82 additions and 2 deletions

View File

@ -1,6 +1,7 @@
import std/sequtils
# import std/sequtils
import std/strutils
import std/sugar
import std/strformat
# import std/sugar
import pkg/ethers
import pkg/upraises
import pkg/questionable
@ -423,3 +424,76 @@ method queryPastEvents*[T: MarketplaceEvent](
return await contract.queryFilter(T,
fromBlock,
BlockTag.latest)
proc blockNumberAndTimestamp(provider: Provider, blockTag: BlockTag):
Future[(UInt256, UInt256)] {.async.} =
without latestBlock =? await provider.getBlock(blockTag), error:
raise error
without latestBlockNumber =? latestBlock.number:
raise newException(EthersError, "Could not get latest block number")
(latestBlockNumber, latestBlock.timestamp)
proc blockNumberForEpoch(epochTime: int64, provider: Provider): Future[UInt256]
{.async.} =
let avgBlockTime = 13.u256
let epochTimeUInt256 = epochTime.u256
let (latestBlockNumber, latestBlockTimestamp) =
await blockNumberAndTimestamp(provider, BlockTag.latest)
let timeDiff = latestBlockTimestamp - epochTimeUInt256
let blockDiff = timeDiff div avgBlockTime
let estimatedBlockNumber = latestBlockNumber - blockDiff
let (estimatedBlockTimestamp, _) = await blockNumberAndTimestamp(
provider, BlockTag.init(estimatedBlockNumber))
var low = 0.u256
var high = latestBlockNumber
if estimatedBlockTimestamp < epochTimeUInt256:
low = estimatedBlockNumber
else:
high = estimatedBlockNumber
while low <= high:
let mid = (low + high) div 2
let (midBlockTimestamp, midBlockNumber) =
await blockNumberAndTimestamp(provider, BlockTag.init(mid))
if midBlockTimestamp < epochTimeUInt256:
low = mid + 1
elif midBlockTimestamp > epochTimeUInt256:
high = mid - 1
else:
return midBlockNumber
let (_, lowTimestamp) = await blockNumberAndTimestamp(
provider, BlockTag.init(low))
let (_, highTimestamp) = await blockNumberAndTimestamp(
provider, BlockTag.init(high))
try:
if abs(lowTimestamp.stint(256) - epochTimeUInt256.stint(256)) <
abs(highTimestamp.stint(256) - epochTimeUInt256.stint(256)):
low
else:
high
except ValueError as e:
raise newException(EthersError, fmt"Conversion error: {e.msg}")
method queryPastEvents*[T: MarketplaceEvent](
market: OnChainMarket,
_: type T,
fromTime: int64): Future[seq[T]] {.async.} =
convertEthersError:
let contract = market.contract
let provider = contract.provider
let blockNumberForEpoch = await blockNumberForEpoch(fromTime, provider)
let fromBlock = BlockTag.init(blockNumberForEpoch)
return await contract.queryFilter(T,
fromBlock,
BlockTag.latest)

View File

@ -248,3 +248,9 @@ method queryPastEvents*[T: MarketplaceEvent](
_: type T,
blocksAgo: int): Future[seq[T]] {.base, async.} =
raiseAssert("not implemented")
method queryPastEvents*[T: MarketplaceEvent](
market: Market,
_: type T,
fromTime: int64): Future[seq[T]] {.base, async.} =
raiseAssert("not implemented")