Documentation Index
Fetch the complete documentation index at: https://docs.orbitflare.com/llms.txt
Use this file to discover all available pages before exploring further.
Install
npm install @orbitflare/sdk @grpc/grpc-js yaml
@grpc/grpc-js and yaml are optional peer dependencies. Install them only if you use the gRPC client (or YAML config).
Building the client
Here’s a client with every option set:
import { GeyserClientBuilder, type RetryPolicy } from '@orbitflare/sdk';
const client = new GeyserClientBuilder()
.url('http://ny.rpc.orbitflare.com:10000')
.fallbackUrl('http://fra.rpc.orbitflare.com:10000')
.retry({
initialDelayMs: 100,
maxDelayMs: 30_000,
multiplier: 2.0,
maxAttempts: 0,
})
.timeoutSecs(30)
.keepaliveSecs(60)
.pingIntervalSecs(10)
.maxMissedPongs(3)
.channelCapacity(4096)
.build();
Minimal setup:
const client = new GeyserClientBuilder()
.url('http://ny.rpc.orbitflare.com:10000')
.build();
Builder methods
.url(url) - The primary gRPC endpoint. Falls back to ORBITFLARE_GRPC_URL env var.
.url('http://ny.rpc.orbitflare.com:10000')
.urls([...]) - Primary + fallbacks in one call. First element is primary.
.urls(['http://ny.rpc.orbitflare.com:10000', 'http://fra.rpc.orbitflare.com:10000'])
.fallbackUrl(url) / .fallbackUrls([...]) - Add fallback endpoints. On connection failure, the SDK rotates through them.
.fallbackUrl('http://fra.rpc.orbitflare.com:10000')
.retry(policy) - Controls reconnection backoff. When a connection drops, the SDK waits initialDelayMs, then doubles it each attempt (capped at maxDelayMs). Set maxAttempts to 0 for infinite retries. Default: 100ms initial, 30s max, 2x multiplier, infinite.
.retry({
initialDelayMs: 200,
maxDelayMs: 15_000,
multiplier: 2.0,
maxAttempts: 0,
})
.timeoutSecs(n) - Per-request gRPC timeout. Default: 30.
.keepaliveSecs(n) - TCP keepalive interval. The OS sends probes at this interval to detect dead connections at the TCP level. Default: 60.
.pingIntervalSecs(n) - How often the SDK sends proto-level Ping messages to the server. The server should respond with a Pong. Default: 10.
.maxMissedPongs(n) - How many consecutive pings can go unanswered before the SDK considers the connection dead and reconnects. Default: 3. With the defaults, a dead connection is detected within 30 seconds.
.channelCapacity(n) - The bounded buffer between the background task and your code. If your code is slow to consume events, the background task pauses when this fills up instead of eating unlimited memory. Default: 4096.
Writing a YAML config
Create a YAML file with the filters you want:
# grpc.yml
transactions:
pumpfun:
vote: false
failed: false
account_include:
- "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
jupiter:
vote: false
failed: false
account_include:
- "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"
accounts:
usdc_mint:
account:
- "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
token_program:
owner:
- "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
slots:
all:
filter_by_commitment: true
commitment: confirmed
YAML filter reference
transactions - each entry is a named filter. A transaction matches if it involves any of the account_include addresses. account_exclude removes matches. account_required means all listed addresses must be present. vote and failed filter by transaction type.
accounts - watch specific accounts by address, or watch all accounts owned by a program via owner.
slots - subscribe to slot updates. filter_by_commitment only sends updates at your commitment level.
commitment - 'processed', 'confirmed', or 'finalized'. Defaults to 'confirmed'.
The YAML supports ${ENV_VAR} expansion:
transactions:
target:
account_include:
- "${TARGET_PROGRAM}"
Subscribing and reading events
From YAML
const stream = client.subscribeYaml('grpc.yml');
Programmatically
For dynamic filters built at runtime:
import { proto } from '@orbitflare/sdk';
const request: proto.geyser.SubscribeRequest = {
transactions: {
target: {
vote: false,
failed: false,
signature: undefined,
accountInclude: [someAddress],
accountExclude: [],
accountRequired: [],
},
},
accounts: {},
slots: {},
transactionsStatus: {},
blocks: {},
blocksMeta: {},
entry: {},
accountsDataSlice: [],
commitment: 1,
ping: { id: 1 },
};
const stream = client.subscribe(request);
Reading the stream
Both subscribeYaml and subscribe return a GeyserStream. It’s an async iterable - use for await:
for await (const update of stream) {
if (update.transaction) {
// update.transaction.slot - the slot this transaction was in
// update.transaction.transaction - the transaction info (signature, accounts, instructions, meta)
} else if (update.account) {
// update.account.slot - the slot
// update.account.account - account info (pubkey, lamports, owner, data)
// update.account.isStartup - true during initial account snapshot
} else if (update.slot) {
// update.slot.slot - the slot number
// update.slot.status - processed, confirmed, finalized, etc.
} else if (update.blockMeta) {
// update.blockMeta.slot, update.blockMeta.blockhash, update.blockMeta.parentSlot
// update.blockMeta.executedTransactionCount
}
}
Or call await stream.next() directly to pull one event at a time. Returns undefined when the stream is closed. If retries are exhausted, the next iteration throws.
Pong messages are consumed internally and never appear in your stream.
Closing
Stops the background task immediately.
Multiple streams
One client can run many streams at once. Each gets its own background connection:
const pumpfun = client.subscribeYaml('config/pumpfun.yml');
const raydium = client.subscribeYaml('config/raydium.yml');
const slots = client.subscribeYaml('config/slots.yml');
They share endpoint health state - if one stream quarantines a failing endpoint, the others skip it on their next reconnect. But their connections and lifecycles are fully independent.
You can spin up new streams at any time, including dynamically based on data from an existing stream.
Full example
A stream that watches pump.fun transactions, decodes the signature, and prints a summary for each one.
import bs58 from 'bs58';
import { GeyserClientBuilder } from '@orbitflare/sdk';
async function main() {
const client = new GeyserClientBuilder()
.url('http://ny.rpc.orbitflare.com:10000')
.fallbackUrl('http://fra.rpc.orbitflare.com:10000')
.build();
const stream = client.subscribeYaml('grpc.yml');
let txCount = 0;
console.log('streaming...');
for await (const update of stream) {
if (update.transaction) {
txCount += 1;
const info = update.transaction.transaction;
if (info?.signature) {
const sig = bs58.encode(info.signature);
const fee = info.meta?.fee ?? 0n;
const ixCount = info.transaction?.message?.instructions.length ?? 0;
console.log(
`#${txCount} slot=${update.transaction.slot} sig=${sig.slice(0, 16)}... fee=${fee} instructions=${ixCount}`,
);
}
} else if (update.slot) {
console.log(`slot ${update.slot.slot} (${update.slot.status})`);
}
}
}
void main();
With this grpc.yml:
transactions:
pumpfun:
vote: false
failed: false
account_include:
- "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
slots:
all:
filter_by_commitment: true
commitment: confirmed