Solana gRPC in TypeScript: Examples
TL;DR
- - Use @triton-one/yellowstone-grpc as the TypeScript gRPC client
- - Connect with endpoint URL and optional auth token
- - Subscribe by sending a filter object on the bidirectional stream
- - Handle reconnection logic for production reliability
The @triton-one/yellowstone-grpc package provides a TypeScript client for Yellowstone gRPC. It handles protobuf serialization and provides typed interfaces for all subscription filters.
Installation
npm install @triton-one/yellowstone-grpc
Connecting
import Client from "@triton-one/yellowstone-grpc";
const client = new Client(
"https://your-grpc-endpoint.example.com",
"your-auth-token"
);
const stream = await client.subscribe();
The client establishes a bidirectional gRPC stream. You send filter requests and receive matching updates on the same connection.
Subscribing to account updates
stream.on("data", (data) => {
if (data.account) {
const account = data.account;
console.log("Account update:", account.account.pubkey);
console.log("Data length:", account.account.data.length);
}
});
await stream.write({
accounts: {
tokenAccounts: {
owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
account: [],
filters: [],
},
},
slots: {},
transactions: {},
blocks: {},
blocksMeta: {},
commitment: 1, // CONFIRMED
});
Subscribing to transactions
await stream.write({
accounts: {},
slots: {},
transactions: {
swaps: {
vote: false,
failed: false,
accountInclude: [
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium AMM
],
accountExclude: [],
},
},
blocks: {},
blocksMeta: {},
commitment: 0, // PROCESSED
});
Handling disconnection
gRPC streams disconnect due to network issues, server restarts, or idle timeouts. Implement reconnection:
function connectWithRetry(maxRetries = 10) {
let retries = 0;
async function connect() {
const stream = await client.subscribe();
stream.on("error", async (err) => {
console.error("Stream error:", err.message);
if (retries < maxRetries) {
retries++;
const delay = Math.min(1000 * 2 ** retries, 30000);
setTimeout(connect, delay);
}
});
stream.on("end", () => {
console.log("Stream ended, reconnecting...");
if (retries < maxRetries) {
retries++;
setTimeout(connect, 1000);
}
});
// Reset retry counter on successful data
stream.on("data", () => {
retries = 0;
});
// Send subscription filters
await stream.write({ /* your filters */ });
}
connect();
}
FAQ
What commitment levels are available? 0 = PROCESSED, 1 = CONFIRMED, 2 = FINALIZED. See commitment levels in streaming.
Can I change filters without reconnecting?
Yes. Send a new write() with updated filters. The server replaces the active subscription.
How do I decode transaction data?
The response includes raw transaction bytes. Use @solana/kit to deserialize the transaction and parse instructions.
Updated: