Go Example

Complete Go implementation for streaming Solana transactions from NextBlock's TX Stream API, optimized for trading bots and fast transaction detection.

The example is hosted at github.com/nextblock-ag/nextblock-stream-examples

Prerequisites

go mod init nextblock-tx-stream-example
go get github.com/gagliardetto/binary github.com/gagliardetto/solana-go
go get google.golang.org/grpc

# Generate the TX Stream proto client from the proto specification
# In the example repo, dependencies and the generated .go files are already available

Example

package main

import (
	"context"
	"fmt"
	"log"
	"math"
	"math/rand/v2"
	"time"

	bin "github.com/gagliardetto/binary"
	"github.com/gagliardetto/solana-go"
	"github.com/nextblock-stream-examples/golang-example/protos"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/keepalive"
)

/*
the auth message needs to be built clients-side.
it is a pipe-separated string made of:
1. domain that's being connected to (e.g. fra.stream.nextblock.io)
2. the publickey that sent the fee to strmuYvHKeA1qvHqooUpwUk2BFwaAmMbK9WXY9mh2GJ
3. a random nonce
4. the current unix timestamp

it is then signed by the supplied publickey.
*/

func buildAuthMessage(domain string, authenticatedPublicKey solana.PublicKey) string {
	return fmt.Sprintf("%s|%s|%d|%d", domain, authenticatedPublicKey.String(), rand.IntN(math.MaxInt64), time.Now().Unix())
}

func main() {
	ctx := context.Background()

	domain := "ny.stream.nextblock.io:22221"
	authenticationPrivateKey := solana.MustPrivateKeyFromBase58("YOUR_PRIVATE_KEY")
	authenticationPublicKey := authenticationPrivateKey.PublicKey()

	authenticationMessage := buildAuthMessage(domain, authenticationPrivateKey.PublicKey())
	authenticationSignature, err := authenticationPrivateKey.Sign([]byte(authenticationMessage))
	if err != nil {
		log.Fatalf("error signing authMessage: %v", err)
	}

	creds := insecure.NewCredentials()
	conn, err := grpc.NewClient(
		domain,
		grpc.WithTransportCredentials(creds),
		grpc.WithKeepaliveParams(keepalive.ClientParameters{
			Time:                5 * time.Second,
			Timeout:             time.Second,
			PermitWithoutStream: false,
		}),
	)
	if err != nil {
		log.Fatalf("error creating new grpc conn: %v", err)
	}

	client := protos.NewNextStreamServiceClient(conn)

	sub, err := client.SubscribeNextStream(
		ctx,
		&protos.NextStreamSubscription{
			AuthenticationPublickey: authenticationPublicKey.String(),
			AuthenticationMessage:   authenticationMessage,
			AuthenticationSignature: authenticationSignature.String(),
			Accounts:                []string{solana.MustPublicKeyFromBase58("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8").String()},
		},
	)
	if err != nil {
		log.Fatalf("error SubscribeNextStream: %v", err)
	}

	for {
		msg, err := sub.Recv()
		if err != nil {
			log.Fatalf("error receiving from sub: %v", err)
		}

		tx := new(solana.Transaction)
		err = tx.UnmarshalWithDecoder(bin.NewBinDecoder(msg.Packet.Transaction))
		if err != nil {
			log.Fatalf("error unmarshaslling tx: %v", err)
		}

		log.Printf("got new sig %s on slot %d", tx.Signatures[0], msg.Packet.Slot)
	}
}

Usage Examples

# Log signature + slot for all filtered transactions
go run main.go

Available Endpoints

Choose the endpoint closest to your location:

  • Frankfurt: fra.stream.nextblock.io:22221

  • Amsterdam: amsterdam.stream.nextblock.io:22221

  • London: london.stream.nextblock.io:22221

  • Singapore: singapore.stream.nextblock.io:22221

  • Tokyo: tokyo.stream.nextblock.io:22221

  • New York: ny.stream.nextblock.io:22221

  • Salt Lake City: slc.stream.nextblock.io:22221

Best Practices for Trading Bots

  1. Use insecure connections: Better performance with NextBlock's optimized network

  2. Filter efficiently: Only subscribe to programs you need to reduce bandwidth

  3. Handle reconnections: Implement automatic reconnection logic

  4. Process quickly: Avoid blocking the stream receiver

  5. Monitor performance: Track processing latency and throughput

  6. Implement graceful shutdown: Handle interrupt signals properly

  7. Use multiple endpoints: Implement redundancy for critical applications

Last updated