Ethereum Dapp Crash Course: Make an ERC20 token faucet + Frontend
Tags: solidity, react, ethereum, dapp
Published: 2021-06-01 13:02:49

> Find all the source code for this project here [Link]( https://github.com/rvmelkonian/erc20-faucet-react)

Ethereum smart contract development has been possible to learn since 2016 or so. But how to actually make a full stack Decentralised Application on the other hand, a different story. 

This post was inspired by Nader Dabit's [amazing post on eth development](https://dev.to/dabit3/the-complete-guide-to-full-stack-ethereum-development-3j13)

## a brief history of Dapp-development 

Conflicting solidity versions, truffle, ganache, web3.js and testnet difficulties, with little written on frontend integration, or even basic design principles, made full-stack Dapp development a precarious endeavour. Whilst the tools above provided some amazing ways to get started in your dapp-dev journey (especially truffle!), two new members of the eth-dev metaverse have joined the party and made life much easier. 

**hardhat** and **ethers.js**

*...*

I'd say that in the last 6 -12 months it's now actually fun and not that hard to get a full stack decentralised application up and running without having all manner of errors riddle your terminal. And any errors you may encounter, I've found easy to solve. 

The Dapp development space is finding its feet and flourishing. We can expect this trend to strengthen and continue over the coming years.

###*If you like building bleeding edge tech, you're in the right place.* 

Before starting this crash course, I'd recommend having a good understanding of how ethereum works, smart contracts, transactions, gas fees and being familiar with javascript and react.

### By the end of this tutorial you will have 
- a working, live decentralised application on a sharable url connected to the Goreli testnet
- an understanding of the Dapp development framework and life cycle 
- an simple (but awesome) dapp
- your mind blown 

Let's get started!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oa3jwkbt3uz9ks5dqowv.png)


## our stack 

**react** - our client side front end 
**react-bootstrap** - fast css component styling 
**hardhat** - ethereum / solidity development environment
**ethers.js** - ethereum / web client library 

## other tools 

**remix** - an in-browser solidity development environment
**metamask** - our in-browser wallet which we will use to interact with our application
**openzeppelin contracts** a library of safe and audited smart contract solidity code
**chai** - a javascript assertion library for running tests
**waffle** - a library for smart contract testing  
**infura.io** - An IPFS API that will connect our application to a live testnet
**Goreli** - The live testnet we'll be using
**Github & Netlify** - To host our client side UI 

## how they fit together 

####[hardhat](https://hardhat.org/) development envrionment
hardhat allows to run a local blockchain to test our application in an isolated environment. It allows us to compile, deploy and test our solidity smart contracts without using a live network. There are also a whole bunch of useful [plugins](https://hardhat.org/plugins/) made for hardhat.

####[ethers.js](https://docs.ethers.io/v5/) 
a javascript library we'll be importing into our code. It allows our client side application to talk to the smart contracts that we'll be deploying onto the blockchain. It does this by generating JSON files containing ABI's which act as an interface between React and the smart contract. 

ABI is an ethereum native term and stands for *application binary interface*. It will basically allow us to call the smart contracts functions. 

It's important to mention here that the reason why we need ABI files is because ethereum uses the EVM, the Ethereum Virtual Machine, to read and write data to the blockchain via our smart contracts. Infact, when we compile our smart contract code, hard hat compiles it down to bytecode which is executed by the EVM. It's the lower level computation layer of the blockchain. 

####[react](https://reactjs.org/) 

a javascript framework created by facebook that allows websites to render html elements live within one page, enabling complex single page sites like twitter to run fast. It's recommended you have some experience with react before starting this crash course!

We'll be using the ethers.js libary in-conjunction with react. Its a powerful combo!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qshi3huu515wfq0w61q2.jpeg)


####[react-bootstrap](https://react-bootstrap.github.io/) 
a powerful library for react that allows us to use bootstrap in our react components. Using it also helps front end devs understand some useful design principles for react in general. 

Part of the benefit of using react is that we can connect our application to the react ecosystem, pulling in other technology that we may want to use in an effortless way.  

####[chai](https://www.chaijs.com/) & [waffle plugin](https://hardhat.org/plugins/nomiclabs-hardhat-waffle.html)

we'll be installing the hardhat waffle plugin which brings in a nice testing library 

##our Dapp - ERC20 token faucet

*Wait, what are we making again?* We're going to be making a simple sinlge page application that allows a user to receive 100 FCT, or faucet token.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s18nq53rfgb9unxh4ugt.png)

Faucet's are useful for getting fake testnet ether in our wallets to use in the development. However what if we want a faucet for our own token? 

If we're building any kind of Dapp, it might be useful to have a button that allows a user to receive some of our token, at least while we're still in development.  

We'll be using the [ERC20 token](https://en.bitcoinwiki.org/wiki/ERC20#:~:text=ERC20%20is%20the%20Ethereum%20token,Ethereum%20token%20has%20to%20implement.&text=The%20ERC20%20token%20standard%20describes,token%20contract%20has%20to%20implement.) standard for our token. 

We'll be adding one function to the smart contract called *faucet()* which will allow a user to receive 100 FCT.

The user will be able to : 
- Get 100 FCT
- Check their FCT balance 
- Send FCT to another address *(they can do this from within metamask wallet, but we'll be adding that functionality to our UI anyway)*

## let's get started 

####Prerequisites
- Node.JS installed
- Metamask wallet installed as an extension in your browser 
- You don't need any ETH at all to do this crash course.

#### setup and install dependencies 

create a boiler plate react app 

```
npx create-react-app react-token-faucet
```

cd into your project directory and install *hardhat* and *ethers.js*. You can use NPM or Yarn. In the same line we're also adding the waffle plugins. During this install you may see some NPM warnings, don't worry about those.  

```
npm install ethers hardhat @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers
```
now we install the react-bootstrap library 
```
npm install react-bootstrap bootstrap@4.6.0
```
and finally we're going to install the Open Zeppelin Lirbary
```
npm install @openzeppelin/contracts
```
open your project in your text editor of choice. You will see the default create-react-app folders. 

In your *package.json* file you will see all the dependencies that we installed. 

```javascript
{
  "name": "react-token-faucet",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@nomiclabs/hardhat-ethers": "^2.0.2",
    "@nomiclabs/hardhat-waffle": "^2.0.1",
    "@openzeppelin/contracts": "^4.1.0",
    "@testing-library/jest-dom": "^5.12.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "bootstrap": "^4.6.0",
    "chai": "^4.3.4",
    "ethereum-waffle": "^3.3.0",
    "ethers": "^5.2.0",
    "hardhat": "^2.3.0",
    "react": "^17.0.2",
    "react-bootstrap": "^1.6.0",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```
in */src* delete *App.Tests.js*, *logo.svg* and *setupTests.js*. We won't be using any of those files and we want to have a clean project. 

Back in your terminal now run and initialise a hardhat project, enter through the initialisation.

```
npx hardhat run
```
now add a .env file to your project 
```
touch .env
```
in your project root, you'll now see the hardhat folders and files added to our project, these are : 

**hardhat.config.js** - project configuration
**.gitignore** - github should not push
**/scripts/sample-script.js** - our deployer script
**/test/sample-test.js** - tests

We need to edit our *.gitignore* file and our *hardhat.config.js* file. 

**.gitignore**

This file contains a list of files that we do not want to push to github for security reasons. 

Open this file and add **.env** under #misc
```
# misc
.env
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
```

**hardhat.config.js**

this file contains all the information that hardhat needs to configure our project correctly. 

change your hardhat config file to: 

```javascript
require("@nomiclabs/hardhat-waffle");
require('dotenv').config()

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
  const accounts = await ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
 module.exports = {
  paths: {
    artifacts: './src/artifacts',
  },
  
  networks: {
    hardhat: {
      chainId: 1337
    },
  },
  solidity: "0.8.3"
};

```
line 2 will require there to be a .env present. 
The module.exports contains the bulk of information for hardhat to check. 

**artifacts** is where our ABI's will be contained when we compile and deploy or solidity code.

**networks** contains information that hardhat needs to know about which network we are deploying our code to: ethereum mainnet, testnets or local network. For now, we are just going to be using our local network, hardhat. NB: The ChainId property needs to be set to 1337 to configure correctly with Metamask.

Finally change the filename of scripts/sample-script.js to scripts/deploy.js. 

##the faucet smart contract##

Ok now we're going to code up the smart contract that we will be deploying to the blockchain and interacting with using our React front end. 

###Remix IDE###

As discussed earlier, Remix is an in-browser solidity development environment. I've found it to be a great way to write smart contracts and test them before integrating them into my projects. Now that our project is set up, we're going to use Remix to test our smart contract. Using Remix IDE might seem a little long winded for this crash course, but I think it's important to cover. Let's check it out. Head over to 

*https://remix.ethereum.org/*

In the left panel upon up Contracts, you'll see some example contracts. Create a new contract by clicking the new contract icon. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iu1gscua3eu0zwb7r5ms.png)

Create a new contract called *FCTToken*

```Javascript

pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

contract FCTToken is ERC20 {

    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _mint(msg.sender, 10000 * (10 ** 18));
    }

    function faucet (address recipient , uint amount) external {
      _mint(recipient, amount);
    }
}

```

This is all the code for our smart contact! We are importing the Open Zeppelin library into our Remix IDE. 

When we declare our Contract with **Contract FCTToken is ERC20** our contract will inherit all the functions from the open zeppelin ERC20 token. 

These functions are:

```
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
``` 
This crash course wont be going into the details of solidity, but if you want to get a good understanding of ERC20 functionality, its worth checking out the Open Zeppelin [repo](https://github.com/OpenZeppelin/openzeppelin-contracts) and docs. 

The **constructor** part of our code will initialise the smart contract parameters **name** and **symbol** with values that  we will pass to it when it is deployed. These will be the name of our token and its symbol, "Faucet", "FCT". 

Inside the constructor we call **_mint** (an inherited function) to mint 10,000 tokens. The math used when we call **_mint** has to be implemented because of [token base units](https://forum.openzeppelin.com/t/understanding-decimals-for-erc20-token-creation/1821/3). 

We added our new function to this smart contract **faucet** which takes two arguments **recipient* of type address and ** amount of type uint.

*NB. Solidity is a statically-typed language, if you're familiar with typescript it follows similar principles.* 

Now let's compile our code to test it out. Click the solidity icon in the furthest left panel. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwiemhufid8ytqnz5oxh.png)

Now click the compile button in the left panel. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jofmaqg282m2nqyt8s4e.png)

If everything is working you'll see the Remix console run the compiler. 

Now click the ethereum icon in the furthest left panel, to deploy our code in the remix environment. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6gc7ir7f2p2wobb77dx.png)

We can see our contract instance awaiting deployment. Click deploy. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qxl4j15gkf23dgbuj21p.png)

If all is working, you'll see a green tick in the Remix console. 

Now we should see our smart contract instance under 'Deployed Contracts.' Click the arrow icon to expand it. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6w5vzp1845tn44bv04i.png)

You'll now see a list of all the available functions we can use in our smart contract. Remember this includes all the functions we inherited from the Open Zeppelin Contracts import. *(This really helped me visualise the smart contract functions when I was starting out with Solidity!)*

Open up our *faucet* function. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbv5p6fzfca7bwxylkwc.png)

You'll see the inputs for each argument, in our case *recipient* and *amount*. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2sl5f9ucj2sidddyr2f.png)

At the top of the left panel you'll see a drop down menu under *Account*. This allows us to switch simulated user accounts, each account is loaded up with test ether. You should play around with Remix to learn solidity for sure. But for now we're going to copy the address of the current account by clicking the copy icon. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1137tyw9n014hfbdekq.png)


Now back in the faucet argument paste in the address for *recipient and 100 for *amount* and click *transact* 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nqpbc3e6ap1780rulbol.png)

We ran a deployed a smart contract function! Now to check it worked, open your smart contract functions and call *balanceOf* with your address as the argument. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbovpbi95252p5m2old0.png)

Before continuing it's worth noting the difference between the functions with orange buttons and the functions with blue buttons. 

The orange functions write data to the blockchain, this counts as a *transaction* which costs gas. This action is immutable. The blue functions read data which counts as a *call*, this is free and doesn't change any data on the blockchain.

So now we know our smart contract is working, we can safely use it in our project. 

In your project in the **/contracts** folder delete any contracts there and create a new contract called **FCTToken.Sol** with the following code, the code we just tested. 

```javascript
pragma solidity ^0.8.3;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract FCTToken is ERC20 {

    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _mint(msg.sender, 100000 * (10 ** 18));
    }

    function faucet (address recipient , uint amount) external {
      _mint(recipient, amount);
    }
}

```

##Running our hardhat local blockchain 

In your terminal, in your project directory run 
```
npx hardhat node 
```

You'll see hard had start running a local blockchain. It will give us a list of addresses loaded up with test eth. Leave this terminal window running and open a new one for the rest of this course. 

>Similar to how we deployed our smart contract in Remix, we are now going to deploy our FCTToken smart contract to our local blockchain.

Open you're **scripts/deploy.js** and update it to 
```
const hre = require("hardhat");

async function main() {
  const [deployer] = await hre.ethers.getSigners();

  console.log(
    "Deploying contracts with the account:",
    deployer.address
  );

  const FCTToken = await hre.ethers.getContractFactory("FCTToken");
  const fctToken = await FCTToken.deploy("FCTToken", "TKN");

  await fctToken.deployed();

  console.log("Token deployed to:", fctToken.address);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });
```
Now we've updated our deploy script, we can compile and deploy the **FCTtoken.sol**

>N.B Compiler won't accept .Sol, file must be name .sol, lowercase S. 

In a new terminal window, cd into your project and run
``` npx hardhat compile```
Then - 
```
npx hardhat run scripts/deploy.js --network localhost
```
Terminal should print out something similar to 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/beqzpmtmam7jguyrrlzy.png)

>N.B Human users have addresses for their wallets, but so do smart contracts. Addresses on ethereum can be thought of as id's for both users/wallets and also smart contracts. 

