ethers.js2:provider提供商

1、Provider

Provider类是对以太坊网络连接的抽象,为标准以太坊节点功能提供简洁、一致的接口。在ethers中,Provider不接触用户私钥,只能读取链上信息,不能写入,这一点比web3.js要安全。

除了之前介绍的默认提供者defaultProvider以外,ethers中最常用的是jsonRpcProvider,可以让用户连接到特定节点服务商的节点。

jsonRpcProvider

2、创建节点服务商的API Key

首先,需要去节点服务商的网站注册并创建API Key,有InfuraAlchemy两家公司API Key的创建方法。

Infura API Key

Infura API Key

3、连接Infura节点 

我们用Infura节点作为例子。在创建好Infura API Key之后,就可以利用ethers.provider.JsonRpcProvider()方法来创建Provider变量。JsonRpcProvider()以节点服务的url作为参数。

 在下面这个例子中,我们分别创建连接到ETH主网和Goerli测试网的provider

// 利用Infura的rpc节点连接以太坊网络
// 填入Infura API Key, 教程:https://github.com/AmazingAng/WTFSolidity/blob/main/Topics/Tools/TOOL02_Infura/readme.md
const INFURA_ID = ''
// 连接以太坊主网
const providerETH = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${INFURA_ID}`)
// 连接Goerli测试网
const providerGoerli = new ethers.providers.JsonRpcProvider(`https://goerli.infura.io/v3/${INFURA_ID}`)

4、利用Provider读取链上数据

Provider类封装了一些方法,可以便捷的读取链上数据:

1. 利用getBalance()函数读取主网和测试网V神的ETH余额:

    // 1. 查询vitalik在主网和Goerli测试网的ETH余额
    console.log("1. 查询vitalik在主网和Goerli测试网的ETH余额");
    const balance = await providerETH.getBalance(`vitalik.eth`);
    const balanceGoerli = await providerGoerli.getBalance(`vitalik.eth`);
    // 将余额输出在console(主网)
    console.log(`ETH Balance of vitalik: ${ethers.utils.formatEther(balance)} ETH`);
    // 输出Goerli测试网ETH余额
    console.log(`Goerli ETH Balance of vitalik: ${ethers.utils.formatEther(balanceGoerli)} ETH`);

V神余额

 2. 利用getNetwork()查询provider连接到了哪条链,homestead代表ETH主网:

  // 2. 查询provider连接到了哪条链
    console.log("\n2. 查询provider连接到了哪条链")
    const network = await providerETH.getNetwork();
    console.log(network);

getNetwork

 3. 利用getBlockNumber()查询当前区块高度:

    // 3. 查询区块高度
    console.log("\n3. 查询区块高度")
    const blockNumber = await providerETH.getBlockNumber();
    console.log(blockNumber);

getBlockNumber

 4. 利用getGasPrice()查询当前gas price,返回的数据格式为BigNumber,可以用BigNumber类的toNumber()toString()方法转换成数字和字符串。

    // 4. 查询当前gas price
    console.log("\n4. 查询当前gas price")
    const gasPrice = await providerETH.getGasPrice();
    console.log(gasPrice);

getGasPrice

5. 利用getFeeData()查询当前建议的gas设置,返回的数据格式为BigNumber

    // 5. 查询当前建议的gas设置
    console.log("\n5. 查询当前建议的gas设置")
    const feeData = await providerETH.getFeeData();
    console.log(feeData);

getFeeData

6. 利用getBlock()查询区块信息,参数为要查询的区块高度:

    // 6. 查询区块信息
    console.log("\n6. 查询区块信息")
    const block = await providerETH.getBlock(0);
    console.log(block);

getBlock

 7. 利用getCode()查询某个地址的合约bytecode,参数为合约地址,下面例子中用的主网WETH的合约地址:

    // 7. 给定合约地址查询合约bytecode,例子用的WETH地址
    console.log("\n7. 给定合约地址查询合约bytecode,例子用的WETH地址")
    const code = await providerETH.getCode("0xc778417e063141139fce010982780140aa0cd5ab");
    console.log(code);

