You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在wagmi的useContractWrite钩子中指定ETH值,实现ETH+ERC20代币转账?

同时发送ETH与ERC20代币的wagmi实现方案

一、核心:在useContractWrite中指定ETH金额

如果是通过自定义合约方法同时处理ETH接收与ERC20转账,可以直接在useContractWrite的配置中通过value字段指定ETH数值(单位为wei)。前提是合约方法需用payable修饰,支持接收ETH。

示例代码

import { useContractWrite, usePrepareContractWrite } from 'wagmi';
import { ethers } from 'ethers';

// 替换为你的合约ABI(需包含同时处理ETH和ERC20的方法)
const customContractAbi = [
  {
    inputs: [{ internalType: 'address', name: 'to', type: 'address' }, { internalType: 'uint256', name: 'tokenAmount', type: 'uint256' }],
    name: 'transferWithEth',
    outputs: [],
    stateMutability: 'payable',
    type: 'function',
  },
];

const contractAddress = '0x...'; // 你的合约地址
const targetAddress = '0x...'; // 接收地址

export function TransferWithEth() {
  // 提前准备合约调用配置
  const { config } = usePrepareContractWrite({
    address: contractAddress,
    abi: customContractAbi,
    functionName: 'transferWithEth',
    args: [targetAddress, ethers.utils.parseUnits('100', 18)], // ERC20转账数量(100代币,18位小数)
    value: ethers.utils.parseEther('0.5'), // 要发送的ETH金额(0.5 ETH)
  });

  // 发起合约调用
  const { write, isLoading, error } = useContractWrite(config);

  return (
    <button onClick={() => write?.()} disabled={isLoading}>
      {isLoading ? '处理中...' : '转ETH+ERC20'}
    </button>
  );
}

二、独立发起ETH+ERC20转账(两个交易)

如果没有自定义合约,需要分别发起ETH转账和ERC20转账,可以结合useSendTransaction(处理ETH)和useContractWrite(处理ERC20),用Promise管理异步逻辑。

1. 并行发起两个交易

import { useContractWrite, usePrepareContractWrite, useSendTransaction, useWaitForTransaction } from 'wagmi';
import { erc20Abi } from 'wagmi';
import { ethers } from 'ethers';

const erc20Address = '0x...'; // ERC20代币地址
const targetAddress = '0x...'; // 接收地址

export function DualTransfer() {
  // 准备ERC20转账配置
  const { config: erc20Config } = usePrepareContractWrite({
    address: erc20Address,
    abi: erc20Abi,
    functionName: 'transfer',
    args: [targetAddress, ethers.utils.parseUnits('100', 18)],
  });
  const { write: writeErc20, data: erc20TxHash } = useContractWrite(erc20Config);

  // 准备ETH转账配置
  const { sendTransaction: sendEth, data: ethTxHash } = useSendTransaction({
    to: targetAddress,
    value: ethers.utils.parseEther('0.5'),
  });

  // 监听交易确认状态
  const { isLoading: ethLoading } = useWaitForTransaction({ hash: ethTxHash?.hash });
  const { isLoading: erc20Loading } = useWaitForTransaction({ hash: erc20TxHash?.hash });

  const handleDualTransfer = async () => {
    try {
      // 并行发起两个交易
      await Promise.all([sendEth?.(), writeErc20?.()]);
      console.log('两个交易已提交');
    } catch (err) {
      console.error('交易失败:', err);
    }
  };

  return (
    <button onClick={handleDualTransfer} disabled={ethLoading || erc20Loading}>
      {ethLoading || erc20Loading ? '处理中...' : '同时转ETH+ERC20'}
    </button>
  );
}

2. 串行发起(确保前一个交易成功后再执行下一个)

如果需要保证ETH转账确认后再发起ERC20转账,调整异步逻辑:

const handleDualTransfer = async () => {
  try {
    // 先发起ETH转账并等待确认
    const ethTx = await sendEth?.();
    if (!ethTx) throw new Error('ETH转账发起失败');
    await ethTx.wait();

    // ETH确认后发起ERC20转账并等待确认
    const erc20Tx = await writeErc20?.();
    if (!erc20Tx) throw new Error('ERC20转账发起失败');
    await erc20Tx.wait();

    console.log('两个交易均已确认');
  } catch (err) {
    console.error('交易失败:', err);
  }
};

三、异步逻辑与嵌套问题的解决技巧

  • 提前准备配置:用usePrepareContractWrite提前解析参数、ABI等,避免在write函数中嵌套复杂逻辑。
  • 用Promise管理异步流:用Promise.all并行或await串行处理交易,替代嵌套回调,代码更清晰。
  • 利用wagmi状态变量:通过isLoading、data(交易哈希)、error直接维护UI状态,无需手动管理复杂状态。
  • 统一错误处理:在async函数中用try/catch捕获所有异常,包括用户拒绝签名、交易失败等场景。

注意:原生ETH转账和ERC20转账是两个独立操作,无法在单个原生交易中完成,必须通过自定义合约中转才能实现同一交易内的双转账。

内容的提问来源于stack exchange,提问作者user130657

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 15:14:54