概述: 用Go订阅以太坊中最新区块的教程。

订阅新区块

在本节中,我们将讨论如何设置订阅以便在新区块被开采时获取事件。首先,我们需要一个支持websocket RPC的以太坊服务提供者。在示例中,我们将使用infura 的websocket端点。

  1. client, err := ethclient.Dial("wss://ropsten.infura.io/ws")
  2. if err != nil {
  3. log.Fatal(err)
  4. }

接下来,我们将创建一个新的通道,用于接收最新的区块头。

  1. headers := make(chan *types.Header)

现在我们调用客户端的SubscribeNewHead方法,它接收我们刚创建的区块头通道,该方法将返回一个订阅对象。

  1. sub, err := client.SubscribeNewHead(context.Background(), headers)
  2. if err != nil {
  3. log.Fatal(err)
  4. }

订阅将推送新的区块头事件到我们的通道,因此我们可以使用一个select语句来监听新消息。订阅对象还包括一个error通道,该通道将在订阅失败时发送消息。

  1. for {
  2. select {
  3. case err := <-sub.Err():
  4. log.Fatal(err)
  5. case header := <-headers:
  6. fmt.Println(header.Hash().Hex()) // 0xbc10defa8dda384c96a17640d84de5578804945d347072e091b4e5f390ddea7f
  7. }
  8. }

要获得该区块的完整内容,我们可以将区块头的摘要传递给客户端的BlockByHash函数。

  1. block, err := client.BlockByHash(context.Background(), header.Hash())
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. fmt.Println(block.Hash().Hex()) // 0xbc10defa8dda384c96a17640d84de5578804945d347072e091b4e5f390ddea7f
  6. fmt.Println(block.Number().Uint64()) // 3477413
  7. fmt.Println(block.Time().Uint64()) // 1529525947
  8. fmt.Println(block.Nonce()) // 130524141876765836
  9. fmt.Println(len(block.Transactions())) // 7

正如您所见,您可以读取整个区块的元数据字段,交易列表等等。

完整代码

block_subscribe.go

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "github.com/ethereum/go-ethereum/core/types"
  7. "github.com/ethereum/go-ethereum/ethclient"
  8. )
  9. func main() {
  10. client, err := ethclient.Dial("wss://ropsten.infura.io/ws")
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. headers := make(chan *types.Header)
  15. sub, err := client.SubscribeNewHead(context.Background(), headers)
  16. if err != nil {
  17. log.Fatal(err)
  18. }
  19. for {
  20. select {
  21. case err := <-sub.Err():
  22. log.Fatal(err)
  23. case header := <-headers:
  24. fmt.Println(header.Hash().Hex()) // 0xbc10defa8dda384c96a17640d84de5578804945d347072e091b4e5f390ddea7f
  25. block, err := client.BlockByHash(context.Background(), header.Hash())
  26. if err != nil {
  27. log.Fatal(err)
  28. }
  29. fmt.Println(block.Hash().Hex()) // 0xbc10defa8dda384c96a17640d84de5578804945d347072e091b4e5f390ddea7f
  30. fmt.Println(block.Number().Uint64()) // 3477413
  31. fmt.Println(block.Time().Uint64()) // 1529525947
  32. fmt.Println(block.Nonce()) // 130524141876765836
  33. fmt.Println(len(block.Transactions())) // 7
  34. }
  35. }
  36. }