Cover photo

Wallet Integration using Thirdweb: A Step-by-Step Guide for Web3 Developer

Developing an accessible and user-friendly onboarding process is crucial to drive the adoption of blockchain technology and decentralized applications (dApps) in the Web3 landscape. This project aims to know various wallet solutions and offer a comprehensive tutorial on seamlessly integrating Thirdweb wallet into a web application.


Challenges and problems with existing wallets

Existing blockchain wallets face several hurdles:

  1. Complex Language: They use confusing terms like "seed phrases" and "cryptographic keys," which can deter newcomers.

  2. Usability: Some wallets are not easy to use, making it hard for people to understand and navigate.

  3. Security Worries: Users are concerned about the safety of their keys and losing their assets.

  4. Limited Compatibility: Not all wallets work with the same blockchains and apps, causing confusion.

  5. Lack of Knowledge: Many users don't know how to use wallets or understand blockchain tech. Addressing these issues is crucial for a more user-friendly blockchain experience.

Overview of the Selected Wallet Solution: Thirdweb

Thirdweb is a platform that helps developers build dApps and games on the blockchain. It provides tools and services that make it easy to integrate Web3 functionality into applications, authenticate users with their wallets, and publish contracts on-chain. Thirdweb also offers secure, fast, and decentralized storage for dApps and games.

Here are some of the key features and reasons behind Thirdweb:

  • EVM-compatibility: Thirdweb is compatible with any EVM-compatible blockchain, such as Ethereum, Polygon, and Solana. This makes it a versatile platform that can be used to build dApps and games on a variety of blockchains.

  • Ease of use: Thirdweb makes it easy for developers to build dApps and games. The platform provides a variety of pre-built tools and templates that can be used to get started quickly.

  • Security: Thirdweb uses a variety of security measures to protect user data and assets, including private keys, multi-factor authentication, and security audits.

  • Community: Thirdweb has a large and active community of developers who are always willing to help. This makes it easy for developers to get help if they have any problems.

  • Scalability: Thirdweb is designed to be scalable, so it can be used to build dApps and games that can support a large number of users.

  • Gasless transactions: Thirdweb supports gasless transactions, which allow users to make transactions without paying gas fees. This can be a valuable feature for users who are on a budget or who want to make a large number of transactions.

  • Customization: Thirdweb allows developers to customize their dApps and games to meet the specific needs of their users. This makes it a versatile platform that can be used to build a wide variety of dApps and games.

Thirdweb is a relatively new platform, but it has already gained a lot of traction in the Web3 community. It is a promising platform that has the potential to make it easier for developers to build and deploy dApps and games on the blockchain. Some of the reasons why developers might choose to use Thirdweb:

  • To build dApps and games that use cryptocurrency and other blockchain-based assets. 

  • To authenticate users with their wallets. 

  • To publish contracts on-chain. 

  • To store user data and assets securely.

 

Differences between Thirdweb and Metamask

Metamask and Thirdweb differences
Metamask and Thirdweb differences

Thirdweb and MetaMask are both popular platforms in the Web3 ecosystem, but they have different target audiences and features. Thirdweb is a platform for developers who want to build dApps and games on the blockchain. It provides a variety of tools and services that make it easy to integrate Web3 functionality into applications, authenticate users with their wallets, and publish contracts on-chain. MetaMask is a wallet for users who want to store and manage their cryptocurrency and other blockchain-based assets. It allows users to connect to dApps and games, send and receive transactions, and store their cryptocurrency.

Here are the main differences between Thirdweb Wallet and MetaMask:

  • Target audience: Thirdweb Wallet is designed for developers who want to build dApps and games on the blockchain, while MetaMask is a more general-purpose wallet that can be used by anyone.

  • Features: Thirdweb Wallet offers a wider range of features for developers, such as the ability to create custom wallets, manage NFTs, and deploy smart contracts. MetaMask is a more basic wallet that allows users to store cryptocurrency, send and receive transactions, and connect to dApps.

  • Security: Thirdweb Wallet uses a variety of security measures to protect user data and assets, such as private keys, multi-factor authentication, and security audits. MetaMask also uses security measures to protect user data and assets, but it is not as comprehensive as Thirdweb Wallet's security measures.

  • Community: Thirdweb Wallet has a growing community of developers who are always willing to help. MetaMask also has a large and active community, but it is more focused on users than developers.

In other words, Thirdweb is for developers who want to build things on the blockchain, while MetaMask is for users who want to use things that are built on the blockchain.

