How To Connect A Smart Contract To Front-End
Deploying and Interacting with Smart Contracts
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.
Obtain your crypto wallet private key, save for later.
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.
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!