ethers.js2:provider提供商

news2025/1/14 1:21:05

1、Provider

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

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

jsonRpcProvider

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

首先,需要去节点服务商的网站注册并创建API Key,有Infura和Alchemy两家公司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();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/915114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DataSecurity Plus:守护企业数据安全的坚实屏障

在数字化时代&#xff0c;数据被誉为企业最重要的资产之一。然而&#xff0c;随着大数据的兴起和信息的日益增长&#xff0c;企业面临着前所未有的数据安全挑战。为了应对这些挑战&#xff0c;数据安全管理变得至关重要。在这个领域&#xff0c;ManageEngine的DataSecurity Plu…

TCP滑动窗口

为什么会有滑动窗口 在计算机网络中&#xff0c;数据通常被分成小块&#xff08;也叫数据段&#xff09;在网络中传输&#xff08;为什么会被分成小块&#xff0c;请了解拥塞窗口和流量控制&#xff09;。这些小块可能会在传输的过程中遇到延迟、丢失或乱序等问题。为了保证数据…

学习ts(六)数据类型(元组、枚举、Symbol、never)与类型推论

1.元组 元组&#xff08;Tuple&#xff09;是固定数量的不同类型的元素的组合。是数组的变种。 元组与集合的不同之处在于&#xff0c;元组中的元素类型可以是不同的&#xff0c;而且数量固定。元组的好处在于可以把多个元素作为一个单元传递。如果一个方法需要返回多个值&…

适配器模式实现stack和queue

适配器模式实现stack和queue 什么是适配器模式&#xff1f;STL标准库中stack和queue的底层结构stack的模拟实现queue的模拟实现 什么是适配器模式&#xff1f; 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff…

微信小程序最新获取头像和昵称的方法 直接用!

调整背景 微信小程序获取用户头像和昵称一个开放接口是wx.getUserInfo&#xff0c;2021年4月5日被废弃&#xff0c;原因是很多开发者在打开小程序时就通过组件方式唤起getUserInfo弹窗&#xff0c;如果用户点击拒绝&#xff0c;无法使用小程序&#xff0c;这种做法打断了用户正…

Camunda_4:监听器相关

Camunda的监听器非常之多&#xff0c;常见的如任务监听与执行监听。我们可以实现相关监听器进行相关操作。 首先明确的是&#xff0c;当执行到某一个节点时&#xff0c;会先进入执行监听&#xff0c;然后进入任务监听。 执行监听和任务监听主要监听以下阶段。 然后我们就能去…

excel中如果A列中某项有多条记录,针对A列中相同的项,将B列值进行相加合并统计

excel中如果A列中某项有多条记录&#xff0c;针对A列中相同的项&#xff0c;将B列值进行相加合并统计。 如&#xff1a; 实现方法&#xff1a; C1、D1中分别输入公式&#xff0c;然后下拉 IF(COUNTIF($A$1:A1,A1)1, A1,"") #A1根据实际情况调整&#xff0c;如果…

学习笔记|课后练习解答|电磁炉LED实战|逻辑运算|STC32G单片机视频开发教程(冲哥)|第八集(下):课后练习分析与解答

课后练习解答 增加按键3&#xff0c;按下后表示启动&#xff0c;选择的对应的功能的LED持续闪烁&#xff0c;表示正在工作&#xff0c;且在工作的时候无法切换功能。 需求分解 1 增加按键3 #define KEY3 P34 //增加按键32 按下后表示启动 电平控制3 工作状态锁定 表示正在…

IDEA项目实践——mybatis实践,创建一个父目录专门存放mybatis项目

系列文章目录 IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍_intellij 创建scala IDEA项目实践——创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介 IDEWA项目实践——mybatis的一些基本原理以及案例 IDEA项目实践——动态SQL、关系映…

方案:AI边缘计算智慧工地解决方案

一、方案背景 在工程项目管理中&#xff0c;工程施工现场涉及面广&#xff0c;多种元素交叉&#xff0c;状况较为复杂&#xff0c;如人员出入、机械运行、物料运输等。特别是传统的现场管理模式依赖于管理人员的现场巡查。当发现安全风险时&#xff0c;需要提前报告&#xff0…

【SpringSecurity】四、登录处理器

文章目录 1、登录成功处理器2、登录失败处理器3、无权限处理器4、登出&#xff08;退出&#xff09;处理器5、安全配置类WebSecurityConfig 前后端分离背景下&#xff0c;前后端通过json进行交互&#xff0c;登录成功或失败&#xff0c;返回的不是一个html页面&#xff0c;而是…

python 基础篇 day 2 基本输入输出转换

文章目录 输入函数——input()原型示例注意 输出函数——print()原型示例 数据类型转换转换路径图示格式举例int(x)float(x)bool(x) 注意 格式化输出法一&#xff1a;%格式 类型表举例第二种&#xff1a;format格式类型表举例第三种&#xff1a;f &#xff08;format简化版&…

论文速递 Nature 2023 | Heat-assisted detection and ranging

注1:本文系“计算成像最新论文速览”系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‐Science & Applications, Optica 等)。 本次介绍的论文是: 2023年,Nature,“…

2023年国赛 高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

6个比较火的AI绘画生成工具

随着人工智能技术的发展&#xff0c;市场上出现了越来越多的人工智能图像生成工具。这些人工智能图像生成工具可以自动创建惊人的图像、艺术作品和设计&#xff0c;以帮助设计师和创意人员更快地实现他们的创造性想法。在本文中&#xff0c;我们将推荐7种最近流行的人工智能图像…

Michael.W基于Foundry精读Openzeppelin第30期——ECDSA.sol

Michael.W基于Foundry精读Openzeppelin第30期——ECDSA.sol 0. 版本0.1 ECDSA.sol 1. 目标合约2. 代码精读2.1 toEthSignedMessageHash(bytes32 hash) && toEthSignedMessageHash(bytes memory s)2.2 toTypedDataHash(bytes32 domainSeparator, bytes32 structHash)2.3…

Just KNIME it[S2C21] 图像识别

朋友们&#xff0c;Just KNIME it 还有在跟进吗? 本季已经到 21 期啦。 本期探讨的主题是图像识别问题&#xff0c;快随指北君一起看看吧。 挑战 21&#xff1a;帮助球童&#xff08;第 1 部分&#xff09; 级别&#xff1a;中 描述&#xff1a;球童汤姆是一位最受欢迎的高尔夫…

thinkphp6.0 配合shell 脚本 定时任务

1. 执行命令&#xff0c;生成自定义命令 php think make:command Custom<?php declare (strict_types 1);namespace app\command;use app\facade\AdmUser; use think\console\Command; use think\console\Input; use think\console\input\Argument; use think\console\i…

第 6 章 递归(3)(八皇后问题)

6.7递归-八皇后问题(回溯算法) 6.7.1八皇后问题介绍 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c…

堆内存和栈内存的区别

什么是栈内存&#xff1f; 栈内存是为线程流出来的临时空间&#xff0c;每一个线程都有它的临时空间&#xff0c;而且每一个栈都只能被当前的线程访问。 所以它是线程安全的。栈内存的分配和回收是由系统完成的。 当函数调用的时候 系统就会为这个函数分配栈空间&#xff0c;当…