Skip to content
LogoLogo

Build your own Client

You can build your own viem Client by using the createClient function and optionally extending (.extend) it – this is how viem's internal Clients (Public, Wallet, and Test) are built.

Building your own Client is useful if you have specific requirements for how the Client should behave, and if you want to extend that Client with custom functionality (ie. create a geth Debug Client).

The createClient function sets up a base viem Client with a given Transport configured with a Chain. After that, you can extend the Client with custom properties (that could be Actions or other configuration).

Import

import {  } from 'viem'

Usage

Initialize a Client with your desired Chain (e.g. mainnet) and Transport (e.g. http).

import { ,  } from 'viem'
import {  } from 'viem/chains'
 
const  = ({ 
  : ,
  : ()
})

Next, you can either extend your Client with Actions or configuration, or you can use it as-is for the purpose of maximizing tree-shaking in your app.

Extending with Actions or configuration

You can extend your Client with custom Actions or configuration by using the .extend function.

Below is a naive implementation of implementing a geth Debug Client with a traceCall Action that uses the debug_traceCall RPC method.

import { 
  , 
  ,
  ,
  type 
} from 'viem'
import {  } from 'viem/chains'
 
const  = ({ 
  : ,
  : (),
}).( => ({
  // ...
  async (: ) {
    return .({
      : 'debug_traceCall',
      : [(), 'latest', {}]
    })
  },
  // ...
}))
 
const  = await .({
  : '0xdeadbeef29292929192939494959594933929292',
  : '0xde929f939d939d393f939393f93939f393929023',
  : 69420n,
  : '0xf00d4b5d00000000000000000000000001291230982139282304923482304912923823920000000000000000000000001293123098123928310239129839291010293810'
})
// { failed: false, gas: 69420, returnValue: '...', structLogs: [] }

For a more succinct implementation of using .extend, check out viem's Public Client implementation extended with Public Actions.

Tree-shaking

You can use the Client as-is, with no decorated Actions, to maximize tree-shaking in your app. This is useful if you are pedantic about bundle size and want to only include the Actions you use.

In the example below, instead of calling getBlock from the Public Client, we are importing the Action directly from viem and then injecting our Client as the first parameter to the Action.

import { ,  } from 'viem'
import {  } from 'viem/chains'
import { ,  } from 'viem/actions'
 
const  = ({ 
  : ,
  : ()
})
 
const  = await (, { : 'latest' })
const  = await (, { ... })

Parameters

transport

The Transport of the Public Client.

const  = ({
  : ,
  : (), 
})

account (optional)

  • Type: Account | Address

The Account to use for the Client. This will be used for Actions that require an account as an argument.

Accepts a JSON-RPC Account or Local Account (Private Key, etc).

import {  } from 'viem/accounts'
 
const  = ({
  : ('0x...'), 
  : ,
  : (),
})

chain (optional)

The Chain of the Public Client.

const  = ({
  : , 
  : (),
})

batch (optional)

Flags for batch settings.

batch.multicall (optional)

  • Type: boolean | MulticallBatchOptions
  • Default: false

Toggle to enable eth_call multicall aggregation.

const  = ({
  : {
    : true, 
  },
  : ,
  : (),
})

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  = ({
  : {
    : {
      : 512, 
    },
  },
  : ,
  : (),
})

batch.multicall.wait (optional)

The maximum number of milliseconds to wait before sending a batch.

const  = ({
  : {
    : {
      : 16, 
    },
  },
  : ,
  : (),
})

key (optional)

  • Type: string
  • Default: "public"

A key for the Client.

const  = ({
  : ,
  : 'public', 
  : (),
})

name (optional)

  • Type: string
  • Default: "Public Client"

A name for the Client.

const  = ({
  : ,
  : 'Public Client', 
  : (),
})

pollingInterval (optional)

  • Type: number
  • Default: 4_000

Frequency (in ms) for polling enabled Actions.

const  = ({
  : ,
  : 10_000, 
  : (),
})

rpcSchema (optional)

  • Type: RpcSchema
  • Default: WalletRpcSchema

Typed JSON-RPC schema for the client.

import {  } from 'viem'
 
type  = [{ 
  : 'eth_wagmi', 
  : [string] 
  : string
}] 
 
const  = ({
  : ,
  : <>(), 
  : ()
})
 
const  = await .({ 
  : 'eth_wa // [!code focus] 
  : ['hello'], 
})