Develop your first Dapp with Web3.js
Tags: blockchain, web3, smartcontract, beginners
Published: 2022-05-10 17:20:59

A world of cryptocurrencies emerged out of new hope for digital payments, and blockchain makes it all possible. It can be hard to envision the implications of a decentralized currency. Dapps represents a whole new vision of the internet completely unlike its current iteration. Digital assets such as cryptocurrencies, smart contracts and NFTs are the core building blocks of decentralized applications (DApps). Web3.js is a collection of libraries that allow you to interact with a local or remote Ethereum node, using HTTP or IPC connection which is also the backbone to develop dapps.

In this article, we will learn to build a decentralized application using Web3js.

## Getting Started
Today, we will learn the basics of Dapps and Web3js.

Let's begin with basic terminologies - blockchain, decentralized application, Ethereum, smart contracts, web3js.

### Blockchain
A blockchain is an auditable and irreversible database where data can only be added. In a blockchain, the data can be added as blocks in which each block has the address of the previous one, hence called the blockchain.

### Ethereum
Ethereum is an open-source decentralized platform built on blockchain and is used to run our smart contracts. It is not only a cryptocurrency but also a sophisticated application that executes the smart contracts on the blockchain so as to avoid the chances of any fraud attempts in the transactions. We use Ethereum Virtual Machine (EVM) as the runtime for running the smart contracts.

### Smart Contracts
Smart contracts are program snippets compiled and executed by the EVM and stored on a blockchain. It is executed automatically when the predefined conditions are met. It helps you to do safe transactions without the involvement of a third party. The good part of smart contract-based transactions is that these transactions are irreversible but traceable.

Solidity is the most widely used programming language to create and write smart contracts even though there are other languages such as Mutan, Serpent and LLL available in the market.

### Decentralized Applications (Dapps)
Dapp is a program that is executed on a blockchain or decentralized network. Dapp is short for Decentralized application. It is not controlled by a single organization and operates on a blockchain network which is free of central control.

![Dapps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4fayl7ht4om78p5wcec1.png)
_Image credits ethereum.stackexchange.com_

A decentralized application has three major components:
- **frontend**: Takes input from the user and sends requests to the smart contract.
- **wallet**: Authenticates the transactions and connects to the respective blockchain.
- **Smart contracts**: An automatically executed program that contains the business logic of the dapp.

Some Dapp features are,
- **No downtime** - Dapp runs on a peer-to-peer network of computers, hence there will be no downtime or restrictions as it doesn't rely on a single point of failure, unlike a hosting server.
- **Transparency** - Data from decentralized applications are stored on a public ledger, which keeps track of everything in a safe and transparent manner such that no one can tamper with it.

### Web3.js
Web3.js is a collection of library that interacts with the Ethereum node using HTTP, IPC or WebSocket. It provides JavaScript APIs such as JSON-RPC internally to communicate with geth. It can communicate with any Ethereum node that supports JSON-RPC, and also exposes all JSON-RPC APIs as JavaScript APIs.

### How it works

![Web3.js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0yn3b363o0nqqam9mzu.png)
_Image credits iotbl_
Web3.js communicates with the Ethereum Blockchain using JSON RPC, which stands for Remote Procedure Call protocol. Ethereum is a peer-to-peer network of nodes that stores a copy of all the data and code on the blockchain. Web3.js reads and writes data to the network by making JSON RPC requests to an Ethereum node, similar to using jQuery with a JSON API.

In order to translate JavaScript code to json-rpc requests, web3.js uses a provider and implements the request method responsible for making an Ethereum RPC method call. Web3.js has its own implementations of the specification mentioned above and makes it available under web3.providers, HttpProvider, WebsocketProvider, and IpcProvider.

### Web3.js packages
web3.js comes with five major packages
- **web3.eth**: Interacts with Ethereum blockchain and smart contracts.
- **web3.bzz**: Interacts with decentralized file stores such as Swarm.
- **web3.shh**: Interacts with Whisper protocol for broadcasting.
- **web3.utils**: Contains utility functions such as converting strings to hex literals and Ether values to Wei.
- **web3.*.net**: Interacts with the network properties of Ethereum node such as the network ID or the peer count.

## First Dapp
We have understood the basic concepts. Now, let's dive into the first dApp.

