cyfuer

Jul 07, 2022

学习笔记:《Full Stack Blockchain Lesson 5:Ethers.js Simple Storage

 
 
 

How to Debug Anything Video

  • Patrick's Original Video
    • 5 steps to solve any coding problem:
      1. Tinker and Experiement
      1. Check the Docs
      1. Do a web search
        1. there are four different types of forms and QA sites where the best place to ask:
          notion image
           
          how to format your question:
          (1). Search
          (2). Summarizing Title
          (3). Introduce the problem first
          (4). Add minimalistic code
          notion image
          (5). Learn Markdown(Use backticks)
          (6). Use Tags
          (7). Read forum rules
      1. Ask Questions on Forums & Q&A Sites
      1. Join & Strengthen the community and tool
      notion image
 
notion image
notion image
notion image
notion image

Installation & Setup

Mac & Linux Setup

Windows Setup

  • WSL
    • When working in WSL, use Linux commands instead of Windows commands
  • curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
⚠️ Please use Gitpod as an absolute last resort

Gitpod

  • Gitpod
    • If using this, NEVER share a private key with real money on Gitpod
    • Ideally you figure out the MacOS, Linux, or Windows install though

Local Development Introduction

  • CMD + K or CTRL + K clears the terminal
  • mkdir ethers-simple-storage-fcc
  • code . to open VSCode in a new VSCode window

Optional Javascript Crash Courses

  • Import your SimpleStorage.sol
  • Format your solidity code with:
    • "[solidity]": { "editor.defaultFormatter": "NomicFoundation.hardhat-solidity" }, "[javascript]":{ "editor.defaultFormatter": "esbenp.prettier-vscode" }
      In your .vscode/settings.json file.

Tiny Javascript Refresher

Asynchronous Programming in Javascript

  • Asynchronous Programming
    • synchronous means it just goes one line after another.
      // Synchronous // 1. Put popcorn in mic rowave // 2. Wait for popcorn to finish // 3. Pour drinks for eve ryone // Asynchronous // 1. Put popcorn in the mirc rowave // 2. Pour drinks for everyone I // 3. Wait for popcorn to finish
  • await keyword
    • async and await make promises easier to write.
      async makes a function return a Promise.
      await makes a function wait for a Promise.
      async function setupMovieNight() { await cookPopcorn() await pourDrinks() startMovie() } function cookPopcorn() { return Promise(/* some coe here */); }
  • Promise in Javascript
    • Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason.
      Promise is in one of these states:
    • pending: initial state, neither fulfilled nor rejected.
    • fulfilled: meaning that the operation was completed successfully.
    • rejected: meaning that the operation failed.
    • async function main() { console.log("hi"); let variable = 5; console.log(variable); } main().then(() => process.exit(0)).catch((error) => { console.error(error); process.exit(1); })

Compiling our Solidity

Ganache & Networks

  • Networks in Metamask
  • RPC URL

Introduction to Ethers.js

  • Ethers.js
    • Intalling
      npm install --save ethers // or yarn add ethers
       
      Importing
      const { ethers } = require("ethers");
Usage
const provider = new ethers.providers.JsonRpcProvider("http://0.0.0. Ø:8545"); const wallet = new ethers.Wallet( "7dbe329dbf45741d3c5f1928e8e301c8358886bf4525e5f69dc2330aØbbe4f63" , provider );
 
  • fs
    • read file
       
      Installing
      yarn add fs-extra
       
      Import
      const fs = require("fs-extra");
       
      Usage
      const abi = fs.readFileSync("./SimpleStorage_solSimpleStorage.abi", "utf8"); const binary = fs.readFileSync( "./SimpleStorage_sol_SimpleStorage.bin", "utf8" ); const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy(); console.log(contract);
       
 
 
 

A Note on the await Keyword

notion image

Adding Transaction Overrides

notion image
const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy({ gasPrice: 1000000000000 });

Transaction Receipts

const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy(); // wait(1) means that you only get a transaction receipt when you wait for a block confirmation. const transactionReceipt = await contract.deployTransaction wait(1) ; console.log("Here is the dep loyment transaction (transaction response): "); console.log(contract.deployTransaction); console.log("Here is the transaction receipt: "); console.log(transactionReceipt);

Sending a "raw" Transaction in Ethers.js

