How to Build an Awesome Web3 Crowd-Funding Platform with React, Solidity, and CometChat
Tags: dapp, web3, react, solidity
Published: 2022-08-25 18:12:00

What you will be building, see [**demo**](https://genesis-45443.web.app/) on the Rinkeby test network and [**git repo**](https://github.com/Daltonic/genesis) here…

![Add Project](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661334753873_genesis-add-project.gif)

## Introduction

A valuable skill in Web3 development is all you need to secure your chances of being relevant in today’s tech-world.

The Web3 economy is booming and the best thing you can do for yourself right now is to learn the craft.

How do you develop a smart contract for your Dapp? How do you best design the Dapp interface? How do you connect the frontend to the backend that sits on the blockchain? All these questions will be resolved in this tutorial.

[**Subscribe to my YouTube channel**](https://www.youtube.com/channel/UCQteXYZ5mC-cuTxplzM4Hlw?sub_confirmation=1) to learn how to build a Web3 app from scratch.

I also offer private and specialized classes for serious folks who want to learn one-on-one from a mentor. [**Book your Web3 classes here**](https://www.buymeacoffee.com/web3classes/e/74614).

With that said, let’s jump into the tutorial.

## Prerequisite

You will need the following tools installed to build along with me:

- NodeJs *(Super important)*
- EthersJs
- Hardhat
- React
- Infuria
- Tailwind CSS
- CometChat SDK
- Metamask
- Yarn
## Installing Dependencies

Clone the project from the repository below and run the following commands.


    git clone https://github.com/Daltonic/genesis <PROJECT_NAME>
    cd <PROJECT_NAME>
    yarn install

Executing the codes below will add the following dependencies and versions to your project.


{% gist https://gist.github.com/Daltonic/282057948f9b975f85d8fada914b4c88 %}



## Configuring CometChat SDK

Follow the steps below to configure the [**CometChat SDK**](https://hubs.la/Q01f8KXv0); at the end, you must save these keys as an environment variable.

**STEP 1:**
Head to [**CometChat**](https://hubs.la/Q01f8H7m0) Dashboard and create an account.

![Register a new CometChat account if you do not have one](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/61700dac76419b7bac2de69d_s_1988D50EEAEE632A7CEA2F32B0824BC13ED61EA41386BA94E99320DDC4403C74_1633934795404_image.png)


**STEP 2:**
Log in to the [**CometChat**](https://hubs.la/Q01f8H7m0) dashboard, only after registering.

![Log in to the CometChat Dashboard with your created account](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/618ea49640681708de79e9c8_s_C05E7B93FFC9B007F6C09747840C5EEC81AFEC86C6C89C570966797151AE7076_1635316482378_Screen%252BShot%252B2021-10-27%252Bat%252B13.34.18.png)


**STEP 3:**
From the dashboard, add a new app called **genesis.**

![Create a new CometChat app - Step 1](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/61700dac7e33a881ced79837_s_1988D50EEAEE632A7CEA2F32B0824BC13ED61EA41386BA94E99320DDC4403C74_1633936628018_image.png)

![Create a new CometChat app - Step 2](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/618ea496d603ba7ef8cabeb3_s_C05E7B93FFC9B007F6C09747840C5EEC81AFEC86C6C89C570966797151AE7076_1635316586805_VLioyzP2.png)


**STEP 4:**
Select the app you just created from the list.

![Select your created app](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/618ea4969bad618548da9ccd_s_C05E7B93FFC9B007F6C09747840C5EEC81AFEC86C6C89C570966797151AE7076_1635316654035_bSCncNJN.png)


**STEP 5:**
From the Quick Start copy the `APP_ID`, `REGION`, and `AUTH_KEY`, to your `.env` file. See the image and code snippet.

![Copy the the APP_ID, REGION, and AUTH_KEY](https://assets-global.website-files.com/5f3c19f18169b62a0d0bf387/618ea4968574a3c1945af0bd_s_C05E7B93FFC9B007F6C09747840C5EEC81AFEC86C6C89C570966797151AE7076_1635316757752_QHRb0reB.png)


Replace the `REACT_COMET_CHAT` placeholders keys with their appropriate values.


    REACT_APP_COMET_CHAT_REGION=**
    REACT_APP_COMET_CHAT_APP_ID=**************
    REACT_APP_COMET_CHAT_AUTH_KEY=******************************

The `**.env**` file should be created in the root of your project.

## Configuring Infuria App

**STEP 1:**
Head to [**Infuria**](https://infura.io/login), create an account.

![Login to your infuria account](https://res.cloudinary.com/practicaldev/image/fetch/s--gVm10h9K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_9E8F3773E2C82153C7799BA2EBF2003A00F1060D3D03339D1C8009A6D5882B0F_1655136978524_screenshoteasy%2B58.png)


**STEP 2:**
From the dashboard create a new project.

![Create a new project step 1](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661341492075_screenshoteasy+23.png)

![Create a new project step 2](https://res.cloudinary.com/practicaldev/image/fetch/s--doyUGyl_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_9E8F3773E2C82153C7799BA2EBF2003A00F1060D3D03339D1C8009A6D5882B0F_1655137248397_screenshoteasy%2B60.png)


**STEP 3:**
Copy the `Rinkeby` test network WebSocket or HTTPs endpoint URL to your `.env` file.

![Rinkeby Testnet Keys](https://res.cloudinary.com/practicaldev/image/fetch/s---VGdwiP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_9E8F3773E2C82153C7799BA2EBF2003A00F1060D3D03339D1C8009A6D5882B0F_1655137632390_screenshoteasy%2B61.png)


After that, enter your Metamask secret phrase and preferred account's private key. If you followed the instructions correctly, your environment variables should now look like this.


    ENDPOINT_URL=***************************
    DEPLOYER_KEY=**********************
    
    REACT_APP_COMET_CHAT_REGION=**
    REACT_APP_COMET_CHAT_APP_ID=**************
    REACT_APP_COMET_CHAT_AUTH_KEY=******************************

See the section below if you don't know how to access your private key.


## Accessing Your Metamask Private Key

**STEP 1:**
Make sure Rinkeby is selected as the test network in your Metamask browser extension. Then, on the preferred account, click the vertical dotted line and choose account details. Please see the image below.

![Step One](https://res.cloudinary.com/practicaldev/image/fetch/s--FXeHUvQp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/NjkWgrf/kpK7sHUA.png)


**STEP 2:**
Enter your password on the field provided and click the confirm button, this will enable you to access your account private key.

![Step Two](https://res.cloudinary.com/practicaldev/image/fetch/s--oYd6FJPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/Tqrx1RT/S5sWkwuA.png)


**STEP 3:**
Click on **"export private key**" to see your private key. Make sure you never expose your keys on a public page such as `Github`. That is why we are appending it as an environment variable.

![Step Three](https://res.cloudinary.com/practicaldev/image/fetch/s--lo9ufSCF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/0sW24xz/iHVXsxjw.png)


**STEP 4:**
Copy your private key to your `.env` file. See the image and code snippet below:

![Step Four](https://res.cloudinary.com/practicaldev/image/fetch/s--yvdexnsQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/MCkMvyz/1KEkvmvw.png)

    ENDPOINT_URL=***************************
    SECRET_KEY=******************
    DEPLOYER_KEY=**********************
    
    REACT_APP_COMET_CHAT_REGION=**
    REACT_APP_COMET_CHAT_APP_ID=**************
    REACT_APP_COMET_CHAT_AUTH_KEY=******************************

As for your `SECRET_KEY`, you are required to paste your `**Metamask**` secret phrase in the space provided in the environment file.


## The Genesis Smart Contract

Now let’s create the smart contract for this project. Before doing that, you need to understand the scope of this project.

We’re creating a crowdfunding platform where startups and projects of great course can raise funds. This platform help founders with the capital to start up their business, it is called Genesis, which means the BEGINING!

Create a folder called **contracts** in the **src** directory of your project. Now, head to **src** >> **contracts** and create a file named **Genesis.sol** and paste the code below inside of it.


{% gist https://gist.github.com/Daltonic/32c1e30477bf739d2b261ecf36238f37 %}


Now let’s discuss the content of this smart contract segment by segment.

**Defining Essential Variables**

    address public owner;
    uint public projectTax;
    uint public projectCount;
    uint public balance;
    
    statsStruct public stats;
    projectStruct[] projects;
    
    mapping(address => projectStruct[]) projectsOf;
    mapping(uint => backerStruct[]) backersOf;
    mapping(uint => bool) public projectExist;

In the above block of codes, we defined the various data types and structures for storing data on the blockchain.

For the single data types, we have the `owner` variable, project `tax`, `count`, and the available `balance` in our smart contract.

For the multi-data types, we have `**statsStruct**` and `**projectStruct**` which defines the model of each project and the statistics in our smart contract.

The mapping bear records of the project owners, backers, also the existence of a project.

If you are new to Solidity, I have a full [**FREE course on YouTube called, Mastering Solidity Basics**](https://www.youtube.com/playlist?list=PLUDcVqFK2t-D0F7eaNdA7NFSdT82RXcwe). So do check it out, like, and subscribe!

**Setting up the Essential Structs and Event**

    enum statusEnum {
        OPEN,
        APPROVED,
        REVERTED,
        DELETED,
        PAIDOUT
    }
    
    struct statsStruct {
        uint totalProjects;
        uint totalBacking;
        uint totalDonations;
    }
    
    struct backerStruct {
        address owner;
        uint contribution;
        uint timestamp;
        bool refunded;
    }
    
    struct projectStruct {
        uint id;
        address owner;
        string title;
        string description;
        string imageURL;
        uint cost;
        uint raised;
        uint timestamp;
        uint expiresAt;
        uint backers;
        statusEnum status;
    }
    
     event Action (
        uint256 id,
        string actionType,
        address indexed executor,
        uint256 timestamp
    );
    

The above code contains structures for declaring enums, structs, and events.
The enum was defined to contain the various states a project can have in our platform.

The `**statsStruct**` contains the code a statistic should have, such as the total number of donations, backings, and projects.

The `**backerStruct**` on the other hand contains data types each person backing a project should have. A backer should definitely have an address, how much he is donating, the time of donation, and a refund status to show if the owner was refunded his money.

The `**projectStruct**` describes what each project must contain and lastly, the event is a dynamic one to output information according to the calling function.

**The Constructor and Owner Modifier function**

    modifier ownerOnly(){
        require(msg.sender == owner, "Owner reserved only");
        _;
    }
    
    constructor(uint _projectTax) {
        owner = msg.sender;
        projectTax = _projectTax;
    }

Whenever the `**ownerOnly()**` modifier is attached to a calling function, it restricts its accessibility to the deployer of the smart contract only.

The `**constructor()**` function on the other hand, initializes the owner state variable along with the tax per project. This tax is what will be charged per an approved project.

**The Project Create Function**

    function createProject(
        string memory title,
        string memory description,
        string memory imageURL,
        uint cost,
        uint expiresAt
        ) public returns (bool) {
        require(bytes(title).length > 0, "Title cannot be empty");
        require(bytes(description).length > 0, "Description cannot be empty");
        require(bytes(imageURL).length > 0, "ImageURL cannot be empty");
        
        projectStruct memory project;
        project.id = projectCount;
        project.owner = msg.sender;
        project.title = title;
        project.description = description;
        project.imageURL = imageURL;
        project.cost = cost;
        project.timestamp = block.timestamp;
        project.expiresAt = expiresAt;
        projects.push(project);
        projectExist[projectCount] = true;
        projectsOf[msg.sender].push(project);
        stats.totalProjects += 1;
    
        emit Action (
            projectCount++,
            "PROJECT CREATED",
            msg.sender,
            block.timestamp
        );
        return true;
    }

This method takes in project information and pushes it to the project's array. Next, it sets other records such as the statistics and project owners. Lastly, an event is emitted bearing some records of the just created project.

**The Project Updation Function**

    function updateProject(
        uint id,
        string memory title,
        string memory description,
        string memory imageURL,
        uint expiresAt
        ) public returns (bool) {
        require(msg.sender == projects[id].owner, "Unauthorized Entity");
        require(projectExist[id], "Project not found");
        require(bytes(title).length > 0, "Title cannot be empty");
        require(bytes(description).length > 0, "Description cannot be empty");
        require(bytes(imageURL).length > 0, "ImageURL cannot be empty");
    
        projects[id].title = title;
        projects[id].description = description;
        projects[id].imageURL = imageURL;
        projects[id].expiresAt = expiresAt;
    
        emit Action (
            id,
            "PROJECT UPDATED",
            msg.sender,
            block.timestamp
        );
        return true;
    }

This function updates a project according to the project Id using the title, description, image URL, and expiration time. On completion, it emits a Project Updated event.

**The Deletion Function**

    function deleteProject(uint id) public returns (bool) {
        require(projectExist[id], "Project not found");
        require(projects[id].status == statusEnum.OPEN, "Project no longer opened");
        require(
            msg.sender == projects[id].owner ||
            msg.sender == owner,
            "Unauthorized Entity"
        );
    
        projects[id].status = statusEnum.DELETED;
        performRefund(id);
    
        emit Action (
            id,
            "PROJECT DELETED",
            msg.sender,
            block.timestamp
        );
        return true;
    }

The function above marks a project as completed, which by so doing, performs a refund operation sending back all the donations to the appropriate donors.

**Other Functions**
These are the duties of the following functions;


- **PerformPayout()**: Releases the contributed money to the project owner as well as paying the platform’s task.
- **PayOutProject()**: Performs criteria checks and calls the **performPayout()** function internally.
- **PerformRefund()**: Returns money to the backer of a specific project.
- **RequestRefund()**: Performs criteria checks and calls the **performRefund()** function.
- **BackProject()**: Makes donation to a specific project.
- **ChangeTax()**: Changes the platform’s task for projects.
- **GetProject()**: Returns a particular project detail by Id.
- **GetProjects()**: Returns all projects on the smart contract.
- **GetBackers()**: Returns a list of backers for a particular project.
- **PayTo()**: Sends a specific amount of money to a specific address.

Fantastic, there you have it for the smart contract, now let’s get into merging it with the React frontend.

## Configuring the Deployment Script

One more thing to do with the smart contract is to configure the deployment script. Head to the **scripts** >> **deploy.js** and paste the codes below inside of it.


    const hre = require('hardhat')
    const fs = require('fs')
    
    async function main() {
      const taxFee = 5 // unit is in percent
      const Contract = await hre.ethers.getContractFactory('Genesis')
      const contract = await Contract.deploy(taxFee)
      await contract.deployed()
      const address = JSON.stringify({ address: contract.address }, null, 4)
    
      fs.writeFile('./src/abis/contractAddress.json', address, 'utf8', (err) => {
        if (err) {
          console.error(err)
          return
        }
        console.log('Deployed contract address', contract.address)
      })
    }
    
    main().catch((error) => {
      console.error(error)
      process.exitCode = 1
    })

The code above when executed compiles the smart contract and deploys it to the specified network.

**Reviewing the Hardhat Config File**
Head to the root of the project and open up `hardhat.config.js`.


    require("@nomiclabs/hardhat-waffle");
    require('dotenv').config()
    
    module.exports = {
      defaultNetwork: "localhost",
      networks: {
        hardhat: {
        },
        localhost: {
          url: "http://127.0.0.1:8545"
        },
        rinkeby: {
          url: process.env.ENDPOINT_URL,
          accounts: [process.env.DEPLOYER_KEY]
        }
      },
      solidity: {
        version: '0.8.11',
        settings: {
          optimizer: {
            enabled: true,
            runs: 200
          }
        }
      },
      paths: {
        sources: "./src/contracts",
        artifacts: "./src/abis"
      },
      mocha: {
        timeout: 40000
      }
    }

Pay heed to the two objects called networks and paths. We specified two networks which are the localhost and the Rinkeby test networks. The localhost is for development purposes and the Rinkeby is for productions/staging purposes. 

The environment variables called `ENDPOINT_URL` and `DEVELOPER_KEY` were gotten from Infuria and Metamask respectively.

For the path, we are specifying where our smart contracts live and where to dump the generated artifacts. For this case, we specified that they should be kept in the **src** folder.

Great, lastly spin up your hardhat blockchain server and deploy the smart contract using the commands below.


    yarn hardhat node
    yarn hardhat run scripts/deploy.js --network localhost


## Developing the Frontend

Let’s put together the various components of the React frontend step by step. 

**Components**
Now create a folder called component in the **src** directory. This is where all the components will live.

**Header Component**

![Header Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661361048453_screenshoteasy+24.png)


This component beautifully features two items, the logo which helps you navigate back to the home page and the `**connect wallet**` button which helps you connect to your Metamask wallet. Create a file named Header.jsx and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/14e3be45f067b0123921f0236493d9e9 %}


**Hero Component**

![The Hero Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661361583282_screenshoteasy+25.png)


This component is responsible for displaying statistics about the projects created on the platform including the total number of backings and donations. 

To replicate, create a component called **Hero.jsx** in the components folder and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/fc0083071b5b6f8a7099d0357de10a5e %}


**Projects and ProjectCard components**

![Projects Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661362009953_screenshoteasy+26.png)


This component is responsible for rendering individual cards of projects. On the components directory, create a file called Projects.jsx and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/3951f025601ffe4825197d344697ccd0 %}


Again, create another file called `**ProjectCard.jsx**` still inside of the components folder and paste the following codes in it.


{% gist https://gist.github.com/Daltonic/1e579ae50d6adfb18561bcd60add1290 %}


Great, we are moving forward.

**AddButton and CreateProject Components**

![Create Project Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661362617079_screenshoteasy+27.png)


This component together enables us to create new projects. Good use of Tailwind’s CSS was what it took to craft out that beautiful modal.

In the components folder, create a component called `**AddButton.jsx**` and paste the codes below in it.


{% gist https://gist.github.com/Daltonic/2b3033928330115ee170a8d2257bbc37 %}


Next, create another component called `**CreateProject.jsx**` which is configured to be launched by the `**AddButton.jsx**` component. Paste the codes below within it.


{% gist https://gist.github.com/Daltonic/f9a1aeae25730b9c5a6d5290ee05a775 %}


**ProjectDetails Component**

![Project Details](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661363372295_screenshoteasy+28.png)


This component is responsible for displaying details of a particular project and also providing some critical buttons to summon other components. To replicate this component, create a file called `**ProjectDetails.jsx**` in the components directory and paste the codes below in it.


{% gist https://gist.github.com/Daltonic/249d0b88790e8e1d143c5f2d1cc8fc25 %}


**UpdateProject Component**

![UpdateProject Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661363829744_screenshoteasy+29.png)


As intuitive as its name sound, this component helps us update projects provided that the user has the right clearance. In the components folder, create a file called `**UpdateProject.jsx**` and paste the codes below in it.


{% gist https://gist.github.com/Daltonic/39bbeedaa1044b14bac46c01f6883132 %}


**DeleteProject Component**

![DeleteProject Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661364143124_screenshoteasy+30.png)


Like the UpdateProject component, this component can only be utilized if you are the owner of the project or if you are the deployer of the smart contract. Head on to the components folder and create a new file called DeleteProject.jsx and paste the codes below in it.


{% gist https://gist.github.com/Daltonic/4abf193fa32f1328916f97ce1378922e %}


**ChatAuth Component**

![Chat Auth](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661364556441_screenshoteasy+31.png)


This little component is responsible for authenticating users for anonymous chat. Also through this component, owners of projects can create new projects and others can join.

Create a file called `**ChatAuth.jsx**` and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/c80065c28a9f1bd110f3f61407506b34 %}


**BackProject Component**

![BackProject Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661364946739_screenshoteasy+32.png)


This component helps you to specify and donate the number of ethers you are willing to contribute to the project. To replicate, let’s create another component called `**BackProject.jsx**` and paste the codes in it.


{% gist https://gist.github.com/Daltonic/020ab1543f05f1dbc5c433bb488469b0 %}


**ProjectBackers Component**

![Project Backers component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661365889903_screenshoteasy+33.png)


This component lists out all the backers of a particular project. Create a file named `**ProjectBackers.jsx**` and paste the codes inside of it.


{% gist https://gist.github.com/Daltonic/55a9398881485b4be9317357953bfa7f %}


**Messages Component**

![Messages Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661366428468_screenshoteasy+34.png)


This component is responsible for rendering chat content to the view. First, create a file called `**Messages.jsx**` and paste the following codes inside of it.


{% gist https://gist.github.com/Daltonic/6d04c52da2223c211a51bbd022b9e620 %}


**The Views**
We have three major views on this project, they include the Home, Project, and Chat pages. Let’s have them created one after the other. 

On the **src** directory create a new folder called **views** and create the following files within it.

**Home Page**

![Home Component](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661418440323_screenshoteasy+35.png)


This component bundles the smaller components and services that make up the home page. Create a file in the views directory called `**Home.jsx**` and paste the codes below in it.


{% gist https://gist.github.com/Daltonic/7e024bc7e48fde88bb552700af192bb2 %}


**Project View**

![ProjectPage](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661442771867_genesis-back-project.gif)


There is a lot of logic that goes into the making of this page which can be seen by the number of actionable buttons integrated with it. To implement, create a new file called `Project.jsx` in the **src** >> **views** and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/ebebb795aa86c65eb76213bf91e38a6a %}


**Chat View**

![Chat View](https://paper-attachments.dropbox.com/s_B8BD210090BD075D2B556F0ACF9B513CB01868DE4B595A7DBFD220FFEF8C9846_1661443835868_genesis-chat-project.gif)


This view allows you to engage in a one-to-many chat using the CometChat SDK. This is how to replicate it, jump into the views directory, create a file called `**Chat.jsx**`, and paste the codes below inside of it.


{% gist https://gist.github.com/Daltonic/aa8860173170c6ffc2d071fc583e08ef %}


**The App Component**
This mother component bundles and regulates all the pages and components in this application. In the **src** folder, replace the codes inside the file named `**App.jsx**` with the one below.


{% gist https://gist.github.com/Daltonic/6a6bd9e66f04507897520e60ed501628 %}


That completes the views and components for this project, now let’s add up the rest of the essential files.

## Other Essential Files

**The Store Service**
We are using a moderate state management library called [**react-hooks-global-state**](https://www.npmjs.com/package/react-hooks-global-state) to store the data coming from the blockchain. Doing this method greatly simplifies the code.

In your **src** directory, create a folder and a file called **store** >> **index.jsx** and paste the codes below inside.


{% gist https://gist.github.com/Daltonic/2a363d6352be03cd9ad23dc337d343f8 %}


**The Blockchain Service**
Now, this is one of the most important files in this project, and all the codes to interact with our smart contract are written here. Create a file called `**Genesis.jsx**` in the **src** folder and paste the codes below.


{% gist https://gist.github.com/Daltonic/8d78cce4cdda155c306c1d0ea59a9353 %}


**The CometChat Services**
This file contains all the functions needed to establish chat communications with the CometChat SDK. On your **src** folder create a file named `**CometChat.jsx**` and paste the codes below inside.


{% gist https://gist.github.com/Daltonic/37b0a446bae40b00d7de3c9f5d605b57 %}


If you need my help resolving issues on your project, [**consult me on this page**](https://www.buymeacoffee.com/web3classes/e/78962).

**The Index.jsx File**
This last step is responsible for initializing your CometChat service. On the src folder, open the `**index.jsx**` and replace its code with the one below.


    import React from 'react'
    import ReactDOM from 'react-dom'
    import { BrowserRouter } from 'react-router-dom'
    import './index.css'
    import App from './App'
    import { initCometChat } from './CometChat'
    
    initCometChat().then(() => {
      ReactDOM.render(
        <BrowserRouter>
          <App />
        </BrowserRouter>,
        document.getElementById('root')
      )
    })

And there you have it, you just completed the entire build.

Run the command below to start up your server.


    yarn start

[**Watch my FREE web3 tutorials on YouTube now**](https://www.youtube.com/channel/UCQteXYZ5mC-cuTxplzM4Hlw?sub_confirmation=1).


## Conclusion

We've reached the end of this Crowd Funding build, and I know you've gained a lot of value from working with me.

Whatever level you are, if you want to grow faster in your web3 development skills, [**get into my private class**](https://www.buymeacoffee.com/web3classes/e/74614).

Till next time, keep building!


## About the Author

Gospel Darlington is a full-stack blockchain developer with `6+` years of experience in the software development industry.

By combining Software Development, writing, and teaching, he demonstrates how to build decentralized applications on EVM-compatible blockchain networks.

His stacks include `JavaScript`, `React`, `Vue`, `Angular`, `Node`, `React Native`, `NextJs`, `Solidity`, and more.

For more information about him, kindly visit and follow his page on [**Twitter**](https://twitter.com/idaltonic), [**Github**](https://github.com/Daltonic), [**LinkedIn**](https://www.linkedin.com/in/darlington-gospel-aa626b125), or on his [**website**](https://daltonic.github.io/).