Readers like you help support MUO. When you make a purchase using links on our site, we may earn an affiliate commission. Read More.

Smart contracts are the primary building blocks for Web3 applications. In order to enable functionalities in Web3 applications, it is important to be able to interact with the functions specified in a smart contract conveniently. You could use a popular language like JavaScript and the well-known Web3.js library to establish this communication.

Introduction to the Web3.js Library

Web3.js is a JavaScript library that offers an interface for interacting with the Ethereum blockchain. It simplifies the process of building decentralized applications (DApps) by providing methods and tools to connect to Ethereum nodes, send transactions, read smart contract data, and handle events.

Web3.js bridges traditional development and blockchain technology, allowing you to create decentralized and secure applications using familiar JavaScript syntax and functionality.

How to Import Web3.js Into a JavaScript Project

To use Web3.js in your Node project, you first need to install the library as a project dependency.

Install the library by running this command inside your project:

 npm install web3

or

yarn add web3

After installing Web3.js, you can now import the library within your Node project as an ES module:

 const Web3 = require('web3');

Interacting With Deployed Smart Contracts

To properly demonstrate how you can interact with a deployed smart contract on the Ethereum network using Web3.js, you will create a web application that functions with deployed smart contract. The purpose of the web app will be a simple voting ballot where a wallet can cast votes for a candidate and have those votes recorded.

To start, create a new directory for your project and initialize it as a Node.js project:

 npm init 

Install Web3.js into the project as a dependency and create simple index.html and styles.css files within the project’s root.

Import the following code in the index.html file:

 <!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <title>Voting App</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <h1>Voting App</h1>

    <div class="candidates">
      <div class="candidate">
        <span class="name">Candidate A</span>
        <button class="vote-btn" data-candidate="A">Vote</button>
        <span class="vote-count">0 votes</span>
      </div>
      <div class="candidate">
        <span class="name">Candidate B</span>
        <button class="vote-btn" data-candidate="B">Vote</button>
        <span class="vote-count">0 votes</span>
      </div>
      <div class="candidate">
        <span class="name">Candidate C</span>
        <button class="vote-btn" data-candidate="C">Vote</button>
        <span class="vote-count">0 votes</span>
      </div>
    </div>

    <script src="main.js"></script>
  </body>
</html>

Inside the styles.css file, import the following code:

 /* styles.css */

body {
    font-family: Arial, sans-serif;
    text-align: center;
  }
  
  h1 {
    margin-top: 30px;
  }
  
  .candidates {
    display: flex;
    justify-content: center;
    margin-top: 50px;
  }
  
  .candidate {
    margin: 20px;
  }
  
  .name {
    font-weight: bold;
  }
  
  .vote-btn {
    padding: 10px 20px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
  
  .vote-count {
    margin-top: 5px;
  }

Below is the resulting interface:

screenshot of the voting UI with 3 candidates

Now that you have a basic interface to get started, create a contract folder in your project's root to contain the code for your smart contract.

The Remix IDE provides a simple way to write, deploy, and test smart contracts. You will be using Remix to deploy your contract to the Ethereum network.

Navigate to remix.ethereum.org and create a new file under the contracts folder. You can name the file test_contract.sol.

screenshot of the remix IDE

The .sol extension indicates that this is a Solidity file. Solidity is one of the most popular languages for writing modern smart contracts.

Inside this file, write and compile your Solidity code:

 // SPDX-License-Identifier: MIT 
pragma solidity ^0.8.0;
contract Voting {
   mapping(string => uint256) private voteCounts;

   function vote(string memory candidate) public {
       voteCounts[candidate]++;
    };
   function getVoteCount(string memory candidate) public view returns (uint256){
        return voteCounts[candidate];
    };
};

When Remix compiles Solidity code, it also creates an ABI (Application Binary Interface) in a JSON format. The ABI defines the interface between a smart contract and a client application.

It would specify the following:

  • The names and types of functions and events that are exposed by the smart contract.
  • The order of the arguments to each function.
  • The return values of each function.
  • The data format of each event.

To get the ABI, copy it from within the Remix IDE. Create a contract.abi.json file inside contract within your project’s root and paste the ABI inside the file.

screenshot of the copy ABI button in remix

You should go ahead and deploy your contract to a test network using a tool like Ganache.

Communicating With Your Deployed Smart Contract Using Web3.js

Your contract has now been deployed to an Ethereum test network. You can start working on interacting with the deployed contract from your UI interface. Create a main.js file in your project’s root. You will import both Web3.js and your saved ABI file into main.js. This file will talk to your smart contract and will be responsible for reading data from the contract, calling its functions, and handling transactions.

Below is how your main.js file should look:

 const Web3 = require('web3');
const contractAddress = "CONTRACT_ADDRESS"; // Replace with the actual deployed contract address
import contractAbi from '../contract/contract.abi.json'

// Create an instance of web3 using the injected provider (e.g., MetaMask)
const web3 = new Web3(window.ethereum);

// Create a contract instance using the contract address and ABI
const votingContract = new web3.eth.Contract(contractAbi, contractAddress);

// Retrieve the candidate elements from the DOM
const candidates = document.querySelectorAll('.candidate');

// Function to handle voting for a candidate
async function vote(candidate) {
  try {
    // Call the 'vote' function of the smart contract
    await votingContract.methods.vote(candidate).send({ from: web3.eth.defaultAccount });

    // Update the vote count in the UI
    const voteCount = await votingContract.methods.getVoteCount(candidate).call();
    const voteCountElement = document.querySelector(`[data-candidate="${candidate}"] .vote-count`);
    voteCountElement.textContent = `${voteCount} votes`;
  } catch (error) {
    console.error(error);
    // Handle error cases, such as invalid transactions or network issues
  }
}

// Add click event listeners to the vote buttons
candidates.forEach(candidate => {
  const candidateName = candidate.getAttribute('data-candidate');
  const voteBtn = candidate.querySelector('.vote-btn');
  voteBtn.addEventListener('click', () => {
    vote(candidateName);
  });
});

The code block above utilizes Web3.js to talk with your smart contract functions from your web interface. Essentially you are using JavaScript functions to call Solidity functions from main.js.

In the code, replace 'CONTRACT_ADDRESS' with the actual deployed contract address. The Remix IDE will provide you with this on deployment.

Here's what's happening in the code:

  1. Update the DOM elements selection based on your HTML structure. In this example, it assumes that each candidate element has a data-candidate attribute that corresponds to the candidate's name.
  2. An instance of the Web3 class is then created using the injected provider from the window.ethereum object.
  3. The votingContract variable creates a contract instance using the contract address and ABI.
  4. The vote function handles the voting process. It calls the vote function of the smart contract using votingContract.methods.vote(candidate).send(). It sends a transaction to the contract, recording the user's vote. The voteCount variable then calls the getVoteCount function of the smart contract to retrieve the current vote count for a specific candidate. It will then update the vote count in the UI to match the retrieved votes.

Remember to include this main.js file in your HTML file using a <script> tag.

Additionally, ensure that the contract address and ABI are correct and that you have proper error handling in place.

JavaScript’s Role in Building DApps

JavaScript has the ability to interact with smart contracts used in decentralized applications. This brings together the Web3 world with a primary programming language used in building Web2 apps, which helps facilitate the adoption of Web3. With Web3.js, Web2 developers can transition to building apps like a Web3 social media platform.