Let's integrate Thirdweb wallet into our dApp. It's a powerful tool that makes dApps more user-friendly and secure

Creating dApp with Thirdweb Wallet.

First we need to setup our development environtment, make sure that you already install some of the list here:

After Vscode and NodeJS installed, let’s install Thirdweb CLI:

To install Thirdweb CLI, open your terminal and paste this command:

npm install -g thirdweb

If the Thirdweb CLI installed successfully, then we can just create the project of the dApp by using this command on the terminal:

npx thirdweb@latest create app

Thirdweb CLI will ask you some of the requirement that needs to set for creating the project. You can follow this list below:

  • Project name e.g: wallet-integration-dapp

  • Blockchain to use e.g**: EVM**

  • Framework to use e.g: Next.js

  • Language to use e.g: Typescript

After that enter the project directory by cd wallet-integration-dapp and Install ChakraUI for easy and ready to use UI component for our project for faster development. Command to install ChakraUI

npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

If it’s installed successfully. open the project on Visual Studio Code. On the terminal you can type code . and hit enter to open VSCode.

After VSCode opened, create new folders on our root project directory named components and const

Create new folders
Create new folders

Next, open _app.jsx inside pages folder and add copy and paste this working code:

// This code sets up a Next.js application with Thirdweb wallet integration.
// It configures the blockchain network, provides wallet functionality, and uses Chakra UI for styling.
// The Navbar and Footer components frame the main content of your web app.

import type { AppProps } from "next/app";
import { ThirdwebProvider } from "@thirdweb-dev/react";
import { ChakraProvider } from "@chakra-ui/react";
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";

// This is the chain your dApp will work on.
// Change this to the chain your app is built for.
// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.
const activeChain = "mumbai";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ThirdwebProvider
      clientId={process.env.NEXT_PUBLIC_TEMPLATE_CLIENT_ID}
      activeChain={activeChain}
    >
      <ChakraProvider>
        <Navbar />
        <Component {...pageProps} />
        <Footer />
      </ChakraProvider>
    </ThirdwebProvider>
  );
}

export default MyApp;

What’s inside this _app.jsx code:

  1. Configures the blockchain network for your web app (set to "Mumbai" in this example).

  2. Wraps your app with Thirdweb wallet functionality.

  3. Uses Chakra UI for styling.

  4. Includes a Navbar at the top and a Footer at the bottom.

  5. Renders your app's main content.

Save the file and type npm run dev on the terminal to run it on local server. It will be catch some errors, so let’s continue our code.

Next on index.tsx still on the pages folder add some working code below:

import {
  Container,
  Flex,
  Stack,
  Heading,
  Text,
  Button,
  Link,
  Box,
  SimpleGrid,
} from "@chakra-ui/react";
import { MediaRenderer } from "@thirdweb-dev/react";
import { NextPage } from "next";
import { FEATURES_IMAGE_URL, HERO_IMAGE_URL } from "../const/addresses";
import FeatureCard from "../components/FeatureCard";
import Events from "../components/Event";

const Home: NextPage = () => {
  return (
    <Container maxW={"1440px"} py={4}>
      <Flex>
        <Flex flexDirection={"row"} h={"75vh"}>
          <Flex flexDirection={"column"} justifyContent={"center"} w={"60%"}>
            <Stack spacing={4}>
              <Heading fontSize={"xl"}>Transfer Token</Heading>
              <Heading fontSize={"6xl"}>
                Initiate Token Transfer to others.
              </Heading>
              <Text fontSize={"xl"}>
                You can transfer token to other wallet address. And send them
                message for the transfer. Connect your Wallet and enjoy the
                transfer!
              </Text>
              <Link href={"/transfer"}>
                <Button colorScheme={"purple"} w={"20%"}>
                  Transfer
                </Button>
              </Link>
            </Stack>
          </Flex>
          <Box>
            <MediaRenderer
              src={HERO_IMAGE_URL}
              height="100%"
              width="100%"
            ></MediaRenderer>
          </Box>
        </Flex>
      </Flex>
      <SimpleGrid columns={2} spacing={4} mt={4}>
        <Flex>
          <MediaRenderer src={FEATURES_IMAGE_URL} height="100%" width="80%" />
        </Flex>
        <Flex
          flexDirection={"column"}
          justifyContent={"center"}
          alignItems={"center"}
        >
          <Stack spacing={4}>
            <FeatureCard
              step={"01"}
              title={"Select a Token"}
              description={"Select a verified Token from list."}
            />
            <FeatureCard
              step={"02"}
              title={"Reciever"}
              description={"Enter the wallet address of the reciever."}
            />
            <FeatureCard
              step={"03"}
              title={"Send a Message"}
              description={"Write a message to the reciever on the transfer."}
            />
          </Stack>
        </Flex>
      </SimpleGrid>
      <Events />
    </Container>
  );
};

