Skip to main content

Making Yellowstone Geyser gRPC Requests with Go

Updated on
Nov 12, 2025

Overviewโ€‹

Go is a statically-typed, compiled language known for its simplicity, efficiency, and strong concurrency support. Follow the official installation guide to install Go. Verify the installation:

go version

Authentication for Go Requestsโ€‹

To securely access Yellowstone gRPC, authentication is required. Quicknode endpoints consist of two components: endpoint name and token. You must use these components to configure a gRPC client with authentication credentials.

There are two authentication methods:

  1. Basic Authentication
  2. x-token Authentication

This document provides implementation details for both methods.


Basic Authenticationโ€‹

The getClientWithBasicAuth function demonstrates how to handle authentication using Basic Authentication. It encodes the credentials in base64 and adds them to the authorization header.

Implementationโ€‹

import (
"context"
"crypto/tls"
"encoding/base64"
"fmt"
"log"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

func getClientWithBasicAuth(endpoint, token string) (*grpc.ClientConn, error) {
target := endpoint + ".solana-mainnet.quiknode.pro:10000"
conn, err := grpc.Dial(target,
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithPerRPCCredentials(basicAuth{
username: endpoint,
password: token,
}),
)
if err != nil {
return nil, fmt.Errorf("unable to dial endpoint: %w", err)
}
return conn, nil
}

type basicAuth struct {
username string
password string
}

func (b basicAuth) GetRequestMetadata(ctx context.Context, in ...string) (map[string]string, error) {
auth := b.username + ":" + b.password
encoded := base64.StdEncoding.EncodeToString([]byte(auth))
return map[string]string{"authorization": "Basic " + encoded}, nil
}

func (basicAuth) RequireTransportSecurity() bool {
return true
}

Usageโ€‹

conn, err := getClientWithBasicAuth("ENDPOINT_NAME", "TOKEN")
if err != nil {
log.Fatalf("failed to connect: %v", err)
}
defer conn.Close()

x-token Authenticationโ€‹

The getClientWithXToken function demonstrates how to authenticate using an x-token. This method attaches the token to the x-token header of each request.

Implementationโ€‹

import (
"context"
"crypto/tls"
"fmt"
"log"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

func getClientWithXToken(endpoint, token string) (*grpc.ClientConn, error) {
target := endpoint + ".solana-mainnet.quiknode.pro:10000"
conn, err := grpc.Dial(target,
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithPerRPCCredentials(xTokenAuth{
token: token,
}),
)
if err != nil {
return nil, fmt.Errorf("unable to dial endpoint: %w", err)
}
return conn, nil
}

type xTokenAuth struct {
token string
}

func (x xTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{"x-token": x.token}, nil
}

func (xTokenAuth) RequireTransportSecurity() bool {
return true
}

Usageโ€‹

conn, err := getClientWithXToken("ENDPOINT_NAME", "TOKEN")
if err != nil {
log.Fatalf("failed to connect: %v", err)
}
defer conn.Close()


Note:

To learn how to split your Solana Yellowstone enabled URL into endpoint and token, refer to this section - Endpoint and Token Configuration

The below section provides a step-by-step process to set up a Go environment for making gRPC requests to the Yellowstone Geyser Plugin. The instructions include setting up Go, configuring dependencies, and implementing authentication mechanisms.

Initiating the Go Project for Yellowstone gRPCโ€‹

Step 1: Create a New Project Directoryโ€‹

Create a dedicated directory for your Yellowstone gRPC project and navigate into it:

mkdir yellowstone-grpc
cd yellowstone-grpc

Step 2: Initialize a Go Moduleโ€‹

Initialize a new Go module for your project:

go mod init yellowstone-grpc # directory name

Step 3: Install Required Dependenciesโ€‹

Install the necessary Go dependencies for gRPC and Protocol Buffers:

go get google.golang.org/grpc
go get google.golang.org/protobuf

Step 4: Organize Your Project Directoryโ€‹

First, create a proto folder to store the .pb.go files:

mkdir proto

You can get the pre-generated files from Yellowstone gRPC official Github Repo. Download all the three files and place the following files into the proto directory:

< br />

  • geyser_pb.go
  • geyser_grpc.pb.go
  • solana_storage_pb.go

The project structure might look like this:

yellowstone-grpc/
โ”œโ”€โ”€ go.mod
โ”œโ”€โ”€ go.sum
โ”œโ”€โ”€ proto/
โ”‚ โ”œโ”€โ”€ geyser_pb.go
โ”‚ โ”œโ”€โ”€ geyser_grpc.pb.go
โ”‚ โ”œโ”€โ”€ solana_storage_pb.go

Step 5: Create a Main Go Fileโ€‹

Set up a main Go file for implementing client or server logic:

touch main.go

You can copy and paste the following sample code into your main.go file to get started. The example demonstrates how to interact with a gRPC service to fetch the latest blockhash information.

package main

import (
"context"
"crypto/tls"
"fmt"
"log"
"time"
// "encoding/json"
// "github.com/mr-tron/base58"

pb "yellowstone-grpc/proto" // proto directory path

"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/encoding/gzip"
"google.golang.org/grpc/keepalive"
)

var (
endpoint = "example-guide-demo.solana-mainnet.quiknode.pro:10000"
token = "123456789abcdefghijklmnopquerst"
)

var kacp = keepalive.ClientParameters{
Time: 10 * time.Second,
Timeout: time.Second,
PermitWithoutStream: true,
}

// tokenAuth implements the credentials.PerRPCCredentials interface
type tokenAuth struct {
token string
}

func (t tokenAuth) GetRequestMetadata(ctx context.Context, in ...string) (map[string]string, error) {
return map[string]string{"x-token": t.token}, nil
}

func (tokenAuth) RequireTransportSecurity() bool {
return true
}

func main() {
opts := []grpc.DialOption{
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithKeepaliveParams(kacp),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(1024*1024*1024), grpc.UseCompressor(gzip.Name)),
grpc.WithPerRPCCredentials(tokenAuth{token: token}),
}

conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()

client := pb.NewGeyserClient(conn)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

latestBlockHash, err := client.GetLatestBlockhash(ctx, &pb.GetLatestBlockhashRequest{})
if err != nil {
log.Fatalf("Failed to get latest blockhash: %v", err)
}

fmt.Printf("Latest Blockhash Information: ")
fmt.Printf(" Blockhash: %+v", latestBlockHash)
}

Step 6: Run Your Codeโ€‹

Before running your code, clean up and ensure all dependencies are correctly resolved:

go mod tidy

Build and run the project using:

go run main.go

Additional Resourcesโ€‹

For more information about working with Yellowstone and the Geyser Plugin in Go, refer to the Yellowstone Go Guide.

We โค๏ธ Feedback!โ€‹

If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!

Share this doc