使用 WebSocket
这是一篇关于使用 WebSocket 和 Alchemy 向以太坊区块链发起请求的入门指南。
(在新标签页中打开)WebSocket 与 HTTP 的对比
与 HTTP 不同,使用 WebSocket 时,你不需要在想要获取特定信息时不断发起请求。WebSocket 会为你维持一个网络连接(如果配置正确的话)并监听变化。
与任何网络连接一样,你不应假设 WebSocket 会永远保持打开状态而不中断,但手动正确处理掉线和重连可能会非常具有挑战性。WebSocket 的另一个缺点是,你无法在响应中获得 HTTP 状态码,只能获得错误消息。
Alchemy Web3 (在新标签页中打开) 自动添加了对 WebSocket 故障和重试的处理,无需任何配置。
试一试
测试 WebSocket 最简单的方法是安装一个用于发起 WebSocket 请求的命令行工具,例如 wscat (在新标签页中打开)。使用 wscat,你可以按如下方式发送请求:
注意:如果你有 Alchemy 账户,你可以将 demo 替换为你自己的 API 密钥。在此处注册免费的 Alchemy 账户! (在新标签页中打开)
wscat -c wss://eth-mainnet.ws.alchemyapi.io/ws/demo
> {"jsonrpc": "2.0", "id": 0, "method": "eth_gasPrice"}
< {"jsonrpc": "2.0", "result": "0xb2d05e00", "id": 0}
如何使用 WebSocket
首先,使用你的应用程序的 WebSocket URL 打开一个 WebSocket。你可以通过在 你的仪表板 (在新标签页中打开) 中打开应用程序页面并点击“View Key”(查看密钥)来找到你的应用程序的 WebSocket URL。请注意,你的应用程序的 WebSocket URL 与其 HTTP 请求的 URL 不同,但两者都可以通过点击“View Key”找到。
Alchemy API 参考 (在新标签页中打开) 中列出的任何 API 都可以通过 WebSocket 使用。为此,请使用与作为 HTTP POST 请求主体发送的相同有效载荷,但改为通过 WebSocket 发送该有效载荷。
使用 Web3
在使用像 Web3 这样的客户端库时,过渡到 WebSocket 非常简单。只需在实例化 Web3 客户端时传递 WebSocket URL 而不是 HTTP URL 即可。例如:
const web3 = new Web3("wss://eth-mainnet.ws.alchemyapi.io/ws/your-api-key")
web3.eth.getBlockNumber().then(console.log) // -> 7946893
订阅 API
通过 WebSocket 连接时,你可以使用两个额外的方法:eth_subscribe 和 eth_unsubscribe。这些方法将允许你监听特定事件并立即收到通知。
eth_subscribe
为指定事件创建新的订阅。了解有关 eth_subscribe 的更多信息 (在新标签页中打开)。
参数
- 订阅类型
- 可选参数
第一个参数指定要监听的事件类型。第二个参数包含取决于第一个参数的附加选项。下面描述了不同的订阅类型、它们的选项以及它们的事件有效载荷。
返回值
订阅 ID:此 ID 将附加到任何接收到的事件中,也可用于使用 eth_unsubscribe 取消订阅。
订阅事件
在订阅处于活动状态时,你将收到事件,这些事件是具有以下字段的对象:
jsonrpc:始终为 "2.0"method:始终为 "eth_subscription"params:具有以下字段的对象:subscription:由创建此订阅的eth_subscribe调用返回的订阅 ID。result:一个对象,其内容因订阅类型而异。
订阅类型
alchemy_newFullPendingTransactions
返回添加到待处理状态的所有交易的交易信息。此订阅类型订阅待处理交易,类似于标准的 Web3 调用 web3.eth.subscribe("pendingTransactions"),但不同之处在于它发出_完整的交易信息_而不仅仅是交易哈希。
示例:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["alchemy_newFullPendingTransactions"]}
< {"id":1,"result":"0x9a52eeddc2b289f985c0e23a7d8427c8","jsonrpc":"2.0"}
< {
"jsonrpc":"2.0",
"method":"eth_subscription",
"params":{
"result":{
"blockHash":null,
"blockNumber":null,
"from":"0xa36452fc31f6f482ad823cd1cf5515177d57667f",
"gas":"0x1adb0",
"gasPrice":"0x7735c4d40",
"hash":"0x50bff0736c713458c92dd1848d12f3354149be1363123dae35e94e0f2a9d56bf",
"input":"0xa9059cbb0000000000000000000000000d0707963952f2fba59dd06f2b425ace40b492fe0000000000000000000000000000000000000000000015b1111266cfca100000",
"nonce":"0x0",
"to":"0xea38eaa3c86c8f9b751533ba2e562deb9acded40",
"transactionIndex":null,
"value":"0x0",
"v":"0x26",
"r":"0x195c2c1ed126088e12d290aa93541677d3e3b1d10f137e11f86b1b9227f01e3b",
"s":"0x60fc4edbf1527832a2a36dbc1e63ed6193a6eee654472fbebbf88ef1750b5344"},
"subscription":"0x9a52eeddc2b289f985c0e23a7d8427c8"
}
}
newHeads
只要有新区块头添加到链中,就会发出一个事件,包括在链重组期间。
当发生链重组时,此订阅将发出一个包含新链所有新区块头的事件。特别是,这意味着你可能会看到发出多个具有相同高度的区块头,当发生这种情况时,应将较晚的区块头视为重组后的正确区块头。
示例:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newHeads"]}
< {"jsonrpc":"2.0","id":2,"result":"0x9ce59a13059e417087c02d3236a0b1cc"}
< {
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"result": {
"extraData": "0xd983010305844765746887676f312e342e328777696e646f7773",
"gasLimit": "0x47e7c4",
"gasUsed": "0x38658",
"logsBloom":
"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x084149998194cc5f",
"number": "0x1348c9",
"parentHash": "0x7736fab79e05dc611604d22470dadad26f56fe494421b5b333de816ce1f25701",
"receiptRoot": "0x2fab35823ad00c7bb388595cb46652fe7886e00660a01e867824d3dceb1c8d36",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xb3346685172db67de536d8765c43c31009d0eb3bd9c501c9be3229203f15f378",
"timestamp": "0x56ffeff8",
"transactionsRoot": "0x0167ffa60e3ebc0b080cdb95f7c0087dd6c0e61413140e39d94d3468d7c9689f"
},
"subscription": "0x9ce59a13059e417087c02d3236a0b1cc"
}
}
logs
发出属于新添加区块且符合指定过滤标准的日志。
当发生链重组时,属于旧链上区块的日志将再次发出,其 removed 属性设置为 true。此外,还会发出属于新链上区块的日志,这意味着在重组的情况下,可能会多次看到同一笔交易的日志。
参数
- 具有以下字段的对象:
address(可选):表示地址的字符串或此类字符串的数组。- 仅发出从这些地址之一创建的日志。
topics:主题说明符数组。- 每个主题说明符要么是
null,要么是表示主题的字符串,要么是字符串数组。 - 数组中非
null的每个位置,都会将发出的日志限制为仅包含在该位置具有给定主题之一的日志。
- 每个主题说明符要么是
主题规范的一些示例:
[]:允许任何主题。[A]:A 在第一个位置(以及之后的任何内容)。[null, B]:任何内容在第一个位置,B 在第二个位置(以及之后的任何内容)。[A, B]:A 在第一个位置,B 在第二个位置(以及之后的任何内容)。[[A, B], [A, B]]:(A 或 B)在第一个位置,(A 或 B)在第二个位置(以及之后的任何内容)。
示例:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["logs", {"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", "topics": ["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]}
< {"jsonrpc":"2.0","id":2,"result":"0x4a8a4c0517381924f9838102c5a4dcb7"}
< {
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x4a8a4c0517381924f9838102c5a4dcb7",
"result": {
"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd",
"blockHash": "0x61cdb2a09ab99abf791d474f20c2ea89bf8de2923a2d42bb49944c8c993cbf04",
"blockNumber": "0x29e87",
"data": "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003",
"logIndex":"0x0",
"topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"],
"transactionHash": "0xe044554a0a55067caafd07f8020ab9f2af60bdfe337e395ecd84b4877a3d1ab4",
"transactionIndex": "0x0"
}
}
}
eth_unsubscribe
取消现有订阅,以便不再发送任何事件。
参数
- 订阅 ID,即先前从
eth_subscribe调用返回的 ID。
返回值
如果成功取消订阅,则返回 true;如果不存在具有给定 ID 的订阅,则返回 false。
示例:
请求
curl https://eth-mainnet.alchemyapi.io/v2/your-api-key
-X POST
-H "Content-Type: application/json"
-d '{"id": 1, "method": "eth_unsubscribe", "params": ["0x9cef478923ff08bf67fde6c64013158d"]}'
结果
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
免费 注册 Alchemy (在新标签页中打开),查看 我们的文档 (在新标签页中打开),如需获取最新消息,请在 推特 (在新标签页中打开) 上关注我们。