比如在代码 https://github.com/linghuccc/multi-call-test/blob/main/src/App.tsx 中,
先完成 action 1,然后再执行 action 2。
在实践中,执行 action 1 的时候, await writeContractAsync 只能保证 startDelay transaction 已经 send 了,而 startDelay 这个 function 在链上执行需要一定时间,await writeContractAsync 并不能保证这个 transaction 已经完成了,所以在执行第二步 doSomething 的时候,有时会出错。
所以我想,如果 useWaitForTransactionReceipt 有类似的 component,就可以 await 它,确定 approve transaction 已经完成了,再执行下一步。
将等待交易确认的逻辑移到组件的最顶层,或者使用另一个自定义的Hooks来封装这个逻辑

const [action1Hash, setAction1Hash] = useState<string | null>(null);
const [action2Hash, setAction2Hash] = useState<string | null>(null);
const { writeAsync: writeContractAsync } = useWriteContract({
abi: contractAbi,
address: contractAddress,
});
const { isLoading: isAction1Loading, isSuccess: isAction1Success } = useWaitForTransactionReceipt({
hash: action1Hash,
});
const { isLoading: isAction2Loading, isSuccess: isAction2Success } = useWaitForTransactionReceipt({
hash: action2Hash,
});
await writeContractAsync 只能保证交易已经被发送到区块链网络,但并不能保证交易已经被矿工确认并完成。为了确保 startDelay 函数在链上执行完成后再执行 doSomething,
可以在 action1 函数中使用它来等待 startDelay 交易的完成。

async function action1() {
try {
// 执行一些异步操作
const action1Tx = await writeContractAsync({
abi: contractAbi,
address: contractAddress,
functionName: 'startDelay',
args: [BigInt(10)],
});
console.log('Action 1 hash:', action1Tx);
// 等待交易完成
await waitForTransaction(action1Tx.hash);
return Promise.resolve('Action 1 completed');
} catch (error) {
console.error('An error occurred in action1:', error);
throw error; // 重新抛出错误,以便在 handleClick 中捕获
}
}
// 使用 useWaitForTransactionReceipt 钩子来等待交易完成
async function waitForTransaction(hash: string) {
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash,
});
// 等待交易成功
if (isLoading) {
return new Promise<void>((resolve, reject) => {
const unsubscribe = useWaitForTransactionReceipt(hash, {
onSettled: (receipt) => {
if (receipt) {
resolve();
} else {
reject(new Error('Transaction failed or was not confirmed'));
}
unsubscribe();
},
});
});
}
if (!isSuccess) {
throw new Error('Transaction failed or was not confirmed');
}
}
为了在组件中正确使用 useWaitForTransactionReceipt,需要创建一个新的状态来跟踪第一个交易的确认状态,并在该状态更新后执行第二个操作

function App() {
// ... 其他状态和钩子
const [action1Completed, setAction1Completed] = useState(false);
// ... action1 和 action2 函数
// 使用 useWaitForTransactionReceipt 钩子来等待 action1 的交易完成
useWaitForTransactionReceipt({
hash: data,
onSuccess: () => {
setAction1Completed(true);
},
});