How to connect smart contracts to frontends
Chimaobi is an enthusiastic blockchain developer and an engineering undergrad. He's passionate about building the next iteration of the internet and building in the web3 space.
A smart contract is a self-executing code that allows for the automated transfer of digital assets between parties without the need for intermediaries. These contracts are stored on the blockchain and can be accessed by anyone with the required permissions. To interact with a smart contract, a frontend is required. This article will look at how to connect a smart contract to a frontend using a sample code.
Before we start, we need to understand the tools and technologies we will be using. We will use Solidity as the programming language to write our smart contract, and the Ethereum network to deploy and execute the contract. We will use React as the framework for the frontend to build our user interface.
Let's write a simple, smart contract to store and retrieve a single string value.
pragma solidity ^0.8.0;
contract SimpleStorage {
string private _value;
function setValue(string memory value) public {
_value = value;
}
function getValue() public view returns (string memory) {
return _value;
}
}
// SimpleStorage.sol
This contract has two functions: setValue and getValue. The setValue function allows the user to set a string value, while the getValue function retrieves the string value that was previously set.
Let's compile and deploy this smart contract to the Ethereum network. We will use Remix, a web-based Solidity IDE, to compile and deploy the contract. Once the contract is deployed, we will get a contract address that we can use to interact with the contract.
With the contract deployed, we can now start building our frontend. We will be using React to build a simple web interface allowing the user to set and get the string value.
First, let's create a new React project using create-react-app.
create-react-app simple-storage
To interact with a smart contract from a frontend, we will use a JavaScript library called ethers.js. Ethers.js is a powerful library that provides a simple and easy-to-use interface for working with Ethereum and other blockchain networks. With ethers.js, we can connect to a blockchain network, interface with smart contracts, and send transactions to the blockchain. It includes features such as a wallet, contract deployment, and interaction with smart contracts. In this example, we'll use it to interact with a simple storage contract.
Next, let's install the required dependencies:
npm install ethers
npm install dotenv
The ethers package is the main library we'll be using, and dotenv is a package that lets us load environment variables from a .env file.
Once we have our dependencies installed, let's create a .env file and add the following:
REACT_APP_CONTRACT_ADDRESS=<your_contract_address>
REACT_APP_INFURA_PROJECT_ID=<your_infura_project_id>
// Enter your private key (with the '0x' prefix)
REACT_APP_PRIVATE_KEY=<your_private_key>
Replace <your_contract_address> with the address of your deployed contract, <your_infura_project_id> with your Infura project ID, and <your_private_key> with your private key.
Next, let's create a new file called SimpleStorage.js. In this file, we'll create a simple React component that allows the user to set and get the value stored in our smart contract.
// SimpleStorage.js
import React, { useState } from "react";
import { ethers } from "ethers";
import dotenv from "dotenv";
dotenv.config();
const contractAddress = process.env.REACT_APP_CONTRACT_ADDRESS;
const infuraProjectId = process.env.REACT_APP_INFURA_PROJECT_ID;
const privateKey = process.env.REACT_APP_PRIVATE_KEY;
const abi = [
{
"inputs": [],
"name": "getValue",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "value",
"type": "string"
}
],
"name": "setValue",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
const SimpleStorage = () => {
const [value, setValue] = useState("");
const handleSetValue = async () => {
try {
const provider = new ethers.providers.InfuraProvider("goerli", infuraProjectId);
const wallet = new ethers.Wallet(privateKey, provider);
const contract = new ethers.Contract(contractAddress, abi, wallet);
await contract.setValue(value);
} catch (err) {
console.error(err);
}
};
const handleGetValue = async () => {
try {
const provider = new ethers.providers.InfuraProvider("goerli", infuraProjectId);
const contract = new ethers.Contract(contractAddress, abi, provider);
const result = await contract.getValue();
setValue(result);
} catch (err) {
console.error(err);
}
};
return (
<div>
<h1>Simple Storage</h1>
<input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
<button onClick={handleSetValue}>Set Value</button>
<button onClick={handleGetValue}>Get Value</button>
<p>Value: {value}</p>
</div>
);
};
export default SimpleStorage;
This code first imports the required packages and loads our environment variables from the .env file. We then create a new React component that initializes the state with an empty string.
The handleSetValue function is called when the user clicks the "Set Value" button. In this function, we first create an ethers provider and wallet using our Infura project ID and private key. We then create a new contract instance using the contract address and ABI.
Once we have our contract instance, we can call the setValue function on the contract, passing in the value from our state. This updates the value stored in the contract on the blockchain.
The handleGetValue function is called when the user clicks the "Get Value" button. In this function, we create a new contract instance using the contract address and ABI, and then call the getValue function on the contract. This retrieves the current value stored in the contract on the blockchain, and updates our state with that value.
Finally, we return a JSX template that displays the current value and provides input fields and buttons for the user to interact with the contract.
Now that we have our component, we can add it to our main App.js file and render it on the page:
javascriptCopy code// App.js
import SimpleStorage from "./SimpleStorage";
function App() {
return (
<div>
<SimpleStorage />
</div>
);
}
export default App;
And that's it! We've successfully connected our smart contract to our frontend using ethers.js.
In summary, ethers.js is a powerful library that provides a simple and easy-to-use interface for interacting with the Ethereum network. By following the steps outlined in this article, you can easily connect your smart contracts to your frontend and build powerful decentralized applications.

