handlers.tsā¢1.7 kB
import type { Abi, AbiFunction, PublicActions, WalletClient } from 'viem';
import { isAddress } from 'viem';
import { base } from 'viem/chains';
import type { z } from 'zod';
import { constructBaseScanUrl } from '../utils/index.js';
import type { CallContractSchema } from './schemas.js';
export async function callContractHandler(
wallet: WalletClient & PublicActions,
args: z.infer<typeof CallContractSchema>,
): Promise<string> {
let abi: string | Abi = args.abi;
try {
abi = JSON.parse(abi) as Abi;
} catch (error) {
throw new Error(`Invalid ABI: ${error}`);
}
if (!isAddress(args.contractAddress, { strict: false })) {
throw new Error(`Invalid contract address: ${args.contractAddress}`);
}
let functionAbi: AbiFunction | undefined;
try {
functionAbi = abi.find(
(item) => 'name' in item && item.name === args.functionName,
) as AbiFunction;
} catch (error) {
throw new Error(`Invalid function name: ${args.functionName}. ${error}`);
}
if (
functionAbi.stateMutability === 'view' ||
functionAbi.stateMutability === 'pure'
) {
const tx = await wallet.readContract({
address: args.contractAddress,
abi,
functionName: args.functionName,
args: args.functionArgs,
});
return String(tx);
}
const tx = await wallet.simulateContract({
account: wallet.account,
abi,
address: args.contractAddress,
functionName: args.functionName,
value: BigInt(args.value ?? 0),
args: args.functionArgs,
});
const txHash = await wallet.writeContract(tx.request);
return JSON.stringify({
hash: txHash,
url: constructBaseScanUrl(wallet.chain ?? base, txHash),
});
}