Skip to content

Quickstart

This page gets you from install to a working scenario quickly.

Prerequisites

  • vitest test runner
  • viem clients/utilities
  • anvil on your PATH (for local runtime/fork execution)

For forked examples, set:

export MAINNET_RPC_URL="https://..."

Install

Choose one package manager:

bun add -D @statecraft/vitest vitest viem
npm install -D @statecraft/vitest vitest viem

Step 1: first passing scenario (local chain)

Start with withChain() so you can run without external RPC:

import { test, expect } from "vitest";
import { parseEther } from "viem";
import { scenario, withChain, withFundedWallet } from "@statecraft/vitest";
 
test(
  "funded wallet on local chain",
  scenario(
    withChain(),
    withFundedWallet({
      balance: parseEther("1"),
    }),
    async ({ wallet, publicClient }) => {
      const 
const balance: bigint
balance
= await publicClient.getBalance({ address: wallet });
expect<bigint>(actual: bigint, message?: string): Assertion<bigint> (+1 overload)
expect
(balance).toBe(parseEther("1"));
}, ), );

Step 2: switch to a pinned fork

Once the local scenario works, move to withFork() for real mainnet state while staying deterministic:

import { test, expect } from "vitest";
import { parseEther } from "viem";
import { scenario, withFork, withFundedWallet } from "@statecraft/vitest";
 
test(
  "funded wallet on pinned mainnet fork",
  scenario(
    withFork({
      rpcUrl: process.env.MAINNET_RPC_URL!,
      blockNumber: 22_000_000n,
    }),
    withFundedWallet({
      balance: parseEther("1"),
    }),
    async ({ wallet, publicClient }) => {
      const balance = await publicClient.getBalance({ address: wallet });
      expect(balance).toBe(parseEther("1"));
    },
  ),
);

Next steps

packages/examples/examples/scenarios.test.ts includes:

  • fresh local chain + funded wallet
  • forked mainnet + funded wallet + real contract call
  • forked mainnet + funded wallet + USDC via withFundedWallet.erc20 or withErc20Balance
  • runtime bytecode injection with withContracts
  • real deployment flow with withDeployments
  • suite-scoped runtime reuse with withExternalRuntime plus withSnapshot

When you are ready for fixture ordering, lifecycle terminology (managed vs external), and typing behavior, read Core concepts.

ERC-20 balances (optional)

On Anvil-style local/forked nodes, you can seed token balances in two ways:

  • withFundedWallet({ erc20: [...] }) when recipient is the scenario wallet
  • withErc20Balance({ token, amount, to? }) when you need explicit recipient control

See Core concepts for behavior and caveats.