Tutorial: Ethereum BlockChain Development (4)
Tags: ethereum, blockchain, javascript, tutorial
Published: 2022-02-22 19:55:46

## Part 4: Creating and Using Tokens

> The purpose of building this blog is to write down the detailed operation history and my memo for learning the dApps.
> If you are also interested and want to get hands dirty, just follow these steps below and have fun!~

### Previous Blog
[Tutorial: Ethereum BlockChain Development (1)](https://dev.to/yongchanghe/ethereum-development-log-part-1-deploy-blockchain-and-smart-contract-1a1j)
[Tutorial: Ethereum BlockChain Development (2)](https://dev.to/yongchanghe/ethereum-development-blog-2-53kk)
[Tutorial: Ethereum BlockChain Development (3)](https://dev.to/yongchanghe/tutorial-ethereum-blockchain-development-3-4ple/edit)

### Intro & Review

Previously we have deployed contract on a real test network - Ropsten Testnet, and we have spent some fake test ETH on deploying contract.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkwtvqvzxuwgv162q139.png)

In this blog let's look at more of a real world use case. When people have created smart contracts, they have some types of tokens that associated with them. Let's take a look at how to create some tokens and we will do that in a couple of different ways. 

We will create our tokens from scratch, and alternatively we will use ERC20 standard to create a token, which is being used in the real cryptocurrency world(will do it in next blog).

### Getting started

We should first go to our code, create a new file named **Token.sol** in the directory: **/contracts/**:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/serigv193l2jjn4ye12z.png)

Next update **Token.sol** with the following code:
```js
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract Token {
  string public name = "Yongchang He Token";
  string public symbol = "YHT";
  uint public totalSupply = 1000000;
  mapping(address => uint) balances;

  constructor() {
    balances[msg.sender] = totalSupply;
  }

  function transfer(address to, uint amount) external {
    require(balances[msg.sender] >= amount, "Not enough tokens");
    balances[msg.sender] -= amount;
    balances[to] += amount;
  }

  function balanceOf(address account) external view returns (uint) {
    return balances[account];
  }
}
```

This new contract **Token.sol** will create a new token called **Yongchang He Token** and set the supply to 1000000. The function `transfer` will transfer tokens to another address, and `balanceOf` will return the latest token balance.

Now let's go to CLI and compile our updated contract:
```linux
npx hardhat compile
```
If run successfully, we should get message as following:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggp4lifpn5pzu1xaxii5.png)

Next let's update the deploy script at **scripts/deploy.js** to include the following new Token contract:

```js
const hre = require("hardhat");

async function main() {
  
  const Greeter = await hre.ethers.getContractFactory("Greeter");
  const greeter = await Greeter.deploy("Hello, Hardhat!");
  await greeter.deployed();
  console.log("Greeter deployed to:", greeter.address);

  const Token = await hre.ethers.getContractFactory("Token");
  const token = await Token.deploy();
  await token.deployed();
  console.log("Token deployed to:", token.address);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

Now let's deploy this new contract to localhost:
```linux
npx hardhat run scripts/deploy.js --network localhost
```
We should get the following message:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2o17bg02qr45jgqw11o.png)

Let's see if we can review the Token in MetaMask. We can go back to localhost and choose the test account, and then click on "Import tokens":

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flngerbyf69wofrgo15h.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sa1cytx9jfki977kov5p.png)

We should copy and paste the **Token Contract Address** (produced in CLI window), **Token Symbol** and fill the decimal text with "0", and Click on **Add custom Token** and **Import Token**:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k0uaa3xe515fa41iztne.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/poc4anugn8u59m23dj4w.png)

We should see the Tokens that we current have:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yiqwnskajrxzj6sa4noo.png)

Let's also update the client code at **src/App.js**:
```js
import { useState } from 'react';
import { ethers } from 'ethers';
import './App.css';
import Greeter from './artifacts/contracts/Greeter.sol/Greeter.json'
import Token from './artifacts/contracts/Token.sol/Token.json'

// Store the contract Address into variable
const greeterAddress = "0x5fbdb2315678afecb367f032d93f642f64180aa3";
const tokenAddress = "0x0165878A594ca255338adfa4d48449f69242Eb8F";

function App() {
  const [greeting, setGreetingValue] = useState('')
  const [userAccount, setUserAccount] = useState('')
  const [amount, setAmount] = useState(0)


  async function requestAccount(){
    // Aims to connect to the Metamask wallet of the user and create a transaction
    // Request users' account information from MetaMask wallet
    // This will prompt the user to connect to one of their MetaMask account
    // if they have already connected and return array of their accounts
    await window.ethereum.request({ method: 'eth_requestAccounts' });
  }

  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, Token.abi, provider)
      const balance = await contract.balanceOf(account);
      console.log("Balance: ", balance.toString());
    }
  }

  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, Token.abi, signer);
      const transation = await contract.transfer(userAccount, amount);
      await transation.wait();
      console.log(`${amount} Coins successfully sent to ${userAccount}`);
    }
  }

  async function fetchGreeting(){
    // When Ethereum window is exist
    // Waiting for the MetaMash extension to be connected
    // If MetaMask is not installed on that user's broswer, 
    //window.ethereum will be rejected
    if (typeof window.ethereum !== 'undefined'){
        // Create a new provider using Ethers
        // In our case we use Web3Provider
        const provider = new ethers.providers.Web3Provider(window.ethereum)
        // When We have the provider instance, we can now create contract instance
        // We should pass in greetAddress, Greeter.abi and provider
        const contract = new ethers.Contract(greeterAddress, Greeter.abi, provider)
        try{
          // Read value from BlockChain, and assign it to variable data
          const data = await contract.greet()
          // Show data to console
          console.log('data: ', data)
        }catch (err) {
          console.log("Error: ", err)
        }
    }
  }

  async function setGreeting(){
    // To check if users have typed in a greeting
    // If no greeting function stop without writing empty string
    if (!greeting) return
    // When Ethereum window is exist
    if (typeof window.ethereum !== 'undefined'){
      // Wait for the user to go ahead and enable the account to be used
      await requestAccount()
      // Create another new provider using Ethers
      // In our case we use Web3Provider
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      // Await to sign a transaction using a signer
      const signer = provider.getSigner();
      // Create contract instance and pass in contract address, abi and signer
      const contract = new ethers.Contract(greeterAddress, Greeter.abi, signer);
      // Passing in greeting variable 
      const transaction = await contract.setGreeting(greeting);
      setGreetingValue('')
      // Waiting the transaction to be confirmed on the BlockChain
      await transaction.wait()
      // Refresh value
      fetchGreeting()
    }
  }

  return (
    <div className="App">
      <header className="App-header">
        <button onClick={fetchGreeting}>Fetch Greeting</button>
        <button onClick={setGreeting}>Set Greeting</button>
        <input onChange={e => setGreetingValue(e.target.value)} placeholder="Set greeting" />

        <br />
        <button onClick={getBalance}>Get Balance</button>
        <button onClick={sendCoins}>Send Coins</button>
        <input onChange={e => setUserAccount(e.target.value)} placeholder="Account ID" />
        <input onChange={e => setAmount(e.target.value)} placeholder="Amount" />
      </header>
    </div>
  );
}

export default App;

// limb proof waste call shrug street poet bike sleep bunker expire panic

```

Let's test it out by running the following the command: 
```linux
npm start
```
Now we can open our test React App which is running locally.
We can click "Get Balance", and we will get a balance of 1000000:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tv5fhlozn8h17cwxpq4.png)

Next we can pick one of our account as a recipient, and click the account name area to copy and paste the account ID and input the amount of coins that we want to send, and then we click "Send Coins":
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gznjiyeeqbg8q3gv2bhu.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwq93e439o52t1mushkm.png)

After that we should see the following result that 150000 YHT has been sent successfully to the recipient account:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nsprzocyh74rlf5ko81c.png)

After we click Confirm, we should see the pop-up message in the Console:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnj0t5m1rmqkd5bg8wkj.png)

And if we click on "Get Balance", we will also get the balance in our console:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2pqbxdrlrnoxtfj23ss.png)

Pretty Cool!

### Reference:
https://www.youtube.com/watch?v=a0osIaAOFSE&t=2239s
https://dribbble.com/shots/14225432-Coder