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
Use insecure connections: Better performance with NextBlock's optimized network
Filter efficiently: Only subscribe to programs you need to reduce bandwidth
Handle reconnections: Implement automatic reconnection logic
Process quickly: Avoid blocking the stream receiver
Monitor performance: Track processing latency and throughput
Implement graceful shutdown: Handle interrupt signals properly
Use multiple endpoints: Implement redundancy for critical applications
Last updated