UNPKG

viem

Version:

TypeScript Interface for Ethereum

83 lines 3.36 kB
import { parseAccount, } from '../../accounts/utils/parseAccount.js'; import { decodeFunctionResult, } from '../../utils/abi/decodeFunctionResult.js'; import { encodeFunctionData, } from '../../utils/abi/encodeFunctionData.js'; import { getContractError, } from '../../utils/errors/getContractError.js'; import { getAction } from '../../utils/getAction.js'; import { call } from './call.js'; /** * Simulates/validates a contract interaction. This is useful for retrieving **return data** and **revert reasons** of contract write functions. * * - Docs: https://viem.sh/docs/contract/simulateContract * - Examples: https://stackblitz.com/github/wevm/viem/tree/main/examples/contracts_writing-to-contracts * * This function does not require gas to execute and _**does not**_ change the state of the blockchain. It is almost identical to [`readContract`](https://viem.sh/docs/contract/readContract), but also supports contract write functions. * * Internally, uses a [Public Client](https://viem.sh/docs/clients/public) to call the [`call` action](https://viem.sh/docs/actions/public/call) with [ABI-encoded `data`](https://viem.sh/docs/contract/encodeFunctionData). * * @param client - Client to use * @param parameters - {@link SimulateContractParameters} * @returns The simulation result and write request. {@link SimulateContractReturnType} * * @example * import { createPublicClient, http } from 'viem' * import { mainnet } from 'viem/chains' * import { simulateContract } from 'viem/contract' * * const client = createPublicClient({ * chain: mainnet, * transport: http(), * }) * const result = await simulateContract(client, { * address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', * abi: parseAbi(['function mint(uint32) view returns (uint32)']), * functionName: 'mint', * args: ['69420'], * account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', * }) */ export async function simulateContract(client, parameters) { const { abi, address, args, dataSuffix, functionName, ...callRequest } = parameters; const account = callRequest.account ? parseAccount(callRequest.account) : client.account; const calldata = encodeFunctionData({ abi, args, functionName }); try { const { data } = await getAction(client, call, 'call')({ batch: false, data: `${calldata}${dataSuffix ? dataSuffix.replace('0x', '') : ''}`, to: address, ...callRequest, account, }); const result = decodeFunctionResult({ abi, args, functionName, data: data || '0x', }); const minimizedAbi = abi.filter((abiItem) => 'name' in abiItem && abiItem.name === parameters.functionName); return { result, request: { abi: minimizedAbi, address, args, dataSuffix, functionName, ...callRequest, account, }, }; } catch (error) { throw getContractError(error, { abi, address, args, docsPath: '/docs/contract/simulateContract', functionName, sender: account?.address, }); } } //# sourceMappingURL=simulateContract.js.map