Write to a Contract with writeAsync
button
This recipe shows how to implement a button that allows users to interact with a smart contract by executing the writeAsync
function returned by useScaffoldContractWrite. 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 { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeAsync, isLoading } = useScaffoldContractWrite({
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
});
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={() => writeAsync()} disabled={isLoading}>
{isLoading ? <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 useScaffoldContractWrite
hookโ
Initialize the useScaffoldContractWrite
hook to set up the contract interaction. This hook provides the writeAsync
function for sending transactions.
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeAsync } = useScaffoldContractWrite({
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
});
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โ
Design the user interface to allow users to input data and trigger the contract interaction. The example below demonstrates a simple form:
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeAsync } = useScaffoldContractWrite({
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
});
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={() => writeAsync()}
>
Send
</button>
</>
);
};
Step 4: Bonus adding loading stateโ
We can use isLoading
returned from useScaffoldContractWrite
while the transaction is being mined and also disable the button.
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");
const { writeAsync, isLoading } = useScaffoldContractWrite({
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
onBlockConfirmation: txnReceipt => {
console.log("๐ฆ Transaction blockHash", txnReceipt.blockHash);
},
});
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={() => writeAsync()}
disabled={isLoading}
>
{isLoading ? <span className="loading loading-spinner loading-sm"></span> : <>Send</>}
</button>
</>
);
};
You can also create a writeAsync button sending args imperatively, here is an example:
<button className="btn btn-primary" onClick={() => writeAsync({ args: ["Hello"], value: parseEther("0.02") })}>
Send imperatively
</button>