How to design back-end and front-end DApp on POSIChain (Part II)

Doris Position
Position Exchange
Published in
5 min readDec 3, 2022

Design front-end DApp

Components of a dApp

The components of a dApp can be split into three different categories: smart contracts, the front-end logic and user interface, and data storage.

  • Smart Contracts: Smart contracts store the business logic for a dApp along with the state of the application. This is the biggest difference between a dApp and a traditional web application, and what gives a dApp all the benefits mentioned above.
  • Frontend/User Interface: While the backend logic of a dApp requires a developer to write smart contract code to be deployed on a blockchain, the frontend or client side of a dApp can use standard web technologies such as HTML and JavaScript. This allows developers to use familiar tools, libraries, and frameworks. The client-side user interface is usually linked to the smart contracts via client-side libraries such as Web3.js or Ethers.js, which are bundled with the frontend resources and sent to the browser together with the UI. Interactions with smart contracts such as signing messages and sending transactions to the smart contracts are usually conducted via a browser-based Web3 wallet, such as MetaMask.
  • Data Storage: Most applications need to store data, but due to the distributed nature of blockchains, storing large amounts of data on-chain is not feasible, and can get very expensive. This is why many dApps that need to store data make use of off-chain data storage services such as IPFS or Filecoin, leaving the blockchain to store crucial business logic and state only. You can also use traditional cloud-based storage services. However, many developers choose decentralized options to maintain and extend the trust-minimized properties that a blockchain-powered dApp provides.

Creating the Frontend Application

The frontend logic and user interface of your dApp can be built using a wide variety of different frameworks.

React is one of the most popular JavaScript libraries for building feature-rich web user interfaces, and is therefore used by a lot of Web3 dApps. In addition to this, Ethers.js is a JavaScript library for connecting to and interacting with EVM-based blockchains and smart contracts. When you combine the two, you have a sensible starting point for building out the frontend of your dApp.

In this section, we’ll create a new React application (ChainLink Dapp Price-Feeds) to fetch the last price from ChainLink ( you can read more about ChainLink price feed here) using the create-react-app boilerplate generator. Then we’ll introduce some off-chain logic that uses Ethers.js to connect the user interface with the deployed smart contract, giving us a full end-to-end dApp.

Creating the React Application:

The first step for creating the frontend is to install and implement the create-react-app boilerplate project, then modify it to suit our dApp. The first step is to install the library into a new “frontend” folder:

cd .. 
npx create-react-app frontend

Once this has completed, you should see a new “frontend” folder in your project with all the associated React code. Expand the “frontend” folder and perform the following actions:

  • Delete /src/setupTests.js
  • Delete /src/ReportWebVitals.js
  • Delete /src/logo.svg
  • Delete /src/App.test.js
  • Delete /src/App.css

We’re now almost ready to start modifying the React application code. But first, be sure to install the libraries for Bootstrap and Ethers.js. Bootstrap is a popular frontend CSS framework that comes with React-friendly UI widgets with CSS styling applied, while Ethers.js allows us to connect our front-end to deployed smart contracts on the blockchain. Ensure these commands are run from within the “frontend” folder.

cd frontend 
npm install bootstrap
npm install ethers

Now we’re ready to modify the React application code. Open up the App.js file in the /src/ folder and remove the contents. We will start building it from scratch.

The first step is to tell the application we want to use React (including useEffect and useState libraries) and Ethers.js:

import React, { useEffect, useState } from 'react'; 
import { ethers } from "ethers";

Next, create a function called “App” and export it:

function App() { } 
export default App;

Now we’ll start filling out the contents of the “App” function. Add the following code to it. The code does the following:

  • Set up the storedPrice and setStoresPrice react hooks.
  • Creates a connection to your MetaMask Web3 wallet.
  • Sets the deployed smart contract address and ABI. Both are required by Ethers.js for us to interact with the deployed smart contract.
  • The smart contract address can be obtained from the deployment step earlier in this guide. Plug this value in place of the REPLACE_WITH_DEPLOYED_CONTRACT_ADDRESS string.
  • The smart contract ABI can be obtained from the /backend/artifacts/contracts/PriceConsumerV3.json file, in the abi element. You can use a code minifier to format it in a better way for storing in your application.
const [storedPrice, setStoredPrice] = useState(''); 
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner();
const contractAddress = <REPLACE_WITH_DEPLOYED_CONTRACT_ADDRESS>''; const ABI = '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"getLatestPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"storeLatestPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]';
const contract = new ethers.Contract(contractAddress, ABI, signer);

Now we’ll create two functions to be used in our application:

  • getStoredPrice will connect to the deployed smart contract and obtain the current value of the storedPrice() getter function.
  • setNewPrice will call the deployed smart contract’s storeLatestPrice function, wait for the transaction to complete, then call the getStoredPrice function to retrieve the stored price in the smart contract.

We’ll also add a call to getStoredPrice in our App function so that it will initially call the getter function on page load:

const getStoredPrice = async () => {
try {
const contractPrice = await contract.storedPrice();
setStoredPrice(parseInt(contractPrice) / 100000000);

} catch (error) {
console.log("getStoredPrice Error: ", error);
}
}
async function updateNewPrice() {
try {
const transaction = await contract.storeLatestPrice();
await transaction.wait();
await getStoredPrice();
} catch (error) {
console.log("updateNewPrice Error: ", error);
}
}
getStoredPrice()
.catch(console.error)

The final step in creating the frontend is for your application to return the JSX code for the browser to render. Paste in the following code at the bottom of your App function, under the getStorePrice() call. This code does the following:

  • Returns a simple two-column grid layout.
  • The first column contains the currently stored ETH/USD price in the smart contract.
  • The second column contains a button that the user can use to interact with the smart contract and update the stored price. Pressing the button calls the setNewPrice function above.
return (
<div className="container">
<div className="row mt-5">
<div className="col">
<h3>Stored Price</h3>
<p>Stored ETH/USD Price: {storedPrice}</p>
</div>
<div className="col">
<h3>Update Price</h3>
<button type="submit" className="btn btn-dark"
onClick={updateNewPrice}>Update</button>
</div>
</div>
</div>
);

Your application is now ready. If required, you can compare your code to the completed example to ensure you’ve done everything correctly. Now you’re ready to run your dApp.

Running Your dApp

After ensuring you have all the files saved, start your dApp locally by running the following command from the frontend folder:

npm run start

After the application loads, a new window should appear in your browser displaying your dApp user interface. You should also receive a popup notification from MetaMask asking you to connect your wallet to the application.

--

--