diff --git a/docs/recipes/MultiWriteFeature.md b/docs/recipes/MultiWriteFeature.md index 79d2b8b..aeab1b2 100644 --- a/docs/recipes/MultiWriteFeature.md +++ b/docs/recipes/MultiWriteFeature.md @@ -18,25 +18,34 @@ This documentation will walk through the code and steps necessary to create a bu Here is full implementation of the mult-write feature: ```tsx title="components/MultiContractInteraction.tsx" +"use client"; + import { useState } from "react"; +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; import { useScaffoldMultiWriteContract } from "~~/hooks/scaffold-stark/useScaffoldMultiWriteContract"; -import { notification } from "~~/utils/scaffold-stark"; -export const MultiSetData = () => { - const [name, setName] = useState(""); - const [age, setAge] = useState(0); +const MultiSetData = () => { + const [inputAmount, setInputAmount] = useState(0n); + const [greeting, setGreeting] = useState(""); + + const { data: YourContract } = useScaffoldContract({ contractName: "YourContract" }); const { sendAsync, isPending } = useScaffoldMultiWriteContract({ calls: [ { - contractName: "ProfileContract", - functionName: "setName", - args: [name], + contractName: "Eth", + functionName: "approve", + args: [YourContract?.address, BigInt(inputAmount)], }, { - contractName: "ProfileContract", - functionName: "setAge", - args: [age], + contractName: "Eth", + functionName: "transfer", + args: [YourContract?.address, BigInt(inputAmount)], + }, + { + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, BigInt(inputAmount)], }, ], }); @@ -44,10 +53,8 @@ export const MultiSetData = () => { 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"); } }; @@ -55,15 +62,17 @@ export const MultiSetData = () => {
setName(e.target.value)} + onChange={e => setGreeting(e.target.value)} /> setAge(Number(e.target.value))} + onChange={e => { + setInputAmount(BigInt(Number(e.target.value) * 10 ** 18)); + }} />
); }; + +export default MultiSetData; ``` @@ -100,29 +111,34 @@ import { notification } from "~~/utils/scaffold-stark"; ### Step 3: Set Up State Variables -- Use the `useState` hook to track user inputs, `name` and `age`. +- Use the `useState` hook to track user inputs, `greeting` and `inputAmount`. ```tsx title="components/MultiContractInteraction.tsx" -const [name, setName] = useState(""); -const [age, setAge] = useState(0); +const [inputAmount, setInputAmount] = useState(0n); +const [greeting, setGreeting] = useState(""); ``` ### Step 4: Configure the [`useScaffoldMultiWriteContract`](https://github.com/Scaffold-Stark/scaffold-stark-2/blob/main/packages/nextjs/hooks/scaffold-stark/useScaffoldMultiWriteContract.ts) Hook -- Configure the hook with the necessary contract calls. Here, we call the `setName` and `setAge` functions of `ProfileContract` in sequence. +- Configure the hook with the necessary contract calls. Here, we call the `setGreeting` and `setInputAmount` functions of `YourContract` and `Eth` in sequence. ```tsx title="components/MultiContractInteraction.tsx" const { sendAsync, isPending } = useScaffoldMultiWriteContract({ calls: [ { - contractName: "ProfileContract", - functionName: "setName", - args: [name], + contractName: "Eth", + functionName: "approve", + args: [YourContract?.address, BigInt(inputAmount)], }, { - contractName: "ProfileContract", - functionName: "setAge", - args: [age], + contractName: "Eth", + functionName: "transfer", + args: [YourContract?.address, BigInt(inputAmount)], + }, + { + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, BigInt(inputAmount)], }, ], }); @@ -148,27 +164,30 @@ const handleSetData = async () => { ### Step 6: Create the UI -- Add inputs for `name` and `age`, and a button to submit the data. +- Add inputs for `gretting` and `inputAmount`, and a button to submit the data. - Disable the button while the transaction is pending. ```tsx return ( -
- setName(e.target.value)} - /> - setAge(Number(e.target.value))} - /> - -
-); +
+ + greeting(e.target.value)} + /> + { + setInputAmount(BigInt(Number(e.target.value) * 10 ** 18)); + /> + +
+ ); +}; ``` diff --git a/docs/recipes/ReadUintFromContract.md b/docs/recipes/ReadUintFromContract.md index 6d733c6..5bb6252 100644 --- a/docs/recipes/ReadUintFromContract.md +++ b/docs/recipes/ReadUintFromContract.md @@ -6,51 +6,57 @@ description: Learn how to read from contract functions which accept arguments / # Read a `uint` from a contract -This recipe demonstrates how to read data from contract functions and display it on the UI. We'll showcase an example that accepts some arguments (parameters), and another with no arguments at all. +This recipe demonstrates how to read data from contract functions and display it on the UI. We'll showcase an example that accepts arguments (parameters) and another with no arguments at all.
-Here is the full code, which we will be implementing in the guide below: +Here is the full code, which we will implement in the guide below: -```tsx title="components/GreetingsCount.tsx" -import { useAccount } from "@starknet-react/core"; +```tsx title="components/Greetings.tsx" +"use client"; + +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; import { useScaffoldReadContract } from "~~/hooks/scaffold-stark/useScaffoldReadContract"; -export const GreetingsCount = () => { - const { account: connectedAddress } = useAccount(); +const Greetings = () => { + const { data: YourContract } = useScaffoldContract({ contractName: "YourContract" }); - const { data: totalCounter, isLoading: isTotalCounterLoading } = useScaffoldReadContract({ + const { data: currentGreeting, isLoading: isCurrentGreetingLoading } = useScaffoldReadContract({ contractName: "YourContract", - functionName: "totalCounter", + functionName: "greeting", }); - const { data: connectedAddressCounter, isLoading: isConnectedAddressCounterLoading } = useScaffoldReadContract({ - contractName: "YourContract", - functionName: "userGreetingCounter", - args: [connectedAddress], // passing args to function + const { data: ethBalance, isLoading: isEthBalanceLoading } = useScaffoldReadContract({ + contractName: "Eth", + functionName: "balance_of", + args: [YourContract?.address], }); return ( -
-
-

Greetings Count

-
-

Total Greetings count:

- {isTotalCounterLoading ? ( +
+
+

Greetings

+
+

Balance ETH in YourContract:

+ {isEthBalanceLoading ? ( ) : ( -

{totalCounter ? totalCounter.toString() : 0}

+

{ethBalance ? (Number(ethBalance) / 10 ** 18).toFixed(6) : "0.000000"} ETH

)} -

Your Greetings count:

- {isConnectedAddressCounterLoading ? ( +
+
+

New Greeting:

+ {isCurrentGreetingLoading ? ( ) : ( -

{connectedAddressCounter ? connectedAddressCounter.toString() : 0}

+

{currentGreeting ? currentGreeting.toString() : "No greeting"}

)}
); }; + +export default Greetings; ```
@@ -59,137 +65,118 @@ export const GreetingsCount = () => { ### Step 1: Create a new Component -Begin by creating a new component in the "components" folder of your application. +Begin by creating a new component in the `components` folder of your application. -```tsx title="components/GreetingsCount.tsx" -export const GreetingsCount = () => { +```tsx title="components/Greetings.tsx" +const Greetings = () => { return (
-

Total Greetings count:

-

Your Greetings count:

+

Balance ETH in YourContract:

+

New Greeting:

); }; +export default Greetings; ``` -### Step 2: Retrieve total greetings count +### Step 2: Retrieve New Greetings -Initialize the [useScaffoldReadContract](/hooks/useScaffoldReadContract) hook to read from the contract. This hook provides the `data` which contains the return value of the function. +Initialize the [`useScaffoldReadContract`](/hooks/useScaffoldReadContract) hook to read from the contract. This hook provides the `data` which contains the return value of the function. -```tsx title="components/GreetingsCount.tsx" +```tsx title="components/Greetings.tsx" import { useScaffoldReadContract } from "~~/hooks/scaffold-stark/useScaffoldReadContract"; -// highlight-end -export const GreetingsCount = () => { - // highlight-start - const { data: totalCounter } = useScaffoldReadContract({ +const Greetings = () => { + const { data: currentGreeting } = useScaffoldReadContract({ contractName: "YourContract", - functionName: "totalCounter", + functionName: "greeting", }); - // highlight-end return (
-

Total Greetings count:

- //highlight-start -

{totalCounter ? totalCounter.toString() : 0}

- //highlight-end -

Your Greetings count:

+

New Greeting:

+

{currentGreeting ? currentGreeting.toString() : "No greeting"}

); }; ``` -In the line `const {data: totalCounter} = useScaffoldReadContract({...})` we are using [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to assign `data` to a new name `totalCounter`. +In the line `const {data: currentGreeting} = useScaffoldReadContract({...})`, we use [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to extract the `data` field and rename it as `currentGreeting`. -In the contract, `totalCounter` returns an `uint` value, which is represented as a [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) in javascript and can be converted to a readable string using `.toString()`. +The contract function returns a `uint`, which is represented as a [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) in JavaScript. You can convert it to a readable string using `.toString()`. -### Step 3: Retrieve connected address greetings count +### Step 3: Retrieve ETH Balance in YourContract -We can get the connected address using the [useAccount](https://starknet-react.com/hooks/account/useaccount) hook and pass it to `args` key in the `useScaffoldReadContract` hook configuration. This will be used as an argument to read the contract function. +We can retrieve the ETH balance of the contract by first getting its address using `useScaffoldContract`. Then, we pass this address as an argument (`args`) to `useScaffoldReadContract`, which will call the contract function. -```tsx title="components/GreetingsCount.tsx" -import { useScaffoldReadContract } from "~~/hooks/scaffold-stark"; -//highlight-start -import { useAccount } from "@starknet-react/core"; -//highlight-end +```tsx title="components/Greetings.tsx" +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; +import { useScaffoldReadContract } from "~~/hooks/scaffold-stark/useScaffoldReadContract"; -export const GreetingsCount = () => { - //highlight-start - const { account: connectedAddress } = useAccount(); - //highlight-end +const Greetings = () => { + const { data: YourContract } = useScaffoldContract({ contractName: "YourContract" }); - const { data: totalCounter } = useScaffoldReadContract({ - contractName: "YourContract", - functionName: "totalCounter", + const { data: ethBalance } = useScaffoldReadContract({ + contractName: "Eth", + functionName: "balance_of", + args: [YourContract?.address], }); - //highlight-start - const { data: connectedAddressCounter } = useScaffoldReadContract({ - contractName: "YourContract", - functionName: "userGreetingCounter", - args: [connectedAddress], // passing args to function - }); - //highlight-end - return (
-

Total Greetings count:

-

{totalCounter ? totalCounter.toString() : 0}

-

Your Greetings count:

- //highlight-start -

{connectedAddressCounter ? connectedAddressCounter.toString() : 0}

- //highlight-end +

Balance ETH in YourContract:

+

{ethBalance ? (Number(ethBalance) / 10 ** 18).toFixed(6) : "0.000000"} ETH

); }; ``` -### Step 4: Bonus adding loading state +### Step 4: Handling Loading State -We can use `isLoading` returned from the [`useScaffoldReadContract`](/hooks/usescaffoldreadcontract) hook. This variable is set to `true` while fetching data from the contract. +We can use the `isLoading` flag returned from `useScaffoldReadContract` to show a loading spinner while fetching data from the contract. -```tsx title="components/GreetingsCount.tsx" +```tsx title="components/Greetings.tsx" +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; import { useScaffoldReadContract } from "~~/hooks/scaffold-stark/useScaffoldReadContract"; -import { useAccount } from "@starknet-react/core"; -export const GreetingsCount = () => { - const { account: connectedAddress } = useAccount(); +const Greetings = () => { + const { data: YourContract } = useScaffoldContract({ contractName: "YourContract" }); - // highlight-start - const { data: totalCounter, isLoading: isTotalCounterLoading } = useScaffoldReadContract({ - // highlight-end + const { data: currentGreeting, isLoading: isCurrentGreetingLoading } = useScaffoldReadContract({ contractName: "YourContract", - functionName: "totalCounter", + functionName: "greeting", }); - // highlight-start - const { data: connectedAddressCounter, isLoading: isConnectedAddressCounterLoading } = useScaffoldReadContract({ - // highlight-end - contractName: "YourContract", - functionName: "userGreetingCounter", - args: [connectedAddress], // passing args to function + const { data: ethBalance, isLoading: isEthBalanceLoading } = useScaffoldReadContract({ + contractName: "Eth", + functionName: "balance_of", + args: [YourContract?.address], }); return ( -
-

Total Greetings count:

- // highlight-start - {isTotalCounterLoading ? ( - - ) : ( -

{totalCounter ? totalCounter.toString() : 0}

- )} - // highlight-end -

Your Greetings count:

- // highlight-start - {isConnectedAddressCounterLoading ? ( - - ) : ( -

{connectedAddressCounter ? connectedAddressCounter.toString() : 0}

- )} - // highlight-end +
+
+

Greetings

+
+

Balance ETH in YourContract:

+ {isEthBalanceLoading ? ( + + ) : ( +

{ethBalance ? (Number(ethBalance) / 10 ** 18).toFixed(6) : "0.000000"} ETH

+ )} +
+
+

New Greeting:

+ {isCurrentGreetingLoading ? ( + + ) : ( +

{currentGreeting ? currentGreeting.toString() : "No greeting"}

+ )} +
+
); }; + +export default Greetings; ``` diff --git a/docs/recipes/WriteToContractWriteAsyncButton.md b/docs/recipes/WriteToContractWriteAsyncButton.md index c4e72c2..bd367fa 100644 --- a/docs/recipes/WriteToContractWriteAsyncButton.md +++ b/docs/recipes/WriteToContractWriteAsyncButton.md @@ -6,50 +6,48 @@ description: Learn how to create a button that executes the writeContractAsync f # Write to a Contract with `sendAsync` button using the `useScaffoldWriteContract` hook. -This recipe demonstrates how to create a button for contract interaction using the `useScaffoldWriteContract` hooks from the Scaffold-Stark 2 hooks. +This recipe demonstrates how to create a button for contract interaction using the `useScaffoldWriteContract` hook from Scaffold-Stark.
Here is the full code, which we will be implementing in the guide below: ```tsx title="components/ContractInteraction.tsx" +"use client"; import { useState } from "react"; import { useScaffoldWriteContract } from "~~/hooks/scaffold-stark/useScaffoldWriteContract"; -export const SetName = () => { - const [newName, setNewName] = useState(""); - +const SetGreeting = () => { + const [greeting, setGreeting] = useState(""); const { sendAsync, isPending } = useScaffoldWriteContract({ - calls: [ - { - contractName: "YourContract", - functionName: "setName", - args: [newName], - }, - ], + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, 0n], // `inputAmount` fixed at 0n }); - const handleSetName = async () => { + const handleSetGreeting = async () => { try { await sendAsync(); } catch (e) { - console.error("Error setting name", e); + console.error("Error setting greeting", e); } }; return ( - <> +
setNewName(e.target.value)} + onChange={e => setGreeting(e.target.value)} /> - - +
); }; + +export default SetGreeting; ```
@@ -58,158 +56,141 @@ export const SetName = () => { ### Step 1: Set Up Your Component -Create a new component in the "components" folder. The component will show a button that will allow users to interact with your smart contract. +Create a new component in the `components` folder. This component will display an input field and a button to interact with your smart contract. ```tsx title="components/ContractInteraction.tsx" -export const SetName = () => { +"use client"; + +const SetGreeting = () => { return ( - <> - - - +
+ + +
); }; + +export default SetGreeting; ``` -### Step 2: Initialize useScaffoldWriteContract hook +### Step 2: Initialize `useScaffoldWriteContract` Hook -Initialize the `useScaffoldWriteContract` hook. This hook provides the `sendAsync` function for sending transactions. We'll create a `handleSetName` function in which we'll call and pass parameters to `sendAsync` required to perform contract interaction. +Now we'll add state management and initialize the hook for contract interaction: -```tsx -// highlight-start +```tsx title="components/ContractInteraction.tsx" +"use client"; import { useState } from "react"; import { useScaffoldWriteContract } from "~~/hooks/scaffold-stark/useScaffoldWriteContract"; -// highlight-end - -export const SetName = () => { - // highlight-start - const [newName, setNewName] = useState(""); - // highlight-end - // highlight-start +const SetGreeting = () => { + const [greeting, setGreeting] = useState(""); const { sendAsync } = useScaffoldWriteContract({ - calls: [ - { - contractName: "YourContract", - functionName: "setName", - args: [newName], - }, - ], + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, 0n], // `inputAmount` fixed at 0n }); - // highlight-end - // highlight-start - const handleSetName = async () => { + const handleSetGreeting = async () => { try { await sendAsync(); } catch (e) { - console.error("Error setting name", e); + console.error("Error setting greeting", e); } }; - // highlight-end return ( - <> - - - +
+ + +
); }; + +export default SetGreeting; ``` -### Step 3: Add input change logic and send transaction when users click the button +### Step 3: Add Input Change Logic and Connect Button -Wire up the input field to update the `newName` state when the user types in a new name and call the `handleSetName` function when the user clicks the button. +Now we'll connect the input to our state and wire up the button click handler: -```tsx +```tsx title="components/ContractInteraction.tsx" +"use client"; import { useState } from "react"; import { useScaffoldWriteContract } from "~~/hooks/scaffold-stark/useScaffoldWriteContract"; -export const SetName = () => { - const [newName, setNewName] = useState(""); - +const SetGreeting = () => { + const [greeting, setGreeting] = useState(""); const { sendAsync } = useScaffoldWriteContract({ - calls: [ - { - contractName: "YourContract", - functionName: "setName", - args: [newName], - }, - ], + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, 0n], // `inputAmount` fixed at 0n }); - const handleSetName = async () => { + const handleSetGreeting = async () => { try { await sendAsync(); } catch (e) { - console.error("Error setting name", e); + console.error("Error setting greeting", e); } }; return ( - <> +
setNewName(e.target.value)} - // highlight-end + onChange={e => setGreeting(e.target.value)} /> - // highlight-start - - // highlight-end - +
); }; + +export default SetGreeting; ``` -### Step 4: Bonus - Adding loading state +### Step 4: Add Loading State -We can use `isPending` returned from `useScaffoldWriteContract` while the transaction is being mined and also disable the button. +Finally, we'll add loading state handling to improve the user experience: -```tsx +```tsx title="components/ContractInteraction.tsx" +"use client"; import { useState } from "react"; import { useScaffoldWriteContract } from "~~/hooks/scaffold-stark/useScaffoldWriteContract"; -export const SetName = () => { - const [newName, setNewName] = useState(""); - // highlight-start +const SetGreeting = () => { + const [greeting, setGreeting] = useState(""); const { sendAsync, isPending } = useScaffoldWriteContract({ - // highlight-end - calls: [ - { - contractName: "YourContract", - functionName: "setName", - args: [newName], - }, - ], + contractName: "YourContract", + functionName: "set_greeting", + args: [greeting, 0n], // `inputAmount` fixed at 0n }); - const handleSetName = async () => { + const handleSetGreeting = async () => { try { await sendAsync(); } catch (e) { - console.error("Error setting name", e); + console.error("Error setting greeting", e); } }; return ( - <> +
setNewName(e.target.value)} + onChange={e => setGreeting(e.target.value)} /> - // highlight-start - - // highlight-end - +
); }; + +export default SetGreeting; ```