Use viem

@rocketh/viem gives a deploy script, a test or a script viem clients on the environment's provider, and typed viem contracts for its deployments. It is a getter extension: it adds a viem property to the environment, not a function.

Setting it up

viem is a peer dependency:

pnpm add -D @rocketh/viem viem
// rocketh/config.ts
import * as deployExtension from '@rocketh/deploy';
import * as readExecuteExtension from '@rocketh/read-execute';
import * as viemExtension from '@rocketh/viem';

const extensions = {...deployExtension, ...readExecuteExtension, ...viemExtension};
export {extensions};

Typed contracts

env.viem.getContract takes a deployment, or a deployment name with the ABI type as its generic (a name alone says nothing about the type):

import {deployScript, artifacts} from '../rocketh/deploy.js';

export default deployScript(
	async ({deploy, viem, namedAccounts}) => {
		const {deployer} = namedAccounts;

		const deployment = await deploy('GreetingsRegistry', {
			account: deployer,
			artifact: artifacts.GreetingsRegistry,
			args: [''],
		});

		// typed from the deployment
		const registry = viem.getContract(deployment);
		const message = await registry.read.messages([deployer]);

		// typed from the generic
		const sameRegistry = viem.getContract<typeof artifacts.GreetingsRegistry.abi>('GreetingsRegistry');
	},
	{tags: ['GreetingsRegistry']},
);

The clients

MemberWhat it is
publicClienta viem PublicClient on the environment's chain and provider
walletClienta viem WalletClient on the same transport
getContract(nameOrDeployment)a read-only viem contract
getWritableContract(nameOrDeployment, {account?})a writable viem contract; account sets the sender

Both clients use viem's custom transport over env.network.provider, so they talk to the same node as the rest of the run, an in-memory or forked chain included:

const blockNumber = await viem.publicClient.getBlockNumber();
const balance = await viem.publicClient.getBalance({address: deployer});

Write with execute, read with viem

A transaction written through a viem contract goes through viem's wallet client, not through rocketh's broadcast path. So it gets none of what rocketh adds to a transaction: the unknown-signer handling (an account rocketh cannot sign for fails as a provider error, never reaching the pause or the onUnknownSigner policy), the pending-transaction record that lets an interrupted run resume, the captured transactions, the gas report and the messages.

For a call that is part of a deployment, use execute from @rocketh/read-execute:

await execute(deployment, {account: deployer, functionName: 'setMessage', args: ['hello']});

Keep getWritableContract for a write you specifically want through viem, from an account you can definitely sign for. Reads have no such caveat.

Search
Search the documentation