How I Built My Own ERC-20 Token (2/2)

In the first part, we connected the front end with Metamask but couldn’t fetch the balance. Let’s try to fetch the balance from the wallet this time. But first, install the ether.js library to communicate with the smart contract.

npm install --save ethers

Import ether.js library to App.js.

import {ethers} from "ethers";

Now we need to import the contract ABI.

💡 The contract ABI is the JSON format of the contract that saves the bytecode of the deployed contract.

Create a contracts folder inside the source folder. Inside this contracts folder, create a JSON file called SilverToken.json.

Copy the ABI of the contract from the Remix IDE and paste it inside the JSON file. Now import the ABI from the JSON file to the app.js.

import contractABI from "./contracts/SilverToken.json";

Create a variable for the contract address.

const contractAddress = "0xC16322799f2645D5b7a1287392072aA668F8144B";

We need to create a contract instance to get access to the methods of our deployed smart contract. We need three things to create an instance of the contract. Those are the provider, signer, and contract ABI.

We already imported the ABI. So, let’s create state variables for the provider, signer, and contract and initially keep all the values null.

const [provider, setProvider] = useState(null);
const [signer, setSigner] = useState(null);
const [contract, setContract] = useState(null);

Inside the connectMetamask button define provider, signer, and contract.

const provider = new Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(

We defined the provider with the help of the Web3Provider method of the ethers library. In our case, the provider would be Metamask.

I was unable to access the providers library of ethers for some unknown reason. That’s why I imported the providers library from the npm Ethereum providers. You can use this link if you need it.

First, install and then import the providers library.

npm i @ethersproject/providers

since we will use the Web3Provider from the providers library, we will import this only.

import { Web3Provider } from "@ethersproject/providers";

We are committing a transaction, so we must need a signer. We called the signer by using the getSigner() method of the provider.

Then we created an instance of our smart contract with the contract() method of the ethers library.

This contract() method takes the contract address, ABI, and the signer as the parameters.

Now the provider, signer, and contract are defined. So, we need to change the state of these three that we have defined as null earlier.

Now let’s console.log the contract to check if all changes occurred.


As you can see in my console, the contract’s state was initially null. But now it returns the contract address that we are connected to.

Get Wallet Balance

Create a getBalance() method to get the balance from the address.

  const getBalance = async () => {
    const balanceInBig = await contract.balanceOf(activeAccount);
    const balanceInNum = Number(balanceInBig) / 100;

We are using the balanceOf method of the contract to get the balance of our address. The balance will be returned as a bigInteger number. Read more about BigInt here.

In the 2nd line, we converted the big integer number to a readable format.

To initiate the getBalance() function, we can use React‘s useEffect() hook.

useEffect(() => {
    if (contract != null) {
  }, [contract]);

The useEffect() hook will trigger the getBalance method if a contract is available. The useEffect() hook will render the page again whenever the contract is changed.

Transfer the Balance

Now to transfer the balance, we need a form where we will input the address of the account to which we will be transferring the amount. Let’s do this part in a separate functional component.

Let’s create a components folder inside the source folder and create a new file called Transaction.js.

Inside this file, create a component structure by pressing “rsc” on the keyboard. If the autocompletion doesn’t work, no need to worry. Write the code manually.

I will create a simple form using custom codes from flowbite. You can check it out or make your own custom one. Inside the return function, paste the following.

  return (
    <div className="w-1/2 mx-auto bg-slate-600 mt-10 p-5 border rounded-lg">
      <form onSubmit={transactionHandler}>
        <div className="mb-6">
            className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
            Receiver Address
            className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            placeholder="Enter Receiver Address"
        <div className="mb-6">
            className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
            Transfer Amount
            className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
          className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
          Send Token
        <div className="mt-5">
          <h3 className="text-slate-100">{transactionHash}</h3>

We created two input fields inside the form. One is text type for the receiver address, and another is a number type for the amount that would be sent to the receiver.

The id of each input filed is changed to “address” and “amount” respectively.

A transactionHandler() function will be triggered whenever you click on the send button. This function will collect the info from the input fields and do something further.

Let’s define the transactionHandler() function.

const transactionHandler = async (event) => {
    let receiverAddress =;
    let sendAmount =;
    let transferAmount = sendAmount * 100;
    let trans = await contract.transfer(receiverAddress, transferAmount);
    setTransactionHash("Transaction confirmed with hash:" + trans.hash);

The transactionHandler() is an async await function that will trigger an event. The preventDefault() method will prevent the function from reloading automatically for changes.

The transferAmount and receiverAddress variables will collect the info from the input fields. “” will access the input fields by using the id of the input field “amount” and “address.”

We need to use the transfer method of the contract to commit the transaction. To access the contract state, we need to pass it as a prop from the app.js file.

Call the transaction.js component from the app.js file and pass the contract as props.

<Transaction contract={contract}></Transaction>

We are using the “contract.transfer” method to commit the transaction. This method will take the receiver address and the send amount as parameters.

We will get a transaction hash as a transfer confirmation when the transaction is done. We can store this transaction hash as a state variable to display it on the user interface.

Let’s create a new account on the Goerli testnet. This will be our receiver account.

Now use this address and send an amount of 50 tokens from the main wallet. We need to multiply the amount by 100 to get the exact value, as we used a two-digit return in the decimals function of the smart contract.

Now if you check this transaction hash on the Etherscan website, you will get the complete transaction details. You will also receive the token balance on the Metamask receiver wallet.

This is the screenshot of my recent transaction. To get your transaction details, just use the transaction hash in the search bar. Make sure you choose the Goerli testnet as the network.

Thanks for reading! ♥️

👉 Github: