Public Client
Read-only access to the Ethereum blockchain through standard JSON-RPC methods
A Public Client provides read-only access to the Ethereum blockchain through standard JSON-RPC methods like eth_blockNumber, eth_getBalance, eth_call, and more.
The CreatePublicClient function sets up a Public Client with a given Transport and optional Chain.
Import
import ("github.com/ChefBingbong/viem-go/client""github.com/ChefBingbong/viem-go/client/transport""github.com/ChefBingbong/viem-go/chain/definitions")
These are the most common imports for setting up a Public Client:
- client: Client constructors and types (e.g.
CreatePublicClient,PublicClientConfig,BlockTag*constants). - transport: Transport factories for JSON-RPC (e.g.
transport.HTTP(...),transport.WebSocket(...)). - definitions: Prebuilt chain definitions (e.g.
definitions.Mainnet). Optional, but recommended.
Import additional packages only when you need them:
- common: Address/hash helpers from go-ethereum (e.g.
common.HexToAddress("0x...")). - public: Public actions & watch parameter types (e.g.
public.WatchBlockNumberParameters).
Go notes
Closing the client
In viem-go, publicClient.Close() closes the underlying transport connection (especially important for WebSocket transports). It’s idiomatic to call it with defer right after successful construction.
Passing a context
Public Client methods and watch actions accept a context.Context as the first argument (e.g. publicClient.GetBalance(ctx, ...), publicClient.WatchBlockNumber(ctx, ...)). Use it to cancel requests or to set timeouts with context.WithTimeout.
Error handling
Most viem-go APIs return (value, error). Always handle errors from CreatePublicClient and from each call.
import ("context""log""time""github.com/ChefBingbong/viem-go/client""github.com/ChefBingbong/viem-go/client/transport""github.com/ChefBingbong/viem-go/chain/definitions")ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})if err != nil {log.Fatal(err)}defer func() { _ = publicClient.Close() }()blockNumber, err := publicClient.GetBlockNumber(ctx)if err != nil {log.Fatal(err)}_ = blockNumber
Usage
HTTP Transport (recommended)
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})if err != nil {log.Fatal(err)}defer publicClient.Close()
WebSocket Transport (subscriptions)
Watch actions will poll on HTTP transports and can use subscriptions when a WebSocket transport is configured. For details on WebSocket configuration, see WebSocket Transport.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Chain: definitions.Mainnet,Transport: transport.WebSocket("wss://eth.llamarpc.com"),})if err != nil {log.Fatal(err)}defer publicClient.Close()
eth_subscribe subscriptions for watch actions, while HTTP transports fall back to polling. Prefer WebSocket for watch-heavy workloads to reduce latency and RPC calls.Watch actions (brief)
The Public Client exposes watch helpers like WatchBlockNumber that stream events over a channel. Cancel the context to stop watching.
ctx, cancel := context.WithCancel(context.Background())defer cancel()events := publicClient.WatchBlockNumber(ctx, public.WatchBlockNumberParameters{EmitOnBegin: true,})for event := range events {fmt.Println(event.BlockNumber)}
Parameters
Transport (required)
- Type:
transport.TransportFactory
Transport factory for JSON-RPC calls. This parameter is required.
If your transport needs its own configuration, keep it in the transport constructor and refer to transport docs (e.g. HTTP Transport or WebSocket Transport).
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
Chain (optional)
- Type:
*chain.Chain
The Chain configuration (e.g. definitions.Mainnet) for the Public Client.
This influences defaults like PollingInterval (based on block time) and is used by some actions for chain-aware behavior. See Clients & Transports.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
Batch (optional)
- Type:
*client.BatchOptions
Batch settings for the client (e.g. enabling multicall-style batching for some actions).
If you don’t need batching, omit this field.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Batch: &client.BatchOptions{Multicall: &client.MulticallBatchOptions{},},Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
eth_call, while JSON-RPC batching combines multiple RPC requests into a single HTTP request.PollingInterval (optional)
- Type:
time.Duration - Default:
min(max(chain.BlockTime/2, 500ms), 4s)(defaults to4swhenChainis not provided)
Frequency for polling-enabled behavior, including watch actions when not using subscriptions.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{PollingInterval: 10 * time.Second,Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
CacheTime (optional)
- Type:
time.Duration - Default:
PollingInterval
Time that cached data will remain in memory.
In viem-go, if CacheTime is not set, it defaults to the client PollingInterval.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{CacheTime: 10 * time.Second,Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
ExperimentalBlockTag (optional)
- Type:
client.BlockTag - Default:
client.BlockTagLatest
Default block tag used by actions when you don’t pass an explicit block tag.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{ExperimentalBlockTag: client.BlockTagSafe,Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
latest (e.g. safe or finalized) may cause unexpected behavior with certain RPC providers that don't fully support these tags. Test with your provider before deploying.Key (optional)
- Type:
string - Default:
"public"
A key for the Client.
This is primarily useful when you have multiple clients in the same process and want a stable identifier for debugging, logging, or internal bookkeeping.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Key: "foo",Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
Name (optional)
- Type:
string - Default:
"Public Client"
A human-readable name for the Client.
This is useful for debugging and for distinguishing multiple client instances in your application.
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{Name: "Foo Public Client",Chain: definitions.Mainnet,Transport: transport.HTTP("https://eth.llamarpc.com"),})
Return Type
CreatePublicClient returns (*PublicClient, error).