Wagmi useContractWrite
with transaction status
This recipe demonstrates how to create a button for contract interaction using the "useTransactor" and "useContractWrite" hooks from the "wagmi" library. The interaction includes the capability provides feedback on the transaction status when using wagmi useContractWrite
.
Here is the full code, which we will be implementing in the guide below:
import * as React from "react";
import { parseEther } from "viem";
import { useContractWrite } from "wagmi";
import { ArrowSmallRightIcon } from "@heroicons/react/24/outline";
import DeployedContracts from "~~/contracts/deployedContracts";
import { useTransactor } from "~~/hooks/scaffold-eth";
export const ContractInteraction = () => {
const writeTx = useTransactor();
const { writeAsync } = useContractWrite({
address: DeployedContracts[31337].YourContract.address,
abi: DeployedContracts[31337].YourContract.abi,
functionName: "setGreeting",
value: parseEther("0.01"),
args: ["Hello world!"],
});
const handleSetGreeting = async () => {
try {
await writeTx(writeAsync, { blockConfirmations: 1 });
} catch (e) {
console.log("Unexpected error in writeTx", e);
}
};
return (
<button className="btn btn-primary" onClick={handleSetGreeting} disabled={isLoading}>
{isLoading ? (
<span className="loading loading-spinner loading-sm"></span>
) : (
<>
Send <ArrowSmallRightIcon className="w-3 h-3 mt-0.5" />
</>
)}
</button>
);
};
Implementationโ
Step 1: Set Up Your Componentโ
Create a new component in the "components" folder. The component will show a button that will allow users to interact with your smart contract.
import * as React from "react";
export const ContractInteraction = () => {
return <button>Send</button>;
};
Step 2: Configure wagmi's useContractWrite
hookโ
Add wagmi's useContractWrite
hook and configure it with abi
, address
, functionName
etc. Get the ABI and address of your smart contract from the DeployedContracts or you can grab it from ExternalContracts object, those will be used to set up the contract interaction.
import * as React from "react";
import { parseEther } from "viem";
import { useContractWrite } from "wagmi";
import DeployedContracts from "~~/contracts/deployedContracts";
export const ContractInteraction = () => {
const { writeAsync } = useContractWrite({
address: DeployedContracts[31337].YourContract.address,
abi: DeployedContracts[31337].YourContract.abi,
functionName: "setGreeting",
value: parseEther("0.01"),
args: ["Hello world!"],
});
return <button>Send</button>;
};
Step 3: Initialize useTransactor
hook and send transactionโ
Initialize the useTransactor
hook, and use it to wrap writeAsync
function which we got from useContractWrite
to show feedback transaction status to user.
import * as React from "react";
import { parseEther } from "viem";
import { useContractWrite } from "wagmi";
import DeployedContracts from "~~/contracts/deployedContracts";
import { useTransactor } from "~~/hooks/scaffold-eth";
export const ContractInteraction = () => {
const { writeAsync } = useContractWrite({
address: DeployedContracts[31337].YourContract.address,
abi: DeployedContracts[31337].YourContract.abi,
functionName: "setGreeting",
value: parseEther("0.01"),
args: ["Hello world!"],
});
const writeTx = useTransactor();
return <button onClick={() => writeTx(writeAsync, { blockConfirmations: 1 })}>Send</button>;
};
Step 4: Bonus adding loading stateโ
We can use isLoading
returned from useContractWrite
while the transaction is being mined and also disable
the button.
import * as React from "react";
import { parseEther } from "viem";
import { useContractWrite } from "wagmi";
import DeployedContracts from "~~/contracts/deployedContracts";
import { useTransactor } from "~~/hooks/scaffold-eth";
export const ContractInteraction = () => {
const { writeAsync, isLoading } = useContractWrite({
address: DeployedContracts[31337].YourContract.address,
abi: DeployedContracts[31337].YourContract.abi,
functionName: "setGreeting",
value: parseEther("0.01"),
args: ["Hello world!"],
});
const writeTx = useTransactor();
return (
<button onClick={() => writeTx(writeAsync, { blockConfirmations: 1 })} disabled={isLoading}>
{isLoading ? <span className="loading loading-spinner loading-sm"></span> : <>Send</>}
</button>
);
};