Search code examples
wagmiviem

sendTransaction vs writeContract, with functionName "transfer"


I'm a bit confused on sending tokens from one address to another.

Say for example, I want to send AVAX native from one address to another,

I can successfully do it with sendTransaction which is just

 await sendTransaction({
                to,
                value: parseEther(value),
            })

I don't need to pass in an erc20 token address, since it's native.

Now, say I want to send USDT on Avalanche, that is an erc20. I can't seem to just use sendTransaction, instead I need to do:

await writeContractAsync({
        abi: erc20Abi,
        address: txDetails.tokenAddress,
        functionName: 'transfer',
        args: [txDetails.to, parsed],
      });

Is that the correct approach? Or am I over complicating things?


Solution

  • Yes, you're taking the correct approach.

    But it's worth giving more context here... for clarity.

    sendTransaction allows you to send any arbitrary transaction. This could be a transaction that interacts with a contract too. But, in your case, you're using it send native funds. Importantly, sendTransaction allows you to tag on a value parameter. This is the amount of the blockchain's native token that you're looking to send with the the transaction you're looking to commit to the blockchain.

    writeContract and it's variants, specifically write data to a contract. As ERC20 tokens are contracts, you need to call a write function on the contract to make it "do" something. In this case, you're calling transfer, with some address and an amount to transfer. This will execute the transfer of ERC20 tokens. But, in reality is just incrementing a number mapped to the receivers address, and decrementing yours.

    There are simpler ways to carry out ERC20 transfers, and contract interaction with Viem. But, they ultimately do the same thing. For example ...

    Instead of calling writeContract, you can interact directly with a Contract object. The object exposes an interface based on it's ABI -- read more about Contract instances. Doing this would allow you to call yourContract.write.transfer(...args) instead. Which is much more readable and intuitive.

    Hope this helps!