export default Home;


What’s inside this index.jsx code:

  1. Imports UI components and libraries like Chakra UI and Next.js for building a web page.

  2. Sets up a home page with a heading, description, and a "Transfer" button.

  3. Displays an image using the MediaRenderer component.

  4. Lists three features using FeatureCard components.

  5. Includes an "Events" section at the bottom of the page.

Next pages is transfer.jsx, here are the working code:

import { Container, Flex } from "@chakra-ui/react";
import TransferCard from "../components/TransferCard";
import Events from "../components/Event";

export default function TransferPage() {
    return (
        <Container maxW={"1440px"} py={4}>
            <Flex flexDirection={"column"} justifyContent={"center"} alignItems={"center"}>
                <TransferCard />
                <Events />
            </Flex>
        </Container>
    )
}


What’s inside this transfer.jsx code:

  1. Imports UI components and libraries, including Chakra UI.

  2. Creates a page called "TransferPage."

  3. Sets up a container to control the page's maximum width and padding.

  4. Places a "TransferCard" component and an "Events" component inside a centered flex container.

It creates a page for transferring tokens, displaying a transfer card and a section for events.

Next pages is claim.tsx, copy and paste the working code below:

import { Box, Container, Flex, Heading, SimpleGrid, Stack, Text, useToast } from "@chakra-ui/react";
import { MediaRenderer, Web3Button, useContract, useContractMetadata } from "@thirdweb-dev/react";
import { CLAIM_TOKEN_CONTRACT_ADDRESS, CLAIM_TOKEN_IMAGE } from "../const/addresses";

export default function ClaimPage() {
    const {
        contract
    } = useContract(CLAIM_TOKEN_CONTRACT_ADDRESS, "token-drop");

    const {
        data: contractMetadata
    } = useContractMetadata(contract);

    const claimAmount = 10;
    const toast = useToast();

    return (
        <Container maxW={"1440px"} h={"80vh"} >
            <SimpleGrid columns={2} spacing={10} h={"100%"}>
                <Flex>
                    <MediaRenderer
                        src={CLAIM_TOKEN_IMAGE}
                        height="100%"
                        width="100%"
                    />
                </Flex>
                <Flex flexDirection={"column"} justifyContent={"center"}>
                    <Stack spacing={4}>
                        <Heading fontSize={"5xl"}>Claim ${contractMetadata?.symbol}</Heading>
                        <Text fontSize={"xl"}>Claim your FREE ${contractMetadata?.symbol}. Just pay for the gas fee to claim your ${contractMetadata?.symbol}. Use this token to test and try the transfer feature of this dApp.</Text>
                        <Text fontWeight={"bold"}>Claim {claimAmount} ${contractMetadata?.symbol} Tokens</Text>
                        <Box>
                            <Web3Button
                                contractAddress={CLAIM_TOKEN_CONTRACT_ADDRESS}
                                action={(contract) => contract.erc20.claim(claimAmount)}
                                onSuccess={() => toast({
                                    title: 'Claim Successful',
                                    description: "You have successfully claimed tokens!",
                                    status: 'success',
                                    duration: 9000,
                                    isClosable: true,
                                })}
                            >Claim Token</Web3Button>
                        </Box>
                    </Stack>
                </Flex>
            </SimpleGrid>
        </Container>
    )
}

What’s inside claim.tsx code:

  1. Imports UI components and libraries, including Chakra UI and Thirdweb components.

  2. Creates a page called "ClaimPage."

  3. Sets up a container to control the page's maximum width and height.

  4. Displays a token image using the MediaRenderer component.

  5. Provides information about claiming free tokens and instructions for users.

  6. Allows users to claim a specified amount of tokens by paying a gas fee using the "Claim Token" button. It also displays a success message using a toast notification.

It creates a page where users can claim free tokens by interacting with a smart contract and provides clear instructions and feedback through the UI.

And for the last pages create new folder called profile inside pages folder and create now file named [walletAddress].tsx and copy this working code:

