viem
Version:
83 lines • 3.36 kB
JavaScript
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