### Run an Example Program Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Navigate to the examples directory, build the project, and execute a specific example program like '01_derive_address'. ```bash cd examples && zig build && ./zig-out/bin/01_derive_address ``` -------------------------------- ### Initialize KZG Trusted Setup Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/kzg.mdx Load the trusted setup once at startup and free it at shutdown. This function is idempotent and thread-safe. ```zig const eth = @import("eth"); try eth.kzg.init(allocator); defer eth.kzg.deinit(); ``` -------------------------------- ### Install eth.zig with Zig Fetch Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Installs the eth.zig library using the `zig fetch` command, saving it to your project's dependency cache. ```bash zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.7.0 ``` -------------------------------- ### Run MEV-Share Backrunner Example Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/examples.mdx This command shows how to build and run the MEV-Share backrunner example. It navigates to the examples directory, builds the project using Zig, and executes the backrunner binary with the DRY_RUN environment variable set to 1 for a dry run against the Sepolia matchmaker. ```bash cd examples && zig build && DRY_RUN=1 ./zig-out/bin/08_mev_share_backrunner ``` -------------------------------- ### Clone and Build eth.zig for Benchmarking Source: https://github.com/strobelabs/eth.zig/blob/main/bench/RESULTS_VOLTAIRE.md Clone the eth.zig repository and build the benchmark suite using Zig. This setup is required to replicate the performance results. ```bash git clone https://github.com/ethzig/eth.zig cd eth.zig zig build bench ``` -------------------------------- ### Quick Start: Interact with Ethereum Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/introduction.mdx This snippet demonstrates basic Ethereum interactions using eth.zig, including initializing a signer, deriving an address, and sending a transaction. It requires setting up an allocator and an HTTP transport for node communication. ```zig const std = @import("std"); const eth = @import("eth"); pub fn main() !void { var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // WARNING: This is the default Anvil/Hardhat test key. Never use it for real funds. const private_key = try eth.hex.hexToBytesFixed(32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"); const signer = eth.signer.Signer.init(private_key); const addr = try signer.address(); const checksum = eth.primitives.addressToChecksum(&addr); _ = checksum; // Sign and send a transaction var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", eth.runtime.blockingIo()); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); const recipient_address = try eth.hex.hexToBytesFixed(20, "0000000000000000000000000000000000000000"); var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider); const tx_hash = try wallet.sendTransaction(.{ .to = recipient_address, .value = eth.units.parseEther(1.0), }); _ = tx_hash; } ``` -------------------------------- ### Run Full Benchmark Comparison Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/benchmarks.mdx Execute the complete benchmark suite comparing eth.zig and alloy.rs. This requires Zig, Rust, and Python 3 to be installed. ```bash bash bench/compare.sh ``` -------------------------------- ### Full Comparison Benchmark Script Source: https://github.com/strobelabs/eth.zig/blob/main/bench/RESULTS.md Execute the full comparison between eth.zig and alloy.rs. This script requires Zig, Rust, and Python 3 to be installed. ```bash # Full comparison (requires Zig, Rust, Python 3) bash bench/compare.sh ``` -------------------------------- ### Verify eth.zig Installation Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/installation.mdx A basic Zig code snippet to verify the eth.zig installation by importing the library and performing a simple cryptographic operation. Note the warning about using test keys. ```zig const eth = @import("eth"); pub fn main() !void { // WARNING: This is a well-known Anvil/Hardhat test key. Never use it for real funds. const private_key = try eth.hex.hexToBytesFixed(32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"); const signer = eth.signer.Signer.init(private_key); const addr = try signer.address(); const checksum = eth.primitives.addressToChecksum(&addr); // checksum == "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" _ = checksum; } ``` -------------------------------- ### Derive Address from Private Key Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/examples.mdx Derives an Ethereum address from a given private key. This example uses a test key and is suitable for testing purposes. ```zig const eth = @import("eth"); // WARNING: This is the default Anvil/Hardhat test key. Never use it for real funds. const private_key = try eth.hex.hexToBytesFixed( 32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ); const signer = eth.signer.Signer.init(private_key); const addr = try signer.address(); const checksum = eth.primitives.addressToChecksum(&addr); // "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" ``` -------------------------------- ### MEV-Share Backrunner Zig Code Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/examples.mdx This Zig code snippet initializes an MEV-Share client, subscribes to the pending transaction stream, and demonstrates how to compose a backrunning bundle. It uses comptime to pre-hash Uniswap swap selectors for efficient matching. The example defaults to a dry-run mode for safe testing. ```zig const eth = @import("eth"); // Comptime: the swap selector is hashed by the compiler. const v2_swap = comptime eth.keccak.selector( "swapExactTokensForTokens(uint256,uint256,address[],address,uint256)", ); var client = eth.mev_share.MevShareClient.init(allocator, relay_url, stream_url, auth_key, eth.runtime.blockingIo()); defer client.deinit(); // Subscribe to the SSE stream; the callback fires per pending-tx hint. try client.on(&onEvent); // Inside onEvent: match the revealed selector, then compose the bundle. const body = [_]eth.flashbots.MevBundleBody{ .{ .hash = user_tx_hash }, // the user's pending swap .{ .tx = .{ .data = signed_backrun_tx } }, // our backrun }; _ = try client.relay.mevSendBundle(.{ .body = &body, .inclusion = .{ .block = target_block, .max_block = target_block + 2 }, }); ``` -------------------------------- ### JSON-RPC Calls over WebSocket Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/websockets.mdx Utilizes WebSocket for efficient JSON-RPC calls, offering lower latency than HTTP for frequent requests. This example demonstrates fetching block number and balance. ```zig const eth = @import("eth"); var ws = eth.ws_transport.WebSocketTransport.init(allocator, "wss://rpc.example.com"); defer ws.deinit(); var provider = eth.provider.Provider.init(allocator, &ws); const block_number = try provider.getBlockNumber(); const balance = try provider.getBalance(address); ``` -------------------------------- ### Get Function Selector Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/abigen.mdx Retrieve the 4-byte selector for a contract function at compile time. This is useful for understanding or manually constructing calldata. ```zig const sel = Erc20.selectorOf("balanceOf"); // sel == [4]u8{ 0x70, 0xa0, 0x82, 0x31 } ``` -------------------------------- ### Build, Test, and Format eth.zig Source: https://github.com/strobelabs/eth.zig/blob/main/CONTRIBUTING.md Commands to clone the repository, build the project, run tests, and format the code using Zig's build system and formatter. ```bash git clone https://github.com/StrobeLabs/eth.zig.git cd eth.zig # Build zig build # Run tests zig build test # Check formatting zig fmt --check src/ tests/ # Format code zig fmt src/ tests/ ``` -------------------------------- ### Pluggable I/O with BlockingIo Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/websockets.mdx Demonstrates using a pluggable I/O system with eth.zig, specifically utilizing `eth.runtime.blockingIo()` for synchronous operations. This allows for flexible event loop integration. ```zig const io = eth.runtime.blockingIo(); var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", io); defer transport.deinit(); const client = try eth.ws_client.WsClient.connect(allocator, "wss://rpc.example.com/ws", io, .{}); defer client.deinit(); ``` -------------------------------- ### Basic Batch eth_call Usage Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/batch-calls.mdx Demonstrates how to initialize a provider, create a batch, add multiple eth_call requests, execute them in a single HTTP request, and retrieve results. ```zig const eth = @import("eth"); // Set up provider var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", eth.runtime.blockingIo()); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); // Create a batch var batch = eth.provider.BatchCaller.init(allocator, &provider); defer batch.deinit(); // Add calls (returns index for result retrieval) const idx0 = try batch.addCall(pool_a_address, quote_calldata_a); const idx1 = try batch.addCall(pool_b_address, quote_calldata_b); const idx2 = try batch.addCall(pool_c_address, quote_calldata_c); // Execute all in one HTTP request const results = try batch.execute(); defer eth.provider.freeBatchResults(allocator, results); // Each result is either .success or .rpc_error switch (results[idx0]) { .success => |data| { // data contains the decoded bytes from the RPC response // Decode as needed (e.g., ABI decode a uint256) }, .rpc_error => |err| { // err.code and err.message describe what went wrong // (e.g., execution reverted, invalid params) }, } ``` -------------------------------- ### Initialize MEV-Share Clients Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/mev-share.mdx Initializes MEV-Share clients for mainnet or a specific testnet like Sepolia. Ensure you provide your Flashbots reputation key and a blocking IO instance. The client should be deinitialized when no longer needed. ```zig const eth = @import("eth"); // auth_key is your Flashbots reputation key (NOT a funded key). const io = eth.runtime.blockingIo(); var client = eth.mev_share.MevShareClient.initMainnet(allocator, auth_key, io); defer client.deinit(); // Or with explicit endpoints (e.g. Sepolia): var sepolia = eth.mev_share.MevShareClient.init( allocator, "https://relay-sepolia.flashbots.net", eth.mev_share.sepolia_stream_url, auth_key, io, ); defer sepolia.deinit(); ``` -------------------------------- ### Perform ERC-20 Transfer Transaction Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/tokens.mdx Example of performing a state-changing ERC-20 operation, specifically a token transfer, using the contract module with a Wallet. This requires a pre-defined wallet and token address. ```zig const eth = @import("eth"); const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)"); const tx_hash = try eth.contract.contractWrite( allocator, &wallet, token_address, transfer_sel, &.{ .{ .address = recipient }, .{ .uint256 = amount }, }, ); ``` -------------------------------- ### Clone and Build Voltaire for Benchmarking Source: https://github.com/strobelabs/eth.zig/blob/main/bench/RESULTS_VOLTAIRE.md Clone the Voltaire repository and build its benchmark suite using Zig. Note that Voltaire may use zbench and its build.zig for specific bench targets. ```bash git clone https://github.com/evmts/voltaire cd voltaire # Voltaire uses zbench; check their build.zig for bench targets zig build bench ``` -------------------------------- ### Compute Function Selectors and Event Topics Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Demonstrates how to compute Keccak-256 hashes for function signatures and event topics at compile time or runtime. ```zig const eth = @import("eth"); // Computed at compile time -- zero runtime cost const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)"); // transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb } // Same function works at runtime too const runtime_sel = eth.keccak.selector(runtime_signature); const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)"); // transfer_topic == keccak256("Transfer(address,address,uint256)") ``` -------------------------------- ### LogWatcher for On-Chain Event Streaming Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/websockets.mdx Implements a LogWatcher to efficiently stream and process filtered logs from Ethereum blocks. It handles new blocks, backfills missed blocks, and reorgs, requiring a WebSocket client and an HTTP provider for initial setup. ```zig const eth = @import("eth"); const io = eth.runtime.blockingIo(); var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", io); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); const client = try eth.ws_client.WsClient.connect(allocator, "wss://rpc.example.com/ws", io, .{}); defer client.deinit(); var watcher = try eth.log_watcher.LogWatcher.init(allocator, &provider, client, .{ .address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH .topics = &.{ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" }, // Transfer }, .{ .start_block_lag = 0, .handle_reorgs = true }); defer watcher.deinit(); while (true) { const logs = try watcher.pollOnce(); // blocks until the next head defer eth.log_watcher.freeLogs(allocator, logs); for (logs) |log| { // process log.address / log.topics / log.data } } ``` -------------------------------- ### Run Unit Tests Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Execute the unit tests for the eth.zig library using the Zig build system. ```bash zig build test ``` -------------------------------- ### Simulate a Bundle Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/mev-share.mdx Simulates a bundle using `mev_simBundle` to assess its outcome before submission. The simulation environment can be configured with options like parent block and timeout. Results indicate success or failure with detailed error messages. ```zig const body = [_]eth.flashbots.MevBundleBody{ .{ .hash = pending_event_hash }, .{ .tx = .{ .data = my_signed_backrun } }, }; var sim = try client.simulateBundle(.{ .body = &body, .inclusion = .{ .block = next_block }, }, .{ .parent_block = next_block - 1, .timeout = 5, // seconds }); defer eth.mev_share.freeSimBundleResult(allocator, &sim); if (sim.success) { // sim.profit, sim.refundable_value, sim.mev_gas_price, sim.gas_used } else { // sim.error_message describes the failure } ``` -------------------------------- ### eth.zig Build Commands Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/installation.mdx Common commands for building, testing, and running integration tests for your Zig project with eth.zig. ```bash zig build # Build zig build test # Unit tests zig build integration-test # Integration tests (requires Anvil) ``` -------------------------------- ### Run eth.zig Benchmarks Source: https://github.com/strobelabs/eth.zig/blob/main/bench/RESULTS.md Compile and run only the benchmarks for the eth.zig library. This command uses the Zig build system. ```bash # eth.zig benchmarks only zig build bench ``` -------------------------------- ### Initialize FallbackProvider with multiple RPC endpoints Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/fallback-provider.mdx Initialize FallbackProvider with a list of endpoint URLs. The provider will use these endpoints in order, failing over on connection errors. Ensure the endpoint URLs outlive the provider instance. ```zig const eth = @import("eth"); var fb = try eth.fallback_provider.FallbackProvider.init(allocator, &.{ "https://primary.example.com", "https://backup-a.example.com", "https://backup-b.example.com", }, eth.runtime.blockingIo(), .{}); defer fb.deinit(); // Same surface as Provider. If the primary's connection fails, this call // transparently retries against backup-a, then backup-b. const block_num = try fb.getBlockNumber(); const balance = try fb.getBalance(some_address); ``` -------------------------------- ### Initialize and Read ERC-20 Token Metadata Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/tokens.mdx Initializes an ERC-20 token wrapper and demonstrates reading its name, symbol, decimals, and total supply. Ensure the allocator and provider are set up correctly. ```zig const eth = @import("eth"); var token = eth.erc20.ERC20.init(allocator, token_addr, &provider); // Read token metadata const name = try token.name(); defer allocator.free(name); const symbol = try token.symbol(); defer allocator.free(symbol); const decimals = try token.decimals(); const total_supply = try token.totalSupply(); ``` -------------------------------- ### Initialize FallbackProvider with custom options Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/fallback-provider.mdx Initialize FallbackProvider with custom failover and recovery probe settings. This allows tuning the failover behavior to specific network conditions or requirements. ```zig var fb = try eth.fallback_provider.FallbackProvider.init(allocator, endpoints, eth.runtime.blockingIo(), .{ .failover_threshold = 5, .recovery_probe_ms = 10_000, }); ``` -------------------------------- ### Encrypt Private Key to Keystore Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/keystore.mdx Produces a v3 JSON keystore document from a private key and password, suitable for writing to disk. The caller owns the returned slice. ```zig const json = try eth.keystore.encrypt(allocator, private_key, "my password", eth.runtime.blockingIo(), .{}); defer allocator.free(json); // json is a complete {"version":3,"id":...,"crypto":{...}} document. ``` -------------------------------- ### Runtime Function Selectors Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/comptime.mdx Use `eth.keccak.selector()` at runtime when the function signature is only known dynamically. This incurs a small runtime cost for hashing. ```zig // Runtime -- useful when the signature is only known at runtime const runtime_sel = eth.keccak.selector(some_signature); ``` -------------------------------- ### Sign and Send Transaction Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Sets up an HTTP transport and provider, then uses a Wallet to sign and send a transaction with a specified value to a recipient address. ```zig const eth = @import("eth"); var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com"); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider); const tx_hash = try wallet.sendTransaction(.{ .to = recipient_address, .value = eth.units.parseEther(1.0), }); ``` -------------------------------- ### Run Integration Tests Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Execute the integration tests for the eth.zig library. This requires Anvil to be running. ```bash zig build integration-test ``` -------------------------------- ### Initializing and Using the Contract Struct Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/contracts.mdx The `Contract` struct simplifies repeated interactions with a contract by binding a provider and address. It supports raw byte calls and typed reads with selectors. ```zig const eth = @import("eth"); var contract = eth.contract.Contract.init(allocator, contract_address, &provider); // Raw read (returns bytes) const result_bytes = try contract.call(calldata); defer allocator.free(result_bytes); // Typed read with selector const result = try contract.readRaw(selector, &.{.{ .address = addr }}); defer allocator.free(result); ``` -------------------------------- ### Import eth.zig in build.zig Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Imports the eth.zig dependency into your `build.zig` file, making its module available for use in your project. ```zig const eth_dep = b.dependency("eth", .{ .target = target, .optimize = optimize, }); exe.root_module.addImport("eth", eth_dep.module("eth")); ``` -------------------------------- ### Compile-Time Event Topics Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/comptime.mdx Use `comptime eth.keccak.hash()` to compute event topics at compile time. This is efficient for known event signatures used in log filtering. ```zig const eth = @import("eth"); const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)"); // transfer_topic == keccak256("Transfer(address,address,uint256)") const approval_topic = comptime eth.keccak.hash("Approval(address,address,uint256)"); ``` -------------------------------- ### Add eth.zig Manually to build.zig.zon Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Manually adds the eth.zig dependency to your `build.zig.zon` file, specifying the Git URL and version. ```zig .dependencies = .{ .eth = .{ .url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.7.0", .hash = "...", // run `zig build` and it will tell you the expected hash }, }, ``` -------------------------------- ### Run alloy.rs Benchmarks Source: https://github.com/strobelabs/eth.zig/blob/main/bench/RESULTS.md Compile and run only the benchmarks for the alloy.rs library. This command navigates to the alloy benchmark directory and uses Cargo. ```bash # alloy benchmarks only (cd bench/alloy-bench && cargo bench --bench eth_comparison) ``` -------------------------------- ### Compile-Time Function Selectors Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/comptime.mdx Use `comptime eth.keccak.selector()` to compute function selectors at compile time, eliminating runtime overhead. This is ideal for known function signatures. ```zig const eth = @import("eth"); // Evaluated at compile time -- zero runtime cost const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)"); // transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb } const approve_sel = comptime eth.keccak.selector("approve(address,uint256)"); // approve_sel == [4]u8{ 0x09, 0x5e, 0xa7, 0xb3 } ``` -------------------------------- ### Encrypt Keystore with PBKDF2 Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/keystore.mdx Generates a v3 JSON keystore using the PBKDF2-HMAC-SHA256 KDF instead of scrypt, with configurable iteration count. ```zig // pbkdf2-HMAC-SHA256 instead of scrypt: const pb = try eth.keystore.encrypt(allocator, key, "pw", eth.runtime.blockingIo(), .{ .kdf = .pbkdf2, .pbkdf2_c = 262144, }); defer allocator.free(pb); ``` -------------------------------- ### Derive Multiple Ethereum Accounts Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/hd-wallets.mdx Demonstrates deriving multiple Ethereum accounts (account 0, 1, and 2) from the same seed using their respective BIP-44 paths. Assumes the 'words' variable is already defined. ```zig const eth = @import("eth"); // Using the same words from the previous example const seed = try eth.mnemonic.toSeed(&words, ""); // m/44'/60'/0'/0/0 const account_0 = try eth.hd_wallet.deriveEthAccount(seed, 0); // m/44'/60'/0'/0/1 const account_1 = try eth.hd_wallet.deriveEthAccount(seed, 1); // m/44'/60'/0'/0/2 const account_2 = try eth.hd_wallet.deriveEthAccount(seed, 2); ``` -------------------------------- ### Decrypt geth Keystore Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/keystore.mdx Parses a v3 keystore document, derives the key from the password, and verifies the MAC to return the 32-byte private key. Use this to load existing encrypted keys. ```zig const eth = @import("eth"); // `json` is the bytes of e.g. ~/.ethereum/keystore/UTC--...--
const private_key = try eth.keystore.decrypt(allocator, json, "my password"); // private_key is [32]u8 -- hand it straight to a Signer or Wallet. var signer = eth.signer.Signer.init(private_key); defer signer.deinit(); // zeroes the key when you are done ``` -------------------------------- ### Initialize Nonce Manager for Concurrent Senders Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/nonce-manager.mdx Initialize the NonceManager with a provider and sender address. The first call to `next()` will seed the manager from the chain. Each worker thread can then safely request a unique nonce using `nm.next()`. ```zig const eth = @import("eth"); var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", eth.runtime.blockingIo()); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); const sender = try wallet.address(); // No RPC happens here. The first `next()` seeds from the pending count. var nonces = eth.nonce_manager.NonceManager.init(&provider, sender); ``` -------------------------------- ### Encrypt Keystore with Faster Scrypt Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/keystore.mdx Generates a v3 JSON keystore using faster scrypt parameters (N=2^12) for use in tests or when speed is prioritized over security. ```zig // Faster scrypt for a test fixture (N = 2^12 = 4096): const fast = try eth.keystore.encrypt(allocator, key, "pw", eth.runtime.blockingIo(), .{ .scrypt_log_n = 12 }); defer allocator.free(fast); ``` -------------------------------- ### Generate Function and Event Selectors Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/examples.mdx Generates function and event selectors using `eth.keccak.selector` and `eth.keccak.hash`. These can be computed at compile time for zero runtime cost. ```zig const eth = @import("eth"); // Computed at compile time -- zero runtime cost const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)"); // transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb } // Same function works at runtime too const runtime_sel = eth.keccak.selector(some_signature); const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)"); // transfer_topic == keccak256("Transfer(address,address,uint256)") ``` -------------------------------- ### Read ERC-20 Token Balance and Info Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/examples.mdx Demonstrates reading an ERC-20 token's balance and name using comptime selectors for efficiency. Requires a token address and holder address. ```zig const eth = @import("eth"); // Comptime selectors -- zero runtime cost const balance_sel = eth.erc20.selectors.balanceOf; // Or use the typed wrapper var token = eth.erc20.ERC20.init(allocator, token_addr, &provider); const balance = try token.balanceOf(holder_addr); const name = try token.name(); defer allocator.free(name); ``` -------------------------------- ### Uniswap V3 Full Multi-Tick Swap Simulation Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/dex-math.mdx Simulates a complete swap in Uniswap V3 across multiple tick boundaries, considering liquidity, fees, and calculating total input consumed, output received, and final price. ```zig const ticks = [_]eth.dex_v3.TickInfo{ .{ .tick = -100, .liquidity_net = 500e18, .sqrt_price_x96 = eth.dex_v3.getSqrtRatioAtTick(-100).? }, .{ .tick = -200, .liquidity_net = 300e18, .sqrt_price_x96 = eth.dex_v3.getSqrtRatioAtTick(-200).? }, }; const result = eth.dex_v3.simulateSwap( current_sqrt_price, current_liquidity, &ticks, amount_in, true, // zero_for_one (selling token0) 3000, // 0.3% fee ); // result.amount_in_consumed -- total input consumed // result.amount_out -- total output received // result.sqrt_price_final_x96 -- final pool price // result.ticks_crossed -- number of tick boundaries crossed ``` -------------------------------- ### Access ERC-20 Comptime Selectors Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/tokens.mdx Shows how to access ERC-20 function selectors as comptime constants, which have zero runtime cost. These selectors can be used for contract interactions. ```zig const selectors = eth.erc20.selectors; // These are computed at compile time -- zero runtime cost const balance_sel = selectors.balanceOf; // balanceOf(address) const transfer_sel = selectors.transfer; // transfer(address,uint256) const approve_sel = selectors.approve; // approve(address,uint256) const allowance_sel = selectors.allowance; // allowance(address,address) const total_sel = selectors.totalSupply; // totalSupply() ``` -------------------------------- ### Uniswap V3 Swap Step Simulation Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/dex-math.mdx Simulates a single swap step within a Uniswap V3 tick range, calculating the resulting price, input consumed, output produced, and fee charged. ```zig // Simulate a single swap step within one tick range const step = eth.dex_v3.computeSwapStep( current_sqrt_price, // current pool price target_sqrt_price, // next initialized tick boundary pool_liquidity, // current active liquidity @as(i256, amount_in), // positive = exact input, negative = exact output 3000, // fee: 0.3% (3000 pips) ); // step.sqrt_ratio_next_x96 -- price after this step // step.amount_in -- tokens consumed // step.amount_out -- tokens produced // step.fee_amount -- fee charged ``` -------------------------------- ### Decrypting a geth keystore Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/keystore.mdx Parses a v3 document, runs the key-derivation function over the password, verifies the MAC, and returns the recovered 32-byte private key. It supports both scrypt and pbkdf2 KDFs and uses aes-128-ctr cipher. ```APIDOC ## Decrypting a geth keystore Parses a v3 document, runs the key-derivation function over the password, verifies the MAC, and returns the recovered 32-byte private key. ### Method `eth.keystore.decrypt(allocator, json, password)` ### Parameters - **allocator**: An allocator for memory management. - **json**: The bytes of the v3 JSON keystore file. - **password**: The password for the keystore. ### Returns A 32-byte private key (`[32]u8`). ### Error Handling - `error.InvalidPassword`: If the password is incorrect or the file is tampered with. ### Example ```zig const eth = @import("eth"); // `json` is the bytes of e.g. ~/.ethereum/keystore/UTC--...-- const private_key = try eth.keystore.decrypt(allocator, json, "my password"); // private_key is [32]u8 -- hand it straight to a Signer or Wallet. var signer = eth.signer.Signer.init(private_key); defer signer.deinit(); // zeroes the key when you are done ``` ### Interoperability Supports both scrypt (geth/ethers default) and pbkdf2 (HMAC-SHA256) KDFs. The cipher is always aes-128-ctr. ``` -------------------------------- ### Subscribe to MEV-Share Event Stream Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/mev-share.mdx Subscribes to the MEV-Share SSE event stream to receive pending transaction and bundle hints. The `on` function is blocking and invokes a callback for each event. Events are freed after the callback returns, so copy any necessary data. ```zig fn onEvent(event: eth.mev_share.PendingEvent) void { switch (event) { .transaction => |tx| { // tx.hash is the event identity (a double-hash, not the tx hash) // Optional hints: tx.to, tx.function_selector, tx.calldata, // tx.logs, tx.value -- null when not revealed. _ = tx; }, .bundle => |bundle| { // bundle.txs holds per-transaction hints _ = bundle; }, } } // Reconnect loop: `on` returns on clean close, errors on transport failure. while (true) { client.on(&onEvent) catch {}; eth.runtime.sleepMs(1_000); } ``` -------------------------------- ### Derive Address from Private Key Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Initializes a Signer from a private key and derives the corresponding Ethereum address. The address is then formatted into a checksummed string. ```zig const eth = @import("eth"); const private_key = try eth.hex.hexToBytesFixed(32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"); const signer = eth.signer.Signer.init(private_key); const addr = try signer.address(); const checksum = eth.primitives.addressToChecksum(&addr); // "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" ``` -------------------------------- ### Configure FallbackProvider options Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/fallback-provider.mdx Define custom options for the FallbackProvider, such as the consecutive failure threshold before an endpoint is considered unhealthy and the recovery probe interval. ```zig pub const FallbackOpts = struct { failover_threshold: u32 = 3, // consecutive failures before "unhealthy" recovery_probe_ms: i64 = 30_000, // wait before re-probing a failed endpoint }; ``` -------------------------------- ### Initialize and Query ERC-721 NFT Ownership Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/tokens.mdx Initializes an ERC-721 NFT wrapper and demonstrates querying the owner of a specific token ID. Ensure the allocator, NFT address, and provider are correctly configured. ```zig const eth = @import("eth"); var nft = eth.erc721.ERC721.init(allocator, nft_addr, &provider); // Query ownership const owner = try nft.ownerOf(token_id); ``` -------------------------------- ### Check ERC-20 Token Balance Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/tokens.mdx Demonstrates how to check the balance of a specific ERC-20 token for a given holder address. Requires an initialized ERC-20 token wrapper. ```zig // Check balance const balance = try token.balanceOf(holder_addr); ``` -------------------------------- ### ERC-20 Token Balance and Name Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/modules.mdx Initialize an ERC-20 token contract and retrieve the balance and name of a token for a given holder address. Requires an allocator, token address, and provider. ```zig const eth = @import("eth"); var token = eth.erc20.ERC20.init(allocator, token_addr, &provider); const balance = try token.balanceOf(holder_addr); const name = try token.name(); defer allocator.free(name); const decimals = try token.decimals(); ``` -------------------------------- ### Derive Ethereum Address from Mnemonic Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/hd-wallets.mdx Converts a 12-word mnemonic phrase into a seed, then derives the first Ethereum account (m/44'/60'/0'/0/0) and retrieves its address. Requires the eth.zig library. ```zig const eth = @import("eth"); // 12-word mnemonic const words = [_][]const u8{ "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "about", }; // Convert mnemonic to seed (BIP-39) const seed = try eth.mnemonic.toSeed(&words, ""); // Derive Ethereum account 0 (BIP-44 path: m/44'/60'/0'/0/0) const key = try eth.hd_wallet.deriveEthAccount(seed, 0); // Get the address const addr = key.toAddress(); const checksum = eth.primitives.addressToChecksum(&addr); ``` -------------------------------- ### Detect Arbitrage Opportunity Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/dex-math.mdx Use `findArbOpportunity` to check for potential arbitrage profits given a circular path and maximum input. The result provides the expected profit and optimal input size. ```zig if (eth.dex_router.findArbOpportunity(&circular_path, max_input)) |arb| { // arb.profit -- expected profit // arb.optimal_input -- optimal trade size (found via binary search) } ``` -------------------------------- ### Initialize WebSocket Transport Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/websockets.mdx Initializes a WebSocket transport connection to an Ethereum node. Supports both ws:// and wss:// URLs, with TLS handled natively in Zig. ```zig const eth = @import("eth"); var ws = eth.ws_transport.WebSocketTransport.init(allocator, "wss://eth-mainnet.ws.alchemyapi.io/v2/YOUR_KEY"); defer ws.deinit(); ``` -------------------------------- ### Build Blob Sidecar Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/kzg.mdx Converts raw blob data into a sidecar containing the blob, its KZG commitment, and proof. Ensure raw blob data consists of canonical BLS12-381 scalars. ```zig var raw_blob: eth.blob.Blob = @splat(0); // ... fill raw_blob with your data ... const sidecar = try eth.blob.buildSidecar(allocator, raw_blob); // sidecar.blob, sidecar.commitment ([48]u8), sidecar.proof ([48]u8) ``` -------------------------------- ### Reusing a BatchCaller Instance Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/batch-calls.mdx Demonstrates how to reset a BatchCaller to clear pending calls and add new calls for subsequent batch executions. ```zig batch.reset(); // Add new calls for the next block... _ = try batch.addCall(new_target, new_calldata); const new_results = try batch.execute(); defer eth.provider.freeBatchResults(allocator, new_results); ``` -------------------------------- ### Custom Compile-Time Selectors Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/comptime.mdx Define custom function selectors at compile time using `comptime eth.keccak.selector()` for specific contract functions, such as those from Uniswap V2 or Aave V3. ```zig const eth = @import("eth"); // UniswapV2 Router const swap_sel = comptime eth.keccak.selector( "swapExactTokensForTokens(uint256,uint256,address[],address,uint256)" ); // Aave V3 Pool const supply_sel = comptime eth.keccak.selector( "supply(address,uint256,address,uint16)" ); // Any custom function const my_sel = comptime eth.keccak.selector( "myFunction(uint256,bytes32,bool)" ); ``` -------------------------------- ### Send Ethereum Transaction with Wallet Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/transactions.mdx Use the Wallet to automatically fill nonce, gas, and chain ID before signing and broadcasting a transaction. This is the recommended way to send simple ETH transfers. ```zig const eth = @import("eth"); var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com", eth.runtime.blockingIo()); defer transport.deinit(); var provider = eth.provider.Provider.init(allocator, &transport); const private_key = try eth.hex.hexToBytesFixed(32, "your_private_key_hex"); var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider); // Send 1 ETH -- nonce, gas, and chain_id are auto-filled const tx_hash = try wallet.sendTransaction(.{ .to = recipient_address, .value = eth.units.parseEther(1.0), }); ``` -------------------------------- ### Subscribe to New Block Headers Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/websockets.mdx Subscribes to new block header events using the WebSocket transport and processes incoming events in a loop. Ensure the transport is initialized before creating the subscription. ```zig const eth = @import("eth"); var ws = eth.ws_transport.WebSocketTransport.init(allocator, "wss://rpc.example.com"); defer ws.deinit(); // Subscribe to new block headers var sub = try eth.subscription.Subscription.init(allocator, &ws, .newHeads); defer sub.deinit(); // Process incoming events while (try sub.next()) |event| { // Handle new block header _ = event; } ``` -------------------------------- ### Attach Nonce Manager to Wallet for Automatic Nonce Handling Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/nonce-manager.mdx Opt-in to automatic nonce management by assigning a NonceManager instance to the wallet's `nonce_manager` field. Subsequent `sendTransaction` calls without an explicit nonce will draw one from the manager. ```zig var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider); var nonces = eth.nonce_manager.NonceManager.init(&provider, try wallet.address()); wallet.nonce_manager = &nonces; // opt-in; leaving it null keeps the old behavior // Now concurrent sends auto-fill collision-free nonces. _ = try wallet.sendTransaction(.{ .to = some_target, .value = 0 }); ``` -------------------------------- ### Uniswap V2 Multi-Hop Path Calculations Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/dex-math.mdx Calculates the output amount for a given input across a series of Uniswap V2 pairs (multi-hop path), and vice-versa for required input. ```zig const path = [_]eth.dex_v2.Pair{ .{ .reserve_in = 100e18, .reserve_out = 200_000e6 }, // ETH (18 dec) -> USDC (6 dec) .{ .reserve_in = 300_000e6, .reserve_out = 50e18 }, // USDC (6 dec) -> DAI (18 dec) }; // Forward: how much DAI for 1 ETH? const output = eth.dex_v2.getAmountsOut(1e18, &path); // Reverse: how much ETH for 10 DAI? const input = eth.dex_v2.getAmountsIn(10e18, &path); ``` -------------------------------- ### Construct EIP-4844 Transaction (Type 3) Source: https://github.com/strobelabs/eth.zig/blob/main/docs/content/docs/transactions.mdx Build an EIP-4844 blob transaction, typically used for Layer 2 scaling solutions to post data efficiently. Requires specifying blob versioned hashes and max fee per blob gas. ```zig const tx = eth.transaction.Transaction{ .eip4844 = .{ .chain_id = 1, .nonce = 0, .max_priority_fee_per_gas = 1_000_000_000, .max_fee_per_gas = 30_000_000_000, .gas_limit = 21_000, .to = recipient, .value = 0, .data = &.{}., .access_list = &.{}., .max_fee_per_blob_gas = 1_000_000_000, .blob_versioned_hashes = &.{blob_hash}, }}; ``` -------------------------------- ### Block-Scoped Log Watching Source: https://github.com/strobelabs/eth.zig/blob/main/README.md Initializes a LogWatcher to efficiently poll for filtered logs on new blocks, handling reconnections and reorgs automatically. ```zig var watcher = try eth.log_watcher.LogWatcher.init(allocator, &provider, client, .{ .address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", }, .{}); defer watcher.deinit(); while (true) { const logs = try watcher.pollOnce(); // blocks until the next head defer eth.log_watcher.freeLogs(allocator, logs); for (logs) |log| { /* liquidate, arb, ... */ } } ```