最近在开发一个 NFT 二创平台,其中包含了很多概念和技术。我会更新一个系列的文章来总结和沉淀在这个过程中的一些知识与思考。
本文是对 ethers.js 进行一个全方位介绍,非常适合 web3 入门学习。
什么是 ethers.js?
Web3 中的各类 DApp,都需要与智能合约进行交互。如果用原生 JS 来做这些事会很麻烦。这时就需要使用专属的 SDK。
目前 JS 环境中有两个主流的库可以用来和智能合约进行交互,一个是 web3.js,另一个是 ethers.js。
ethers.js VS web3.js
web3.js 比 ethers.js 出现的更早。但是目前 ethers.js 更受欢迎。
主要原因有如下两点:
1.体积:ethers.js 体积仅有 116.5kb,web3.js 有 590.6kb。相差 5 倍左右。
2.设计理念:由于设计理念不同。web3.js 认为用户会在本地部署以太坊节点,私钥和网络连接状态由这个节点管理。但实际上大部分人都不会在本地部署以太坊节点。ethers.js 充分考虑了这一点,它是用 Provider 管理网络连接状态,用 Wallet 管理密钥,更加安全和灵活。而且原生支持 ENS。
ethers.js 基本使用介绍
节点即服务
由于在本地部署一个区块链节点的成本并不低,很少会有人真的部署一个节点,而是选择使用节点即服务。
这类服务有很多,比如老牌的 Alchemy、Infura、Moralis 以及今年估值 102 亿美金的新秀 Tenderly。
在这里我们选择 Alchemy,目前它的市场占有率是最高的。
alchemy 的网址在这:dashboard.alchemy.com/。具体的注册登陆就不讲了。
登陆之后我们创建一个 App。
Chain 选择 Ethereum,Network 选择 Goerli。
这样就成功创建了一个 App,点击后面的 view key,就可以查看 key。
我们把它复制下来,后面会用到。
构造合约
在对合约进行读取或交互之前,我们首先需要构造一个合约对象。
合约对象有三个构造参数,第一个是合约地址,是一个字符串。第二个是合约的 abi,可以是一个 JSON,第三个参数是 provider 对象,它用于管理网络连接状态。
下面的例子中就是使用 alchemy 提供的 JSON RPC 接口作为网络连接。
const rpc = `https://eth-goerli.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`;
const provider = new ethers.providers.JsonRpcProvider(rpc);
const contract = new ethers.Contract(contractAddress, abi, provider)
除了 JsonRpcProvider 以外,ethers 还有 IpcProvider、InfuraProvider、AlchemyProvider、Web3Provider 等多种 Provider。
读取合约信息
abi 中的方法会直接挂载到 contract 对象上,我们可以直接调用。
不过需要注意,所有的操作都是异步的。
(async () => {const owner = await contract.owner();console.log(owner);
})();
连接钱包
由于和合约交互需要支付 gas 费用,所以必须有一个数字钱包。
钱包有很多种,比如 MetaMask、Rainbow、Coinbase Wallet 等。其中 MetaMask 是最常用的一种数字钱包。
这里主要介绍如何连接到 MetaMask。
MetaMask 有一个浏览器插件,如果用户安装了该插件,在 window 对象下会有一个 ethereum 对象。我们可以调用 ethereum.request 方法发起请求,参数是一个对象,对象的 method 描述该次请求的操作。
ethereum.request 方法是异步的,会返回一个数组,该数组是所有登陆钱包的账户地址字符串,第一个账户就是当前激活的账户。如果返回的数组长度为 0,则意味着没有登陆任何账户。
(async ()=> {const accounts = await ethereum.request({ method: 'eth_requestAccounts' })if(accounts.length === 0) {throw Error('未登录任何账户')}const activeAccount = accounts[0]console.log(a