Write to a Contract with writeContractAsync button
This recipe shows how to implement a button that allows users to interact with a smart contract by executing the writeContractAsync function returned by useScaffoldWriteContract. By following this guide, you can create a user interface for writing data to a contract.
Here is the full code, which we will be implementing in the guide below:
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeContractAsync, isPending } = useScaffoldWriteContract("YourContract");
const handleSetGreeting = async () => {
try {
await writeContractAsync(
{
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
},
{
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
},
);
} catch (e) {
console.error("Error setting greeting", e);
}
};
return (
<>
<input
type="text"
placeholder="Write your greeting"
className="input border border-primary"
onChange={e => setNewGreeting(e.target.value)}
/>
<button className="btn btn-primary" onClick={handleSetGreeting} disabled={isPending}>
{isPending ? <span className="loading loading-spinner loading-sm"></span> : "Send"}
</button>
</>
);
};
Implementationโ
Step 1: Set Up Your Componentโ
Create a new component in the "components" folder. This component will enable users to write data to a smart contract.
export const Greetings = () => {
return (
<>
<input type="text" placeholder="Write your greeting" className="input border border-primary" />
<button>Send</button>
</>
);
};
Step 2: Initialize useScaffoldWriteContract hookโ
Initialize the useScaffoldWriteContract hook. This hook provides the writeContractAsync function for sending transactions, we'll create handleSetGreeting function in which we'll call and pass parameters to writeContractAsync required to perform contract interaction.
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeContractAsync } = useScaffoldWriteContract("YourContract");
const handleSetGreeting = async () => {
try {
await writeContractAsync(
{
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
},
{
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
},
);
} catch (e) {
console.error("Error setting greeting", e);
}
};
return (
<>
<input type="text" placeholder="Write your greeting" className="input border border-primary" />
<button>Send</button>
</>
);
};
Step 3: Add input change logic and send transaction when users click the buttonโ
Wire up the input field to update the newGreeting state when the user types in a new greeting and call handleSetGreeting function when user click on the button.
import { parseEther } from "viem";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeContractAsync } = useScaffoldWriteContract("YourContract");
const handleSetGreeting = async () => {
try {
await writeContractAsync(
{
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
},
{
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
},
);
} catch (e) {
console.error("Error setting greeting", e);
}
};
return (
<>
<input
type="text"
placeholder="Write your greeting"
className="input border border-primary"
onChange={e => setNewGreeting(e.target.value)}
/>
<button
className="btn btn-primary"
onClick={handleSetGreeting}
>
Send
</button>
</>
);
};
Step 4: Bonus adding loading stateโ
We can use isPending returned from useScaffoldWriteContract while the transaction is being mined and also disable the button.
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeContractAsync, isPending } = useScaffoldWriteContract("YourContract");
const handleSetGreeting = async () => {
try {
await writeContractAsync(
{
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
},
{
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
},
);
} catch (e) {
console.error("Error setting greeting", e);
}
};
return (
<>
<input
type="text"
placeholder="Write your greeting"
className="input border border-primary"
onChange={e => setNewGreeting(e.target.value)}
/>
<button
className="btn btn-primary"
onClick={handleSetGreeting}
disabled={isPending}
>
{isPending ? <span className="loading loading-spinner loading-sm"></span> : "Send"}
</button>
</>
);
};