Infura 以太坊 API 入门
如果要使用 Infura 的 API 接入以太坊网络,您会怎么做?首先需要确保有一个 Infura 账户。请查看本教程以开始使用!接下来需要确定您需要使用的接口 — Infura 支持 HTTPS 和 WebSocket 接口上的 JSON-RPC。在本教程中,我们将介绍您为什么要使用每个接口,以及以 Node.js 为例来演示如何通过两种方式接入以太坊 API。
如果要使用 Infura 的 API 接入以太坊网络,您会怎么做?首先需要确保有一个 Infura 账户。请查看本教程以开始使用!接下来需要确定您需要使用的接口 — Infura 支持 HTTPS 和 WebSocket 接口上的 JSON-RPC。在本教程中,我们将介绍您为什么要使用每个接口,以及以 Node.js 为例来演示如何通过两种方式接入以太坊 API。
HTTPS
HTTP/HTTPS 是单向连接 — 客户端发送请求,然后服务器发送应答 — 并且无状态关联,意味着每个请求获得一个应答后即终止连接。如果您需要获取的数据只需要收集一次或者您要访问旧数据,则使用 HTTPS 接口。HTTPS 经常与简单的 RESTful 应用一起使用。
示例:
在本示例中,我们将编写一个 Node.js 程序。该程序使用 Rinkeby 端点,并使用 eth_getBlockByNumber 向 Infura 发送 RPC 请求,以获得最新的区块数据。从这里开始,我们将该区块编号从十六进制转换为整数,并将区块编号打印到终端。准备好了吗?我们开始吧!
编写该代码的第一步是安装节点(如果您还没有安装,可以使用 npm 或下载)、DotEnv 以及依赖项。如果您不熟悉 dotenv,它是一个单独的文件,不会上传到 GitHub,因此可以确保您的项目 ID 和项目密钥(即环境变量)仍然隐秘地留在您的代码中!有关更多信息,请参阅本媒介文章。
安装完成后,我们可以继续创建 app.js 文件并要求 dotenv 和 request 在顶层。这使得我们可以访问请求数据以及包含在 dotenv 文件中的变量。
const dotenv = require('dotenv').config();
var request = require('request');
复制
接下来,我们查阅文档以了解 eth_getBlockByNumber 所需的标头。标头需包含 Content-Type:application/json,所以我们将它添加到 app.js 文件中:
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
复制
接下来,我们将确定需要发送到服务器的数据。在本例中,我们希望指定:
1.JSON-RPC(最新版本)
2.我们调用的方法
3.我们需要包括的任何区块参数(在本例中,我们需要最新区块的数据,因此将包括参数 `[“latest”,true]`)
4.ID
您可以认为该 dataString 是我们在提交至服务器之前需要填写的 HTML 表单区域。
如需查看如何布局,可以使用 CURL 命令查看文档中提供的示例(不完全是我们需要的参数,但您可以有一个大致的了解):
查看句法,确保代码相同,我们将 var dataString 添加到 app.js:
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var dataString = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",true], "id":1}';
复制
现在我们已经完成了一些工作!但我们从哪里获得数据呢?这是流程的第二步。我们需要创建一个变量,其中声明:
1.url
2.方法(即,POST/GET/等等)
3.标头
4.主体
5.任何必需的授权(您将在其中包括项目密钥的信息)。
我们来看看它们各包含哪些内容:
- url:您要用来接入 API 的 URL。在我们的文档中可以找到一份含有所有网络及其对应 URL 的列表。
• 注:如果在文档中的 URL 部分显示“YOUR-PROJECT-ID”,则表示您将放入来自 dotenv 文件的项目 ID
• 我们要使用的是 Rinkeby 端点,因此将使用 Rinkeby HTTP URL - 方法:要使用的 HTTP 方法(与 dataString 中的“方法”不相同)— 在文档中可找到,每个 JSON-RPC 调用对应具体的 HTTP 方法
• 可能选项:POST/GET/PUT/PATCH/DELETE
• getBlockByNumber 是一个 POST 请求 - 标头:调用所必需的标头
• 我们已经在 var headers 中指定! - 主体:我们随请求一起发送的所有信息
• 在本例中,我们再次通过创建 var dataString 执行了此操作! - 授权:您完成请求所必需的授权(如有,非必需)
• 这是我们的项目密钥所在的位置 — 请注意,user 字段为空,项目密钥(隐藏在 dotenv 文件中)进入 pass 字段
• 在本示例中,我们不需要项目密钥,但为了句法,将它作为备注包含在其中:
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var dataString = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",true], "id":1}';
var options = {
url: `https://rinkeby.infura.io/v3/${process.env.PROJECT_ID}`,
method: 'POST',
headers: headers,
body: dataString,
// auth: {
// 'user': '',
// 'pass': `${process.env.PROJECT_SECRET}`
// }
};
复制
• 注:模板字面量的句法非常重要 — 如果您需要帮助,请参阅本文!
我们现在终于完成了所有设置!现在只需编写函数,该函数将发送请求、获取应答并从该应答中得到 JSON 的可读形式:
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var dataString = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",true], "id":1}';
var options = {
url: `https://rinkeby.infura.io/v3/${process.env.PROJECT_ID}`,
method: 'POST',
headers: headers,
body: dataString,
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
json = response.body;
var obj = JSON.parse(json);
console.log(obj)
}
}
request(options, callback);
复制
这将为我们提供完整的原始 JSON 应答,初一看非常多:
但是,我们知道我们需要的是最新的区块编号(我们得到的是十六进制形式,然后将它转换为整数进行打印输出):
对于本特定情景,您可以通过使用最新的交易并获取其区块编号来获得最新区块,但如果区块中不包含交易,则该方法不可用!使用下面的方法,不管区块中是否包含交易,都能获得区块信息:
查看上一个打印输出的 JSON 数据,我们可以看到 obj.result.number 为我们提供了最新区块的十六进制数据:
每个区块还有一个唯一的哈希存储在哈希字段中,这有时会对后续请求更加有用,但我们现在只着重看这个编号。当我们 console.log(obj.result.number) 时,我们获得该相同的突出显示的十六进制值(无论如何,最好仔细检查您从代码中得到了您需要的内容):
我们可以在代码中定义 hex 作为该 obj.result.number,以访问该十六进制值:
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var dataString = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",true], "id":1}';
var options = {
url: `https://rinkeby.infura.io/v3/${process.env.PROJECT_ID}`,
method: 'POST',
headers: headers,
body: dataString,
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
json = response.body;
var obj = JSON.parse(json);
hex = obj.result.number;
}
}
request(options, callback);
复制
现在到了最后一个关键时刻:将十六进制值转换为整数并打印输出!我们需要调用 parseInt(hex, 16) 来将十六进制字符串转换为整数,然后在控制台中记录该最终结果。hex 是我们在上一步中找到的十六进制代码,16 表示 hex 是一个基数为 16 的十六进制数(如果您未指定,则将假设任何以“0x”开始的字符串均为十六进制数,因此基数为 16,否则基数将为 10):
const dotenv = require('dotenv').config();
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var dataString = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",true], "id":1}';
var options = {
url: `https://rinkeby.infura.io/v3/${process.env.PROJECT_ID}`,
method: 'POST',
headers: headers,
body: dataString,
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
json = response.body;
var obj = JSON.parse(json);
hex = obj.result.number;
final = parseInt(hex, 16)
console.log(final)
}
}
request(options, callback);
复制
当我们运行代码时,我们获得:
成功!您现在知道了如何使用 Infura API 通过 HTTPS 接入以太坊端点!如果您需要查找更多历史数据或只需要获得一次数据,则适合使用该方法,但如果您需要更加频繁地定期获得数据呢?那么您需要使用 WebSocket 连接!
WebSocket
WebSockets 是双向连接且有状态,这意味着客户端与服务器之间的连接始终保持有效,直到任何一方(客户端或服务器)终止。关闭连接后即终止连接。最适合使用 WebSocket 的场合是您希望持续推送/传输数据到已经建立的连接,例如在加密货币交易平台、游戏应用程序或聊天应用程序中,您希望不断地实时更新数据。
示例:
在本示例中,我们将编写一个 Node.js 程序,再次使用 Rinkeby 端点,利用 WebSocket 连接并通过 WebSocket 连接上的 newHeads 订阅类型来获取最新的区块标头信息。在这里,我们希望看到来自 WebSocket 连接的最新区块标头数据的跟踪日志输出。我们开始吧!
首先,我们需要安装 npm 并要求必需的常量 — dotenv 和 ws(适用于 WebSocket)。这使我们能够分别隐藏项目 ID 和密钥并连接到 WebSocket。
const dotenv = require('dotenv').config();
const WebSocket = require('ws');
接下来,我们将通过创建新的 WebSocket 实例来打开 WebSocket 连接:
const dotenv = require('dotenv').config();
const WebSocket = require('ws');
const ws = new WebSocket(`wss://ropsten.infura.io/ws/v3/${process.env.PROJECT_ID}`);
复制
我们再次使用 dotenv 文件来隐秘地保存我们的项目 ID,因此,我们在这里使用了模板字面量。
如果您浏览 HTTPS 部分,希望您熟悉其中的某些内容!建立 WebSocket 连接后,我们将打开它,然后发送数据(再次将它看作是我们要向服务器提交表单,将我们的请求告诉它)。在本例中,我们采用的方法是 eth_subscribe(因此我们需要订阅最新标头),参数为 newHeads,这是我们需要从中获得结果的订阅类型:
const dotenv = require('dotenv').config();
const WebSocket = require('ws');
const ws = new WebSocket(`wss://ropsten.infura.io/ws/v3/${process.env.PROJECT_ID}`);
ws.on('open', function open() {
ws.send('{"jsonrpc":"2.0","method":"eth_subscribe","params":["newHeads"], "id":1}');
});
复制
我们现在需要能查看在应答中收到的数据,因此我们将为解析的 JSON 数据分配一个变量并 console.log,以获取我们需要的标头数据:
const dotenv = require('dotenv').config();
const WebSocket = require('ws');
const ws = new WebSocket(`wss://ropsten.infura.io/ws/v3/${process.env.PROJECT_ID}`);
ws.on('open', function open() {
ws.send('{"jsonrpc":"2.0","method":"eth_subscribe","params":["newHeads"], "id":1}');
});
ws.on('message', function incoming(data) {
var obj = JSON.parse(data);
console.log(obj);
ws.close()
});
复制
请注意,我们最后关闭了 WebSocket — 这一步非常重要,因为我们只需要获得最新的区块标头数据!由于我们关闭了 WebSocket,因此我们获得了正好符合我们需要的应答(最新区块的标头及其数据):
想知道如果不关闭 WebSocket 连接会发生什么吗?当然!我们快速获得该打印输出,因此它会不断地进行更新……明白了?下面的示例说明了保持 WebSocket 连接状态会发生什么:
就是这样!您现在知道了如何建立 WebSocket 连接、使用参数调用方法以及获得最新区块(以及最新区块的运行列表(如果您需要))的输出。
现在去进一步了解 Infura API 吧!
希望了解更多?
在我们的文档中查看通过 HTTPS 和 WebSocket 可以进行哪些请求以及一些更加复杂的概念,例如速率限制!
订阅我们的新闻资讯,以获取更多 Web3 教程和产品新闻。和往常一样,如果您有任何问题或请求,可以加入我们的社区或直接联系我们。