Make std.Io an explicit, caller-provided dependency (remove hidden global)#95
Conversation
…obal) Zig 0.16 moved networking, HTTP, sleeping, clocks, and randomness behind the std.Io interface so the execution model is the caller's choice. The library previously manufactured a global blocking Io internally, which hid that dependency and prevented callers from running eth.zig on their own event loop or honoring its cancellation -- the exact thing 0.16 is designed to make pluggable. Io is now an explicit parameter everywhere it is needed: - runtime.defaultIo() -> runtime.blockingIo() (a convenience value the caller passes; never used implicitly). milliTimestamp/sleepMs take io. - Network constructors take io: HttpTransport.init, WsTransport.connect, WsClient.connect, ws_transport.connectWithReconnect, flashbots.Relay .init, FallbackProvider.init, MevShareClient.init/initMainnet, sse_transport.subscribe/subscribeWithReconnect. - Randomness needs an Io in 0.16: mnemonic.generate(io, ...), keystore.encrypt(..., io, ...). - Wrappers inherit it from the transport they wrap (single source of truth): Provider.io() returns transport.io; Wallet, RetryingProvider, and NonceManager read provider.io() -- no new params on those. Pass eth.runtime.blockingIo() for the previous default behavior. Example 08 threads the real init.io from std.process.Init. All examples, tests, and docs updated. Breaking change. Verified: 812/812 unit tests on 0.16.0 and 0.17-dev, 23/23 Anvil integration tests, examples build, docs build, fmt clean.
📝 WalkthroughWalkthroughThis PR threads explicit ChangesExplicit IO Threading Throughout eth.zig
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/content/docs/websockets.mdx (1)
13-14:⚠️ Potential issue | 🟠 MajorFix websocket docs: use
WsTransport.connect(..., io)(the repo has noWebSocketTransport.init)
src/ws_transport.zigexportsWsTransportwithpub fn connect(allocator: std.mem.Allocator, url: []const u8, io: std.Io) ...; there is noWebSocketTransportorWebSocketTransport.initsymbol in the codebase. The examples indocs/content/docs/websockets.mdxat lines 13-14 (also 26-27, 47-48) therefore won’t compile as written. Update the docs to callWsTransport.connect(allocator, url, io)(and adjust the module listing, e.g.docs/content/docs/modules.mdxline 102).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/content/docs/websockets.mdx` around lines 13 - 14, The docs call a non-existent symbol WebSocketTransport.init; update the examples to use the real exported API by replacing WebSocketTransport.init(...) calls with WsTransport.connect(allocator, "wss://...", io) and ensure the third parameter (io) is passed, then adjust any module listing that references WebSocketTransport to reference WsTransport instead (matching the implementation's pub fn connect signature).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@docs/content/docs/websockets.mdx`:
- Around line 13-14: The docs call a non-existent symbol
WebSocketTransport.init; update the examples to use the real exported API by
replacing WebSocketTransport.init(...) calls with WsTransport.connect(allocator,
"wss://...", io) and ensure the third parameter (io) is passed, then adjust any
module listing that references WebSocketTransport to reference WsTransport
instead (matching the implementation's pub fn connect signature).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 82428e73-8562-49c5-b3cd-bc73c1898be9
📒 Files selected for processing (38)
CHANGELOG.mddocs/content/docs/batch-calls.mdxdocs/content/docs/ens.mdxdocs/content/docs/examples.mdxdocs/content/docs/fallback-provider.mdxdocs/content/docs/introduction.mdxdocs/content/docs/keystore.mdxdocs/content/docs/mev-share.mdxdocs/content/docs/nonce-manager.mdxdocs/content/docs/transactions.mdxdocs/content/docs/websockets.mdxexamples/01_derive_address.zigexamples/02_check_balance.zigexamples/03_sign_message.zigexamples/04_send_transaction.zigexamples/05_read_erc20.zigexamples/06_hd_wallet.zigexamples/07_selectors.zigexamples/08_mev_share_backrunner.zigsrc/contract.zigsrc/erc20.zigsrc/erc721.zigsrc/fallback_provider.zigsrc/flashbots.zigsrc/http_transport.zigsrc/keystore.zigsrc/mev_share.zigsrc/mnemonic.zigsrc/multicall.zigsrc/nonce_manager.zigsrc/provider.zigsrc/retry_provider.zigsrc/runtime.zigsrc/sse_transport.zigsrc/wallet.zigsrc/ws_client.zigsrc/ws_transport.zigtests/integration_tests.zig
Why
Zig 0.16's whole point is making the execution model pluggable: networking, HTTP, sleeping, clocks, and randomness live behind
std.Io, and the idiom (per the 0.16 language reference) is "explicit passing of context (allocators, I/O handles) over hidden global dependencies."eth.zig previously manufactured a global blocking
Iointernally (runtime.defaultIo()), which hid that dependency and prevented callers from running the library on their own event loop or honoring its cancellation/timeouts. This was raised by the community, and it's right.What
Iois now an explicit parameter everywhere it's needed -- no hidden global remains (rg defaultIoreturns nothing):runtime.defaultIo()→runtime.blockingIo(): a convenience blockingIovalue the caller passes; the library never reaches for it implicitly.milliTimestamp(io)/sleepMs(io, ms)takeio.io:HttpTransport.init,WsTransport.connect,WsClient.connect,ws_transport.connectWithReconnect,flashbots.Relay.init,FallbackProvider.init,MevShareClient.init/initMainnet,sse_transport.subscribe/subscribeWithReconnect.Iocapability in 0.16:mnemonic.generate(io, ...),keystore.encrypt(..., io, ...).Provider.io()returnstransport.io;Wallet,RetryingProvider,NonceManagerreadprovider.io()-- no new params.Example 08 threads the real
init.iofromstd.process.Init-- the canonical 0.16 entry-point pattern.Breaking
Public-API breaking: every transport/client construction now takes an
io. Passeth.runtime.blockingIo()for the previous behavior. Lands in v0.7.0 (not yet released), so the library ships idiomatic from the start.Verification
812/812 unit tests on 0.16.0 and 0.17-dev, 23/23 Anvil integration tests, all examples build, docs build,
zig fmtclean. Includes a test asserting the caller'sIois threaded through to the transport'shttp.Client.🤖 Generated with Claude Code
Summary by CodeRabbit
std.Ioparameter:HttpTransport.init(),WsTransport.connect(),FallbackProvider.init(),mnemonic.generate(),keystore.encrypt(), and runtime timing/sleep functions.runtime.defaultIo()renamed toruntime.blockingIo().