# 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](https://github.com/nextblock-ag/nextblock-stream-examples/tree/main/golang-example)

## Prerequisites

```bash
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

```go
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

```bash
# 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`
* **Dublin**: `dublin.stream.nextblock.io:22221`
* **Vilnius**: `vilnius.stream.nextblock.io:22221`

## Best Practices for Trading Bots

1. **Match the endpoint requirements**: Follow the transport settings shown in the example for the current TX Stream service
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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nextblock.io/api/tx-stream/golang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
