@igroza/yellowstone-grpc-client
v1.1.2
Published
Solana Yellowstone Geyser gRPC client
Maintainers
Readme
Yellowstone Geyser gRPC Client
A fully-typed TypeScript client for the Solana Yellowstone Geyser gRPC service, providing real-time access to Solana blockchain data with complete type safety and @solana/web3.js compatibility.
Installation
npm install @igroza/yellowstone-grpc-clientProto Files
Copy the gRPC proto files to your project's proto folder:
cp ./node_modules/@igroza/yellowstone-grpc-client/proto/* ./proto/This will copy the required .proto files (geyser.proto and solana-storage.proto) to your project for gRPC connection.
Dependency Security
Production dependencies
These dependencies will not be installed in your project, but are included in the release bundle file via esbuild.
Dependency graph:

Development dependencies
These dependencies used for building the package.
- @typescript-eslint/[email protected]
- @typescript-eslint/[email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
Quick Start
Run example from repository
Clone the repository:
git clone https://github.com/igroza/yellowstone-grpc-client.git cd yellowstone-grpc-clientreplace
grpc-url.com:10101with your actual gRPC endpoint in the example/example.ts fileInstall dependencies:
npm installRun example code:
npm run example
Example code
import { YellowstoneGeyserClient, CommitmentLevel, TransactionFormatter } from '@igroza/yellowstone-grpc-client';
// Create client
const client = new YellowstoneGeyserClient({
endpoint: 'grpc-url.com:10101',
credentials: 'your-api-token' // optional
});
// Connect to server
await client.connect();
// Subscribe to transactions
const stream = client.createSubscription(
{
transactions: {
'my_filter': {
vote: false,
failed: false,
account_include: ['YourAccountAddressHere']
}
},
commitment: CommitmentLevel.PROCESSED
},
(update) => {
if (update.transaction) {
const tx = TransactionFormatter.formTransactionFromJson(update);
console.log('Transaction:', tx.transaction.signatures[0]);
}
},
(error) => console.error('Error:', error),
() => console.log('Stream ended')
);API Reference
YellowstoneGeyserClient
Constructor
const client = new YellowstoneGeyserClient(config: YellowstoneGeyserClientConfig);Configuration:
interface YellowstoneGeyserClientConfig {
endpoint: string; // gRPC endpoint
credentials?: string; // Optional authentication token (added to 'x-token' header)
options?: grpc.ChannelOptions; // Optional gRPC channel options
}Example with authentication:
const client = new YellowstoneGeyserClient({
endpoint: 'grpc-url.com:10101',
credentials: 'your-api-token-here'
});Methods
connect(): Promise<void>
Establishes connection to the gRPC server.
await client.connect();createSubscription(request, onData, onError?, onEnd?)
Creates a subscription with callback handlers for data, errors, and stream end.
const stream = client.createSubscription(
{ transactions: { 'filter': { vote: false } }, commitment: CommitmentLevel.PROCESSED },
(update) => console.log('Update:', update),
(error) => console.error('Error:', error),
() => console.log('Stream ended')
);subscribe(request: SubscribeRequest, options?: grpc.CallOptions)
Low-level method that creates a bidirectional streaming subscription. Returns a gRPC stream object.
const stream = client.subscribe({
transactions: { 'filter': { vote: false } },
commitment: CommitmentLevel.PROCESSED
});getVersion(): Promise<GetVersionResponse>
Retrieves the Geyser server version information.
const version = await client.getVersion();
console.log('Version:', version.version);getSlot(request?: GetSlotRequest): Promise<GetSlotResponse>
Gets the current slot number.
const slot = await client.getSlot();
console.log('Current slot:', slot.slot);getBlockHeight(request?: GetBlockHeightRequest): Promise<GetBlockHeightResponse>
Gets the current block height.
const blockHeight = await client.getBlockHeight();
console.log('Block height:', blockHeight.block_height);getLatestBlockhash(request?: GetLatestBlockhashRequest): Promise<GetLatestBlockhashResponse>
Gets the latest blockhash.
const { blockhash, slot, last_valid_block_height } = await client.getLatestBlockhash();isBlockhashValid(request: IsBlockhashValidRequest): Promise<IsBlockhashValidResponse>
Checks if a blockhash is still valid.
const { valid } = await client.isBlockhashValid({ blockhash: 'your-blockhash' });ping(request: PingRequest): Promise<PongResponse>
Sends a ping to test connectivity.
const response = await client.ping({ count: 1 });sendPing(stream, id: number): void
Sends a ping through an existing subscription stream to keep the connection alive.
client.sendPing(stream, Date.now());close(): void
Closes the gRPC client connection.
client.close();Subscription Types
Account Subscriptions
Subscribe to account updates with flexible filtering options.
client.createSubscription(
{
accounts: {
'my_accounts': {
account: ['AccountPubkey1', 'AccountPubkey2'],
owner: ['ProgramId1', 'ProgramId2'],
filters: [
{ memcmp: { offset: 0, base58: 'SomeData' } },
{ datasize: 165 },
{ token_account_state: true },
{ lamports: { gt: 1000000 } }
],
nonempty_txn_signature: true
}
},
commitment: CommitmentLevel.CONFIRMED
},
(update) => {
if (update.account) {
const { account, slot } = update.account;
console.log('Account updated:', {
pubkey: Buffer.from(account.pubkey).toString('base64'),
lamports: account.lamports,
slot: slot
});
}
}
);Transaction Subscriptions
Subscribe to transactions with filtering options.
client.createSubscription(
{
transactions: {
'my_transactions': {
vote: false,
failed: false,
account_include: ['Account1', 'Account2'],
account_exclude: ['Account3'],
account_required: ['Account4']
}
},
commitment: CommitmentLevel.PROCESSED,
from_slot: 100000000
},
(update) => {
if (update.transaction) {
const tx = TransactionFormatter.formTransactionFromJson(update);
console.log('Transaction:', {
signature: tx.transaction.signatures[0],
slot: tx.slot,
success: tx.meta?.err === null
});
}
}
);Slot Subscriptions
Subscribe to slot status updates.
client.createSubscription(
{
slots: {
'my_slots': {
filter_by_commitment: true,
interslot_updates: true
}
},
commitment: CommitmentLevel.FINALIZED
},
(update) => {
if (update.slot) {
console.log('Slot:', update.slot.slot, 'Status:', update.slot.status);
}
}
);Block Subscriptions
Subscribe to complete block data.
client.createSubscription(
{
blocks: {
'my_blocks': {
account_include: ['AccountToMonitor'],
include_transactions: true,
include_accounts: true,
include_entries: true
}
},
commitment: CommitmentLevel.CONFIRMED
},
(update) => {
if (update.block) {
console.log('Block:', update.block.slot, 'Txs:', update.block.executed_transaction_count);
}
}
);Block Meta Subscriptions
Subscribe to lightweight block metadata.
client.createSubscription(
{
blocks_meta: { 'my_block_meta': {} },
commitment: CommitmentLevel.FINALIZED
},
(update) => {
if (update.block_meta) {
console.log('Block:', update.block_meta.slot, update.block_meta.blockhash);
}
}
);Entry Subscriptions
Subscribe to entry updates.
client.createSubscription(
{ entry: { 'my_entries': {} } },
(update) => {
if (update.entry) {
console.log('Entry:', update.entry.slot, update.entry.index);
}
}
);Transaction Status Subscriptions
Subscribe to lightweight transaction status updates.
client.createSubscription(
{
transactions_status: {
'my_tx_status': {
vote: false,
failed: false
}
}
},
(update) => {
if (update.transaction_status) {
console.log('Status:', update.transaction_status.slot);
}
}
);TransactionFormatter
Utility class for converting between Yellowstone transaction data and Solana web3.js compatible formats.
formTransactionFromJson(update: SubscribeUpdate): VersionedTransactionResponse
Converts raw Yellowstone transaction data into Solana web3.js VersionedTransactionResponse format.
import { TransactionFormatter } from '@igroza/yellowstone-grpc-client';
const tx = TransactionFormatter.formTransactionFromJson(update);
console.log('Signature:', tx.transaction.signatures[0]);
console.log('Fee:', tx.meta.fee);
console.log('Success:', tx.meta.err === null);
console.log('Slot:', tx.slot);
console.log('Block Time:', tx.blockTime);toJSON(transaction: VersionedTransactionResponse): any
Converts a VersionedTransactionResponse to plain JSON format for serialization or storage.
import { TransactionFormatter } from '@igroza/yellowstone-grpc-client';
const tx = TransactionFormatter.formTransactionFromJson(update);
const json = TransactionFormatter.toJSON(tx);
// Store or transmit as JSON
console.log(JSON.stringify(json, null, 2));
// Save to file or database
fs.writeFileSync('transaction.json', JSON.stringify(json));Update Types
Check the update_oneof field to determine update type:
import { UpdateType } from '@igroza/yellowstone-grpc-client';
client.createSubscription(request, (update) => {
switch (update.update_oneof) {
case UpdateType.ACCOUNT:
console.log('Account:', update.account);
break;
case UpdateType.TRANSACTION:
const tx = TransactionFormatter.formTransactionFromJson(update);
console.log('Transaction:', tx);
break;
case UpdateType.SLOT:
console.log('Slot:', update.slot);
break;
case UpdateType.PING:
client.sendPing(stream, Date.now());
break;
case UpdateType.PONG:
console.log('Pong:', update.pong?.id);
break;
}
});Filtering
Memory Compare
filters: [{ memcmp: { offset: 32, base58: 'YourMintAddress' } }]Data Size
filters: [{ datasize: 165 }]Lamports
filters: [{ lamports: { gt: 1000000 } }] // gt, lt, eq, neData Slicing
accounts_data_slice: [{ offset: 0, length: 32 }]Commitment Levels
CommitmentLevel.PROCESSED // Fastest, may be rolled back
CommitmentLevel.CONFIRMED // Confirmed by supermajority
CommitmentLevel.FINALIZED // Finalized, cannot be rolled backError Handling
client.createSubscription(
request,
(update) => { /* handle data */ },
(error) => {
console.error('Error:', error.message, error.code);
// Common codes: 14 (UNAVAILABLE), 4 (DEADLINE_EXCEEDED), 13 (INTERNAL)
},
() => console.log('Stream ended')
);
// Graceful shutdown
process.on('SIGINT', () => {
client.close();
process.exit(0);
});Event Handling
The client extends EventEmitter and emits various events during its lifecycle. Use the YellowstoneGeyserClientEvents enum for type-safe event handling:
import { YellowstoneGeyserClient, YellowstoneGeyserClientEvents } from '@igroza/yellowstone-grpc-client';
const client = new YellowstoneGeyserClient({ endpoint: 'grpc-url.com:10101' });
// Listen to lifecycle events
client.on(YellowstoneGeyserClientEvents.INITIALIZED, () => {
console.log('Client initialized');
});
client.on(YellowstoneGeyserClientEvents.CONNECTED, () => {
console.log('Connected to server');
});
client.on(YellowstoneGeyserClientEvents.SUBSCRIBED, (request) => {
console.log('Subscription created:', request);
});
client.on(YellowstoneGeyserClientEvents.ERROR, (error) => {
console.error('Error occurred:', error);
});
client.on(YellowstoneGeyserClientEvents.STREAM_ENDED, () => {
console.log('Stream ended');
});
client.on(YellowstoneGeyserClientEvents.CLOSED, () => {
console.log('Client closed');
});
client.on(YellowstoneGeyserClientEvents.STATUS, (status) => {
console.log('Status update:', status);
});Available Events:
INITIALIZED- Client has been initializedCONNECTED- Successfully connected to the gRPC serverSUBSCRIBED- Subscription has been createdERROR- An error occurredSTREAM_ENDED- Subscription stream has endedCLOSED- Client connection has been closedSTATUS- gRPC status update received
License
MIT
