Starknet Multi-Write Feature Recipe
This recipe shows how to perform multiple contract write operations in a single transaction using the useScaffoldMultiWriteContract hook from Scaffold-Stark.
Overviewโ
In this guide, we will implement a feature that allows writing to multiple contracts or executing multiple transactions in a single action. This is particularly useful when your decentralized application (dApp) requires multiple state changes at once.
This documentation will walk through the code and steps necessary to create a button that triggers the multi-write contract interaction.
Here is full implementation of the mult-write feature:
components/MultiContractInteraction.tsx
"use client";
import { useState } from "react";
import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract";
import { useScaffoldMultiWriteContract } from "~~/hooks/scaffold-stark/useScaffoldMultiWriteContract";
const MultiSetData = () => {
const [inputAmount, setInputAmount] = useState<bigint>(0n);
const [greeting, setGreeting] = useState<string>("");
const { data: YourContract } = useScaffoldContract({ contractName: "YourContract" });
const { sendAsync, isPending } = useScaffoldMultiWriteContract({
calls: [
{
contractName: "Strk",
functionName: "approve",
args: [YourContract?.address, BigInt(inputAmount)],
},
{
contractName: "Strk",
functionName: "transfer",
args: [YourContract?.address, BigInt(inputAmount)],
},
{
contractName: "YourContract",
functionName: "set_greeting",
args: [greeting, BigInt(inputAmount)],
},
],
});
const handleSetData = async () => {
try {
await sendAsync();
} catch (e) {
console.error("Error in multi-write", e);
}
};
return (
<div>
<input
type="text"
placeholder="Enter your greeting"
className="input border border-primary"
onChange={e => setGreeting(e.target.value)}
/>
<input
type="number"
placeholder="Enter your STRK amount"
className="input border border-primary"
onChange={e => {
setInputAmount(BigInt(Number(e.target.value) * 10 ** 18));
}}
/>
<button className="btn btn-primary" onClick={handleSetData} disabled={isPending}>
{isPending ? <span className="loading loading-spinner loading-sm"></span> : "Submit"}
</button>
</div>
);
};
export default MultiSetData;
Implementation Guideโ
1. Create a New Componentโ
Create a new component in your component folder, named MultiContractInteraction.tsx. This component will handle multiple write operations on different contracts
components/MultiContractInteraction.tsx
export const MultiContractInteraction = () => {
return <div>Your MultiContractInteraction</div>;
};
2. Import Required Hooks and Utilitiesโ
- import the
useScaffoldMultiWriteContractfrom scaffold-stark package to handle multiple contract function calls. - Use
utility to display success or error messages.
components/MultiContractInteraction.tsx
import { useScaffoldMultiWriteContract } from "~~/hooks/scaffold-stark/useScaffoldMultiWriteContract";
import { notification } from "~~/utils/scaffold-stark";
3. Set Up State Variablesโ
- Use the
useStatehook to track user inputs,greetingandinputAmount.
components/MultiContractInteraction.tsx
const [inputAmount, setInputAmount] = useState<bigint>(0n);
const [greeting, setGreeting] = useState<string>("");
4. Configure the useScaffoldMultiWriteContract Hookโ
- Configure the hook with the necessary contract calls. Here, we call the
setGreetingandsetInputAmountfunctions ofYourContractandStrkin sequence.
components/MultiContractInteraction.tsx
const { sendAsync, isPending } = useScaffoldMultiWriteContract({
calls: [
{
contractName: "Strk",
functionName: "approve",
args: [YourContract?.address, BigInt(inputAmount)],
},
{
contractName: "Strk",
functionName: "transfer",
args: [YourContract?.address, BigInt(inputAmount)],
},
{
contractName: "YourContract",
functionName: "set_greeting",
args: [greeting, BigInt(inputAmount)],
},
],
});
- The
isPendingvariable will manage the loading state of the button, andsendAsyncwill handle the contract transaction.
5. Handle Submissionโ
- Create a
handleSetDatafunction that triggers the multi-write action. If successful, display a success notification; otherwise, log the error and display a failure message.
components/MultiContractInteraction.tsx
const handleSetData = async () => {
try {
await sendAsync();
notification("Multi-write successful!", "success");
} catch (e) {
console.error("Error in multi-write", e);
notification("Multi-write failed.", "error");
}
};
6. Create the UIโ
- Add inputs for
grettingandinputAmount, and a button to submit the data. - Disable the button while the transaction is pending.
return (
<div>
<input
type="text"
placeholder="Enter your gretting"
className="input border border-primary"
onChange={e =>
greeting(e.target.value)}
/>
<input
type="number"
placeholder="Enter your STRK amount"
className="input border border-primary"
onChange={(e) => {
setInputAmount(BigInt(Number(e.target.value) * 10 ** 18));
/>
<button className="btn btn-primary" onClick={handleSetData} disabled={isPending}>
{isPending ? <span className="loading loading-spinner loading-sm"></span> : "Submit"}
</button>
</div>
);
};