Skip to content

Test onEvent where from config.yaml to rows over real HyperSync and RPC sources - #1762

Merged
DZakh merged 5 commits into
mainfrom
claude/quirky-allen-575h83-where-tests
Oct 22, 2026
Merged

DZakh merged 5 commits into
mainfrom
claude/quirky-allen-575h83-where-tests

Conversation

@DZakh

@DZakh DZakh commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Replaces the white-box onEvent where tests with tests from the outside. The old tests asserted on resolved topic selections, parseWhereOrThrow output and registration fields. The new ones run a real config.yaml, real handler source and the real indexer loop on Postgres. The real HyperSync and RPC sources fetch from local servers that return only the logs the query's filter matches. The tests assert two things: the rows the handlers wrote, and the filters each source sent.

This is groundwork for anonymous EVM events (discussed on #1706). That work changes how topics are assembled, and these tests don't depend on the internals it touches. Production code is unchanged.

Harness

  • mock_hypersync_server.rs (test-only):
    • A fixed port. config.yaml is parsed while vitest collects, before any hook runs.
    • Accepts Cap'n Proto queries, which is what a config-built client sends, including the query-id "not cached" round trip. They are re-serialized to JSON for takeQueries.
    • A chain mode that answers any query with the matching logs and blocks.
  • Scenario.run ~yamlSources: every chain keeps the source its YAML names instead of MockSource.
  • ServedEvmChain:
    • Serves one log set over both HyperSync and RPC (eth_getLogs filtered on address and topics).
    • Normalizes each source's filters into {fromBlock, filters: [{address, topics}]}.
    • Shares the chain YAML, a Routed schema and handler (one row per log, keyed chain-block-logIndex-name), and a run that drains old queries, runs the scenario and waits for every chain to reach its end block.

Old → new

Old (white-box) New (outside-in)
EventFilters: every indexed type, boundary values, complex topics, RPC client OnEventWhereParams: a matching and a non-matching log per type, rows over HyperSync (chains 1, 2) and RPC (chains 3, 4)
EventFilters: multichain callback, checksummed addresses, wildcard callback OnEventWhereParams Transfer
EventFilters / ClientAddressFilter: chain.X.addresses, address-param groups OnEventWhereAddresses: rows plus the address topics sent, including an address registered mid-run and client-side filtering
EventFilters: params: [], equal-resolving second registration, where: false OnEventWhereParams Unfiltered / Dropped (no rows, no raw_events)
EventBlockFilter: _gte, block + params, true/false/per-chain callbacks, start_block override, first fromBlock OnEventWhereBlock: rows and first from_block on both sources
EventBlockFilter / EventFilters / ClientAddressFilter / HandlerRegisterLifecycle: registration errors OnEventWhereErrors: exact text
OnEventRegistration: wildcard + where OnEventWhereParams Dropped
HandlerRegister: handler vs contractRegister where, callback once per chain, where: false + raw events OnEventWhereAddresses; a WhereCalls entity; a raw_events assertion
EventBlockFilter: Fuel block.height / block.number FuelOnEventWhere (expected failure, see below)

Deleted:

  • EventFilters_test.res, EventBlockFilter_test.res and ClientAddressFilter_test.res.
  • The where cases in OnEventRegistration_test, HandlerRegister_test and HandlerRegisterLifecycle_test. Their onBlock tests stay.
  • HandlerRegister_test.res was also reformatted by the formatter hook; it wasn't formatted on main.

Gaps found (kept as expected failures)

  1. Fuel ignores where. buildFuelOnEventRegistration drops it, so block.height._gte never sets a start block and block.number is never rejected. The old tests called parseWhereOrThrow with the Fuel schema directly, a path Fuel itself never takes.
  2. An AND of chain.X.addresses params misses logs across address partitions. Take {from: addresses, to: addresses}, with one address from config and one added by contractRegister. HyperSync is queried with from∈{R1},to∈{R1} and from∈{R2},to∈{R2}, so the transfer R1→R2 is never fetched. It works when both addresses are configured, and with client-side filtering. Turning this case into a normal test fails with expected [] to deeply equal ['1-9-0-Moved','2-9-0-Moved'].

Not reproduced from the outside: a where callback on a handler registered before startRegistration. The old test only asserted that nothing threw.

Verification

  • cargo fmt --check and cargo clippy --all-targets --all-features -D warnings are clean. Mock-server Rust tests: 6/6.
  • Postgres, after merging main, on 12 files (the new ones, the touched ones, WhereStartBlockStall, RegistrationStartBlock, HyperSyncSourceContract, SharedAddressRouting): 59 passed + 3 expected failures. The run was repeated twice after the simplification, with the same result.
  • ClickHouse (ENVIO_TEST_STORAGE=clickhouse) on the scenario files: 7 passed + 1 expected failure.
  • Breaking two of the simplified expectations on purpose (an address row's block, the lone event's first block) fails them.
  • pnpm lint and rescript format --check are clean.
  • The HyperSync chains need ENVIO_API_TOKEN, which the envio-tests CI job already gets.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WdwJuj1pgyeoPb8vfekdfy

Summary by CodeRabbit

  • New Features
    • Local test servers can use a requested or automatically assigned port, serve configured chain data, and handle JSON and Cap’n Proto queries.
  • Tests
    • Added integration coverage for event filtering by block range, indexed parameters, and configured addresses across HyperSync and RPC.
    • Added validation scenarios for unsupported event filters and Fuel block-height filtering.
    • Added test support for serving matching chain data through local HyperSync and JSON-RPC endpoints.

A Scenario chain can now be left unmocked with `~servedChains`, so its
config.yaml HyperSync or RPC url reaches a local server and the real source
builds, sends and decodes the query. The mock HyperSync server gains a fixed
port, the Cap'n Proto query format the configured client sends by default,
and a chain mode that answers each query with the logs its selection
matches. `ServedEvmChain` serves one set of logs over both HyperSync and
JSON-RPC, filtering eth_getLogs the same way, and reads back the filters each
source sent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdwJuj1pgyeoPb8vfekdfy
The `where` coverage asserted on resolved topic selections, parser output and
registration fields. It now runs the real indexer loop on Postgres against
served chains, over HyperSync and RPC alike, and asserts the rows the
handlers wrote and the filters each source sent: every indexed param type,
OR alternatives, per-chain callbacks, `false`, chain.<Contract>.addresses
(including an address registered mid-run and client-side filtering), and
block start blocks. Registration errors are asserted from a user test
module calling indexer.onEvent.

Two cases can't pass from the outside today and are marked as expected
failures: a Fuel registration drops its `where` entirely, and an AND of
address params misses a log whose addresses sit in different address
partitions when queried server-side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdwJuj1pgyeoPb8vfekdfy
@DZakh
DZakh deployed to internal October 20, 2026 15:36 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 585dba72-8380-47db-ad95-78f29797dbac
📥 Commits

Reviewing files that changed from the base of the PR and between 073c1cb and 54e460b.

📒 Files selected for processing: 6
  • packages/envio-tests/test/helpers/TestChainMetrics.res
  • packages/envio/src/Config.res
  • packages/envio/src/Internal.res
  • packages/envio/src/LogSelection.res
  • packages/envio/src/TopicFilter.res
  • packages/envio/src/bindings/Viem.res
💤 Files with no reviewable changes: 6
  • packages/envio/src/Internal.res
  • packages/envio/src/bindings/Viem.res
  • packages/envio-tests/test/helpers/TestChainMetrics.res
  • packages/envio/src/Config.res
  • packages/envio/src/LogSelection.res
  • packages/envio/src/TopicFilter.res

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.

📝 Walkthrough

The mock HyperSync server now supports optional fixed ports, Cap’n Proto queries, and responses generated from configured chain data. Test helpers add local HyperSync and RPC sources. Integration tests add and adjust coverage for event block, address, and parameter filters.

Changes: Served-chain event filter testing

Layer / File(s) Summary
Chain-backed HyperSync mock responses
packages/cli/src/mock_hypersync_server.rs, packages/envio-tests/test/helpers/MockHyperSyncServer.res
The mock server accepts an optional port, handles Cap’n Proto queries, and can answer unqueued queries from configured chain data. The test helper exposes port configuration and chain setup.
Served-chain test harness
packages/envio-tests/test/helpers/ServedEvmChain.res, packages/envio-tests/test/helpers/Scenario.res
The helpers serve chain data through HyperSync and RPC, match RPC log filters, and capture normalized queries. Scenario helpers can retain YAML-configured sources for local-server scenarios.
Block-filter coverage and validation
packages/envio-tests/test/OnEventWhereBlock_test.res, packages/envio-tests/test/FuelOnEventWhere_test.res, packages/envio-tests/test/OnEventWhereErrors_test.res, packages/envio-tests/test/EventBlockFilter_test.res, packages/envio-tests/test/HandlerRegisterLifecycle_test.res, packages/envio-tests/test/helpers/TestChainMetrics.res
New tests cover block predicates, fetch start heights, and invalid filters across EVM and Fuel scenarios. The earlier block-filter suite and selected lifecycle tests were removed.
Parameter and address filter coverage
packages/envio-tests/test/OnEventWhereParams_test.res, packages/envio-tests/test/OnEventWhereAddresses_test.res, packages/envio-tests/test/ClientAddressFilter_test.res, packages/envio-tests/test/EventFilters_test.res, packages/envio-tests/test/HandlerRegister_test.res, packages/envio-tests/test/OnEventRegistration_test.res, packages/envio/src/Config.res, packages/envio/src/Internal.res, packages/envio/src/LogSelection.res, packages/envio/src/TopicFilter.res, packages/envio/src/bindings/Viem.res
New tests cover parameter and address filters across HyperSync and RPC. Earlier filter suites and selected registration assertions and filter cases were removed. The event-config lookup and topic-filter helpers, types, and bindings were also removed.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 54e46

No actionable risk is established in these changes; they are mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title accurately summarizes the main change: testing onEvent where behavior from config.yaml through rows using HyperSync and RPC sources. It is specific enough for a teammate to understand th…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title accurately summarizes the main change: testing onEvent where behavior from config.yaml through rows using HyperSync and RPC sources. It is specific enough for a teammate to understand the pull request scope.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@DZakh
DZakh deployed to internal October 22, 2026 11:30 — with GitHub Actions Active
- Mock HyperSync chain mode: drop transaction rows and include_all_blocks
  handling; the indexer loop needs neither, and chain_page can't fail.
- ServedEvmChain: own the ports/height, emit config.yaml chain entries,
  share the Routed schema/handler prelude, and run a scenario to its end
  block with a fresh exit flag per run (replaces the per-test endBlock
  value and the served() thunk).
- Scenario: a run either mocks every chain or leaves every chain on its
  YAML source (~yamlSources), instead of a per-chain served list.
- Drop the unused EmptyFiltersArray event from HandlerRegisterLifecycle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdwJuj1pgyeoPb8vfekdfy
@DZakh
DZakh deployed to internal October 22, 2026 11:45 — with GitHub Actions Active
With EventFilters, EventBlockFilter and ClientAddressFilter gone, nothing
calls LogSelection.materializeTopicSelections or Config.getEventConfig.
That leaves Internal.topicSelection, the TopicFilter module and the
Viem pad/toHex bindings unused too. TestChainMetrics.caughtUpAt was
already unused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdwJuj1pgyeoPb8vfekdfy
@DZakh
DZakh deployed to internal October 22, 2026 20:17 — with GitHub Actions Active
@DZakh
DZakh enabled auto-merge (squash) October 22, 2026 20:24
@DZakh
DZakh disabled auto-merge October 22, 2026 20:25
@DZakh
DZakh merged commit 135f016 into main Oct 22, 2026
10 checks passed
@DZakh
DZakh deleted the claude/quirky-allen-575h83-where-tests branch October 22, 2026 20:25

This branch was successfully deployed

1 active deployment
internal — 54e460b9 Deployed Oct 22, 2026 by DZakh via authorize #3839
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.

2 participants