UNPKG

@tevm/test-matchers

Version:

Vite test matchers for Tevm or EVM-related testing in TypeScript.

71 lines (62 loc) 2.45 kB
import { getAccountHandler } from '@tevm/actions' import { createTevmNode, type TevmNode } from '@tevm/node' import { type Address, type Client, type Hex, isAddress } from 'viem' import type { ContainsAddress } from '../../common/types.js' import type { ExpectedState } from './types.js' export const toHaveState = async ( received: Address | ContainsAddress, client: Client | TevmNode, expectedState: ExpectedState, ) => { const address = typeof received === 'string' ? received : received.address if (!isAddress(address)) throw new Error(`Invalid address: ${address}`) const node = 'request' in client ? createTevmNode({ fork: { transport: client } }) : client const account = await getAccountHandler(node, { throwOnFail: false })({ address, returnStorage: true }) if (account.errors) throw new Error(account.errors[0]?.message ?? 'Could not retrieve account') const { storage = {}, ...state } = expectedState const mismatchedKeys: (keyof ExpectedState)[] = [] // Check provided state entries (except storage) Object.entries(state).forEach(([_key, expectedValue]) => { const key = _key as keyof Omit<ExpectedState, 'storage'> const actualValue = account[key] if (actualValue !== expectedValue) mismatchedKeys.push(key) }) // Check provided storage entries for (const [_slot, expectedValue] of Object.entries(storage)) { const slot = _slot as Hex const actualValue = account.storage?.[slot] if (actualValue !== expectedValue) { mismatchedKeys.push('storage') break } } const pass = mismatchedKeys.length === 0 return { pass, message: () => pass ? `Expected account ${address} not to have state.` : `Expected account ${address} to have state but received mismatched state at keys: ${mismatchedKeys.join(', ')}`, // Only show provided keys with their actual values so it's not confusing actual: pass ? undefined : { ...Object.fromEntries( Object.entries(expectedState) .filter(([key]) => key !== 'storage') .map(([key]) => [key, account[key as keyof typeof account] ?? undefined]), ), ...(Object.keys(expectedState).includes('storage') && expectedState.storage ? { storage: Object.fromEntries( Object.entries(expectedState.storage).map(([slot]) => [ slot, account.storage?.[slot as Hex] ?? undefined, ]), ), } : {}), }, expected: pass ? undefined : expectedState, } }