import { Avatar, Container, Flex, Heading, SimpleGrid, Spinner, Text } from "@chakra-ui/react";
import { useAddress, useContract, useContractRead } from "@thirdweb-dev/react";
import { TRANSFER_CONTRACT_ADDRESS } from "../../const/addresses";
import BalanceCard from "../../components/BalanceCard";

export default function AccountPage() {
    const address = useAddress();
    
    function truncateAddress(address: string) {
        return `${address.substring(0, 6)}...${address.substring(address.length - 4)}`;
    };

    const { 
        contract: transferContract,
    } = useContract(TRANSFER_CONTRACT_ADDRESS);

    const {
        data: verifiedTokens,
        isLoading: isVerifiedTokensLoading,
    } = useContractRead(
        transferContract,
        "getVerifiedTokens"
    );
    
    return (
        <Container maxW={"1440px"} py={4}>
            {address ? (
                <Flex>
                    <Flex flexDirection={"column"} mr={8} p={10}>
                        <Avatar size={"2xl"} mb={4}/>
                        <Text 
                            fontSize={"sm"} 
                            border={"1px solid black"} 
                            textAlign={"center"} 
                            borderRadius={4}
                        >{truncateAddress(address)}</Text>
                    </Flex>
                    <Flex flexDirection={"column"} w={"100%"}>
                        <Heading>Token Balances</Heading>
                        <SimpleGrid columns={3} spacing={4} mt={4}>
                        {!isVerifiedTokensLoading ? (
                            verifiedTokens.map((token: string) => (
                                <BalanceCard
                                    key={token}
                                    tokenAddress={token}
                                />
                            ))
                        ) : (
                            <Spinner />
                        )}
                        </SimpleGrid>
                    </Flex>
                </Flex>
            ) : (
                <Flex>
                    <Text>Connect Wallet</Text>
                </Flex>
            )}
            
        </Container>
    )
}


What’s inside [walletAddress].tsx code

  1. Imports UI components and libraries, including Chakra UI and Thirdweb components.

  2. Creates a page called "AccountPage."

  3. Retrieves the user's address and truncates it for display.

  4. Fetches a contract related to token transfers and retrieves verified tokens and their balances.

  5. Displays the user's avatar, address, and token balances in a grid layout.

  6. If the user is not connected to a wallet, it prompts them to "Connect Wallet."

It creates a user account page that shows their address, avatar, and token balances once they are connected to a wallet. If not connected, it prompts them to do so.

Coding for the pages and integrating it with the Thirweb wallet is done, but you will still catch bunch of errors because the component code inside components folder is not found. So let’s get the component done !

Create a new file inside components folder, here are the list of the .tsx code files:

components
components

And copy and paste the working code here for our components:

TransferCard.tsx code:

import { Box, Card, Flex, Heading, Input, Text } from "@chakra-ui/react";
import { useAddress, useContract, useContractRead } from "@thirdweb-dev/react";
import { TRANSFER_CONTRACT_ADDRESS } from "../const/addresses";
import TokenSelection from "./TokenSelection";
import { useState } from "react";
import TokenBalance from "./TokenBalance";
import TransferButton from "./TransferButton";
import styles from "../styles/Home.module.css";

export default function TransferCard() {
    const address = useAddress();

    const {
        contract
    } = useContract(TRANSFER_CONTRACT_ADDRESS);

    const {
        data: verifiedTokens,
        isLoading: isVerifiedTokensLoading,
    } = useContractRead(contract, "getVerifiedTokens");

    const [formData, setFormData] = useState({
        receiver: '',
        amount: '',
        message: ''
    });

    const [selectedToken, setSelectedToken] = useState('');

    const handleChange = (event: any, name: any) => {
        setFormData((prevState) => ({
            ...prevState,
            [name]: event.target.value
        }));
    };

    const handleTokenSelection = (tokenAddress: string) => {
        setSelectedToken(tokenAddress);
    };

    return (
        <Card w={"50%"} p={20}>
            <Heading>Transfer:</Heading>

            <Text mt={4} fontWeight={"bold"}>Select Token:</Text>
            <Flex flexDirection={"row"} mt={4}>
                {!isVerifiedTokensLoading && 
                    verifiedTokens.map((token: string) => (
                        <Box
                            key={token}
                            onClick={() => handleTokenSelection(token)}
                            className={styles.tokenButton}
                        >
                            <TokenSelection
                                tokenAddress={token}
                                isSelected={selectedToken === token}
                            />
                        </Box>
                        
                    ))}
            </Flex>

            <TokenBalance tokenAddress={selectedToken} />

            <Text mt={4} fontWeight={"bold"}>Send To:</Text>
            <Input
                placeholder="0x0000000"
                type="text"
                value={formData.receiver}
                onChange={(event) => handleChange(event, "receiver")}
            />
            <Text mt={4} fontWeight={"bold"}>Amount:</Text>
            <Input
                placeholder="0.0"
                type="number"
                value={formData.amount}
                onChange={(event) => handleChange(event, "amount")}
            />
            <Text mt={4} fontWeight={"bold"}>Message:</Text>
            <Input
                placeholder="Add short message here."
                type="text"
                value={formData.message}
                onChange={(event) => handleChange(event, "message")}
            />
            <Box mt={8}>
                {address ? (
                    <TransferButton
                        tokenAddress={selectedToken}
                        receiver={formData.receiver}
                        amount={formData.amount.toString()}
                        message={formData.message}
                    />
                ) : (
                    <Text>Please connect your wallet to make a transfer.</Text>
                )}
            </Box>
            
        </Card>
    );
};

