Das Free-Tier deckt persönliche Projekte ab. Pay-as-you-go skaliert ohne Karte.
Rust
rust-web3 is the established crate for talking to OP Mainnet from Rust, exposing the standard JSON-RPC surface that this EVM-equivalent rollup (chain ID 10, ETH for gas) shares with Ethereum L1. It is async to the core and built on Tokio, so add both to your Cargo.toml: tokio with version = "1" and features = ["full"], alongside web3 = "0.19". With those in place, every network call returns a future you drive on the Tokio runtime.
rust-web3 relies on Tokio for its async support, so OP Mainnet calls run on the Tokio runtime. Declare both dependencies in Cargo.toml: tokio = { version = "1", features = ["full"] } and web3 = "0.19".
Web3-rs
Build the connection in two steps: create an HTTP transport with web3::transports::Http::new(url) pointed at your OP Mainnet endpoint, then wrap it with Web3::new(transport) to get the client. Every network method returns a Result, so propagate failures with the ? operator inside your async functions and let the caller decide how to handle a dropped request or a reverted call.
Key features: native async support, type-safe interfaces, contract interactions on OP Mainnet, transaction management, ENS resolution, and WebSocket subscriptions
Contract Integration
To work with a deployed contract on OP Mainnet, load its ABI and bind it to an on-chain address with Contract::from_json. From there, read-only views go through contract.query() — no gas, no signature — while state-changing methods go through contract.call(), which submits a signed, ETH-paid transaction to chain ID 10.
Use thiserror to derive a typed error enum that wraps web3::Error alongside your own variants for invalid addresses and contract failures — callers then match on one clean error type rather than stringly-typed messages. Layer convenience methods like safe_get_balance and safe_send on top: they handle the conversion from a U256 wei value to an f64 ether figure for display, while keeping the underlying high-precision arithmetic intact for anything that actually moves funds on OP Mainnet.
subscribe_new_heads returns a Stream of block headers, which means it needs a WebSocket transport — the HTTP transport cannot receive pushed events, so subscriptions only work over a ws:///wss:// connection. Bring futures::StreamExt into scope and consume the stream in a while let Some(...) = stream.next().await loop; on OP Mainnet new headers arrive roughly every 2 seconds, so the loop stays busy.
Mark async test functions with #[tokio::test] so each gets its own Tokio runtime. Point those tests at a local node on http://localhost:8545 or a forked OP Mainnet environment rather than your production endpoint — that keeps test runs deterministic, free, and isolated from real chain ID 10 state and rate limits.