DEV Community

fangjun
fangjun

Posted on • Updated on

01 Understanding Blockchain with `Ethers.js`: 4 Tasks of Basics and Transfer

As a web3 developer, you can play with Ethereum blockchain using Ethers.js to get a deeper understanding. This 3-parts tutorial lists 12 tasks for you.

Ethers.js is a Javascript API for Ethereum blockchain which can work with Mainnet, testnet such as Ropsten, Rinkeby, local testnet, Layer 2 and sidechains.

We will use Hardhat Ethereum development environment to set up a playground as it can provide all the components we need:

  • local testnet: Hardhat Network based on @ethereumjs/vm
  • interactive console: Hardhat console
  • solidity development tools: Hardhat
  • Ethers.js: Ethereum Javascript API

Hardhat brings in Ethers.js with plugin hardhat-ethers.

Ethers.js documents: https://docs.ethers.io/v5/


Task 1: Setup Ethers.js playground with Hardhat

You need to have node.js and yarn installed in your computer.

Task 1.1 Install Hardhat

Run in command line:

mkdir playeth && cd playeth
yarn add hardhat
Enter fullscreen mode Exit fullscreen mode

Task 1.2 Init Hardhat project

You can init a Hardhat project by running:

yarn hardhat 
Enter fullscreen mode Exit fullscreen mode

Choose Option "Create an advanced sample project that uses TypeScript". A sample hardhat project will be created.

Task 1.3 Run a stand-alone local testnet

In another terminal, run a stand-alone local testnet "Hardhat Network" by running:

yarn hardhat node
Enter fullscreen mode Exit fullscreen mode

More about in-process and stand-alone mode of Hardhat Network can be found here.

Task 1.4 Enter Hardhat console

Run Hardhat console connecting to blockchain testnet localhost:

yarn hardhat console --network localhost
Enter fullscreen mode Exit fullscreen mode

Check Ethers.js version and get the current blocknumber in console:

ethers.version
//'ethers/5.5.3'

await ethers.provider.getBlockNumber()
//0
Enter fullscreen mode Exit fullscreen mode

Now, you have an Ethers.js playground with an interactive console and a local testnet.


Task 2: Have a look at blockchain

Currently Hardhat console is connected to a local blockchain testnet at http://localhost:8545. Let's have a look at the blockchain with Ethers.js.

Ethers.js provide "Provider" and "Signer" for interaction with blockchain. Its document explains:

  • A Provider in ethers is a read-only abstraction to access the blockchain data.

  • A Signer in ethers is an abstraction of an Ethereum Account, which can be used to sign messages and transactions and send signed transactions to the Ethereum Network to execute state changing operations.

Task 2.1 check connection

We can access provider ether.provider,an Ethers.js wrapped Ethereum RPC provider.

const provider = ethers.provider
ethers.provider.connection
// { url: 'http://localhost:8545' }
Enter fullscreen mode Exit fullscreen mode

Task 2.2 check network of provider

await provider.getNetwork()
//{ chainId: 31337, name: 'unknown' }
Enter fullscreen mode Exit fullscreen mode

Ethereum network with chainId 31337 is local testnet at 127.0.0.1:8545.

Task 2.3 get signer

The big difference between ethers.js and web3.js is that it separate signer from provider. Provider can only read data from blockchain while signer can send transactions to change data on blockchain. Ethers.js docs explain signer:

const signer = await provider.getSigner()
//this is a JsonRpcSigner

await signer.getAddress()
//'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
Enter fullscreen mode Exit fullscreen mode

Task 2.4 get all the accounts with Hardhat console

Hardhat console is running with 20 test accounts.

accounts = await ethers.getSigners();
accounts.length
//20

for (const account of accounts) console.log(account.address)

Result: 
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
0x90F79bf6EB2c4f870365E785982E1f101E93b906
...
Enter fullscreen mode Exit fullscreen mode

There is a sample hardhat plugin accounts, you can run it in command line:

yarn hardhat accounts
Enter fullscreen mode Exit fullscreen mode

Task 3: Get ETH balance of an address

We can use getBalance() to get ETH balance of an address (reference link). Since we only need to read data from blockchain, we will use provider instead of signer.

Task 3.1 getBalance

firstaddress = accounts[0].address
balance = await provider.getBalance(firstaddress)
//BigNumber { value: "10000000000000000000000" }
Enter fullscreen mode Exit fullscreen mode

The return result is BigNumber, which means 10000.0 ethers. Every account has 10000.0 test ethers in Hardhat local testnet.

Task 3.2 formatEther

We can use ethers.js utilities for Display Logic and Input to display it in a friendly manner.

ethers.utils.formatEther(balance)
//'10000.0'
Enter fullscreen mode Exit fullscreen mode

Task 3.3 parseEther

We can also transfer from string to Bignumber easily.

ethers.utils.parseEther("0.5");
//BigNumber { value: "500000000000000000" }
Enter fullscreen mode Exit fullscreen mode

Task 4: Send ETH from one address to another

Task 4.1 Send ETH using MetaMask