This code:

  1. Imports UI components, libraries (including Chakra UI), and various custom components.

  2. Creates a "TransferCard" component that allows users to initiate token transfers.

  3. Retrieves the user's address, a contract for token transfers, and a list of verified tokens.

  4. Manages form data for the transfer, including the receiver's address, amount, and message.

  5. Allows users to select a token and displays the token's balance.

  6. Provides input fields for entering the receiver's address, amount, and message.

  7. Offers a "Transfer" button for making the transfer, but only if the user is connected to a wallet. Otherwise, it prompts them to connect their wallet.

TransferButton.tsx code:

import { Web3Button, useContract } from "@thirdweb-dev/react";
import { TRANSFER_CONTRACT_ADDRESS } from "../const/addresses";
import { ethers } from "ethers";
import { useToast } from "@chakra-ui/react";

type Props = {
    tokenAddress: string;
    receiver: string;
    amount: string;
    message: string;
};

const TransferButton: React.FC<Props> = ({ tokenAddress, receiver, amount, message }) => {
    const {
        contract: tokenContract
    } = useContract(tokenAddress, 'token');

    const {
        contract: transferContract
    } = useContract(TRANSFER_CONTRACT_ADDRESS);

    const toast = useToast();
    
    return (
        <Web3Button
        style={{ backgroundColor: 'lightpink', color: 'black' }}
            contractAddress={TRANSFER_CONTRACT_ADDRESS}
            action={async (contract) => {
                await tokenContract?.setAllowance(
                    TRANSFER_CONTRACT_ADDRESS,
                    ethers.utils.parseEther(amount).toString()
                );

                await transferContract?.call(
                    "transfer",
                    [
                        tokenAddress,
                        receiver,
                        ethers.utils.parseEther(amount),
                        message
                    ]
                )
            }}
            onSuccess={() => toast({
                title: "Transfer Successful",
                description: "You have successfully transferred token!",
                status: "success",
                duration: 9000,
                isClosable: true
            })}>
            Transfer Token
        </Web3Button>
    )
};

export default TransferButton;

This code:

  1. Imports necessary libraries, components, and contracts, including the Thirdweb React components, contract addresses, ethers for Ethereum interactions, and Chakra UI for toasting.

  2. Defines a TransferButton component that allows users to initiate token transfers with specified details.

  3. Sets up contracts for the selected token and the transfer contract.

  4. Uses a Chakra UI toast for displaying success messages.

  5. Provides a button that, when clicked, triggers a series of asynchronous actions:

    • It sets the allowance for transferring a specified amount of the selected token.

    • Then, it calls the "transfer" function on the transfer contract, passing in the token address, receiver's address, transfer amount, and message.

  6. Displays a "Transfer Token" button, which, when clicked, initiates the transfer and shows a success message on completion.

TokenSelection.tsx code:

import { Box, Card, Spinner, Text } from "@chakra-ui/react";
import { useContract, useContractMetadata } from "@thirdweb-dev/react";

type Props = {
  tokenAddress: string;
  isSelected?: boolean;
};

const TokenSelection: React.FC<Props> = ({ tokenAddress, isSelected }) => {
  const { contract } = useContract(tokenAddress);

  const { 
    data: tokenMetadata, 
    isLoading: isTokenMetadataLoading 
} =
    useContractMetadata(contract);

  let coinBorderColor = "gray.200";
  if(isSelected) {
    coinBorderColor = "purple.500";
  }

  return (
        <Card p={4} mr={2} border={"2px solid"} borderColor={coinBorderColor}>
            {!isTokenMetadataLoading ? (
                <Box>
                    <Text>{tokenMetadata?.symbol}</Text>
                </Box>
            ) : (
                <Spinner/>
            )}
        </Card>
)
};

