Learn to Build Smart Contracts in React with web3.js: Here’s How! (1/2)

A question often asked by newbie learners while developing the smart contract is, “How to connect my frontend code with the smart contract?โ€.

The answer should be web3.js till day. web3.js has a collection of libraries that allows you to interact with a local or remote Ethereum node. Consider it an interface connecting the front end with the blockchain world.

Today we will see how a simple, smart contract interacts with the react frontend using web3.js.

I have my react app initialized inside the truffle development environment. We also have a very simple smart contract that will be deployed soon on the locally running test blockchain. In our case, the locally running test blockchain is ganache.

Letโ€™s connect with the local blockchain first.

Connect Ganache with Truffle

Now move to ganache and create a new workspace. Locate the directory of “truffle-config.js” file and save the workspace. You will get ten demo accounts that can be used for transactions on the local blockchain.

Move to “truffle-config.js” file and uncomment the development section. Change the port to 7545, as it is the port of the ganache.

Now get back to the terminal and type:

truffle migrate

If the connection is established, you will see some balance deducted from the first account of the ganache.

Connect Metamask with Ganache

Itโ€™s time to connect our locally running Ethereum network with the Metamask wallet.

Move to Metamask and choose the “add network” option from the dropdown. Letโ€™s change the configuration. I am keeping the network name as ganache_host. The new RPC URL would be as same as the ganache RPC SERVER i.e.;

Network Name: ganache_host
New RPC URL:  http://127.0.0.1:7545
Chain ID: 1337
Currency symbol: eth
Press the save button. Your new ganache network is ready.

Connect Metamask to the React Frontend

To connect the front end with the Metamask wallet, we need to initiate web3. Move to the frontend directory by using the terminal and type:

npm install --save web3

Now import the web3 in the app.js file.

import Web3 from "web3";

In the user interface, we will create a simple button connecting us with the Metamask wallet when clicked.

<button onClick={onConnect}>Connect to metamask</button>

An onConnect function will be initiated when we click the “Connect to metamaskโ€ button. Letโ€™s define the onConnect function

const onConnect = async () => {
    let provider = window.ethereum;
    if (typeof provider !== "undefined") {
      await provider.request({ method: "eth_requestAccounts" });
      const web3 = new Web3(provider);
      const accounts = await web3.eth.getAccounts();
      const account = accounts[0];
      console.log(account);
    } else {
      console.log("Non-ethereum browser detected.Please install Metamask");
    }
  };

onConnect is an async await function that will trigger if the Metamask is installed on the browser. Otherwise, it will throw an error. You can consider “window.ethereumโ€ as a synonym of Metamask.

If the Metamask connects with the user interface, the provider will request the accounts from the ganache. Then we will create an instance of the web3 with the provider. The web3.eth.getAccounts() method will help us to get all the account’s addresses from the ganache. We will use the first account address as our account.

Deploy the Smart Contract

Let’s get familiar with our simple smart-contract. We have declared myNumber as a publicly accessible unsigned integer.

We have created a function setMyNumber() which allows us to change that number after the deployment. We will be able to set the number as we desire. So itโ€™s a straightforward one. Just a couple of lines. Now let’s deploy the contract.

To deploy the contract, we need to create a migration file under the migration folder, the same as 1_initial_migration.js. Let’s name it 2_twist_migration.js. Now create a copy of the “1_initial_migrations.json” file and replace the “migrations” word with our contract name “twist”.

Go back to the terminal and type

truffle migrate

truffle automatically understands which contracts to migrate. It will start deploying the 2nd one.

If the smart contract is deployed properly, you will see a “twist.json” file inside the build folder. That is actually the ABI or Application Binary Interface. This is simply a JSON format of our smart contract.

We will use this ABI to communicate with the smart contract.

But first, we need to create an instance of the abi inside the source folder so that the react app can locate the directory. There are several ways we can do it. But I will follow the easiest one: copy and paste the file inside the source folder.

Interact with the Smart Contract

Itโ€™s time to import the file to app.js from the directory.

import configuration from "./twist.json";

Now we can create an instance of the address and the ABI.

const contractAddress = configuration.networks["5777"].address;
const contractABI = configuration.abi;
const web3 = new Web3(Web3.givenProvider || "http://127.0.0.1:7545");
const contract = new web3.eth.Contract(contractABI, contractAddress);

We have just created a new instance of web3. web3.eth.contract is a method of the web3 that will allow us to interact with the deployed smart contract. It takes two parameters; contractABI and contractAddress.

๐Ÿ‘‰ Reference: https://web3js.readthedocs.io/en/v1.2.11/web3-eth.html

Since we have created an instance of our smart contract, we can now call different functions from the smart contracts.

Let’s call the setMyNumber() function from the smart contract. โ€œcontract.methodsโ€ will help us to call any functions or methods from the smart contract.

Set the myNumber as 10. The send() method is used to indicate the account from which the transaction will take place.

Now to check if the myNumber is set to 10, call myNumber variable of the smart contract from the onConnect function.

let theNumber = await contract.methods.myNumber().call();
console.log(theNumber);

Move to the browser and check the console. I hope you get the myNumber on the screen, which will be 10.

To display the number on the user interface, I will create a finalNumber state variable with the help of the useState hook of react.

const [finalNumber, setFinalNumber] = useState("");

Now just set theNumber as the finalNumber from the onConnect function.

setFinalNumber(theNumber);

We will create a heading with <h1> tag inside the return function to display the number on the user interface.

<h1>The number from the smart contract is : {finalNumber}</h1>

The finalNumber will be displayed as dynamic content on the UI.

If you refresh the page and hit the connect to Metamask button, the number from the smart contract will be displayed on the UI.

Change the number

Now suppose you want to change the myNumber integer of the smart contract. You can do it by calling the setMyNumber function from the contract again.

Letโ€™s call the function inside the onConnect function.

Or you can just change the input inside the setMyNumber() that we have previously declared as 10.

await contract.methods
        .setMyNumber(30)
        .send({ from: account });

We have set the new number as 30.

If you go back to the browser now and hit the “connect to metamask” button, Metamask will ask for permission to commit the transaction and the new number will be set as myNumber. Refresh the page again and connect to Metamask; the new number will be displayed on the user interface.

That was all for today. We have seen how to call functions or methods and fetch data from the smart contract by using web3. In the next part, we will do the same thing from the Remix IDE. Hope this will be an interesting one.

๐Ÿ‘‰ Recommended Tutorial: Learn to Build Smart Contracts in React with web3.js: Hereโ€™s How! (2/2)