Take note of the *Token Deployed To* address as we'll be using that later. 

Cool! So we've deployed our FCTtoken.sol contract to our local hardhat blockchain.

If you're still with me, now would be a good time for that 10 minute break ;)

<img width="100%" style="width:100%" src="https://media.giphy.com/media/xUySTrbCFX1h4B8kmc/giphy.gif"> 

##React Frontend##

We can interact with the contract straight from our terminal using lots of nice hardhat commands. But for this crash course, we're going to get straight into react. 

Our aim is to have a webpage with a few buttons. These buttons will call our smart contract functions. We want:
- **faucet button** send FCT to user wallet
- **check balance** display a message with current FCT user balance
- **send FCT** user can send FCT to another address
- **amount input** an input for the amount to send
- **address input** an input for the address of the payee

In our **/src/app.css** file, delete all the default code and replace it with: 

```css

.App {
  text-align: center;
  background-color: rgba(252, 203, 250, 0.65);
  height: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.App-header {
  background-color: rgb(253, 204, 251);
  padding: 20px;
  color: white;
}

.App-intro {
  font-size: large;
}

```
Let's clean up our **App.js** file. Let's start with 

```javascript
import './App.css';
import FCTToken from './artifacts/contracts/FCTToken.sol/FCTToken.json'

function App() {

  const Token = FCTToken;

  return (
    <div className="App">
    </div>
  );
}

export default App;
```
now in your terminal run to start your localhost
```
npm run start 
```
this will load up at **localhost:3000** our blank page with a lovely light, purple-pink. 


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rpx1q637rw9xd33b8xr.png)

*yum*

Now let's build out the App.js component a little more.

```javascript
import './App.css';
import FCTToken from './artifacts/contracts/FCTToken.sol/FCTToken.json'
import 'bootstrap/dist/css/bootstrap.min.css'
import { Container, Row, Col } from 'react-bootstrap'

function App() {

  const Token = FCTToken;

  return (
    <div className="App">
    <Container>
    <Row className="justify-content-md-center">
      <Col>
      <div>our faucet</div>
      </Col>
      <Col>
      <div> our send area</div>
      </Col>
    </Row>
    </Container>
    </div>
  );
}

export default App;
```

We imported some bootstrap-react components, and have just sketched out where we want our main UI components to be on the page. 

Check out the beautiful [bootstrap-react docs page on layout](https://react-bootstrap.github.io/layout/grid/) if you've never implemented them in react before.

You should see the page reload every time you make a change / save a change to your react code. 

Lets create our Faucet component in our code by adding this snippet at line 22

```html
 <Faucet  tokenContract={Token}/>
```
This creates a react component and sends it the prop *Token*. This variable contains the ABI (remember those?) which we're importing at line 5.

Now lets code up the Faucet Component. 

in your terminal run 
```
cd src 
mkdir components 
cd components 
touch Faucet.js 
```
to create the Faucet.js file. You should have this file structure for react components. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1498k2ymkizvhh62owxe.png)