export default TokenSelection;

This code:

  1. Imports necessary UI components and Thirdweb React hooks for contract interaction.

  2. Defines a TokenSelection component that displays token symbols within cards, with an option to highlight the selected token.

  3. Fetches contract metadata for a given token address, including its symbol.

  4. Determines the border color for the card based on whether the token is selected.

  5. Displays a card with the token's symbol or a spinner if the metadata is loading.

It creates a compact component for showing token symbols in cards, allowing for easy selection and highlighting when needed, and providing feedback during loading.

TokenBalance.tsx code:

import { Box, Text } from "@chakra-ui/react";
import { useAddress, useContract, useTokenBalance } from "@thirdweb-dev/react";

type Props = {
    tokenAddress: string;

};

const TokenBalance: React.FC<Props> = ({ tokenAddress }) => {
    const address = useAddress();

    const {
        contract
    } = useContract(tokenAddress);
    const {
        data: balance,
        isLoading: isbalanceLoading
    } = useTokenBalance(contract, address);

    return(
        <Box mt={4}>
            {!isbalanceLoading && (
                <Text>Balance: {balance?.displayValue}</Text>
            )}
        </Box>
    )
};

export default TokenBalance;

This code:

  1. Imports necessary UI components and Thirdweb React hooks for contract interaction.

  2. Defines a TokenBalance component that retrieves and displays the token balance for a specific address.

  3. Uses the useAddress hook to get the user's address.

  4. Fetches the contract associated with the specified token address.

  5. Retrieves the token balance for the user's address from the contract.

  6. Displays the user's token balance or a loading indicator if the balance is still loading.

Navbar.tsx code:

import { Container, Flex, Text } from "@chakra-ui/react";
import { ConnectWallet, useAddress } from "@thirdweb-dev/react";
import Link from "next/link";

export default function Navbar() {
    const address = useAddress();

    return (
        <Container maxW={"1440px"} py={4}>
            <Flex flexDirection={"row"} justifyContent={"space-between"} alignItems={"center"}>
                <Link href={"/"}>
                    <Text fontWeight={"bold"}>Thirdweb Wallet Integration</Text>
                </Link>
                {address && (
                    <Flex flexDirection={"row"}>
                        <Link href={"/transfer"}>
                            <Text mr={8}>Transfer</Text>
                        </Link>

                        <Link href={"/claim"}>
                            <Text mr={8}>Claim</Text>
                        </Link>

                        <Link href={`/profile/${address}`}>
                            <Text>My Account</Text>
                        </Link>
                    </Flex>
                )}
                <ConnectWallet />
            </Flex>
        </Container>
    )
}

This code:

  1. Imports necessary UI components and Thirdweb React hooks for wallet integration.

  2. Defines a Navbar component for displaying navigation links and the option to connect a wallet.

  3. Uses the useAddress hook to get the user's address if connected.

  4. Sets up a container for controlling the maximum width and padding of the navbar.

  5. Creates a flex layout with navigation links, including "Transfer," "Claim," and "My Account."

  6. Displays the "Connect Wallet" component, which allows users to connect their wallets.

It creates a user-friendly navigation bar that adapts based on whether the user is connected to a wallet, providing relevant links and a wallet connection option.

Footer.tsx code:

import { Container, Divider, Text } from "@chakra-ui/react";

export default function Footer() {
    return (
        <Container maxW={"100%"} mt={20} height={"100px"}>
            <Divider />
            <Container maxW={"1440px"} py={4}>
                <Text fontWeight={"bold"}>Footer</Text>
            </Container>
        </Container>
    )
}

This code:

  1. Imports necessary UI components for creating a footer.

  2. Defines a Footer component to display a footer section at the bottom of the web page.

  3. Sets up a container to control the maximum width and margin-top of the footer.

  4. Inserts a horizontal divider line to separate the footer content from the rest of the page.

  5. Adds another container inside the footer to manage the maximum width and padding.

  6. Displays bold text within the footer, which can be customized to provide footer-related information.

It creates a basic footer section at the bottom of the page, which can be customized to display relevant information or links.

FeatureCard.tsx code:

import { Card, Flex, Heading, Stack, Text } from "@chakra-ui/react";

type Props = {
    step: string;
    title: string;
    description: string;
};