### 1. Setup the environment
Basically, dApp requires nodejs, truffle and ganache installed on your system.
- **Node.js** - An open-source JavaScript runtime environment used to execute JavaScript code outside a web browser.
- **Truffle** - The most popular development framework for Ethereum.
- **Ganache** - Provides a local network that shows different test / real blockchain accounts and transactions on the IDE/console. It is a part of the Truffle suite.
- **Solc** - JavaScript bindings for the Solidity compiler.
Download and install node.js.
- Install Truffle globally.
```
  npm install -g truffle
```
![truffle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jim195sdy4jxzn3q0tee.png)
![truffle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gdtrwz6si6kjxp23cia.png)
- [Download](https://objects.githubusercontent.com/github-production-release-asset-2e65be/79269625/f157fd00-185e-11eb-9efb-d7c749098bd0?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220106%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220106T122145Z&X-Amz-Expires=300&X-Amz-Signature=5e3aebb5f97b2bf4b8e84d9cdb8015aa036b2b58763902c2141e953e423d2125&X-Amz-SignedHeaders=host&actor_id=16046782&key_id=0&repo_id=79269625&response-content-disposition=attachment%3B%20filename%3DGanache-2.5.4-win-x64.appx&response-content-type=application%2Foctet-stream) and install [ganache-cli](https://www.trufflesuite.com/ganache).
![ganache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/876b77sjunaoqzje2hfv.png)
- Install [solc](https://www.npmjs.com/package/solc) globally
```
  npm install -g solc
```
![solc](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao39411ccp7vbcvsyldk.PNG)
The software installations are completed. Now, we can setup the project.
Let's start building our own dapps by creating a project folder named dapp-demo. Switch to the folder and initialize with truffle. 
```
  mkdir dapp-demo
  cd dapp-demo
  truffle init
```
![truffle init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmbcb0kkaoquankerpcg.png)
`truffle init` creates necessary project files which include `Migrations.sol`, `1_initial_migration.js` and `truffle-config.js`. 
The initial project structure will look like this,
![project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6d7gmi36o8uveabddwy.png)
### 2. Write the contract
Now, we can create a greeting smart contract. Create a file named `Greeting.sol` and place it under the contracts folder and add the following code to it.
```
  // SPDX-License-Identifier: MIT
  pragma solidity >=0.4.22 <0.9.0;
  contract Greeting {
    string public greeting = "hello";  
    function sayHello() external view returns (string memory) {
        return greeting;
    }  
    function updateGreeting(string calldata _greeting) external {
        greeting = _greeting;
    }
  }
```
### 3. Setup the migration
Create a new file in the migrations folder with a prefix greater than 1, for example, 2_greeting_migartion.js to deploy the HelloWorld.sol contract.
```
  const Greeting = artifacts.require("Greeting");
  module.exports = function (deployer) {
      deployer.deploy(Greeting);
  };
```
### 4. Compile and deploy
Compile your project using the following command
```
  truffle compile
```
![truffle compile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15ldseo8331lt7ifw807.png)
The `build` folder is created in the project folder after successful compilation.

Now, we need to work with both Turffle and Ganache to deploy and test the contract. For that, Open Ganache, select "QuickStart".

Mention the network on which you would like to deploy the smart contract by going `truffle-config.js` and modifying the network details by uncommenting the development section. 

> Ensure that the RPC server port from Ganache is mapped to the `networks.port` value.
![Ganache network port](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv9lxe22kcqlylvadvaj.png)
![network config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/moxjtap7wn5ka2g7u4ev.png)
Deploy the contract using the following command.
```
  truffle deploy --network development
```
After the successful deployment, you will get some contract details such as the contract address and the block information.
![deployment info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuq7jwjrvx7gb0g2ch0k.png)

## 5. Connect the front end with the smart contract
### 5.1 Setup the environment
Create a new folder named client under the root directory and initialize it using npm. 
Install web3.js and lite-server dependencies:
```
  mkdir client
  cd client
  npm init
  npm install web3
  npm install lite-server --save-dev
  npm install jquery
```

![client dependencies](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2graiins34c1922ygou.png)
![web3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc7yuwk5zh9pxn43t78g.png)
![web3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dlskpb3xeoj74g0qyayl.png)
![lite server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miae1etx5ybc7kpcl7ro.png)
![jquery](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lp3mw5qi2j8t5evip3yi.png)
Create a new folder called src and add two scripts: `index.js` and `utils.js`. You also need to create `index.html` file under the root folder (client folder) and add the following code to it.
```
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Dapp Demo</title>
  </head>
  <body>
      <h1>Dapp Demo</h1>
      <br/>
      <h2></h2>
      <form id="form">
          <input id="input" type="text"/>
          <input type="submit" value="submit"/>
      </form>
      <script type="text/javascript" 
 src="node_modules/jquery/dist/jquery.min.js"></script>
      <script type="text/javascript" src="node_modules/web3/dist/web3.min.js"></script>
      <script type="text/javascript" src="src/utils.js"></script>
      <script type="text/javascript" src ="src/index.js"></script>
  </body>
  </html>
```
### 5.2 Get a web3 instance
Once you have web3.js as a dependency in your project, all you need to do is to instantiate a web3 object using an instance of a provider. In this demo, we will learn to connect with ganache using its RPC server address.

Open util.js file to create a `getWeb3()` method for creating a web3js instance using the Ganache RPC server address.

```
  const getWeb3 = () => {
    return new Promise((resolve, reject) => {
      window.addEventListener("load", async () => {
          try {
            const web3 = new Web3("http://127.0.0.1:7545");
            resolve(web3);
          } catch (error) {
            reject(error);
          }
      });
    });
  };
```

### 5.3 Create a contract instance
In order to create a contract instance, we need the contract ABI and its address. If you take a look at the artifacts in the build directory, you will find a file named `Greeting.json`. If you open it, you will find a lot of information about the contract, including the contract name, ABI etc.

Create a new folder called contracts under the client folder and copy-paste the `Greeting.json` file.

First, we need to get the ID of the network to which Ganache is connected using `web3.eth.net.getId()`. Use the returned ID to get the address of the contract from the `Greeting.json` file, which will also provide us with the contract ABI and will create an instance of the contract using `web3.eth.Contract`

Create a `getContract()` method in `util.js` file and add the following code to it.
```
  const getContract = async (web3) => {
    const data = await $.getJSON("./contracts/Greeting.json");
    const netId = await web3.eth.net.getId();
    const deployedNetwork = data.networks[netId];
    const greeting = new web3.eth.Contract(
      data.abi,
      deployedNetwork && deployedNetwork.address
    );
    return greeting;
  };
```

### 5.4 Interact with the smart contract
After contract instance creation, we can start calling methods using,
```
  myContract.methods.myMethod([arguments]).
```
If the function is pure or read-only, you can call it using,
```
  myContract.methods.myMethod([arguments]).call()
```
If the function can modify the state, you can call it using,
```
myContract.methods.myMethod([arguments]).send()
```
Finally, add the following content to the `index.js` file.
```
  const displayGreeting = async (greeting, contract) => {
    greeting = await contract.methods.sayHello().call();
    $("h2").html(greeting);
  };
  const updateGreeting = (greeting, contract, accounts) => {
    let input;
    $("#input").on("change", (e) => {
      input = e.target.value;
    });
    $("#form").on("submit", async (e) => {
      e.preventDefault();
      await contract.methods
        .updateGreeting(input)
        .send({ from: accounts[0], gas: 40000 });
      displayGreeting(greeting, contract);
    });
  };
  async function greetingApp() {
    const web3 = await getWeb3();
    const accounts = await web3.eth.getAccounts();
    const contract = await getContract(web3);
    let greeting;
    displayGreeting(greeting, contract);
    updateGreeting(greeting, contract, accounts);
  }
  greetingApp();
```
The final project structure will look like this,
![project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l853fyz3kdv7swqw239x.png)

### 5.5 Run the app
The development is completed. Now, we can run the project after adding the start script to the `package.json` file.
```
  "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "start": "lite-server"
   },
```
Run the project using the following command.
```
  npm start
```
![start project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1s8c6qp0nsvv2adwn36f.png)
There you have it! Your own Dapp with web3js :)
![final output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6f9l7bjirapytiqfkaps.png)
Thanks for reading this article.

If you enjoyed this article, please click on the heart button ♥ and share to help others find it!

The full source is available on https://github.com/codemaker2015/dapp-web3js-demo
Here are some useful links,
- [INTRODUCTION TO DAPPS](https://ethereum.org/en/developers/docs/dapps/)
- [web3.js - Ethereum JavaScript API](https://web3js.readthedocs.io/en/v1.5.2/)

Originally posted on Medium - 
[Develop your first Dapp with Web3.js](https://medium.com/@codemaker2016/develop-your-first-dapp-with-web3-js-c038bc10710b)