Quote frontend
We will create a frontend to the smart contract Quote, used in last module.
Create the project
Create a folder named Quote, and start an npm project in the Quote folder by typing the following commands below into the terminal:
mkdir Quote
cd Quote
npm init -y
For example, I will create a folder at this location: C:\RSK\
My project can be located in the folder C:\RSK\Quote
.
Requirements on project
Some requirements must be installed directly in the project.
Express
Express is a Node.js web application framework that helps to develop web applications. It is a minimalist HTTP server.
To install Express, input the command below into the terminal and press enter
at your project location:
npm install -E express
The option -E is to save dependencies with an exact version rather than using npm's default.
More info:
Web3.js
The Web3.js library is an Ethereum Javascript API which connects using the generic JSON-RPC spec.
To install web3.js, input the command below into the terminal and press enter
at your project location:
npm install -E web3@1.3.6
Check package.json
package.json
is a file created by npm with some configurations, including the packages which we installed before using the command npm init -y
.
After the installations, I will open the project folder in VSCode and verify the file package.json. Let's take a look at the dependencies in the file:
You will find the previously installed packages:
"dependencies": {"express": "4.17.1","web3": "1.3.6"}
Client-Side Application - The front end
Now let's start building out the front end that will interact with the smart contract.
We have only 2 files in the front end:
- index.html
- index.js
index.html
In Quote folder, create a file named index.html.
Copy and paste the code below:
<!DOCTYPE html><html><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Quote</title><linkhref="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"type="text/css"/><script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script><script src="./node_modules/web3/dist/web3.min.js"></script><script src="./index.js"></script></head><body class="container"><h1 class="page-header">Quote dApp</h1><br /><h2><label id="lastInfo"></label></h2><h3>Set quote</h3><form id="form" class="form-inline" role="form"><input class="form-control" id="input" type="text" /><input type="submit" class="btn btn-primary" value="Set quote" /></form></body></html>
index.js
In Quote folder, create a file named index.js.
Copy and paste the code below:
// Web3const getWeb3 = () => {return new Promise((resolve, reject) => {window.addEventListener('load', async () => {if (window.ethereum) {const web3 = new Web3(window.ethereum)try {// ask user permission to access his accountsawait window.ethereum.request({ method: 'eth_requestAccounts' })resolve(web3)} catch (error) {reject(error)}} else {reject('MetaMask is NOT installed')}})})}const contractAddress = '0xF2FD988A92484ff16Edd5BD9DAbE5eb809c5B3Dd'const abi = JSON.parse('[ { "inputs": [ { "internalType": "address", "name": "_member", "type": "address" } ], "name": "addMember", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_member", "type": "address" } ], "name": "delMember", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "_message", "type": "string" } ], "name": "setQuote", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "getQuote", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], "name": "whiteList", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" } ]',)// Contractconst getContract = async web3 => {const quote = new web3.eth.Contract(abi, contractAddress)return quote}//Smart contract functionsconst getQuote = async (result, contract) => {result = await contract.methods.getQuote().call()document.getElementById('lastInfo').innerHTML = result}const setQuote = (result, contract, accounts) => {let input$('#input').on('change', e => {input = e.target.value})$('#form').on('submit', async e => {e.preventDefault()await contract.methods.setQuote(input).send({ from: accounts[0] })getQuote(result, contract)})}// Appasync function quoteApp() {const web3 = await getWeb3()const accounts = await web3.eth.getAccounts()const contract = await getContract(web3)let quotegetQuote(quote, contract)setQuote(quote, contract, accounts)}quoteApp()
Update index.js
Did you remember the address of the smart contract that you copied after deploying it?
Locate the line which start with const contractAddress = '...' (around line 21) and update it:
const contractAddress = '0xF2FD988A92484ff16Edd5BD9DAbE5eb809c5B3Dd'
HTML server
Also we need a HTML server to act like a provider for our dApp.
In the Quote folder, create a file named server.js.
const express = require('express')const app = express()app.use(express.static(__dirname))app.listen('3300')console.log('Running at\nhttp://localhost:3300')
This file configures the express HTML server.
Run Server
The last step is to execute the express server. Input the command below into the terminal.
node server.js
In your browser, go to:
http://localhost:3300
It you are using the Metamask web wallet, click on the Connect button when the Metamask pops up.
Interact with the smart contract
Set quote
Enter any message in the text field and click on the Set quote button.
The web3 instance will call the setQuote() function at the smart contract instance, with the message that you defined.
I will enter the message "Have a nice day".
Wait a few seconds for the transaction to be included in a block.
Get quote
The getQuote function is used internally, every time you load the app or change the message.
Probaly it you be update automaticaly, but, if not, you can reload the page.
Note
Remember that only an address which is in the whitelist can call the function setQuote().
The botton line
Congratulations!
You have successfully built and deployed your first decentralized application (DApp) powered by RSK smart contracts!