> For the complete documentation index, see [llms.txt](https://simsimbutdifferent.gitbook.io/prompt_web3/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simsimbutdifferent.gitbook.io/prompt_web3/lesson-3/lesson-3-assignments-and-excercises/e1-nextjs-front-end.md).

# E1: NextJs Front End

<figure><img src="/files/MFTT3MA8C65JUNP9lYYD" alt=""><figcaption></figcaption></figure>

## Front-end project aims:

1. Have a front end that properly connects and works with the backend.
2. Have a working wallet button, so I could interact with the contract using Metamask
3. Have links to all my other information.
4. All built with a production ready framework.

I will outline the code below, but you can find the full repo here - <https://github.com/SimSimButDifferent/L3-EthWalletFrontEnd>

Or check the deployment here - <https://ethwalletapp.on.fleek.co/>

### Code outline

### App folder

#### /app/layout&#x20;

```typescript
import { ReactNode } from "react"
import { Web3ModalProvider } from "@/context/Web3Modal"

import Header from "@/components/Header"
import EthWallet from "@/components/EthWallet"
import { Poppins } from "next/font/google"
import "./globals.css"

const inter = Poppins({
    weight: ["200", "300", "400", "500", "600"],
    subsets: ["latin"],
})

export const metadata = {
    title: "EthWalletApp",
    description: "Simple EthWalletApp by simsimbutdifferent",
}

export default function RootLayout({ children }: { children: ReactNode }) {
    return (
        <html lang="en">
            <body className="flex flex-col justify-between bg-[url(../public/Space-Background.jpg)] bg-cover bg-fixed">
                <Web3ModalProvider>
                    <Header />
                    <EthWallet />
                    {children}
                </Web3ModalProvider>
            </body>
        </html>
    )
}
```

#### /app/page.ts

```typescript
import Head from "next/head"

export default function Home() {
    return (
        <div>
            <Head>
                <title>Eth Wallet App</title>
                <meta name="description" content="Eth Wallet App"></meta>
            </Head>
            <main className="flex min-h-screen flex-col items-center justify-between p-24 pt-4 ">
                <div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-3 lg:text-left">
                    <a
                        href="https://github.com/SimSimButDifferent/L3-EthWalletFrontEnd"
                        className="group rounded-lg border border-transparent px-10 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        <h2 className={`mb-3 text-2xl font-semibold`}>
                            Front End Repo{" "}
                            <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
                                -&gt;
                            </span>
                        </h2>
                        <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
                            Check out the repo if you want to mess around with
                            the code yourself.
                        </p>
                    </a>

                    <a
                        href="https://github.com/SimSimButDifferent/L3-EthWallet"
                        className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        <h2 className={`mb-3 text-2xl font-semibold`}>
                            Backend Repo{" "}
                            <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
                                -&gt;
                            </span>
                        </h2>
                        <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
                            Take a look at the hardhat deployment of the smart
                            contract.
                        </p>
                    </a>

                    <a
                        href="https://simsimbutdifferent.gitbook.io/prompt_web3/"
                        className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        <h2 className={`mb-3 text-2xl font-semibold`}>
                            My Journey{" "}
                            <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
                                -&gt;
                            </span>
                        </h2>
                        <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
                            Have a look into my self-learning journey into web3
                            using chatGpt.
                        </p>
                        <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
                            A template to learn anything software related.
                        </p>
                    </a>
                </div>
            </main>
        </div>
    )
}
```

#### /app/styles.css

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
    --foreground-rgb: 0, 0, 0;
    --background-start-rgb: 214, 219, 220;
    --background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
    :root {
        --foreground-rgb: 255, 255, 255;
        --background-start-rgb: 0, 0, 0;
        --background-end-rgb: 0, 0, 0;
    }
}

body {
    color: rgb(var(--foreground-rgb));
    background: linear-gradient(
            to bottom,
            transparent,
            rgb(var(--background-end-rgb))
        )
        rgb(var(--background-start-rgb));
}

button,
label,
input {
    align-self: center;
    margin-bottom: 5px;
    font-size: 24px;
    border-radius: 8px;
    margin-top: 10px;
    text-align: center;
    font-weight: 300;
}
```

***

### Components folder

#### /components/EthWallet.tsx

```tsx
"use client"

import { ethers, Contract, BrowserProvider } from "ethers"
import { useWeb3ModalAccount } from "@web3modal/ethers/react"
import { contractAddresses, abi } from "../context"

import React, { useState } from "react"
import * as dotenv from "dotenv"