getCode

完整代码:

{/* <script src="https://cdn.ethers.io/lib/ethers-5.6.9.min.js"></script> */}
const ethers = require("ethers");
// import { ethers } from "ethers";
// import { ethers } from "https://cdn-cors.ethers.io/lib/ethers-5.6.9.esm.min.js";

const INFURA_ID = '012dac20ba9f43c0ad4fd8be46ae2c37';

const providerETH = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/012dac20ba9f43c0ad4fd8be46ae2c37');
const providerGeorli = new ethers.providers.JsonRpcProvider('https://goerli.infura.io/v3/012dac20ba9f43c0ad4fd8be46ae2c37');

const main = async () => {
    //查询vitalik在主网和georli上的eth余额
    console.log('1、查询vitalik的ETH余额');
    const balanceETH = await providerETH.getBalance('vitalik.eth');
    const balanceGeorliETH = await providerGeorli.getBalance('vitalik.eth');
    console.log('ETH balance of vitalik:' + ethers.utils.formatEther(balanceETH) +'ETH' );
    console.log('GeorliETH balance of vitalik:' + ethers.utils.formatEther(balanceGeorliETH) + 'ETH');

    console.log('\n 2、查询现在是哪条链');
    const network = await providerETH.getNetwork();
    console.log(network);

    console.log('\n 3、查询当前区块高度');

    const blockNum = await providerETH.getBlockNumber();
    console.log(blockNum);

    console.log('\n 4、查询当前gasPrice');
    const gasPrice = (await providerETH.getGasPrice()).toString();
    console.log(gasPrice);

    console.log('\n5、查询当前区块信息');
    const blockInfo = await providerETH.getBlock(17969422);
    console.log(blockInfo);

    console.log('\n6、查询某个合约地址的代码字节码');
    const bytecode = await providerETH.getCode('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984');
    console.log(bytecode);

};

main()

总结

ethers.js的Provider类,并用Infura的节点API Key创建了jsonRpcProvider,读取了ETH主网和Goerli测试网的链上信息。 

踩坑记录:

运行后仍然跟上一次一样报错:

import { ethers } from "https://cdn-cors.ethers.io/lib/ethers-5.6.9.esm.min.js";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:74:18)
    at wrapSafe (node:internal/modules/cjs/loader:1141:20)
    at Module._compile (node:internal/modules/cjs/loader:1182:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1272:10)
    at Module.load (node:internal/modules/cjs/loader:1081:32)
    at Module._load (node:internal/modules/cjs/loader:922:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47

Node.js v18.13.0

原因是,在一个非模块化的环境中使用了ES6的 import 语句,导致了错误。代码运行在普通的JavaScript环境中,而不是模块化环境,您可以将 import 语句替换为传统的脚本引入方式。将以下代码:

import { ethers } from "ethers";

替换为:

const ethers = require("ethers");

另外再修改原来代码中的一些错误写法,比如少一个括号,把$去掉等。

就可以正常运行并得到结果:

ETH balance of vitalik:3933.795127185004997518ETH

2、报错:

const network = await ethers.providerETH.getNetwork(); 
                                             ^ 
 
TypeError: Cannot read properties of undefined (reading 'getNetwork') 

 在const network = await ethers.providersETH.getNetwork();中语法错误,改为:

const network = await providersETH.getNetwork();
即可解决。

3、报错:

console.log('\n 4、查询当前gasPrice');

    const gasPrice = (await providerETH.getGasPrice()).toString;

    console.log(gasPrice);

};


运行结果是:

[Function (anonymous)]

因为在代码中,toString我少写了一个括号,应该是:

    const gasPrice = (await providerETH.getGasPrice()).toString;

另外,有一次我的代码是:

console.log('\n 4、查询当前gasPrice');

    const gasPrice = await providerETH.getGasPrice().toString();

    console.log(gasPrice);

};

运行得到的结果是:

undefined
原因是,const gasPrcie = await providerETH.getGasPrice().toString().要改为:
 

const gasPrcie = (await providers.getGasPrice()).toString();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值