const FeatureCard: React.FC<Props> = ({ step, title, description }) => {
    return (
        <Card px={8} py={10}>
            <Stack spacing={6}>
                <Flex flexDirection={"row"} alignItems={"center"}>
                    <Text fontSize={"lg"} mr={4}>{step}</Text>
                    <Heading fontSize={"2xl"}>{title}</Heading>
                </Flex>
                <Text fontSize={"lg"} ml={10}>
                    {description}
                </Text>
            </Stack>
        </Card>
    )
};

export default FeatureCard;

This code:

  1. Imports necessary UI components for creating feature cards.

  2. Defines a FeatureCard component to display individual feature cards with a step number, title, and description.

  3. Creates a card with padding and a stack layout for organizing the content.

  4. Sets up a stack layout with specific spacing.

  5. Displays the step number and title in a flex layout with aligned text.

  6. Shows the feature's description below the title.

Event.tsx code:

import { useContract, useContractEvents } from "@thirdweb-dev/react";
import { TRANSFER_CONTRACT_ADDRESS } from "../const/addresses";
import { Box, Card, Flex, Text, Heading, Spinner } from "@chakra-ui/react";
import { ethers } from "ethers";

export default function Events() {
    function truncateAddress(address: string) {
        return `${address.substring(0, 6)}...${address.substring(address.length - 4)}`;
    };

    const {
        contract,
    } = useContract(TRANSFER_CONTRACT_ADDRESS);

    const {
        data: events,
        isLoading: isEventsLoading,
    } = useContractEvents(contract, "TransactionCompleted", {
        queryFilter: {
            fromBlock: -7000,
        }
    });
    return (
         <Box mt={20} w={"100%"}>
            <Heading>Recent Transfer:</Heading>
            {!isEventsLoading ? (
                events?.map((event: any, index) => (
                    <Card key={index} p={8} my={4}>
                        <Flex flexDirection={"row"} alignItems={"center"}>
                            <Text p={2} border={"1px solid grey"} borderRadius={6} fontSize={"xs"}>{truncateAddress(event.data.sender)}</Text>
                            <Text mx={2} fontSize={"sm"}>To</Text>
                            <Text p={2} border={"1px solid grey"} borderRadius={6} fontSize={"xs"}>{truncateAddress(event.data.receiver)}</Text>
                        </Flex>
                        <Text fontSize={"xl"} my={4}>{event.data.message}</Text>
                        <Text>Amount: {ethers.utils.formatEther(event.data.amount)}</Text>
                    </Card>
                )).reverse()
            ) : (
                <Spinner />
            )}
        </Box>
    )
}

This code:

  1. Imports necessary libraries, including Thirdweb React hooks, contract addresses, and UI components.

  2. Defines an Events component for displaying recent transfer events.

  3. Defines a function truncateAddress to shorten Ethereum addresses for display.

  4. Retrieves the contract associated with the transfer contract address.

  5. Fetches recent "TransactionCompleted" events from the contract, filtering events from the last 7000 blocks.

  6. Displays a heading for "Recent Transfer" events.

  7. Maps and displays the events in reverse order, showing sender and receiver addresses, transfer message, and the transferred amount.

  8. If events are loading, it displays a spinner.

It creates a component that showcases recent transfer events with sender and receiver addresses, messages, and amounts, providing a user-friendly way to view recent activity.

BalanceCard.tsx code:

import { Card, Spinner, Stack, Text } from "@chakra-ui/react";
import { useAddress, useContract, useContractEvents, useContractMetadata, useTokenBalance } from "@thirdweb-dev/react";

type Props = {
    tokenAddress: string;
};

export default function BalanceCard({ tokenAddress }: Props) {
    const address = useAddress();

    const {
        contract
    } = useContract(tokenAddress);

    const {
        data: contractMetadata,
        isLoading: isContractMetadataLoading,
    } = useContractMetadata(contract);

    const {
        data: tokenBalance,
        isLoading: isTokenBalanceLoading,
    } = useTokenBalance(contract, address);

    const {
        data: events,
        isLoading: isEventsLoading,
    } = useContractEvents(
        contract,
        "get"
    );

    return (
        <Card p={4} width={"100%"} height={"100%"} border={"2px solid"} borderColor={"gray.100"}>
            {!isContractMetadataLoading ? (
                <Stack textAlign={"center"}>
                    <Text fontWeight={"bold"} fontSize={"2xl"}>{contractMetadata?.symbol}</Text>
                    <Text>Balance:</Text>
                    {!isTokenBalanceLoading ? (
                        <Text fontSize={"3xl"} fontWeight={"bold"}>{tokenBalance?.displayValue}</Text>
                    ) : (
                        <Spinner />
                    )}
                </Stack>
            ) : (
                <Spinner />
            )}
        </Card>
    )
};

