Viem
Viem is a low-level TypeScript Interface for Ethereum that enables developers to interact with the Ethereum blockchain, including: JSON-RPC API abstractions, Smart Contract interaction, wallet & signing implementations, coding/parsing utilities and more.
Wagmi Core is essentially a wrapper over Viem that provides multi-chain functionality via Wagmi Config and automatic account management via Connectors.
Leveraging Viem Actions
All of the core Wagmi Actions are friendly wrappers around Viem Actions that inject a multi-chain and connector aware Wagmi Config.
There may be cases where you might want to dig deeper and utilize Viem Actions directly (maybe an Action doesn't exist in Wagmi yet). In these cases, you can import Viem Actions directly via viem/actions
and plug in a Viem Client returned by the getClient
Action.
The example below demonstrates two different ways to utilize Viem Actions:
- Tree-shakable Actions (recommended): Uses
getClient
(for public actions) andgetConnectorClient
(for wallet actions). - Client Actions: Uses
getPublicClient
(for public actions) andgetWalletClient
(for wallet actions).
TIP
It is highly recommended to use the tree-shakable method to ensure that you are only pulling modules you use, and keep your bundle size low.
// 1. Import modules.
import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { getLogs, watchAsset } from 'viem/actions'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Client for the current active chain.
const publicClient = getClient(config)
const logs = await getLogs(publicClient, /* ... */)
// 4. Extract a Viem Client for the current active chain & account.
const walletClient = getConnectorClient(config)
const success = await watchAsset(walletClient, /* ... */)
// 1. Import modules.
import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { getLogs, watchAsset } from 'viem/actions'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Client for the current active chain.
const publicClient = getClient(config)
const logs = await getLogs(publicClient, /* ... */)
// 4. Extract a Viem Client for the current active chain & account.
const walletClient = getConnectorClient(config)
const success = await watchAsset(walletClient, /* ... */)
// 1. Import modules.
import { http, createConfig, getPublicClient, getWalletClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Public Client for the current active chain.
const publicClient = getPublicClient(config)
const logs = await publicClient.getLogs(publicClient, /* ... */)
// 4. Extract a Viem Wallet Client for the current active chain & account.
const walletClient = getWalletClient(config)
const success = await walletClient.watchAsset(walletClient, /* ... */)
// 1. Import modules.
import { http, createConfig, getPublicClient, getWalletClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Public Client for the current active chain.
const publicClient = getPublicClient(config)
const logs = await publicClient.getLogs(publicClient, /* ... */)
// 4. Extract a Viem Wallet Client for the current active chain & account.
const walletClient = getWalletClient(config)
const success = await walletClient.watchAsset(walletClient, /* ... */)
Multi-chain Viem Client
The Viem Client provides an interface to interact with an JSON-RPC Provider. By nature, JSON-RPC Providers are single-chain, so the Viem Client is designed to be instantiated with a single chain
. As a result, setting up Viem to be multi-chain aware can get a bit verbose.
The good news is that you can create a "multi-chain Viem Client" with Wagmi by utilizing createConfig
and getClient
.
// 1. Import modules.
import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { getBlockNumber, sendTransaction } from 'viem/actions'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Client for the current active chain.
const publicClient = getClient(config)
const blockNumber = await getBlockNumber(publicClient)
// 4. Extract a Viem Client for the current active chain & account.
const walletClient = getConnectorClient(config)
const hash = await sendTransaction(walletClient, /* ... */)
// 1. Import modules.
import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { getBlockNumber, sendTransaction } from 'viem/actions'
// 2. Set up a Wagmi Config
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
// 3. Extract a Viem Client for the current active chain.
const publicClient = getClient(config)
const blockNumber = await getBlockNumber(publicClient)
// 4. Extract a Viem Client for the current active chain & account.
const walletClient = getConnectorClient(config)
const hash = await sendTransaction(walletClient, /* ... */)
// Manually set up Viem Clients without wagmi. Don't do this, it's only here
// to demonstrate the amount of boilerplate required.
import { createPublicClient, createWalletClient, http } from 'viem'
import { base, mainnet, optimism, zora } from 'viem/chains'
const publicClient = {
base: createPublicClient({
chain: base,
transport: http()
}),
mainnet: createPublicClient({
chain: mainnet,
transport: http()
}),
optimism: createPublicClient({
chain: optimism,
transport: http()
}),
zora: createPublicClient({
chain: zora,
transport: http()
})
} as const
const walletClient = {
base: createWalletClient({
chain: base,
transport: custom(window.ethereum)
}),
mainnet: createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
}),
optimism: createWalletClient({
chain: optimism,
transport: custom(window.ethereum)
}),
zora: createWalletClient({
chain: zora,
transport: custom(window.ethereum)
})
} as const
const blockNumber = await publicClient.mainnet.getBlockNumber()
const hash = await walletClient.mainnet.sendTransaction(/* ... */)
// Manually set up Viem Clients without wagmi. Don't do this, it's only here
// to demonstrate the amount of boilerplate required.
import { createPublicClient, createWalletClient, http } from 'viem'
import { base, mainnet, optimism, zora } from 'viem/chains'
const publicClient = {
base: createPublicClient({
chain: base,
transport: http()
}),
mainnet: createPublicClient({
chain: mainnet,
transport: http()
}),
optimism: createPublicClient({
chain: optimism,
transport: http()
}),
zora: createPublicClient({
chain: zora,
transport: http()
})
} as const
const walletClient = {
base: createWalletClient({
chain: base,
transport: custom(window.ethereum)
}),
mainnet: createWalletClient({
chain: mainnet,
transport: custom(window.ethereum)
}),
optimism: createWalletClient({
chain: optimism,
transport: custom(window.ethereum)
}),
zora: createWalletClient({
chain: zora,
transport: custom(window.ethereum)
})
} as const
const blockNumber = await publicClient.mainnet.getBlockNumber()
const hash = await walletClient.mainnet.sendTransaction(/* ... */)
Private Key & Mnemonic Accounts
It is possible to utilize Viem's Private Key & Mnemonic Accounts with Wagmi by explicitly passing through the account via the account
argument on Wagmi Actions.
import { http, createConfig, sendTransaction } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { parseEther } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
const account = privateKeyToAccount('0x...')
const hash = await sendTransaction({
account,
to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
value: parseEther('0.001')
})
import { http, createConfig, sendTransaction } from '@wagmi/core'
import { base, mainnet, optimism, zora } from '@wagmi/core/chains'
import { parseEther } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
export const config = createConfig({
chains: [base, mainnet, optimism, zora],
transports: {
[base.id]: http(),
[mainnet.id]: http(),
[optimism.id]: http(),
[zora.id]: http(),
},
})
const account = privateKeyToAccount('0x...')
const hash = await sendTransaction({
account,
to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
value: parseEther('0.001')
})
INFO
Wagmi currently does not support hoisting Private Key & Mnemonic Accounts to the top-level Wagmi Config – meaning you have to explicitly pass through the account to every Action. If you feel like this is a feature that should be added, please open an discussion.