Building Web3 Applications with NextJS, Solidity, and Truffle

Web3 development is becoming increasingly popular as more and more applications are being built on blockchain technology. In this blog post, we will explore how to build web3 applications with NextJS, Solidity, and Truffle.

Web3

NextJS

Blockchain Development

Smart Contracts

Solidity

Building Web3 Applications with NextJS, Solidity, and Truffle

Introduction

Web3 development has gained a lot of traction in recent years, especially with the rise of decentralized applications built on blockchain technology. Web3 development involves building applications that interact with the Ethereum blockchain, which is a decentralized, distributed ledger that records transactions between parties.

NextJS is a popular framework for building server-side rendered React applications. Solidity is a programming language used to write smart contracts on the Ethereum blockchain. Truffle is a development environment, testing framework, and asset pipeline for Ethereum. It provides a suite of tools for developing smart contracts and deploying them to the blockchain.

In this blog post, we will explore how to build web3 applications with NextJS, Solidity, and Truffle. We will cover the basics of creating a Solidity smart contract, compiling and deploying the contract with Truffle, integrating the contract with a web3 application using the web3.js library, and creating a component that interacts with the contract.

Requirements

To follow this tutorial, you will need the following:

  • Node.js installed on your machine
  • Basic knowledge of React and JavaScript
  • A text editor of your choice
  • Truffle installed on your machine

Getting Started

To get started, let’s initialize a new NextJS project. Open your terminal and navigate to the directory where you want to create the project. Then, run the following command:

npx create-next-app my-app

This will create a new NextJS project in the my-app directory.

Next, navigate to the my-app directory and install the necessary dependencies:

cd my-app
npm install web3 @truffle/contract

Solidity Smart Contract

Solidity is a programming language used to write smart contracts on the Ethereum blockchain. In this example, we will create a simple smart contract that stores a message.

Create a new file called Message.sol in the contracts directory and add the following code:

pragma solidity ^0.8.0;

contract Message {
    string private message;
    function setMessage(string memory _message) public {
        message = _message;
    }
    function getMessage() public view returns (string memory) {
        return message;
    }
}

This contract has two functions: setMessage and getMessage. The setMessage function sets the message variable and the getMessage function retrieves it.

Truffle Configuration

Truffle is a development environment, testing framework, and asset pipeline for Ethereum. It provides a suite of tools for developing smart contracts and deploying them to the blockchain.

Create a new file called truffle-config.js in the root directory and add the following code:

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*", // Match any network id
    },
  },
  compilers: {
    solc: {
      version: "0.8.0",
    },
  },
};

This configuration file specifies the development network and the Solidity compiler version.

Compiling and Deploying Smart Contract

Now that we have our smart contract and Truffle configuration set up, we can compile and deploy the contract to the blockchain.

First, let’s compile the contract by running the following command:

truffle compile

This will compile the contract and create an output file in the build/contracts directory.

Next, let’s deploy the contract to the blockchain by running the following command:

truffle migrate

This will deploy the contract to the blockchain and create a new instance of the contract.

Web3 Integration

Now that we have our smart contract deployed to the blockchain, we can integrate it with our web3 application.

Create a new file called web3.js in the lib directory and add the following code:

import Web3 from "web3";
import messageArtifact from "../build/contracts/Message.json";

const getWeb3 = () =>
  new Promise((resolve, reject) => {
    window.addEventListener("load", async () => {
      if (window.ethereum) {
        const web3 = new Web3(window.ethereum);
        try {
          await window.ethereum.enable();
          resolve(web3);
        } catch (error) {
          reject(error);
        }
      }
      // Legacy dapp browsers...
      else if (window.web3) {
        const web3 = window.web3;
        console.log("Injected web3 detected.");
        resolve(web3);
      }
      // Non-dapp browsers...
      else {
        console.log("Non-Ethereum browser detected. You should consider trying MetaMask!");
      }
    });
  });

const getContract = async (web3) => {
  const networkId = await web3.eth.net.getId();
  const deployedNetwork = messageArtifact.networks[networkId];
  const contract = new web3.eth.Contract(
    messageArtifact.abi,
    deployedNetwork && deployedNetwork.address
  );
  return contract;
};

export { getWeb3, getContract };

This file exports two functions: getWeb3 and getContract. The getWeb3 function initializes a new instance of the Web3 class and returns it. The getContract the function retrieves the contract instance from the blockchain and returns it.

Example Component

Now that we have our smart contract and web3 integration set up, we can create a new component that interacts with the contract.

Create a new file called Message.js in the pages directory and add the following code:

import React, { useState, useEffect } from "react";
import { getWeb3, getContract } from "../lib/web3";

const Message = () => {
  const [web3, setWeb3] = useState(null);
  const [contract, setContract] = useState(null);
  const [message, setMessage] = useState("");
  
useEffect(() => {
    const init = async () => {
      const web3 = await getWeb3();
      const contract = await getContract(web3);
      setWeb3(web3);
      setContract(contract);
    };
    init();
  }, []);

  const getMessage = async () => {
    const message = await contract.methods.getMessage().call();
    setMessage(message);
  };

  const setMessageValue = async () => {
    await contract.methods.setMessage("Hello, world!").send({ from: (await web3.eth.getAccounts())[0] });
    getMessage();
  };

  return (
    <div>
      <h1>Message</h1>
      <p>{message}</p>
      <button onClick={getMessage}>Get Message</button>
      <button onClick={setMessageValue}>Set Message</button>
    </div>
  );
};

export default Message;

In this component, we initialize the web3 instance and contract instance using the getWeb3 and getContract functions. We then define two functions: getMessage and setMessageValue. The getMessage function retrieves the message from the contract and sets it in the message state. The setMessageValue function sets a new message value in the contract and retrieves the updated message value.

Conclusion

In this tutorial, we learned how to build web3 applications with NextJS, Solidity, and Truffle. We covered the basics of creating a Solidity smart contract, compiling and deploying the contract with Truffle, integrating the contract with a web3 application using the web3.js library, and creating a component that interacts with the contract. With these tools and techniques, you can build powerful decentralized applications that interact with the Ethereum blockchain.

Web3 development is a rapidly evolving field, and there are many exciting developments on the horizon. As blockchain technology continues to mature, we can expect to see more sophisticated and powerful web3 applications being built.


Get latest updates

I post blogs and videos on different topics on software
development. Subscribe newsletter to get notified.


You May Also Like

When to Use a Monorepo: Benefits, Drawbacks, and Practical Examples

When to Use a Monorepo: Benefits, Drawbacks, and Practical Examples

Learn when to use a monorepo, its benefits, and drawbacks. This guide includes practical examples to help you decide if a monorepo is right for your development projects.

NodeJS: An Introduction to Streams for Efficient Data Handling

NodeJS: An Introduction to Streams for Efficient Data Handling

Learn the basics of NodeJS streams, including reading, writing, and piping data, to efficiently handle large data sets in your applications with practical code examples.

Exploring What's New in React 19: Actions, Async Scripts, Server Components, and More

Exploring What's New in React 19: Actions, Async Scripts, Server Components, and More

Dive into React 19's features like Actions for state management, async scripts support, server components, and enhanced error handling, revolutionizing modern web development.