Here's the code for our Faucet.js react component. 

```javascript

import { useState } from 'react';
import { ethers } from 'ethers'
import Card from 'react-bootstrap/Card'
import Button from 'react-bootstrap/Button'

const tokenAddress = "{YOUR DEPLOYED TOKEN ADDRESS}"

const Faucet = (props) => {

  const [balance, setBalance] = useState()
  const [showBalance, setShowBalance] = useState(false)


  async function getBalance() {
    if (typeof window.ethereum !== 'undefined') {
      const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const contract = new ethers.Contract(tokenAddress, props.tokenContract.abi, provider)
      const balance = await contract.balanceOf(account);
      console.log("Balance: ", balance.toString());
      setBalance(balance.toString());
      setShowBalance(true);
    }
  }

  async function faucet() {
    if (typeof window.ethereum !== 'undefined') {
      const account = await window.ethereum.request({ method: 'eth_requestAccounts' });
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner();
      const contract = new ethers.Contract(tokenAddress, props.tokenContract.abi, signer);
      contract.faucet(account[0], 100);
    }
  }
    return (
        <div>
        <Card style={{background: "rgba(227, 104, 222, 0.71)"}}>
        <Card.Body>
        <Card.Subtitle>recieve faucet ERC20 to your wallet
        </Card.Subtitle><br></br>
        <div className="d-grid gap-2">
        <Button onClick={faucet}>get faucet token!</Button>
        <Button onClick={getBalance} variant="warning">check my balance</Button>   
        </div>
        </Card.Body>
        </Card>
        </div>
    )
}

export default Faucet
```
On line 7, you'll need to **replace the tokenAddress value with the 'Token Deployed To' address we got from our terminal earlier on.**

The code above might look a little clunky, but it's actually pretty simple once we break it down. We've declared two async functions *getBalance()* and *faucet()*. These need to be asynchronous functions as we are calling the smart contract which lives in the block chain so we need to Javascript to be patient with ethereum! 

>Read up on asynchronous programming in Javascript if it's unfamiliar to you as you'll be doing it a lot in Dapp development.

In our function we check if the user has metamask running, then we get the data we need using the ethers.js library and assign that data to local variables.  Again, this data is made accessible via the ABI, which we're importing at **App.js** and passing in as a prop to **Faucet.js**. 

The beauty of react design principles, flowing with ethereum ABI's! 

##Phew!##

Ok, now we need to import our lovely component in to our **App.js** at the top of the file.
```javascript
import Faucet from './components/Faucet.js'
```
Back on your localhost:3000 you should see something like this ... 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4lxi2ic5s8s1rlecmw8.png)

The pink background around our Faucet component happens because we wrapped it in a <Card> react-bootstrap component which we customised inline with some CSS styling. 

The different colour buttons are set using the variant prop, you can read about how they work [here](https://react-bootstrap.github.io/components/buttons/). 

## Testing the faucet component

Let's play with our UI. First we need to setup our Metamask Wallet so that its connected to our hardhat blockchain node 

*'...not another setup,'* I hear you screaming in the void...

When we ran our hardhat blockchain node, the terminal gave us a list of addresses and private keys for testing. Your node should still be running. Scroll up until you see something like this: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63cxpm4ynht0sft86i0v.png)

We can use any of these accounts to connect to our Metamask to our local blockchain instance. Use the first one for the sake of clarity. Copy the **private key** of the first account in the list.

Open Metamask and select the available networks dropdown. Connect to localhost:8545, this is the port of our local blockchain

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ii6tw98mmf1zicubi87p.png)

Now go to **Import Account**. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k56owacnov0kagitnjjl.png)

Paste in the **private key** of the first account from your terminal. Once the account is connected, you'll see your account loaded up with fake test eth!

<img width="100%" style="width:100%" src="https://media.giphy.com/media/f6nnxfCtLfhXD0Jzf6/giphy.gif"> 

In our UI click **get balance**

Open your browser developer console and you should see this console log.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxob67p93y645h2c748o.png)

This is the our wallet balance of FCT token. We minted the contract and in our smart contract, the minter receives the whole supply. 
 
In our UI lets click **get faucet token!**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctpebkl86usd1z5g8nvy.png)

