subscribe gRPC Method
Please note that this RPC method requires the Yellowstone gRPC add-on enabled on your QuickNode endpoint.
Parameters
This method does not accept any parameters
Returns
result
object
The result representing the return value of a bidirectional stream method call with a Geyser gRPC subscription request and subscription update
Request
package main import ( "context" "crypto/tls" "fmt" "log" "time" "github.com/mr-tron/base58" "encoding/json" pb "yellowstone/proto" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" "google.golang.org/grpc/keepalive" ) // QuickNode endpoints consist of two crucial components: the endpoint name and the corresponding token // For eg: QN Endpoint: https://docs-demo.solana-mainnet.quiknode.pro/abcde123456789 // endpoint will be: docs-demo.solana-mainnet.quiknode.pro:10000 {10000 is the port number for gRPC} // token will be : abcde123456789 var ( endpoint = "YOUR_QN_ENDPOINT:10000" token = "YOUR_TOKEN_NUMBER" ) 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.NewClient(endpoint, opts...) if err != nil { log.Fatalf("Failed to connect: %v", err) } defer conn.Close() client := pb.NewGeyserClient(conn) commitment := pb.CommitmentLevel_FINALIZED subReq := &pb.SubscribeRequest{ Commitment: &commitment, BlocksMeta: map[string]*pb.SubscribeRequestFilterBlocksMeta{ "blocks": {}, }, Slots: map[string]*pb.SubscribeRequestFilterSlots{ "slots": {}, }, } d, _ := json.Marshal(subReq) fmt.Printf("Subscription request: %s\n", string(d)) stream, err := client.Subscribe(context.Background()) if err != nil { fmt.Printf("Failed to subscribe to yellowstone: %v\n", err) return } if err = stream.Send(subReq); err != nil { fmt.Printf("Failed to send subscription request: %v\n", err) return } for { m, err := stream.Recv() if err != nil { fmt.Printf("Failed to receive yellowstone message: %v\n", err) return } switch { case m.GetBlock() != nil: fmt.Printf("Block: %d\n", m.GetBlock().GetBlockHeight()) case m.GetBlockMeta() != nil: fmt.Printf("BlockMeta: %d\n", m.GetBlockMeta().GetBlockHeight()) case m.GetTransaction() != nil: fmt.Printf("Transaction: %s\n", base58.Encode(m.GetTransaction().GetTransaction().GetSignature())) case m.GetSlot() != nil: fmt.Printf("Slot: %d\n", m.GetSlot().GetSlot()) } } }
import Client, { CommitmentLevel, SubscribeRequest, SubscribeUpdate, SubscribeUpdateTransaction } from "@triton-one/yellowstone-grpc"; // QuickNode endpoints consist of two crucial components: the endpoint name and the corresponding token // For eg: QN Endpoint: https://docs-demo.solana-mainnet.quiknode.pro/abcde123456789 // endpoint will be: docs-demo.solana-mainnet.quiknode.pro:10000 {10000 is the port number for gRPC} // token will be : abcde123456789 const ENDPOINT = "YOUR_QN_ENDPOINT:10000"; const TOKEN = "YOUR_TOKEN_NUMBER"; async function main() { const client = new Client(ENDPOINT, TOKEN, {}); const commitment = CommitmentLevel.CONFIRMED; try { const stream = await client.subscribe(); // Set up error and end handlers stream.on("error", (error) => { console.error("Stream error:", error); stream.end(); }); stream.on("end", () => { console.log("Stream ended"); }); // Handle incoming data stream.on("data", (data: SubscribeUpdate) => { handleSubscribeUpdate(data); }); // Create subscription request const request: SubscribeRequest = { slots: { client: { filterByCommitment: true } }, transactions: { client: { vote: false, failed: false, signature: undefined, accountInclude: [], accountExclude: [], accountRequired: [], }, }, commitment: commitment, accounts: {}, transactionsStatus: {}, entry: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], ping: undefined, }; // Send subscription request await new Promise<void>((resolve, reject) => { stream.write(request, (err: Error | null | undefined) => { if (err) { reject(err); } else { resolve(); } }); }); console.log("Subscription started. Waiting for events..."); // Keep the script running await new Promise(() => {}); } catch (error) { console.error("Error in subscription process:", error); } } function handleSubscribeUpdate(data: SubscribeUpdate) { if ("slot" in data) { console.log("Slot update:", data.slot); } else if ("transaction" in data) { const transaction = data.transaction as SubscribeUpdateTransaction; if (transaction && transaction.transaction) { console.log("Transaction update:", { signature: Buffer.from(transaction.transaction.signature).toString('base64'), slot: transaction.slot, }); } } else { console.log("Other update:", data); } } main() .catch((err) => { console.error("Unhandled error:", err); process.exit(1); });
Don't have an account yet?
Create your QuickNode endpoint in seconds and start building
Get started for free