dotenv.config()

const EthWallet: React.FC = () => {
    const { address, chainId, isConnected } = useWeb3ModalAccount()

    const contractAddress =
        chainId in contractAddresses ? contractAddresses[chainId][0] : null

    const [depositAmount, setDepositAmount] = useState("")
    const [withdrawAmount, setWithdrawAmount] = useState("")
    const [successMessage, setSuccessMessage] = useState("")

    const [isLoading, setIsLoading] = useState(false)

    async function deposit(value: any) {
        if (!isConnected) throw Error("User Disconnected")
        const provider = new BrowserProvider(window.ethereum)

        const getSigner = provider.getSigner()
        const signer = await getSigner
        const ethWallet = new Contract(contractAddress, abi, signer)
        const tx = await ethWallet.deposit({ value: ethers.parseEther(value) })
        const receipt = await tx.wait()

        console.log(`${value.toString()} ETH Deposited!`)
        return receipt
    }

    async function withdraw(value: any) {
        if (!isConnected) throw Error("User Disconnected")
        const provider = new BrowserProvider(window.ethereum)

        const getSigner = provider.getSigner()
        const signer = await getSigner
        const ethWallet = new Contract(contractAddress, abi, signer)
        const tx = await ethWallet.withdraw(ethers.parseEther(value))
        const receipt = await tx.wait()

        console.log(`${value.toString()} ETH Withdrawn!`)
        return receipt
    }

    async function getUserBalance() {
        const provider = new BrowserProvider(window.ethereum)

        const getSigner = provider.getSigner()
        const signer = await getSigner
        const ethWallet = new Contract(contractAddress, abi, signer)
        console.log(signer)

        const balance = await ethWallet.getUserBalance()

        return balance.toString()
    }

    const handleDepositSubmit = async (
        event: React.FormEvent<HTMLFormElement>,
    ) => {
        event.preventDefault()
        setIsLoading(true)
        try {
            await deposit(depositAmount)

            setSuccessMessage(`Successfully deposited ${depositAmount} ETH!`)
            setDepositAmount("") // Optional: Reset input field after successful deposit
            setTimeout(() => setSuccessMessage(""), 10000)
        } catch (error) {
            console.error("Error during deposit: ", error)
            setSuccessMessage("User Disconnected!")
        }
        setIsLoading(false)
    }

    const handleWithdrawSubmit = async (event) => {
        event.preventDefault()
        setIsLoading(true)
        try {
            await withdraw(withdrawAmount)

            setSuccessMessage(`Successfully withdrawn ${withdrawAmount} ETH!`)
            setWithdrawAmount("") // Optional: Reset input field after successful deposit
            setTimeout(() => setSuccessMessage(""), 10000)
        } catch (error) {
            console.error("Error during withdraw: ", error)
            setSuccessMessage("User Disconnected!")
        }
        setIsLoading(false)
    }

    const handleGetUserBalance = async (event) => {
        event.preventDefault()
        setIsLoading(true)
        try {
            const balance = await getUserBalance()

            setSuccessMessage(
                `User Balance: ${ethers.formatEther(balance)} ETH!`,
            )

            setTimeout(() => setSuccessMessage(""), 10000)
        } catch (error) {
            console.error("User does not exist!", error)
            setSuccessMessage("User does not exist!")
        }
        setIsLoading(false)
    }

    return (
        <div className="">
            <form onSubmit={handleDepositSubmit}>
                <div className="p-4">
                    <h1 className="text-6xl text-center rounded-lg border border-transparent px-5 py-4 transition-colors border-neutral-300 bg-gray-100 dark:border-neutral-700 dark:bg-neutral-800/30">
                        Eth Wallet App
                    </h1>
                </div>
                <div className="flex flex-col p-4">
                    <input
                        type="text"
                        value={depositAmount}
                        onChange={(e) => setDepositAmount(e.target.value)}
                        className="text-black text-xl text-align-center py-2"
                        placeholder="Deposit amount..."
                    />
                    <button
                        type="submit"
                        disabled={isLoading}
                        className={`px-4 pb-1 ${
                            isLoading
                                ? "bg-violet-600"
                                : "bg-sky-500 hover:bg-sky-400"
                        } text-white rounded-lg`}
                    >
                        Deposit
                    </button>
                </div>
            </form>
            <form onSubmit={handleWithdrawSubmit}>
                <div className="flex flex-col p-4">
                    <input
                        type="text"
                        value={withdrawAmount}
                        onChange={(e) => setWithdrawAmount(e.target.value)}
                        className="text-black text-xl text-align-center py-2"
                        placeholder="Withdraw amount..."
                    />
                    <button
                        type="submit"
                        disabled={isLoading}
                        className={`px-4 pb-1 ${
                            isLoading
                                ? "bg-violet-600"
                                : "bg-sky-500 hover:bg-sky-400"
                        } text-white rounded-lg`}
                    >
                        Withdraw
                    </button>
                </div>
            </form>
            <div className="flex flex-col justify-center pt-8">
                <button
                    onClick={handleGetUserBalance}
                    className="flex justify-center px-4 py-2 text-2xl bg-sky-500 hover:bg-sky-400 text-white rounded-lg"
                >
                    Get user balance
                </button>
            </div>
            {successMessage && (
                <div className="flex items-center justify-center pt-10">
                    <div className="flex justify-center px-4 py-2 text-2xl bg-purple-900 rounded-lg max-w-fit font-light animate-fadeOut">
                        {successMessage}
                    </div>
                </div>
            )}
        </div>
    )
}