Metamask will ask you to connect to the site. We will then be shown this transaction to confirm in our metamask wallet. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xixohi7ndut1hm2jovkl.png)

This shows the gas fee to run the transaction. Obviously we are just using test eth, but on the mainnet, this would cost actual eth. 

Click confirm. 

> Remember that every time we interact with a smart contract, if we are changing data stored in the blockchain that counts as a transaction. 

Now if you click **get balance**. You should see the updated balance. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqovxxmy62jgrpehhicd.png)

You can see our balance has updated by 100 Wei. 

> Getting the balance of the user address as a read only call, which doesn't count as a transaction, so requires no gas to run. 

Let's turn that console.log into a message so our UI updates dynamically. 

Create a new file **Message.js** in your components folder. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9muv9q6fwlq4770xvz9.png)

The code for our Message react component. 

```javascript
import Alert from 'react-bootstrap/Alert'

const Message = ({ balance }) => {
    return (
      <div>
      <Alert variant="info"> balance : {balance}</Alert>
      </div>
  )
}

export default Message
```
we're importing the **Alert** component from bootstrap. And passing in the **balance** prop. 

Back in your **Faucet.js** file add the following code, in my file, at line 45. Right under your **get Balance button** 

```javascript
{ showBalance ? <Message balance={balance}/> : null }
```
And import the component into the **Faucet.js** file at the top of your code

```javascript 
import Message from './Message'
``` 
Now if we click **get balance** in our UI, we will see the message component render to our page. 
 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8c3bhmez6jy904d0dn2l.png)

Now let's create our **send token** component

In our **App.js** file the new component where we have the dummy text *"our send area"*

```html
<TokenSend tokenContract={Token}/>
```
Again we're passing our TokenABI as a prop to this component.

Create a new file in your components folder named **TokenSend.js**

Add the following code.

```javascript

import { useState } from 'react';
import { ethers } from 'ethers'
import Card from 'react-bootstrap/Card'
import Button from 'react-bootstrap/Button'

const tokenAddress = "{YOUR DEPLOYED TOKEN ADDRESS}"

const TokenSend = (props) => {

  const [userAccount, setUserAccount] = useState()
  const [amount, setAmount] = useState()

  // request access to the user's MetaMask account
  async function requestAccount() {
    await window.ethereum.request({ method: 'eth_requestAccounts' });
  }

  async function sendCoins() {
  if (typeof window.ethereum !== 'undefined') {
    await requestAccount()
    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(tokenAddress, props.tokenContract.abi, signer);
    const transation = await contract.transfer(userAccount, amount);
    await transation.wait();
    console.log(`${amount} Coins successfully sent to ${userAccount}`);
  }
}
    return (
        <Card style={{background: "rgba(227, 104, 222, 0.71)"}}>
        <Card.Body>
        <Card.Subtitle> send faucet to an address
        </Card.Subtitle>
        <br></br>
        <div className="d-grid gap-2">
        <input onChange={e => setUserAccount(e.target.value)} placeholder="Payee 0x address" />
        <input onChange={e => setAmount(e.target.value)} placeholder="Amount" />
        <Button onClick={sendCoins} variant="success">send </Button>
        </div>
        </Card.Body>
        </Card>
    )
}

export default TokenSend
``` 

Update the variable **tokenAddress** with your deployed contract address. 

And finally back in your **App.js** file import the **TokenSend.js** component. 

```javascript
import TokenSend from './components/TokenSend.js'
```
You will now be able to send tokens to different wallets/users. 

In **amount** enter 1000000000000000000 (equal to one whole token in wei), then add an address from on of the addresses supplied to us by hardhat. 

Click **send**. Confirm the transaction in Metamask in our browser terminal we should see the console.log: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a65civtzrxptuc7rht4n.png)

You simulate multiple users by importing different accounts into your metamask and switching between them to test the functionality. 

##Well Done

We now have a working Decentralised Application. Our front end is running on localhost:3000 and our local hardhat blockchain on localhost:8545.

Now we're going to test it our on real network - real miners will process our transactions!

##Preparing for live testnet

<img width="100%" style="width:100%" src="https://media.giphy.com/media/9wv8qIAq9njgY/giphy.gif"> 

We're going to use the **Goreli testnet** to deploy our smart contract.

You'll need to load up your wallet with test eth for the Goreli network, or GOeth.

