Public Client
A Public Client is an interface to "public" JSON-RPC API methods such as retrieving block numbers, transactions, reading from smart contracts, etc through Public Actions.
The createPublicClient
function sets up a Public Client with a given Transport configured for a Chain.
Import
import { createPublicClient } from 'viem'
Usage
Initialize a Client with your desired Chain (e.g. mainnet
) and Transport (e.g. http
).
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
Then you can consume Public Actions:
const blockNumber = await publicClient.getBlockNumber()
Optimization
The Public Client also supports eth_call
Aggregation for improved performance.
eth_call
Aggregation (via Multicall)
The Public Client supports the aggregation of eth_call
requests into a single multicall (aggregate3
) request.
This means for every Action that utilizes an eth_call
request (ie. readContract
), the Public Client will batch the requests (over a timed period) and send it to the RPC Provider in a single multicall request. This can dramatically improve network performance, and decrease the amount of Compute Units (CU) used by RPC Providers like Alchemy, Infura, etc.
The Public Client schedules the aggregation of eth_call
requests over a given time period. By default, it executes the batch request at the end of the current JavaScript message queue (a zero delay), however, consumers can specify a custom wait
period (in ms).
You can enable eth_call
aggregation by setting the batch.multicall
flag to true
:
const publicClient = createPublicClient({
batch: {
multicall: true,
},
chain: mainnet,
transport: http(),
})
You can also customize the
multicall
options.
Now, when you start to utilize readContract
Actions, the Public Client will batch and send over those requests at the end of the message queue (or custom time period) in a single eth_call
multicall request:
import { getContract } from 'viem'
import { abi } from './abi'
import { publicClient } from './client'
const contract = getContract({ address, abi, client: publicClient })
// The below will send a single request to the RPC Provider.
const [name, totalSupply, symbol, balance] = await Promise.all([
contract.read.name(),
contract.read.totalSupply(),
contract.read.symbol(),
contract.read.balanceOf([address]),
])
Read more on Contract Instances.
Parameters
transport
- Type: Transport
The Transport of the Public Client.
const publicClient = createPublicClient({
chain: mainnet,
transport: http(),
})
chain (optional)
- Type: Chain
The Chain of the Public Client.
const publicClient = createPublicClient({
chain: mainnet,
transport: http(),
})
batch (optional)
Flags for batch settings.
batch.multicall (optional)
- Type:
boolean | MulticallBatchOptions
- Default:
false
Toggle to enable eth_call
multicall aggregation.
const publicClient = createPublicClient({
batch: {
multicall: true,
},
chain: mainnet,
transport: http(),
})
batch.multicall.batchSize (optional)
- Type:
number
- Default:
1_024
The maximum size (in bytes) for each multicall (aggregate3
) calldata chunk.
Note: Some RPC Providers limit the amount of calldata that can be sent in a single request. It is best to check with your RPC Provider to see if there are any calldata size limits to
eth_call
requests.
const publicClient = createPublicClient({
batch: {
multicall: {
batchSize: 512,
},
},
chain: mainnet,
transport: http(),
})
batch.multicall.wait (optional)
- Type:
number
- Default:
0
(zero delay)
The maximum number of milliseconds to wait before sending a batch.
const publicClient = createPublicClient({
batch: {
multicall: {
wait: 16,
},
},
chain: mainnet,
transport: http(),
})
cacheTime (optional)
- Type:
number
- Default:
client.pollingInterval
Time (in ms) that cached data will remain in memory.
const publicClient = createPublicClient({
cacheTime: 10_000,
chain: mainnet,
transport: http(),
})
ccipRead (optional)
- Type:
(parameters: CcipRequestParameters) => Promise<CcipRequestReturnType> | false
- Default:
true
CCIP Read configuration.
CCIP Read is enabled by default, but if set to false
, the client will not support offchain CCIP lookups.
const publicClient = createPublicClient({
ccipRead: false,
chain: mainnet,
transport: http(),
})
ccipRead.request (optional)
- Type:
(parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>
A function that will be called to make the offchain CCIP lookup request.
const publicClient = createPublicClient({
ccipRead: {
async request({ data, sender, urls }) {
// ...
}
},
chain: mainnet,
transport: http(),
})
key (optional)
- Type:
string
- Default:
"public"
A key for the Client.
const publicClient = createPublicClient({
chain: mainnet,
key: 'public',
transport: http(),
})
name (optional)
- Type:
string
- Default:
"Public Client"
A name for the Client.
const publicClient = createPublicClient({
chain: mainnet,
name: 'Public Client',
transport: http(),
})
pollingInterval (optional)
- Type:
number
- Default:
4_000
Frequency (in ms) for polling enabled Actions.
const publicClient = createPublicClient({
chain: mainnet,
pollingInterval: 10_000,
transport: http(),
})
rpcSchema (optional)
- Type:
RpcSchema
- Default:
PublicRpcSchema
Typed JSON-RPC schema for the client.
import { rpcSchema } from 'viem'
type CustomRpcSchema = [{
Method: 'eth_wagmi',
Parameters: [string]
ReturnType: string
}]
const publicClient = createPublicClient({
chain: mainnet,
rpcSchema: rpcSchema<CustomRpcSchema>(),
transport: http(),
})
const result = await publicClient.request({
method: 'eth_waeth_wagmi
params: ['hello'],
})
Live Example
Check out the usage of createPublicClient
in the live Public Client Example below.