Infura 以太坊 API 入门

如果要使用 Infura 的 API 接入以太坊网络,您会怎么做?首先需要确保有一个 Infura 账户。请查看本教程以开始使用!接下来需要确定您需要使用的接口 — Infura 支持 HTTPSWebSocket 接口上的 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.任何必需的授权(您将在其中包括项目密钥的信息)。

我们来看看它们各包含哪些内容:

  1. url:您要用来接入 API 的 URL。在我们的文档中可以找到一份含有所有网络及其对应 URL 的列表。
    • 注:如果在文档中的 URL 部分显示“YOUR-PROJECT-ID”,则表示您将放入来自 dotenv 文件的项目 ID
    • 我们要使用的是 Rinkeby 端点,因此将使用 Rinkeby HTTP URL
  2. 方法:要使用的 HTTP 方法(与 dataString 中的“方法”相同)— 在文档中可找到,每个 JSON-RPC 调用对应具体的 HTTP 方法
    • 可能选项:POST/GET/PUT/PATCH/DELETE
    • getBlockByNumber 是一个 POST 请求
  3. 标头:调用所必需的标头
    • 我们已经在 var headers 中指定!
  4. 主体:我们随请求一起发送的所有信息
    • 在本例中,我们再次通过创建 var dataString 执行了此操作!
  5. 授权:您完成请求所必需的授权(如有,非必需)
    • 这是我们的项目密钥所在的位置 — 请注意,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 教程和产品新闻。和往常一样,如果您有任何问题或请求,可以加入我们的社区直接联系我们