export default EthWallet
```

#### /components/Header.tsx

```tsx
"use client"

import React from "react"

const Header: React.FC = () => {
    return (
        <nav>
            <div className="flex flex-cols-2 justify-end">
                <div className="p-2">
                    <w3m-button size="md" />
                </div>
                <div className="p-2">
                    <w3m-network-button />
                </div>
            </div>
        </nav>
    )
}
export default Header
```

***

### Context folder

#### /context/Web3Modal.tsx

```tsx
"use client"

import { createWeb3Modal, defaultConfig } from "@web3modal/ethers/react"

// 1. Get projectId at https://cloud.walletconnect.com
const projectId = "cf80e8dfdf111fd756361f3117399405"

// 2. Set chains
const mainnet = {
    chainId: 1,
    name: "Ethereum",
    currency: "ETH",
    explorerUrl: "https://etherscan.io",
    rpcUrl: "https://cloudflare-eth.com",
}

const sepolia = {
    chainId: 11155111,
    name: "Sepolia",
    currency: "ETH",
    explorerUrl: "https://sepolia.etherscan.io",
    rpcUrl: "https://rpc.sepolia.org",
}

const localhost = {
    chainId: 31337,
    name: "Localhost 8545",
    currency: "ETH",
    explorerUrl: "",
    rpcUrl: "http://localhost:8545",
}

// 3. Create modal
const metadata = {
    name: "Eth Wallet",
    description: "Simple Eth Wallet app created by Simeon Campbell",
    url: "ethwalletapp.on.fleek.co",
    icons: ["https://avatars.mywebsite.com/"],
}

createWeb3Modal({
    ethersConfig: defaultConfig({ metadata }),
    chains: [mainnet, sepolia, localhost],
    projectId,
})

import { ReactNode } from "react"

export function Web3ModalProvider({ children }: { children: ReactNode }) {
    return children
}
```

#### /context/abi.json

```json
[
    {
        "inputs": [],
        "name": "EthWallet_InsufficientContractBalance",
        "type": "error"
    },
    {
        "inputs": [],
        "name": "EthWallet__DepositMustBeAboveZero",
        "type": "error"
    },
    {
        "inputs": [],
        "name": "EthWallet__WalletIsEmpty",
        "type": "error"
    },
    {
        "inputs": [],
        "name": "EthWallet__WithdrawalExceedsUserBalance",
        "type": "error"
    },
    {
        "inputs": [],
        "name": "EthWallet__WithdrawalMustBeAboveZero",
        "type": "error"
    },
    {
        "inputs": [],
        "name": "dailyWithdrawalLimit",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "deposit",
        "outputs": [],
        "stateMutability": "payable",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "getUserBalance",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_withdrawalAmount",
                "type": "uint256"
            }
        ],
        "name": "withdraw",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
]
```

#### /context/contractAddresses.json

```json
{
    "11155111": ["0x0597071313ae58624FFbbDAB8643aD96E27eD3bc"],
    "31337": ["0x5FbDB2315678afecb367f032d93F642f64180aa3"]
}
```

#### /context/index.js

```javascript
const contractAddresses = require("./contractAddresses.json")
const abi = require("./abi.json")

module.exports = {
    contractAddresses,
    abi,
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://simsimbutdifferent.gitbook.io/prompt_web3/lesson-3/lesson-3-assignments-and-excercises/e1-nextjs-front-end.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