You can use MetaMask to transfer test ethers between accounts:

  1. Switch network to Localhost8545 in MetaMask
  2. Import account #0 with privateKey
  3. Transfer 100 test ETH from Account #0 to Account #1
Accounts #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
privateKey: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 
Accounts #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
Enter fullscreen mode Exit fullscreen mode

Address #00 and privateKey to add account to MetaMask. Address #1 is the receiver.

Note: Remember to change chainId from "1337" to "31337" in MetaMask network setting.

You can check the results in console:

provider = ethers.provider
acccount_1='0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
await provider.getBalance(acccount_1).then((r)=>console.log(ethers.utils.formatEther(r)))
//'10100.0'
Enter fullscreen mode Exit fullscreen mode

Send ETH from one address to another can be done by call sendTransaction using Ethers.js. Related Ether.js docs is here.

Detailed explanation of Transaction can be found in Andreas M. Antonopoulos's book Mastering Ethereum Chapter 6 Transactions.

Task 4.2 Prepare for sendTransaction

signer = await ethers.provider.getSigner()
send_address = await signer.getAddress()

accounts = await ethers.getSigners();
to_address = accounts[1].address

nonce = await signer.getTransactionCount()
gas_price = await signer.getGasPrice()
gas_limit = ethers.utils.hexlify(21000)

value = ethers.utils.parseUnits('100.0')
Enter fullscreen mode Exit fullscreen mode

Task 4.3 Format transaction

tx = {
  from: send_address,
  to: to_address,
  value: value,
  nonce: nonce,
  gasLimit: gas_limit,
  gasPrice: gas_price,
}
Enter fullscreen mode Exit fullscreen mode

Task 4.4 Call sendTransaction

Send transaction:

await signer.sendTransaction(tx)
Enter fullscreen mode Exit fullscreen mode

Task 4.5 Check results

provider = ethers.provider
await provider.getBalance(to_address).then((r)=>console.log(ethers.utils.formatEther(r)))
//'10200.0'
await provider.getBalance(send_address).then((r)=>console.log(ethers.utils.formatEther(r)))
//'9799.999923543659375'
Enter fullscreen mode Exit fullscreen mode

The balance of send_address is a little less than 9800.0 because it paid some ether as gas fee for the transactions.

When sendTransaction called, it returns receipt of the transaction executed on the blockchain.

{
  hash: '0x8915f9df88e4f2af2eefe05922e026c66723678b7df3de11e525a03c11b391a2',
  type: 0,
  accessList: null,
  blockHash: '0xfae5411b597d02b1c36a6842f14db5aad7ac2b974474f06355bd1b4eb5d438ed',
  blockNumber: 1,
  transactionIndex: 0,
  confirmations: 1,
  from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  gasPrice: BigNumber { value: "1875000000" },
  gasLimit: BigNumber { value: "135168" },
  to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
  value: BigNumber { value: "100000000000000000000" },
  nonce: 0,
  data: '0x',
  r: '0x116a4e2acba174b04a6f44248fef0170012d956d20e03d93b1b3368fce09c8e8',
  s: '0x14f1104a1fa98fed53a06a4a7a6464503d1f8a822191c022a2180e45c258809b',
  v: 62710,
  creates: null,
  chainId: 31337,
  wait: [Function (anonymous)]
}
Enter fullscreen mode Exit fullscreen mode

You can also have a look at the terminal running yarn hardhat node. Transaction details are logged on the screen:

  Transaction: 0x8915f9df88e4f2af2eefe05922e026c66723678b7df3de11e525a03c11b391a2
  From:        0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:          0x70997970c51812dc3a010c7d01b50e0d17dc79c8
  Value:       100 ETH
  Gas used:    21000 of 135168
  Block #1:    0xfae5411b597d02b1c36a6842f14db5aad7ac2b974474f06355bd1b4eb5d438ed
Enter fullscreen mode Exit fullscreen mode

Tutorial List:

1. A Concise Hardhat Tutorial(3 parts)

https://dev.to/yakult/a-concise-hardhat-tutorial-part-1-7eo

2. Understanding Blockchain with ethers.js(5 parts)

https://dev.to/yakult/01-understanding-blockchain-with-ethersjs-4-tasks-of-basics-and-transfer-5d17

3. Tutorial : build your first DAPP with Remix and Etherscan (7 Tasks)

https://dev.to/yakult/tutorial-build-your-first-dapp-with-remix-and-etherscan-52kf

4. Tutorial: build DApp with Hardhat, React and ethers.js (6 Tasks)

https://dev.to/yakult/a-tutorial-build-dapp-with-hardhat-react-and-ethersjs-1gmi

5. Tutorial: build DAPP with Web3-React and SWR

https://dev.to/yakult/tutorial-build-dapp-with-web3-react-and-swr-1fb0

6. Tutorial: write upgradeable smart contract (proxy) using OpenZeppelin(7 Tasks)

https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916

7. Tutorial: Build a NFT marketplace DApp like Opensea(5 Tasks)

https://dev.to/yakult/tutorial-build-a-nft-marketplace-dapp-like-opensea-3ng9


If you find this tutorial helpful, follow me at Twitter @fjun99

Discussion (0)