Skip to content

Commit

Permalink
Update recipe to a iterative approach
Browse files Browse the repository at this point in the history
  • Loading branch information
Pabl0cks committed Nov 8, 2023
1 parent 06f3ff4 commit 2d86afe
Showing 1 changed file with 135 additions and 79 deletions.
214 changes: 135 additions & 79 deletions docs/recipes/WriteToContractWriteAsyncButton.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,113 +4,157 @@ title: Write to contract with writeAsync button
description: Learn how to create a button that executes the writeAsync function to interact with a smart contract.
---

# Write to a Contract with writeAsync button
# 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. By following this guide, you can create a user interface for writing data to a contract.

## Before You Begin
In this recipe you will use [useScaffoldContractWrite](/hooks/useScaffoldContractWrite) Scaffold ETH-2 hook, and [ParseEther viem utility](https://viem.sh/docs/utilities/parseEther.html#parseether).

Before you proceed with this recipe, make sure you have the [required dependencies installed](/quick-start/installation), and you're familiar with setting up your [Ethereum development environment](/quick-start/environment).
Here is the full code, which we will be implementing in the guide below:

In this recipe you will use [useScaffoldContractWrite](/hooks/useScaffoldContractWrite) Scaffold ETH-2 hook, and [ParseEther viem utility](https://viem.sh/docs/utilities/parseEther.html#parseether). We recommend checking out the details of these hook and utility before start implementing this recipe.

## Implementation

### Step 1: Create Your Component

Start by creating a new component, which we'll call "Greetings.tsx." This component will enable users to write data to a smart contract.

Import the required libraries and components:

```tsx
```tsx title="components/Greetings.tsx"
import { useState } from "react";
import type { NextPage } from "next";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
```

Define the functional component "Greetings" which will be used to create the user interface:
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");

```tsx
const Greetings: NextPage = () => {
// Your component code will go here.
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>
</>
);
};
```

### Step 2: Initialize Hooks for Contract Interaction
## Implementation

Initialize the `useScaffoldContractWrite` hook to set up the contract interaction. This hook provides the `writeAsync` function for sending transactions.
### Step 1: Set Up Your Component

```tsx
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);
},
});
Create a new component in the "components" folder. This component will enable users to write data to a smart contract.

```tsx title="components/Greetings.tsx"
export const Greetings = () => {
return (
<>
<input type="text" placeholder="Write your greeting" className="input border border-primary" />
<button>Send</button>
</>
);
};
```

### Step 3: Create the User Interface with writeAsync Button
### Step 2: Initialize `useScaffoldContractWrite` hook

Design the user interface to allow users to input data and trigger the contract interaction. The example below demonstrates a simple form:
Initialize the `useScaffoldContractWrite` hook to set up the contract interaction. This hook provides the `writeAsync` function for sending transactions.

```tsx
return (
<div className="p-8">
<input
type="text"
placeholder="Write your greeting"
className="input border border-primary"
onChange={e => setNewGreeting(e.target.value)}
/>
<div className="rounded-full mt-4">
<button className="btn btn-primary" onClick={() => writeAsync()} disabled={isLoading}>
Send
</button>
</div>
</div>
);
```
// highlight-start
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
// highlight-end

:::info Hint
You can also create a writeAsync button sending args imperatively, here is an example:
export const Greetings = () => {
// highlight-start
const [newGreeting, setNewGreeting] = useState("");

```tsx
<button className="btn btn-primary" onClick={() => writeAsync({ args: ["Hello"], value: parseEther("0.02") })}>
Send imperatively
</button>
const { writeAsync } = useScaffoldContractWrite({
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
value: parseEther("0.01"),
onBlockConfirmation: txnReceipt => {
console.log("📦 Transaction blockHash", txnReceipt.blockHash);
},
});
// highlight-end
return (
<>
<input type="text" placeholder="Write your greeting" className="input border border-primary" />
<button>Send</button>
</>
);
};
```

:::info Hint
### Step 3: Add input change logic and send transaction when users click the button

### Step 4: Test and Deploy
Design the user interface to allow users to input data and trigger the contract interaction. The example below demonstrates a simple form:

Test your component to ensure that it correctly interacts with the smart contract. You can verify if you are getting the same output as executing the Smart Contract `setGreeting` function directly from `Debug` tab.
```tsx
import { useState } from "react";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";

## Conclusion
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");

By following these steps, you've created a button that allows users to write data to a smart contract by clicking it.
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"
// highlight-start
onChange={e => setNewGreeting(e.target.value)}
// highlight-end
/>
<button
className="btn btn-primary"
// highlight-start
onClick={() => writeAsync()}
// highlight-end
>
Send
</button>
</>
);
};
```

## Full Recipe Code
### Step 4: Bonus adding loading state

<details>
<summary>Here's the complete code for the "Greetings" component:</summary>
We can use `isLoading` returned from `useScaffoldContractWrite` while the transaction is being mined and also disable the button.

```tsx
import { useState } from "react";
import type { NextPage } from "next";
import { parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";

const Greetings: NextPage = () => {
export const Greetings = () => {
const [newGreeting, setNewGreeting] = useState("");

// highlight-start
const { writeAsync, isLoading } = useScaffoldContractWrite({
// highlight-end
contractName: "YourContract",
functionName: "setGreeting",
args: [newGreeting],
Expand All @@ -119,24 +163,36 @@ const Greetings: NextPage = () => {
console.log("📦 Transaction blockHash", txnReceipt.blockHash);
},
});

return (
<div className="p-8">
<>
<input
type="text"
placeholder="Write your greeting"
className="input border border-primary"
onChange={e => setNewGreeting(e.target.value)}
/>
<div className="rounded-full mt-4">
<button className="btn btn-primary" onClick={() => writeAsync()} disabled={isLoading}>
Send
</button>
</div>
</div>

<button
className="btn btn-primary"
onClick={() => writeAsync()}
// highlight-start
disabled={isLoading}
>
{isLoading ? <span className="loading loading-spinner loading-sm"></span> : <>Send</>}
</button>
</>
// highlight-end
);
};
export default Greetings;
```

</details>
:::info Hint
You can also create a writeAsync button sending args imperatively, here is an example:

```tsx
<button className="btn btn-primary" onClick={() => writeAsync({ args: ["Hello"], value: parseEther("0.02") })}>
Send imperatively
</button>
```

:::info Hint

0 comments on commit 2d86afe

Please sign in to comment.