Prerequisites
You need:
Node.js 18+ (or a Rust environment for the Rust client)
An OrbitFlare gRPC endpoint URL and token (available from your Dashboard under Licenses )
Installation
Install the official Yellowstone gRPC TypeScript client:
npm install @triton-one/yellowstone-grpc
Or with yarn:
yarn add @triton-one/yellowstone-grpc
Connect to Your Endpoint
import Client , { CommitmentLevel , SubscribeRequest } from "@triton-one/yellowstone-grpc" ;
const GRPC_URL = "https://your-endpoint.grpc.orbitflare.com" ;
const X_TOKEN = "YOUR_GRPC_TOKEN" ;
const client = new Client ( GRPC_URL , X_TOKEN , {
"grpc.max_receive_message_length" : 64 * 1024 * 1024 , // 64 MiB
});
Your gRPC URL and token are found in the Licenses section of your OrbitFlare Dashboard. The token is passed as the second argument to new Client() — it is not an HTTP header in the TypeScript client.
Open a Stream
const stream = await client . subscribe ();
// Handle errors and stream lifecycle
const streamClosed = new Promise < void >(( resolve , reject ) => {
stream . on ( "error" , ( error ) => {
console . error ( "Stream error:" , error );
reject ( error );
stream . end ();
});
stream . on ( "end" , () => resolve ());
stream . on ( "close" , () => resolve ());
});
// Handle incoming data
stream . on ( "data" , ( data ) => {
if ( data . slot ) {
console . log ( "Slot update:" , data . slot . slot );
} else if ( data . transaction ) {
console . log ( "Transaction:" , data . transaction );
} else if ( data . account ) {
console . log ( "Account update:" , data . account );
} else if ( data . pong ) {
console . log ( "Pong received" );
}
});
Send Your First Subscription
Subscribe to all slot updates at the confirmed commitment level:
const subscribeRequest : SubscribeRequest = {
slots: {
slot: { filterByCommitment: true },
},
commitment: CommitmentLevel . CONFIRMED ,
accounts: {},
accountsDataSlice: [],
transactions: {},
transactionsStatus: {},
blocks: {},
blocksMeta: {},
entry: {},
};
await new Promise < void >(( resolve , reject ) => {
stream . write ( subscribeRequest , ( err ) => {
if ( err == null ) resolve ();
else reject ( err );
});
});
// Wait for the stream to close
await streamClosed ;
Keep the Connection Alive
Cloud load balancers terminate idle gRPC connections after ~10 minutes. Send a ping every 30 seconds:
const pingRequest : SubscribeRequest = {
ping: { id: 1 },
accounts: {},
accountsDataSlice: [],
transactions: {},
transactionsStatus: {},
blocks: {},
blocksMeta: {},
slots: {},
entry: {},
};
const pingInterval = setInterval ( async () => {
await new Promise < void >(( resolve , reject ) => {
stream . write ( pingRequest , ( err ) => {
if ( err == null ) resolve ();
else reject ( err );
});
});
}, 30_000 );
// Clear the interval when the stream closes
streamClosed . finally (() => clearInterval ( pingInterval ));
Reconnection
For production applications, implement automatic reconnection with exponential backoff:
async function connectWithRetry ( maxRetries = 10 ) {
let attempt = 0 ;
let delay = 1000 ;
while ( attempt < maxRetries ) {
try {
const stream = await client . subscribe ();
// ... attach handlers and send subscription
await streamClosed ; // waits until stream closes
break ; // clean exit
} catch ( err ) {
attempt ++ ;
console . error ( `Stream error (attempt ${ attempt } ):` , err );
if ( attempt >= maxRetries ) throw err ;
await new Promise (( r ) => setTimeout ( r , delay ));
delay = Math . min ( delay * 2 , 30_000 ); // max 30s backoff
}
}
}
Next Steps
Account Monitoring Stream token balances, wallet changes, and program account updates.
Transaction Monitoring Filter and process live transactions by program or account.
Slots & Blocks Track consensus progress and full block data.
Entry Monitoring Access low-level block entries.