const nonce = await wallet.getTransactionCount() ; const tx = [ nonce: nonce , gasPrice: 20000000000, gasLimit: 1000000, to: null, value: 0, data: "0x608060405234801561001057600080fd5b50610771806100206000396000f3fe608060405234", chainId: 1337, ]; const sentTxResponse = await wallet.sendTransaction(tx); await sentTxResponse.wait(1); console.log(sentTxResponse);

Interacting with Contracts in Ethers.js

Environment Variables

  • dotenv
    • Instailling
      yarn add dotenv
       
      Usage
      1. create file named ”.env“
        1. notion image
      1. code
        1. require("dotenv").config(); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
          notion image
          notion image

Better Private Key Management

  • wallet.encrypt
    • Encrypt
      const ethers = require("ethers"); const fs = require("fs-extra"); require ("dotenv").config(); async function main() { const wallet = new ethers.Wallet(process.env.PRIVATE_ KEY); const encryptedJsonKey = await wallet.encrypt( process.env.PRIVATE_KEY_PASSWORD, process.env.PRIVATE_KEY ); console.log(encryptedJsonKey); fs.writeFileSync("./.encryptedKey.json", encryptedJsonKey); /* log {' address" : "b1e94f2b209e4f433d994986efc5ca , " id" :"1c04c5f3- d869- -4c3e- 986d- -8c84c1a262f2" "version : 3 , "Crypto'" {"cipherl :"aes-128-ctrl , "cipherparams" :{" iv" :"0b27385c3a7d3d25 f5ab7888cde85aa9} , "ciphertext" :"03 e7a9ba1b29f5577c537dca7b7de714 , "kdf" :"scrypt" , "kdfparams" : {"salt" :"e964335f aa8db2bb65f2b3e6adadc47edf2d9f89b4cb5 , "n" 131072, "dklen" 32, "p'":1," r":8}, "mac" :"68fba984 53703bd5c4437320436391cc529d84300544263bdc599c68e327"}} */ }
       
      Decrypt
      const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL); // const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider) ; const encryptedJson = fs.readFileSync("./.encryptedKey.json", "utf8"); let wallet = new ethers.Wallet.fromEncryptedJsonSync( encryptedJson, process.env.PRIVATE_KEY_PASSWORD ); wallet = await wallet.connect(provider);
       
  • THE .ENV PLEDGE
    • The Pledge I solemnly swear, that I will never place a private key or secret phrase or mnemonic in a .env file that is associated with real funds. I will only place private keys in a .env file that have ONLY testnet ETH, LINK, or other cryptocurrencies. When I'm testing and developing, I will use a different wallet than the one associated with my real funds. I am aware that if I forget a .gitignore and push my key/phrase up to GitHub even for a split-second, or show my key/phrase to the internet for a split second, it should be considered compromised and I should move all my funds immediately. If I am unsure if my account has real funds in it, I will assume it has real funds in it. If I assume it has real funds in it, I will not use it for developing purposes. I am aware that even if I hit add account on my metamask (or other ETH wallet) I will get a new private key, but it will share the same secret phrase/mnemonic of the other accounts generated in that metamask (or other ETH wallet). Pledge Additions For this course, I will only use funds associated with a brand new never-before-used metamask (or other ETH wallet). I am aware that my account associated with my private key is the same on testnets that it is on mainnets. If I must use a private key associated with real funds in the future, until I am 100% sure what I am doing I will always either: Use the encryption methods Patrick showed (ideally) Use some better encryption stuff Patrick didn't show Use the command line way to pass private keys, and delete my command line history right after If I never actually deploy anything to mainnet myself or work with a private key with real funds, I do not need to be concerned. EDIT Look at all you safe people! I'd like all your comments if I could, but love how you're all being safe!! Keep it up!

Optional Prettier Formatting

  • Prettier
      1. install prettier
        1. npm install --save-dev --save-exact prettier
      1. create file named ”.prettierrc“.(this file will take precedent over the default configuration)
        1. notion image
          notion image
 

Deploying to a Testnet or a Mainnet

  • Alchemy
    • alchemy has a node as a service, and allows us to connect to any blockchain that they support for.
      notion image
      notion image
 
  • CTRL + C stops any terminal command

Verifying on Block Explorers from the UI

notion image

Alchemy Dashboard & The Mempool

Copyright © 2025 cyfuer

logo