First, connect your Metamask wallet to the Goreli testnet. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52p29pb5bive43k2tiaf.png)

I used [this one](https://goerli-faucet.slock.it/), but there are others if you have a google. 

To connect to Goreli, we'll need to make use of an API, [Infura.io](https://infura.io/) has us covered, and its fast to set up.

Set up a free account and sign in. Go into dashboard and click the **ethereum** icon in the left panel. 

Now click the **create new project** button in the top right of the page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ic4e3z8ykkzi1onmyno3.png)

Name your project. 

In your project settings set the endpoints dropdown box to **Goreli**

Now you want to copy and save somewhere your 
- ProjectID
- end point URL

That's all we need from Infura. 

###Change Configuration 

Open your **hardhat.config.js** file and update it to 

```javascript
require("@nomiclabs/hardhat-waffle");
require('dotenv').config()

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
  const accounts = await ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
 module.exports = {
  paths: {
    artifacts: './src/artifacts',
  },
  networks: {
    hardhat: {
      chainId: 1337
    },
    goreli: {
      url: "{YOUR END POINT URL}",
      accounts: [`0x${process.env.PRIVATE_KEY}`]

    }
  },
  solidity: "0.8.3"
};
```
Update the **gorlei.url** property to be the endpoint URL that we saved from Infura, (no curly braces, just a string). 

In **goreli.accounts** we are referencing the variable PRIVATE_KEY stored in our .env file. This file won't be pushed to github as its stored in our .gitignore file.

To get the private key, open your metamask, make sure you're in the account with the Goreli test eth.  

Click the three button icon, and go to **Account Details**. In the next pop up click export Private Key. 

>You should have different metamask accounts for developing and anything with real crypto assets.
 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/je2k2elo6ug1k7l2znep.png)

In your **.env** file update your private key.
 
```
PRIVATE_KEY="{YOUR-PRIVATE-KEY}"
```

**Never expose your private key in your config file, if you do anyone can access your wallet and steal your funds**

By referencing the secret variable in our config file, our private keys are safe. 

##Deploy!

<img width="100%" style="width:100%" src="https://media.giphy.com/media/9XZALusvhpsuxlZKx2/giphy.gif"> 

In your terminal run 
```
npx hardhat run scripts/deploy.js --network goreli
```
If all is working you'll see something like 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp6nc4klaqfdrricdtqb.png)

If you search the deployed contract address on the [Goreli etherscan](https://goerli.etherscan.io/), you'll see it live on the blockchain. In etherscan you can see useful information about the contract, its total supply and even its original source code. 

Before we can test out our UI we need to update two lines in our react code. 

In **Faucet.js**, line 7. 

```javascript
const tokenAddress = "{YOUR-DEPLOYED-TOKEN-ADDRESS}"
```

And in **Token.js**, the same local variable name needs the same address. 

Now our UI works. When we click **get faucet token** or **send** we call a function to our smart contract on the Goreli testnet!

You may have to wait a little while for the transaction to be mined on Goreli, but you can check the status of your transaction on the Goreli etherscan as you would any normal transaction. 

Pretty Cool!

## Hosting Our UI 

Wouldn't it be nice if we could share our Dapp with a single URL?

It would. And that's what we're going to do. 

First, make a new repo and push your project to the master branch. I won't be going into how to do that here. Our .gitignore file is configured so that we will only push our source code to Github. 

Once you've pushed to your new Git repo. Go to [netlify](https://app.netlify.com/), create a new account or log in. 

Click **new site from git button**. Connect Netlify with your Github account and select the repo you just created, to deploy your UI. 

> Netlify will count any react compiler warnings and errors, so make sure there are no warnings in your react project before you deploy.

That's it! Once its deployed Netlify will supply you with a URL for your Dapp, connected to the Goreli test net, so you can share your work. 

[Here's mine](https://60b43852a834858831d84c15--inspiring-liskov-361eb4.netlify.app/)

###Summary 

In this crash course I tried to show what the full development cycle of a decentralised application might look like. Note we didn't do any testing with Mocha on this project and that's a topic for another day. 

Feel free to share and adapt, create your own UI's, add custom smart contract functionality with UI capabilities. I'd love to see your work. 

*I'm an eth/solidity dev ready hire specialising in front end integration and UI. Let's chat.*