description: Tutorial on how to query transactions on the blockchain with Go.

Querying Transactions

In the previous section we learned how to read a block and all its data given the block number. We can read the transactions in a block by calling the Transactions method which returns a list of Transaction type. It’s then trivial to iterate over the collection and retrieve any information regarding the transaction.

  1. for _, tx := range block.Transactions() {
  2. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  3. fmt.Println(tx.Value().String()) // 10000000000000000
  4. fmt.Println(tx.Gas()) // 105000
  5. fmt.Println(tx.GasPrice().Uint64()) // 102000000000
  6. fmt.Println(tx.Nonce()) // 110644
  7. fmt.Println(tx.Data()) // []
  8. fmt.Println(tx.To().Hex()) // 0x55fE59D8Ad77035154dDd0AD0388D09Dd4047A8e
  9. }

In order to read the sender address, we need to call AsMessage on the transaction which returns a Message type containing a function to return the sender (from) address. The AsMessage method requires the EIP155 signer, which we derive the chain ID from the client.

  1. chainID, err := client.NetworkID(context.Background())
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. if msg, err := tx.AsMessage(types.NewEIP155Signer(chainID)); err == nil {
  6. fmt.Println(msg.From().Hex()) // 0x0fD081e3Bb178dc45c0cb23202069ddA57064258
  7. }

Each transaction has a receipt which contains the result of the execution of the transaction, such as any return values and logs, as well as the status which will be 1 (success) or 0 (fail).

  1. receipt, err := client.TransactionReceipt(context.Background(), tx.Hash())
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. fmt.Println(receipt.Status) // 1
  6. fmt.Println(receipt.Logs) // ...

Another way to iterate over transaction without fetching the block is to call the client’s TransactionInBlock method. This method accepts only the block hash and the index of the transaction within the block. You can call TransactionCount to know how many transactions there are in the block.

  1. blockHash := common.HexToHash("0x9e8751ebb5069389b855bba72d94902cc385042661498a415979b7b6ee9ba4b9")
  2. count, err := client.TransactionCount(context.Background(), blockHash)
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. for idx := uint(0); idx < count; idx++ {
  7. tx, err := client.TransactionInBlock(context.Background(), blockHash, idx)
  8. if err != nil {
  9. log.Fatal(err)
  10. }
  11. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  12. }

You can also query for a single transaction directly given the transaction hash by using TransactionByHash.

  1. txHash := common.HexToHash("0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2")
  2. tx, isPending, err := client.TransactionByHash(context.Background(), txHash)
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  7. fmt.Println(isPending) // false

Full code

transactions.go

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "math/big"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/core/types"
  9. "github.com/ethereum/go-ethereum/ethclient"
  10. )
  11. func main() {
  12. client, err := ethclient.Dial("https://mainnet.infura.io")
  13. if err != nil {
  14. log.Fatal(err)
  15. }
  16. blockNumber := big.NewInt(5671744)
  17. block, err := client.BlockByNumber(context.Background(), blockNumber)
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. for _, tx := range block.Transactions() {
  22. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  23. fmt.Println(tx.Value().String()) // 10000000000000000
  24. fmt.Println(tx.Gas()) // 105000
  25. fmt.Println(tx.GasPrice().Uint64()) // 102000000000
  26. fmt.Println(tx.Nonce()) // 110644
  27. fmt.Println(tx.Data()) // []
  28. fmt.Println(tx.To().Hex()) // 0x55fE59D8Ad77035154dDd0AD0388D09Dd4047A8e
  29. chainID, err := client.NetworkID(context.Background())
  30. if err != nil {
  31. log.Fatal(err)
  32. }
  33. if msg, err := tx.AsMessage(types.NewEIP155Signer(chainID)); err == nil {
  34. fmt.Println(msg.From().Hex()) // 0x0fD081e3Bb178dc45c0cb23202069ddA57064258
  35. }
  36. receipt, err := client.TransactionReceipt(context.Background(), tx.Hash())
  37. if err != nil {
  38. log.Fatal(err)
  39. }
  40. fmt.Println(receipt.Status) // 1
  41. }
  42. blockHash := common.HexToHash("0x9e8751ebb5069389b855bba72d94902cc385042661498a415979b7b6ee9ba4b9")
  43. count, err := client.TransactionCount(context.Background(), blockHash)
  44. if err != nil {
  45. log.Fatal(err)
  46. }
  47. for idx := uint(0); idx < count; idx++ {
  48. tx, err := client.TransactionInBlock(context.Background(), blockHash, idx)
  49. if err != nil {
  50. log.Fatal(err)
  51. }
  52. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  53. }
  54. txHash := common.HexToHash("0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2")
  55. tx, isPending, err := client.TransactionByHash(context.Background(), txHash)
  56. if err != nil {
  57. log.Fatal(err)
  58. }
  59. fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
  60. fmt.Println(isPending) // false
  61. }