Create DAPP using Ganache, Solidity, Truffle, React & Ethers JS.(Crowd Funding)
Hello there! In this blog I will show you how to create a decentralized application (i.e. : DAPP) using ganache, solidity, truffle, react and ethers js.
Crowd Funding is a decentralized application where people can create their own fund raising projects for others to fund. Since creating this application is a long process, I will separate the process in to 3 different parts. They are as follows :-
- Setting up our development environment and project base(seed project) .
- Writing smart contract and tests for it.
- Creating React App and connect it to our smart contract.
I promise you, this trilogy of blog article is all you need to start calling yourself a blockchain developer. 👊
GITHUB REPO OF COMPLETE PROJECT DOWN HERE !!!
In this first chapter of the trilogy, lets setup our development environment first.
LETS GET STARTED !!!
PART 1 : Setting up
After that, open that project folder and then run these 2 commands :-
- yarn install
- yarn clientPkg
The project structure should look like this after installing all the packages required.
Before jumping into next step, lets first explain the folder structure of the project. I will explain only the folders and files we are going to need.
This folder holds our frontend i.e. React. Here we are going to develop our UI and connect React UI with our smart contract.
This folder holds our smart contracts.
This folder will hold a JS file which we will run to deploy our smart contract in to a blockchain network. For now we will deploy our contract in Ganache.
This folder will hold a JS file which we will write our test cases for our smart contract.
This file holds the configuration of our truffle environment for this project.
That’s it !!!
You have successfully setup your blockchain development environment.
You have started your journey to become a decentralized application developer. Congratulations!!!
Brace yourself because its only up hills from now 👀.
PART 2 : Write and test our smart contract
Lets create a file called Crowdfunding.sol inside ./contracts folder of our project. But before that lets connect our contract with our Ganache network. I will guide you step wise through this process.
Step 1: Open Ganache and click on NEW WORKSPACE.
Step 2: Give name to the workspace and connect ganache with your projects truffle-config.js file. And just save.
So simple right.😪
I will first explain what our smart contract should achieve, in simpler words what functionalities should our contract have for a basic crowdfunding project. ( After learning these basics you can go bonkers.👌 ). Our contract should have the following functionalities :-
- User should be able to open a funding project.
- User should be able to fund an existing project.
- User should be able to close the project if he/she is the owner of that project.
To achieve all these functionality, we need to define state variables where we store data. Listed below are the state variables required :-
name :- Stores the name of our contract. (Optional)
projectCount :- Stores the total number of project.
Project:- Solidity struct data type. It stores the details of fund project.
projects :- Solidity mapping. It maps project number to project details(i.e. Project described above).
contributors:- Solidity mapping. It maps fund project id to array of addresses that contributed to the fund project.
Now, put your coding glasses on and lets get started 🤓. At first create a .sol file inside ./contracts folder. In my case, I have created CrowdFunding.sol, this file is the our smart contract. In this fie add the following lines.
So now lets create all the events our contract should emit when certain transactions occurs. Listed below are the events required :-
- ProjectCreated :- Event triggered when a project is opened/created.
- ProjectFunded :- Event triggered when a project is funded.
- ProjectEnded :- Event triggered when a project is closed.
Before moving on ahead lets test our contract to see if everything is working as expected. Lets define a constructor of our contract where we define our smart contract name.
Now, lets test our contract up till now by writing our test.
To do that,
i. create a file named 1_deploy_contract in ./migrations folder and add the following code.
ii . create a file named Test.js in ./test folder and add following code.
Now run, yarn test or truffle test on your terminal.
Wow, you have written your first test case for your contract. Pat yourself on the back.😱
We now have to create function modifiers for our contract. Function modifiers allows you to control the behavior of your smart contract functions. It includes a variety of use cases, such as restricting who has the ability to run a given function, unlocking functions at a certain time frame, etc.. In our case, we will create the following modifiers :-
this allows only the project owner to run a given function.
this checks if project exists or not.
Lets add the following lines of code in our contract.
Now lets add our core functionality of the contract, shall we?
- Create Project.
- Fund Project.
- Close project.
- Create project :-
This function will create a new fund project and emits ProjectCreated event when transaction completes.
2. Fund project :-
This function checks if the project exists and if it does exist, this function will carry out 3 things :-
i. fund the project,
ii. saves record of the contributor,
iii. emits ProjectFunded event
3. Close project :-
This function first checks if the user who called this function is the owner of the fund project and if the project exists. If both conditions are satisfied, the function will carry out 3 things :-
i. transfers all the fund collected by the project to the project owner,
ii. closes the project,
iii. emits ProjectEnded event.
That’s it!!! Now our contract can successfully create, fund and close fund project.
But our contract is still not complete as we also need few more view functions for our react application to show crucial information like balance of the project, contributors and the total contributions they gave to a project.
We will declare the functions given below :-
> balanceOfProject :-
This function returns the balance of the contract.
> getContibutionsLength :-
This function returns the total number of contributors of a project.
> getContributor :-
This function returns the address of the contributor that contributed to a project given the project id and the index of the contributor.
Put the above code in your contract.
Now run, yarn migrate in your terminal to deploy the smart contract in Ganache.
Little assignment for you all, write your own test cases for the core functions of the contract. I request you to do so.😉
Finally, our contract is all done and deployed. 😍
Part 3: Connecting the smart contract with React frontend
Well done guys, now this is the part that is going to make or break our whole project, that is frontend **oh dear 😐** .
In this part I will guide you oh how to connect your React application with Metamask and our smart contract.
Disclaimer :- I won’t be going through the process of creating all the UI part/component in React because I know everyone else is a better UI designer than I am 😣.
So lets get going.
First let me explain the project structure I decided to use. ( You can change in to your own preference ).
We will focus on only the src folder because it is a React application and only the folder that is used to connect our React application with Metamask and our smart contract.
- ./contracts/abis :- This folder will hold our compiled contract as specified on our truffle-config.js file.
- ./modules/context :- This folder holds the application context for our React application. We will be using React context for state management.
- ./services :- This folder hold the file that parses signer and provider contract.
- ./utils :- This folder holds the utility file for converting values returned from smart contract to user readable data.
- .env :- This file holds the react environment variable. In here i have stored our contract address deployed on blockchain network (In our case Ganache).
HOW I CONNECTED METAMASK AND SMART CONTRACT WITH REACT APPLICATION.
I assume you added Metamask extension in your browser.
- Configure Metamask :-
Go to Metamask Settings > Network and Add Network with the following configuration.
Now import Accounts that are generated by ganache into Metamask wallet.
(Quick advice, import multiple accounts).
2. Connect our Application with Smart contract
For connecting our React application with our smart contract, I will separate this process into 3 different steps. The steps are as follows :-
i. Configuring .env file :-
In .env file lets store the contract address deployed in our ganache server. To find the deployed contract address, simply go to CONTRACTS tab on ganache window, there you will find contracts that have been deployed.
ii. Getting Signer and Provider contract :-
Signer contract is an instance of contract that is required to execute any kind of transaction in another words any function that requires gas fee.
Provider contract is an instance of contract that can only execute view functions of our smart contract.
So lets create a file called contract.js inside our ./src/service folder and add the following lines.
Here , the function getContractByProvider returns the provider contract and function getContractBySigner returns the signer contract.
iii. Creating our Application Context
This is going to be a little long one. Lets divide and conquer this one too by dividing this into 3 process, they are :-
a. Defining Actions :-
Create actions.js file inside ./src/modules/context folder and add these lines of code.
These actions will help us define what we are performing on our reducer.
b. Defining Reducers :-
Create reducers.js file inside ./src/modules/context folder and add these lines of code.
Reducers help us to update/modify state of our context.
c. Constructing our Context :-
Create an context.js file in ./src/modules/context folder. First lets import all the necessary files into our context file.
Declare the initial state of our context.
Create our context using the reducer and initial state we created.
Now lets define our context functions.
Add event listener that initializes our context whenever we change Blockchain network or Wallet on our Metamask.
Now lets make our state variables accessible to all the children component that are wrapped by our context.
And that’s it. We have created our context.
All that’s left is to make our context globally available to all the components you are going to build.
If you have followed through all these steps, you have successfully accomplished to create a DAPP from front to back. Now go along and celebrate this achievement. And I want you to fiddle around this project and go bonkers with it to make it your own version of crowd funding.
I hope reading this blog post gave you some insight on how to be a blockchain developer and helped you take the first step on becoming one heck of a blockchain savvy. Peace.