@tevm/test-matchers
Version:
Vite test matchers for Tevm or EVM-related testing in TypeScript.
55 lines (48 loc) • 2.05 kB
text/typescript
import type { AbiParameter, AbiParametersToPrimitiveTypes, ExtractAbiFunction } from 'abitype'
import { type Abi, type ContractFunctionName, decodeAbiParameters } from 'viem'
import { parseChainArgs } from '../../chainable/chainable.js'
import type { ChainState, MatcherResult } from '../../chainable/types.js'
import type { ToCallContractFunctionState } from './types.js'
export const withFunctionArgs = <
TAbi extends Abi | undefined = Abi | undefined,
TFunctionName extends TAbi extends Abi ? ContractFunctionName<TAbi> : never = TAbi extends Abi
? ContractFunctionName<TAbi>
: never,
TInputs extends readonly AbiParameter[] = TAbi extends Abi
? ExtractAbiFunction<TAbi, TFunctionName> extends { inputs: infer U extends readonly AbiParameter[] }
? U
: readonly AbiParameter[]
: never,
>(
_received: unknown,
...argsAndChainState: readonly [
...AbiParametersToPrimitiveTypes<TInputs>,
ChainState<unknown, ToCallContractFunctionState>,
]
): MatcherResult => {
const {
args,
chainState: { previousState },
} = parseChainArgs<unknown, ToCallContractFunctionState>(argsAndChainState)
if (!previousState || !('abiFunction' in previousState))
throw new Error('withFunctionArgs() requires a contract with abi and function name')
const { abiFunction, selector, calldataMap } = previousState
const calldata = calldataMap.get(selector)
const actualDecodedArgs = calldata
? calldata.map((calldata) => decodeAbiParameters(abiFunction.inputs, calldata))
: undefined
const argsMatched = actualDecodedArgs
? actualDecodedArgs.some((decodedArgs) => {
return Array.isArray(decodedArgs) && args.every((arg, i) => decodedArgs[i] === arg)
})
: false
return {
pass: argsMatched,
actual: actualDecodedArgs ? Object.fromEntries(actualDecodedArgs.map((decodedArgs, i) => [i, decodedArgs])) : {},
expected: args,
message: () =>
argsMatched
? 'Expected transaction not to call function with the specified arguments'
: 'Expected transaction to call function with the specified arguments',
}
}