Interacting with Smart Contracts using Web3
Tags: webdev, javascript, blockchain, web3
Published: 2022-06-27 11:22:25

by [Chisom Uma](https://blog.openreplay.com/authors/chisom-uma)

Web3.js is a collection of libraries that make it easier to interact with the [Ethereum blockchain](https://www.blockchain.com/learning-portal/ether-basics). For example, it can be used to check if a given string is a valid Ethereum address, retrieve user accounts, send transactions, and make interacting with contracts much easier. In this article, we will look at how you can interact with the blockchain from your React web application using [Web3.js](https://web3js.readthedocs.io/en/v1.7.3/), a library that lets you interact with the blockchain efficiently.

## Creating our React app

Creating a React app project is pretty straightforward. All you have to do is go into your terminal and type in the following command:

```
npx create-react-app my-web3
```

Go into your device folder and open the newly created React app project on your code editor. Then, open your `App.js` file in your directory and edit the code to look like this.

```javascript
import React, {useEffect} from 'react';
import Web3 from 'web3'

function App() {
  useEffect(() => {
    
}, []);
  return <div className='App'></div>;
}
export default App;
```

Then go ahead and run the following command in your terminal, to install Web3.

```
npm install web3 --save
```

## Ethereum nodes and providers

Let's look at how you can pass in a provider URL, which will be a link to your Ethereum node. 

```javascript
function App() {
  const providerUrl = process.env.PROVIDER_URL;

  useEffect(() => {
    const web3 = new Web3(providerUrl)
}, []);
  return <div className='App'></div>;
```

This node is your gateway to the rest of the network. But not to worry, you won't need to set up your own node and host it on something like AWS. Luckily, there are many services, such as [Infura](https://infura.io/) or [Alchemy](https://www.alchemy.com/), that already do all that. All you need is a link from them, to paste in `providerUrl`.

## Deploying Smart Contracts to Blockchain

For this article, you will have your own smart contract that you will deploy using [Truffle](https://trufflesuite.com/docs/truffle/). In this tutorial, we have a straightforward [NFT](https://en.wikipedia.org/wiki/Non-fungible_token) smart contract.


![1](https://blog.openreplay.com/static/3c9cf6e308c4b6f6cbc582a2555a1390/79ee7/image01.png)


This will be deployed to the local [Ganache](https://trufflesuite.com/docs/ganache/) instance, a local blockchain that you can use for testing purposes. So, go to your terminal and run this command:

```
npx ganache-cli
```

Once you run the command, you should be able to see something like this on your terminal.

![2](https://blog.openreplay.com/static/d5c886d7f06bc0e2c8e928468b670622/d21f0/image02.png)

Now let's deploy the contract. To do this, go to your terminal and run these commands, so Truffle will compile the contracts.

```
truffle init
npx truffle migrate
```

## How the user interacts with your dApp

The thing with [dApps](https://www.techtarget.com/iotagenda/definition/blockchain-dApp) (decentralized applications) is that your users will need a wallet to sign the transactions, and the most popular wallet of all is, of course, [Metamask](https://metamask.io/). If your users are already familiar with crypto and the blockchain space, they probably already have installed Metamask as a Chrome extension. To follow this tutorial, you should also have it installed. (If your users are unfamiliar with crypto and blockchain, they can use other services such as [Fortmatic](https://fortmatic.com/); they will give your users a wallet without installing anything.) In this article, I will only be showing you how to integrate Metamask, but steps for other wallets should be pretty similar.

Metamask injects itself into the browser, so when you make any transactions or calls, you will be dealing with Metamask itself, not with your provider. Metamask also uses Infura in the background, but you will not be interacting directly with them, and you will be dealing with Metamask or the wallet service you are using. We are going to look at how we can integrate Metamask. If you haven't already done so, you can download the Metamask extension [here](https://metamask.io/download/). 

```javascript
useEffect(() => {
  const web3 = new Web3(providerUrl)  
  
  let provider = window.ethereum;

  if (typeof provider !== 'undefined') {
      //Metamask is installed
  provider
  .request({method: 'eth_requestAccounts' })
  .then((accounts) => {
    console.log(accounts);
  })
  .catch((err) => {
    console.log(err);
  });
  }
}, []);
```    

Here we check if Metamask is installed using `let provider = window.ethereum;`. We then asked the user to connect their [wallet](https://www.investopedia.com/terms/b/bitcoin-wallet.asp) to the website by sending a `.request` to the `provider` to gain access to the user's account. If you save and run this using the `npm start` command, you should be able to get something like this.

![3](https://blog.openreplay.com/953cd721eabe420e6910f1a3756388be/image03.gif)

You can also listen to Metamask account changes by adding an event listener.

```javascript
provider
    .request({method: 'eth_requestAccounts' })
    .then((accounts) => {
      console.log(accounts);
    })
    .catch((err) => {
      console.log(err);
    });
    window.ethereum.on('accountsChanged', function (accounts) {
      console.log(accounts);
    });
    }
    const web3 = new Web3(provider);
  }, []);

Once you save this, go to your browser console and open your Metamask. Change your wallet account, and you should be able to see that there is another output on the console, as shown below.

![4](https://blog.openreplay.com/43232b3b48ae08f4a3620f46e560a7cc/image04.gif)


So, with a few lines of code, we have linked Metamask and can now start interacting with smart contracts. But first, we need to do some tidying up because this code isn't very reusable. So, we create a new file in our `src` folder titled `Web3Client.js` and edit it to look like this.

```javascript
import Web3 from 'web3'

let selectedAccount;

export const init = () => {
    let provider = window.ethereum;

    if (typeof provider !== 'undefined') {
    
    provider
    .request({method: 'eth_requestAccounts' })
    .then((accounts) => {
      selectedAccount = accounts[0];
      console.log(`Selected account is ${selectedAccount}`);
    })
    .catch((err) => {
      console.log(err);
    });
    window.ethereum.on('accountsChanged', function (accounts){
      selectedAccount = accounts[0];
      console.log(`Selected account changed to ${selectedAccount}`);
    });
  }
  const web3 = new Web3(provider);
};
```

Then edit the `App.js` file to look like this.

```javascript
import React, { useEffect } from 'react';
import {init} from './Web3Client';

function App() {
  
  useEffect(() => {
    init();
  }, []);

  return <div className='App'></div>;
}
export default App;
```    

Rerun the code, and you will still get the same results.

## Adding a Smart Contract to your Web app

We will now look at how we can define the [smart contract](https://www.investopedia.com/terms/s/smart-contracts.asp#:~:text=A%20smart%20contract%20is%20a,a%20distributed%2C%20decentralized%20blockchain%20network.).

```javascript
import Web3 from 'web3'
import NFTContractBuild from '../truffle/build/contracts/NFT.json';
let selectedAccount;

export const init = async () => {
    let provider = window.ethereum;

    if (typeof provider !== 'undefined') {
    
    provider
    .request({method: 'eth_requestAccounts' })
    .then((accounts) => {
      selectedAccount = accounts[0];
      console.log(`Selected account is ${selectedAccount}`);
    })
    .catch((err) => {
      console.log(err);
    });
    window.ethereum.on('accountsChanged', function (accounts){
      selectedAccount = accounts[0];
      console.log(`Selected account changed to ${selectedAccount}`);
    });
  }
  const web3 = new Web3(provider);
  const networkId = await web3.eth.net.getId();
  const nftContract = new web3.eth.Contract(NFTContractBuild.abi,NFTContractBuild.networks[networkId].address
  );
};
```

You will probably get this error when you try to run this code.

![5](https://blog.openreplay.com/static/f82db047e3efea48d27445fec4120845/34b6e/image05.png)

If you used the `create-react-app` to create your own application, then all you need to do is go into your dependencies for React, and add a new dependency, as shown in the example below.

![6](https://blog.openreplay.com/static/5e26e71901cc5fe0f89509a660e0e91c/4a9ff/image06.png)

As you can see, `"contracts": "file:./truffle/build/contracts"` was added to the dependencies. Next, enter the command `npm i' to install the dependency. Now we can do different things with the NFT contract. For this article, we will only use the smart contract to make a transaction (mint a token).


## Open Source Session Replay

_[OpenReplay](https://github.com/openreplay/openreplay) is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._

![replayer.png](https://static.openreplay.com/images/banner-blog.png)

_Start enjoying your debugging experience - [start using OpenReplay for free](https://github.com/openreplay/openreplay)._



## Making a transaction

Let's take a look at how we can make a transaction.

```javascript
import Web3 from 'web3'
import NFTContractBuild from '../truffle/build/contracts/NFT.json';

let selectedAccount;
let nftContract;
let isInitialized = false;

export const init = async () => {
    let provider = window.ethereum;

    if (typeof provider !== 'undefined') {
    
    provider
    .request({method: 'eth_requestAccounts' })
    .then((accounts) => {
      selectedAccount = accounts[0];
      console.log(`Selected account is ${selectedAccount}`);
    })
    .catch((err) => {
      console.log(err);
      return;
    });
    window.ethereum.on('accountsChanged', function (accounts){
      selectedAccount = accounts[0];
      console.log(`Selected account changed to ${selectedAccount}`);
    });
  }
  const web3 = new Web3(provider);
  const networkId = await web3.eth.net.getId();
  nftContract = new web3.eth.Contract(NFTContractBuild.abi,NFTContractBuild.networks[networkId].address
  );
  isInitialized = true;
};

export const mintToken async = () => {
  if (!isInitialized) {
    await init();
}
  return nftContract.methods
    .mint(selectedAccount)
    .send({from: selectedAccount})
}
```

Here, what we did is [mint](https://corporatefinanceinstitute.com/resources/knowledge/data-analysis/minting-crypto/) a new token. Now, let's go back into our `App.js` component and make more changes.

```javascript
import React, { useEffect } from 'react';
import {init, mintToken} from './Web3Client';

function App() {
  const [minted, setMinted] = useState(false);
  const mint = () => {
    mintToken().then(tx => {
    console.log(tx);
    setMinted(true);
    }).catch(err => {
    console.log(err);
    });
}
  return <div className='App'>
    {!minted ? (
        <button onClick={() => mint()}>Mint Token</button>
        ):(
        <p>Token minted successfully!</p>
        )}
        </div>
      );
}
export default App;
```

We created a button that says "Mint token" if no token is minted, then a paragraph that says "Token minted successfully" if a token is already minted. Then we imported `mintToken` from our `./Web3Client` file. We also `setMinted` to `true`. Once you rerun the code, click on Mint token, and you should see something like this.


![7](https://blog.openreplay.com/static/6584d7f579ae119148603cf9ce60b4d6/8f459/image07.png)

Metamask will now pop up and ask us to approve and send the transaction. However, we do not have any [ether](https://ethereum.org/en/eth/) to pay the [gas fee](https://www.investopedia.com/terms/g/gas-ethereum.asp). So, let's go back to our terminal, run the `npx ganache-cli` command again, and find and copy the private key.

![8](https://blog.openreplay.com/static/498fcadf7fcb523181877446a6e3b6a1/c8356/image08.png)

Head back to your Metamask, click on Import Account, and paste.

![9](https://blog.openreplay.com/static/b64ff0e7aa73a438b4c628a3ee3a10f0/ff011/image09.png)

Click on import.

![10](https://blog.openreplay.com/static/071984f364c2f39c54f76e6b339558d3/2f9ba/image10.png)

You should now be able to see this.

![11](https://blog.openreplay.com/static/f180a3bfa979673f485a8b23d305c388/df43e/image11.png)

Note that this is not real Ethereum, and it appears this way because when you run the `ganache` command, it will automatically generate some ether, 100 by default. Click on confirm.

![12](https://blog.openreplay.com/static/29c57580e18bc12dd9ef96c164a5f8cc/db1b4/image12.png)

You should see this.

![13](https://blog.openreplay.com/static/197810206f82d3dd6a3083fc50aed4c0/30f8e/image13.png)

So, that's it!

## Conclusion

In this article, we looked at how we can use web3.js to interact with smart contracts, especially with the Ethereum smart contract. We also looked at how users interact with the dApp (decentralized applications) and how transactions can be made.

Here is the link to the complete code on my [GitHub](https://github.com/ChisomUma/Web3-tutorial).

[![newsletter](../newsletter.png)](https://newsletter.openreplay.com/)