【前言】
這兩天來記錄 ethers.js 我覺得蠻重要的一些學習筆記,今天主要聚焦在一些常見名詞,還有連動的基本設定。省略了大部分的東西因為篇幅還有時間有限!
【ethers.js】
ethers.js 是一個完整的 JavaScript 套裝 library,是專門使用於與以太坊區塊鏈和相關生態系連動。此套件原本是特別設計在使用 ethers.io上,最後擴展至更全面性的套件。
Ethers.io is an collection of Libraries, Web Tools, Command-Line Utilities and Server Components to assist in the development, deployment, hosting and sharing of Ethereum applications.
What is Ethers? - ethers.io 0.0.1 documentation
下載套件:
npm install --save ethers
導入套件:
// Node.js
const { ethers } = require("ethers");
import { ethers } from "ethers";
常見術語:
【Connection】
Connecting to Ethereum: Metamask
如果要開始體驗或開發以太坊,最快又最簡單的方式就是使用 MetaMask。
// A Web3Provider wraps a standard Web3 provider, which is
// what Metamask injects as window.ethereum into each page
const provider = new ethers.providers.Web3Provider(window.ethereum)
// The Metamask plugin also allows signing transactions to
// send ether and pay to change state within the blockchain.
// For this, you need the account signer...
const signer = provider.getSigner()
Connecting to Ethereum: RPC
另外一個著名連動以太坊的方法就是使用 JSON-RPC API,其也可以實作在任何主要的以太坊節點應用 (e.g. Geth and Parity) ,以及許多第三方網頁服務上 (e.g. INFURA)。
// If you don't specify a //url//, Ethers connects to the default
// (i.e. ``http:/\/localhost:8545``)
const provider = new ethers.providers.JsonRpcProvider();
// The provider also allows signing transactions to
// send ether and pay to change state within the blockchain.
// For this, we need the account signer...
const signer = provider.getSigner()
【Provider API - Etherscan Provider】
Provider API Keys:
當我們使用某些可作為 Provider 的 API service (例如 Alchemy, Etherscan or INFURA),我們將會需要 API KEY 來允許每一個用來追蹤各種目標的服務。
此外,ethers.js 對於每個服務都提供預設的 API keys,因此每個 Provider 都是開箱即用的。 這些 API keys 被提供用來作為社會資源,像是低流量企劃或仍在草創期的企劃。當然因為他們被所有使用者共用,所以如果被越頻繁的使用就會使 response 更慢。
The ethers 強烈建議使用者針對每個服務都申請一個免費的 API keys,因為每個免費的 API keys 都有免付費額度,而其有以下優點:
Etherscan:
Etherscan.io 是一個以太坊區塊的觀察者。是所有用來建設區塊和 debug 的開發者工具裡面最有用的,並提供額外的 API 終端來連動以太坊區塊鏈。
Sign up for a free API key on Etherscan
【Application Binary Interface】
Application Binary Interface (ABI) 是一個統合介面,專門用來描述如何與智能合約裡面元件連動。也就是 Fragments 的統合介面,有 Error, Events, Function 和 Constructor。大部分開發者並不會使用這個比較低階 (encoding 和 decoding) 的介面來處理網路上的二進位資料,更多的是會使用智能合約裡面原本就定義好的介面。
【Contract】
Contract 是一段以太坊區塊鏈中的程式碼。Contract 物件使鏈上的合約可以像普通的 JavaScript 物件一樣被使用 ( with the methods mapped to encoding and decoding data )。這個概念有點像資料庫裏面的 Object Relational Mapper (ORM)。
為了要與鏈上的智能合約連動,這個被稱為 Contract 的類別需要知道在智能合約裡面有什麼方法可以被 encode 和 decode 成 data,也就是 ABI 所提供的功能。此外我們在使用 Contract 物件的時候,也可以忽視智能合約裡面我們不需要的方法,或稱函式。也就是說我們可以把這個 Contract 物件當作 ABI 的子集合。
通常 ABI 都是來自於 Solidity 或 Vyper 的編譯器,但使用者可以在程式碼裡面使用 Human-Readable ABI,像是以下的例子:
// You can also use an ENS name for the contract address
const daiAddress = "dai.tokens.ethers.eth";
// The ERC-20 Contract ABI, which is a common contract interface
// for tokens (this is the Human-Readable ABI format)
const daiAbi = [
// Some details about the token
"function name() view returns (string)",
"function symbol() view returns (string)",
// Get the account balance
"function balanceOf(address) view returns (uint)",
// Send some of your tokens to someone else
"function transfer(address to, uint amount)",
// An event triggered whenever anyone transfers to someone else
"event Transfer(address indexed from, address indexed to, uint amount)"
];
// The Contract object
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);
【ethers.erc20】
所謂的 meta-class 是一個在 run-time 時就被定義的類別。而 Contract 則是被 Application Binary Interface (ABI) 宣告其應該擁有的方法和事件。這些宣告也是在 run-time 時就被創造並加入的。所以我們可以說 Contract 物件是一個屬於 meta-class 的類別。
Connecting to a Contract
利用現有的智能合約的地址,並創造一個新的 Contract 物件來與其連接,其 ABI 通常為 Provider 或 Signer。如果是使用 Provider 的話,這些智能合約就會在唯讀的情況下被讀取,如果是 Signer 則可存取或使用其他更進階的方法。
// A Human-Readable ABI; for interacting with the contract, we
// must include any fragment we wish to use
const abi = [
// Read-Only Functions
"function balanceOf(address owner) view returns (uint256)",
"function decimals() view returns (uint8)",
"function symbol() view returns (string)",
// Authenticated Functions
"function transfer(address to, uint amount) returns (bool)",
// Events
"event Transfer(address indexed from, address indexed to, uint amount)"
];
// This can be an address or an ENS name
const address = "0x4f3b15e4421902c09895fB12c8e0B8821134eA39";
// Read-Only; By connecting to a Provider, allows:
// - Any constant function
// - Querying Filters
// - Populating Unsigned Transactions for non-constant methods
// - Estimating Gas for non-constant (as an anonymous sender)
// - Static Calling non-constant methods (as anonymous sender)
const erc20 = new ethers.Contract(address, abi, provider);
// Read-Write; By connecting to a Signer, allows:
// - Everything from Read-Only (except as Signer, not anonymous)
// - Sending transactions for non-constant functions
const erc20_rw = new ethers.Contract(address, abi, signer);
這邊我印象最深刻的函式是 erc20.balanceOf ( owner [ , overrides ] )
⇒ Promise< BigNumber >;其會 Return 這個 owner 所持有的 ERC-20 token 數量。
await erc20.balanceOf(signer.getAddress())
// { BigNumber: "100000000000000000000" }
【小結】
今天感覺篇幅有點短哈哈哈哈哈哈哈哈,反正東西多到永遠學不完,重點就是!大家在使用的時候要記得不要在網站裡面亂 call Private Key 喔!
【參考資料】
Documentation
ethereum(Docker)