Getting blockchain data from Bitquery in Golang

In this tutorial, we will learn how to retrieve the latest 10 token transfers for a specific Ethereum token using the Go language to make an HTTP request to the Bitquery server and parse the JSON response to extract the necessary information.

We will also use the hashicorp/go-retryablehttp package to automatically retry failed HTTP requests with an exponential backoff strategy.

Prerequisites

  1. Install Go on your system if you haven’t already. You can download the latest version of Go from the official website: All releases - The Go Programming Language
  2. Open a terminal or command prompt and navigate to your project directory.
  3. Run the following command to install the required packages:

go get github.com/hashicorp/go-retryablehttp
This command will download and install the “go-retryablehttp” package from the GitHub repository.

Once the packages are installed, you can proceed with running the code.

Tutorial

  1. First, create a new Go file and name it main.go.

  2. Add the following package statement to the top of the file:

    package main

    This tells Go that this is the main package for the file.

  3. Add the required import statements:

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
    "time"

    "github.com/hashicorp/go-retryablehttp"
)

These import statements bring in the required packages and libraries for the code to work.

  1. Define a struct for the response:
type Response struct {
    Data interface{} `json:"data"`
}

This defines a struct named Response that has a single field Data, which is an interface{} that can hold any data type. The json tag is used to specify the field name for marshaling and unmarshaling JSON.

  1. Define the main function:
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

This function sets up a basic HTTP server that listens on port 8080 and routes all incoming requests to the handler function.

  1. Define the handler function:

The handler function is an HTTP request handler function that is invoked by the Go HTTP server whenever a client sends an HTTP request to the server’s root URL (“/”).

This function first sets up the required variables and parameters for the GraphQL API request to be sent to the Bitquery server. It sets the API endpoint URL, the HTTP method to be used (POST), and the authentication key required to access the API.

func handler(w http.ResponseWriter, r *http.Request) {
    url := "https://streaming.bitquery.io/graphql"
    method := "POST"
    apiKey := "YOUR KEY"
    payload := strings.NewReader(`{"query":"{\n  EVM(dataset: archive, network: eth) {\n    Transfers(\n      where: {Transfer: {Currency: {SmartContract: {is: \"0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D\"}}}}\n      limit: {count: 10, offset: 0}\n      orderBy: {descending: Block_Number}\n    ) {\n      Transfer {\n        Currency {\n          SmartContract\n          Name\n          Decimals\n          Fungible\n          HasURI\n          Symbol\n        }\n        Id\n        URI\n        Data\n        owner: Receiver\n      }\n    }\n  }\n}\n","variables":"{}"}`)

    // Set up the retryable client with a maximum of 5 retries and a wait time of 5-30 seconds between retries.
    retryClient := retryablehttp.NewClient()
    retryClient.RetryMax = 5
    retryClient.RetryWaitMin = 5 * time.Second
    retryClient.RetryWaitMax = 30 * time.Second

    // Create the request and set headers.

    req, err := retryablehttp.NewRequest(method, url, payload)
    if err != nil {
        fmt.Println(err)
        return
    }
    req.Header.Add("Content-Type", "application/json")
    req.Header.Add("X-API-KEY", apiKey)

    // Send the request using the retryable client.
    res, err := retryClient.Do(req)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer res.Body.Close()

    // Read the response body.
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    // Unmarshal the JSON response into the Response struct.
    var response Response
    err = json.Unmarshal(body, &response)
    if err != nil {
        fmt.Println(err)
        return
    }

Next, it creates a new retryablehttp.Client with some custom retry configuration settings, such as the maximum number of retries and the minimum and maximum wait times between retries.

It then creates a new HTTP request with the previously defined variables and sends it to the Bitquery server using the retryClient.Do(req) method call.

Once a response is received, it reads the response body and attempts to unmarshal the JSON response into a Response struct, which contains a Data field that holds the GraphQL query results.

Finally, the function sets the content type of the response to JSON and writes the response body to the client using the json.NewEncoder(w).Encode(response.Data) method call.

Run the code with the command

 go run main.go

open localhost:8080 on your browser and you should see the data

You can get the complete code repo here