Skip to content

[BCN] Vendor block-by-date helper for Alchemy + MultiProvider#4172

Open
leolambo wants to merge 5 commits into
bitpay:masterfrom
leolambo:alchemyBlockByDateVendor
Open

[BCN] Vendor block-by-date helper for Alchemy + MultiProvider#4172
leolambo wants to merge 5 commits into
bitpay:masterfrom
leolambo:alchemyBlockByDateVendor

Conversation

@leolambo
Copy link
Copy Markdown
Contributor

@leolambo leolambo commented May 19, 2026

Description

The Alchemy adapter and MultiProvider's verification fallback were both running handwritten binary searches over eth_getBlockByNumber to resolve date to block. Both now use a small in-tree helper ported from monosux/ethereum-block-by-date that uses average-block-time interpolation instead. Typically converges in fewer RPC calls than vanilla bisect and handles future-date and pre-genesis edges.

This is the vendor counterpart to #4167. Same algorithm, but ported into ~120 lines under src/utils/ethDater.ts so we don't pull in ethereum-block-by-date and its moment transitive dep. Pick one PR to merge; the other can be closed.

Changelog

  • Add src/utils/ethDater.ts (port of the getDate path, no moment, native Date + unix-second math)
  • Use EthDater in the Alchemy adapter's getBlockNumberByDate
  • Use EthDater in MultiProvider's _verifyBlockBeforeDate fallback (replaces _binarySearchBlockByTimestamp)
  • Cache EthDater instances per chain:network (Alchemy) / per network (MultiProvider) so boundary state survives across calls
  • Add unit tests for the vendored module (boundaries, interpolation, per-call probe cache, bigint timestamps) plus tests for the new wiring

Testing Notes

hit any date-to-block resolving endpoint on a chain backed by Alchemy or MultiProvider (e.g., GET /api/<chain>/<network>/block/before/<timestamp>) and verify the block returned matches what the previous bisect would have returned. The bounded RPC walk in MultiProvider remains unchanged, so the common case still finishes in ≤16 hops without invoking the new helper.


Checklist

  • I have read CONTRIBUTING.md and verified that this PR follows the guidelines and requirements outlined in it.
  • I have added the appropriate package tag(s) (e.g. `BWC` if modifying the bitcore-wallet-client package, `CLI` if modifying the bitcore-cli package, etc.)
  • I have verified that this is not an existing PR (open or closed)

leolambo added 3 commits May 18, 2026 16:00
Ports the getDate path from monosux/ethereum-block-by-date as a tiny
local module. Trims everything we don't use: no getEvery, no viem
support, no moment dep (native Date + unix-second math). Owning the
algorithm in-tree lets the Alchemy adapter and MultiProvider fallback
share an interpolation-based block lookup without pulling moment into
bitcore-node.
Replaces the handwritten binary search in getBlockNumberByDate with
the interpolation-based EthDater. Typically converges in fewer RPC
calls than vanilla bisect, and handles future-date and pre-genesis
edges for us. Daters are cached per chain:network so repeated lookups
reuse the boundary state.
Replaces the in-CSP binary search fallback (invoked when the bounded
walk in _verifyBlockBeforeDate can't converge in 16 RPC steps) with
the vendored EthDater. The bounded walk remains the fast path that
nudges adapter-returned candidates; EthDater only runs when the
candidate is too far off. Daters are cached per network so the
boundary state survives across calls.
@leolambo leolambo force-pushed the alchemyBlockByDateVendor branch from 3736f23 to ddad38f Compare May 19, 2026 21:20
leolambo added 2 commits May 19, 2026 17:23
The test queried a 10000-block range to verify three transfers all
clustered within ~510 blocks. getErc20Transfers walks in 100-block
windows, so the wide range cost ~200 sequential eth_getLogs calls and
routinely tripped the 10s in-test timeout on the public Base sepolia
RPC. Same expected payload, ~10 calls now.
The fakeWeb3 helper claimed 'latest' as a valid key on its input map
but no caller passed it (we compute the latest block number from the
max numeric key). Strict tsc on CI rejected the mismatch. Narrow the
parameter type so callers compile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant