How To Connect A Smart Contract To Front-End

Deploying and Interacting with Smart Contracts

How To Connect A Smart Contract To Front-End

This article will showcase how to deploy a smart-contract on the rinkeby network.

Tools Needed

hardhat: Development environment used to test, compile, and deploy smart-contracts. Alchemy: Acts as the middleman, helping developers build on top of blockchains.

Before getting started, set up a alchemy account and create a project on the rinkeby network.

Save the https URL for later, we will need it.

AlchemyKey.PNG

Obtain your crypto wallet private key, save for later.

MetamaskPrivateKey.PNG

Installation:

In a folder make a directory called "hardhat-tutorial": Run these commands below.

npm init --yes 
npm install --save-dev hardhat

Then run in terminal to create project.

npx hardhat

If using a windows operating system, do the the following command below. Other wise don't.

npm install -save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers

Navigate to your contracts sub directory and create a file called test.sol

pragma solidity ^0.8.4;
contract simpleContract{ 

uint256 public value;
emit ValueChanged(uint256 newValue);

function setValue(string newValue) public {
value = newValue;
emit ValueChange(newValue);

 }
function retrieve()  public view returns(uint256) { 
return value; 
}

}

In your terminal write command

npx hardhat compile

To compile and save the contracts.

Next, navigate to the scripts file sub-directory in your hardhat-tutorial folder Create a file called deploy.js. Copy and paste below.

const {ethers} = require("hardhat");

async function main() { 

    const greeter = await ethers.getContractFactory("simpleContract"); 
    const deployContract = await greeter .deploy();

    console.log(
        "Greeter address located at",
        deployContract.address
    );
};

main()
    .then(() => process.exit(0))
    .catch((error) => { 
        console.error(error)
        process.exit(1)
    })

Proceed, navigate to your hardhat.config.ts file. Within that file you'll see..

module.exports = {
  solidity: "0.8.4"
  }
};

Using the alchemy key and private key we obtained earlier add update the previous code.

module.exports = {
  solidity: "0.8.4",
  networks: {
    rinkeby: {
      url: ALCHEMY_API_KEY_URL, 
      accounts: [RINKEBY_PRIVATE_KEY],
    }
  }
};

Run the following command in your terminal.

npx hardhat run scripts/deploy.js --network rinkeby

Output should be the following.

AddresSaved.PNG

Save the address for later.

Navigate to your artifacts directory, in the contracts sub-directory their would be a file called simpleContract.json

You're going to want to copy and save the abi array for later.

 "abi": [
    {
      "inputs": [],
      "name": "retrieve",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newValue",
          "type": "uint256"
        }
      ],
      "name": "setValue",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "value",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],

Congratulations you just coded your first smart-contract!(maybe not -_-) Now! lets connect this the front-end

Dependencies

nodeJs web3modal ethers web3

Create a folder called hardhatTutorial-FrontEnd.

In the terminal, type the following commands.

npx create-next-app@latest

In your my-app folder, type the following commands in the terminal.

npm install --save-dev ethers web3 web3modal@latest

In your my-app next folder, create a directory called constants in that directory create a file called index.js

Paste the following code(update it with your deployed address and abi)

export const ADDRESS = "0x461097859cF2539f148557556F033CE2B19444A5"
 export const ABI =  [
    {
      "inputs": [],
      "name": "retrieve",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newValue",
          "type": "uint256"
        }
      ],
      "name": "setValue",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "value",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ]

Lets set up the front-end connections

In your pages directory, in the sub-directory index.js paste the following code.

import {useState, useRef, useEffect} from 'react';
import {Contract, ethers, providers, signers, utils} from 'ethers'
import Web3 from 'web3';
import Web3modal from 'web3modal';
import { ADDRESS, ABI } from '../constants';

Let's check for some state changes

  const [isConnected, setIsConncted] = useState(false); 
  const [loading, setLoading] = useState(false); 
  const [numberValue,setNumberValue ]= useState(0);

Here we will create a function getProviderOrSigner to get access to ethereum blockchain and/or metamask.

 const getProviderOrSigner = async(needSigner = false) => { 
    const provider = await web3modal.current.connect(); 
    const web3provider = new providers.Web3Provider(provider);
    //get access of signer 
    const signer =  web3provider.getSigner();



    //Make sure your connected to the Goreli network; 
    const {chainId} = await web3provider.getNetwork();
    if(chainId !== 6284) { 
      window.alert("You are on the wrong network");
    }

    if(needSigner) { 
      const signer = web3provider.getSigner();
      return signer;
    }
    return web3provider;

  }

Here we will create a connect function that will run onload of webpage.

  const Connect = async() => { 
    await getProviderOrSigner();
    setIsConncted(true);
  };

So it will load on webpage, lets add it to a useEffect hook.

  useEffect(() => { 
    if(!isConnected) { }
    web3modalref.current = new Web3modal( { 
      network: "Goerli",
      providerOptions: {},
      disableInjectedProvider: false
    })
    Connect();
  })

Okay, lets create the retrieve function.

 const retrieveValue= async() => {
    try { 
      const provider  = await getProviderOrSigner();
      const contract = new Contract(ADDRESS, ABI, provider);

      //lets get retrieve the value 
      const tx = await contract.retrieve();
      //Convert the tx from a Big Number to a string.
      console.log(tx.toString())
    }catch(err) { 
      console.log(err);
    }


  }

When create a new Contract the order must be address, abi, provider/signer

Lets create the set function

const set = async(e) => { 
    try { 
      const signer = await getProviderOrSigner(true);
      const contract = new Contract(ADDRESS, ABI, signer); 
      //call the contract
      const tx = await contract.setValue(e);
      setLoading(true); 
      await tx.wait()
      setLoading(false);
      window.alert("This worked")
    }catch(err) { 
      console.error(err); 
    }


  }

We set the getProivderOrSigner to true because we are now writing to the blockchain for this transaction.

In our core app copy and paste below

  return (
    <div>
        <input
          type= "number"
          onChange = {e => setNumberValue(BigNumber.from(e.target.value))}
          >
          </input>
          <button onClick={() => set(numberValue)}>Set Number</button>
      <button onClick={retrieveValue}>Get Number</button>

    </div>
  )

Test the code and tell me how it works!!! I hope this helped!