feat(scanner): connect ChainProvider over WebSocket#31
Merged
Conversation
…command
First concrete network code. ChainProvider wraps a chain's HTTP RPC via
alloy's ProviderBuilder::on_builtin, which auto-selects the transport
from the URL scheme. Today it's HTTP-only — WebSocket follows in the
next chunk alongside the block listener.
Add `test-connection --chain <key>` subcommand that connects to the
named chain and prints its latest block number. Verified against the
public BSC endpoint:
charon: connected — latest block chain=bnb block=93617402
charon-cli now depends on charon-scanner.
Refs #6
No functional change — purely rustfmt output. Lands ahead of upcoming WebSocket provider work so subsequent commits diff cleanly against a formatted baseline.
Swap the HTTP builder call for an explicit WebSocket handshake via `ProviderBuilder::on_ws(WsConnect)`. WebSocket is required for the upcoming block listener's `subscribe_blocks` — polling HTTP would waste RPC quota and add latency to the hot path. - `ChainProvider::connect` now performs a WS handshake against `ws_url` - `provider()` exposes the pub-sub `RootProvider<PubSubFrontend>` for downstream consumers (block listener, scanner, executor) - `test_connection()` remains a lightweight `get_block_number()` probe, now over WS - Errors carry chain name + URL in context; no panics, no silent fallbacks Verified against BSC mainnet: `test-connection --chain bnb` returns the latest block number over a live wss endpoint.
This was referenced Apr 22, 2026
Closed
…oviderT + Arc - redact_url() strips the final path segment (typically the API-key slug) before any debug! or error includes the URL. WebSocket errors and boot debug logs now show 'wss://bsc-mainnet.nodereal.io/<redacted>' instead of the raw bearer-token URL. Three unit tests cover the redaction helper. - connect() wraps ProviderBuilder::on_ws in tokio::time::timeout (DEFAULT_CONNECT_TIMEOUT = 10 s; connect_with_timeout exposes a caller-chosen deadline). Unreachable RPC no longer hangs the process forever. - After the WS handshake, call eth_chainId and reject any endpoint whose chain id does not match config.chain_id. Misconfigured URLs pointing at the wrong network fail fast at boot, before any state-dependent call runs. - Introduce ChainProviderT trait (Send + Sync) + MockChainProvider so downstream scanner logic can be unit-tested without a live node. Concrete ChainProvider implements the trait. - connect() now returns Arc<Self>; a compile-time assertion pins ChainProvider: Send + Sync so accidental non-Send fields become compile errors rather than task-spawn failures. - async-trait added to charon-scanner dependencies. Closes #87 #88 #89 #90 #91
# Conflicts: # crates/charon-cli/src/main.rs # crates/charon-core/src/config.rs # crates/charon-core/src/traits.rs # crates/charon-scanner/Cargo.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #7
Adds the per-chain RPC connection wrapper. WebSocket is required for
subscribe_blocks/subscribe_logs— the scanner's hot path depends on push events, not polling.ChainProvider::connect(name, &ChainConfig)— WS handshake viaProviderBuilder::on_ws(WsConnect::new(url))RootProvider<PubSubFrontend>usable by listener + adapterstest_connection()— lightweightget_block_number()health checkVerified against BSC mainnet:
test-connection --chain bnbreturns the latest block over a livewss://endpoint.Depends on #6 (
feat/05-clap-cli).