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>
</>
);
};