使用wagmi v2.5.7与RainbowKit调用合约时遇write不是函数问题
解决wagmi v2.5.7中useContractWrite的'write is not a function'错误
问题根源
wagmi从v1升级到v2后,useContractWrite的API有重大变更:
- 原
write方法已更名为writeAsync - 参数传递逻辑调整,动态参数需要特殊处理才能实时更新
具体修复步骤
替换
write为writeAsync
这是报错的直接原因,v2中不再提供write方法,统一使用异步的writeAsync。动态处理合约调用参数
你的代码中args直接依赖newRate状态,但组件初始化时newRate为空,且后续状态变化不会自动同步到useContractWrite的参数中。需要将args改为函数形式,确保每次调用时获取最新值:
const { writeAsync, // 替换原write为writeAsync isLoading, error: writeError, } = useContractWrite({ address: contractAddress, // v2推荐用address替代旧的addressOrName abi: contractABI, // 替代旧的contractInterface functionName: "adjustRates", // 改为函数形式实时获取最新newRate args: () => [newRate ? BigInt(newRate) : 0], onSettled(data, error) { if (error) { console.error("Transaction Error:", error); setError(error.message || "Adjustment failed."); } else { console.log("Transaction Success:", data); setError(""); } }, });
- 更新调用逻辑
在handleAdjustRates中调用writeAsync:
try { const tx = await writeAsync(); console.log("Transaction initiated:", tx); } catch (err) { console.error("Adjustment failed:", err); setError(err.message || "An unexpected error occurred."); }
额外注意事项
- v2中
addressOrName和contractInterface已被address和abi替代,旧字段虽暂时兼容,但建议使用新字段避免后续版本问题。 - 确保wagmi Client配置正确,必须包含
publicClient和walletClient实例,这是合约交互的基础。
修改后的完整组件代码
import React, { useState } from "react"; import { useAccount, useContractWrite } from "wagmi"; import { Button, Input, Text } from "@nextui-org/react"; import { presaleAdr as contractAddress, presale_ABI as contractABI, } from "@/constants/presaleAdr"; function ModifyRate() { const [newRate, setNewRate] = useState(""); const [error, setError] = useState(""); const { isConnected } = useAccount(); const { writeAsync, isLoading, error: writeError, } = useContractWrite({ address: contractAddress, abi: contractABI, functionName: "adjustRates", args: () => [newRate ? BigInt(newRate) : 0], onSettled(data, error) { if (error) { console.error("Transaction Error:", error); setError(error.message || "Adjustment failed."); } else { console.log("Transaction Success:", data); setError(""); } }, }); const handleAdjustRates = async () => { setError(""); if (!isConnected) { setError("请先连接钱包。"); return; } if (!newRate) { setError("请输入新的费率。"); return; } try { const tx = await writeAsync(); console.log("交易已发起:", tx); } catch (err) { console.error("费率调整失败:", err); setError(err.message || "发生未知错误。"); } }; return ( <div className="w-1/2 m-auto h-auto"> <Input clearable bordered fullWidth color="primary" size="lg" placeholder="输入新费率" value={newRate} onChange={(e) => setNewRate(e.target.value)} disabled={isLoading} /> <Button auto disabled={isLoading || !newRate || !isConnected} onClick={handleAdjustRates} > {isLoading ? "处理中..." : "调整费率"} </Button> {writeError && <Text color="error">{writeError.message}</Text>} </div> ); } export default ModifyRate;
内容的提问来源于stack exchange,提问作者angryhayder
相关产品推荐
相关产品推荐

