Skip to main content

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 useScaffoldMultiWriteContract from 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 useState hook to track user inputs, greeting and inputAmount.
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 setGreeting and setInputAmount functions of YourContract and Strk in 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 isPending variable will manage the loading state of the button, and sendAsync will handle the contract transaction.

5. Handle Submissionโ€‹

  • Create a handleSetData function 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 gretting and inputAmount, 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>
);
};