This code:

  1. Imports necessary libraries, including Thirdweb React hooks and Chakra UI components.

  2. Defines a BalanceCard component for displaying the balance of a specific token.

  3. Retrieves the user's address using the useAddress hook.

  4. Gets the contract associated with the specified token address.

  5. Fetches metadata about the contract, including its symbol.

  6. Fetches the user's token balance for that contract.

  7. Fetches events from the contract.

  8. Displays a card with token-related information, including the token's symbol and the user's balance.

  9. If data is loading, it displays a spinner.

It creates a component for showing the balance of a specific token, providing real-time information and feedback during loading.

Finally ! its done for our components code, Last step is configuring addresses of Transfer Contract Address, Claim Token Address, and another address for load the image that store on the IPFS.

Let’s create new file on const folder called addresses.ts and copy paste the configuration below:

export const TRANSFER_CONTRACT_ADDRESS = '0x0532f89a79aB8df6f06Fc65ad7e69b94D196E3aF';
export const CLAIM_TOKEN_CONTRACT_ADDRESS = '0x46167A7973aac3644cDdFf62c94a6e518cCf22F6';

export const HERO_IMAGE_URL = 'ipfs://QmcEpkFf8qQShQ1uLNKqkThMXrHpdxQ3CDTramRCK5hG8Y/79a6e40b-0e59-4288-8519-84a5f76e72cd.jpg';
export const FEATURES_IMAGE_URL = 'ipfs://QmckQJWCesjuVjgaM4E2TjYeuu7A8HxPNpy3UZ9kpCz1Z7/8faabff0-4520-42b8-a9ba-47d9d0e7efff.jpg';
export const CLAIM_TOKEN_IMAGE = 'ipfs://QmdrXD23jZ2s3yjeFs6u6AVfpbdZj1Tjw3LvWfpTQp1Bv5/07055471-25b2-45da-bdd7-9a74b13763cb.jpg';

here's an explanation of the provided code:

  1. TRANSFER_CONTRACT_ADDRESS: This constant defines the Ethereum address of a smart contract called the "Transfer Contract." This contract is likely used for handling token transfers within a decentralized application (dApp) or blockchain system.

  2. CLAIM_TOKEN_CONTRACT_ADDRESS: This constant defines the Ethereum address of another smart contract, specifically the "Claim Token Contract."

  3. HERO_IMAGE_URL: This constant contains an IPFS (InterPlanetary File System) URL pointing to an image named "79a6e40b-0e59-4288-8519-84a5f76e72cd.jpg." IPFS is a decentralized file storage system used in blockchain applications. This URL likely represents the location of a hero or banner image used in the application.

  4. FEATURES_IMAGE_URL: Similar to the previous constant, this one contains an IPFS URL pointing to an image named "8faabff0-4520-42b8-a9ba-47d9d0e7efff.jpg." It likely represents an image used for showcasing features or content within the application.

  5. CLAIM_TOKEN_IMAGE: This constant holds an IPFS URL pointing to an image named "07055471-25b2-45da-bdd7-9a74b13763cb.jpg." Like the others, it likely represents an image used in the context of claiming tokens within the application.

Maybe you asking, what url is that and how do i get them ?

You can create your own address by creating a contract and storing your files on thirdweb.com and copy the address of your own, and paste it to the addresses file code. But for this project u can use my address to get quick jump on integrating the thirdweb wallet to the project. Since creating a contract will overcomplicated this tutorial i'll give you some documentation below:

https://portal.thirdweb.com/

And don’t forget to create account on Thirdweb.com

Create API KEY
Create API KEY

and create CLIENT API KEY and create .env file on root project directory and follow this code below and use your CLIENT API KEY:

post image

Congrats! you finished the integration of thirdweb wallet ! on this dApps you can Connect to Wallet and transfer some token to other address, and claim some token !.

In conclusion, integrating Thirdweb into this project has significantly enhanced its functionality and user experience in the Web3 and blockchain ecosystem. With Thirdweb's robust set of React hooks and components, developers were able to seamlessly integrate wallet functionality, access contract data, and manage blockchain interactions.


Here are some of the links to this Github Repo and Deployed site of this project: