DEV Community

Cover image for Develop your first Dapp with Web3.js
Vishnu Sivan
Vishnu Sivan

Posted on

Develop your first Dapp with Web3.js

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
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
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
Enter fullscreen mode Exit fullscreen mode

truffle
truffle

  npm install -g solc
Enter fullscreen mode Exit fullscreen mode

solc
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
Enter fullscreen mode Exit fullscreen mode

truffle init
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

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;
    }
  }
Enter fullscreen mode Exit fullscreen mode

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);
  };
Enter fullscreen mode Exit fullscreen mode

4. Compile and deploy

Compile your project using the following command

  truffle compile
Enter fullscreen mode Exit fullscreen mode

truffle compile
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
network config
Deploy the contract using the following command.

  truffle deploy --network development
Enter fullscreen mode Exit fullscreen mode

After the successful deployment, you will get some contract details such as the contract address and the block information.
deployment info

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
Enter fullscreen mode Exit fullscreen mode

client dependencies
web3
web3
lite server
jquery
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>
Enter fullscreen mode Exit fullscreen mode

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);
          }
      });
    });
  };
Enter fullscreen mode Exit fullscreen mode

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;
  };
Enter fullscreen mode Exit fullscreen mode

5.4 Interact with the smart contract

After contract instance creation, we can start calling methods using,

  myContract.methods.myMethod([arguments]).
Enter fullscreen mode Exit fullscreen mode

If the function is pure or read-only, you can call it using,

  myContract.methods.myMethod([arguments]).call()
Enter fullscreen mode Exit fullscreen mode

If the function can modify the state, you can call it using,

myContract.methods.myMethod([arguments]).send()
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

The final project structure will look like this,
project structure

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"
   },
Enter fullscreen mode Exit fullscreen mode

Run the project using the following command.

  npm start
Enter fullscreen mode Exit fullscreen mode

start project
There you have it! Your own Dapp with web3js :)
final output
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,

Originally posted on Medium -
Develop your first Dapp with Web3.js

Discussion (0)