description: Tutorial on how to subscribe to latest blocks in Ethereum with Go.

Subscribing to New Blocks

In this section we’ll go over how to set up a subscription to get events when their is a new block mined. First thing is we need an Ethereum provider that supports RPC over websockets. In this example we’ll use the infura websocket endpoint.

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

Next we’ll create a new channel that will be receiving the latest block headers.

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

Now we call the client’s SubscribeNewHead method which takes in the headers channel we just created, which will return a subscription object.

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

The subscription will push new block headers to our channel so we’ll use a select statement to listen for new messages. The subscription object also contains an error channel that will send a message in case of a failure with the subscription.

  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. }

To get the full contents of the block, we can pass the block header hash to the client’s BlockByHash function.

  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()) // 1529525947
  8. fmt.Println(block.Nonce()) // 130524141876765836
  9. fmt.Println(len(block.Transactions())) // 7

As you can see, you can read the entire block’s metadata fields, list of transactions, and much more.

Full code

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()) // 1529525947
  32. fmt.Println(block.Nonce()) // 130524141876765836
  33. fmt.Println(len(block.Transactions())) // 7
  34. }
  35. }
  36. }