Skip to main content

Overview

LaserStream is a managed Solana gRPC streaming service. It is wire-compatible with the open Yellowstone gRPC protocol — so any Yellowstone client works out of the box — and adds production features like historical replay, multi-node failover, and a fully managed environment. LaserStream uses the open source gRPC protocol, ensuring no vendor lock-in and maximum compatibility with existing gRPC implementations. You can connect either with the standard @triton-one/yellowstone-grpc client or use the performance-optimized Helius LaserStream SDK for added benefits including higher throughput, automatic reconnects, subscription management, error handling, and more.

LaserStream SDK is 40x Faster vs. JavaScript Yellowstone Clients

Learn how we used Rust Core with zero-copy NAPI bindings to maximize JavaScript SDK performance
Performance Notice: If you experience any lag or performance issues with your LaserStream connection, please refer to the Troubleshooting section for common causes and solutions.

Endpoints & Regions

LaserStream is available in multiple regions worldwide. Choose the endpoint closest to your application for optimal performance:

Mainnet Endpoints

Devnet Endpoint

Network & Region Selection:
  • For production apps, pick the mainnet endpoint nearest your server for best performance (e.g., if deploying in Europe, use Amsterdam (ams) or Frankfurt (fra))
  • For testing, use: https://laserstream-devnet-ewr.helius-rpc.com.

zstd Compression

All LaserStream gRPC endpoints support zstd compression. Compression is opt-in: responses remain uncompressed unless your client advertises zstd support. Enable zstd in the Helius LaserStream TypeScript SDK:
zstd reduces network bandwidth but adds compression work. Benchmark it with your subscription workload before enabling it for latency-sensitive streams.

Log Truncation

By default, LaserStream truncates transaction log messages to 10 KB for better speed and performance. If you need full logs, dedicated untruncated endpoints are available — see Log Truncation.

Quickstart

Get started with LaserStream from your Helius Dashboard. Mainnet requires a Business or Professional plan; Devnet is available on Developer and above. See Plans & Pricing for details.
1

Create a New Project

2

Install Dependencies

We use tsx because the default npx tsc --init on TypeScript 5.x sets verbatimModuleSyntax, module: "nodenext", and types: [], which all break a quick ts-node index.ts run. tsx runs .ts files without a tsconfig.
3

Obtain Your API Key

Generate a key from the Helius Dashboard.This key will serve as your authentication token for LaserStream.
Plan Requirements: LaserStream devnet is available on all plans. LaserStream mainnet requires a Business or Professional plan.
4

Create a Subscription Script

Create index.ts with the following:
5

Replace Your API Key and Choose Your Region

In index.ts, update the config object with:
  1. Your actual API key from the Helius Dashboard
  2. The LaserStream endpoint closest to your server location
Network & Region Selection Examples:
  • For Production (Mainnet):
    • Europe: Use fra (Frankfurt), ams (Amsterdam), or lon (London)
    • US East: Use ewr (New York)
    • US West: Use slc (Salt Lake City) or lax (Los Angeles)
    • Asia: Use tyo (Tokyo) or sgp (Singapore)
  • For Development (Devnet):
    • Use https://laserstream-devnet-ewr.helius-rpc.com
6

Run and View Results

Whenever a confirmed token transaction involves TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA, you’ll see the data in your console.

Common Workflows

Step-by-step guides for the workflows we see most often. Each guide uses the helius-laserstream SDK with auto-reconnect and historical replay built in.

Account Subscriptions

Monitor balance, data, and ownership changes on specific accounts with filters.

Transaction Monitoring

Stream transactions involving target accounts, filter by program, vote, or failure status.

Slot & Block Monitoring

Track network consensus, block production, and commitment-level transitions.

Decoding Transaction Data

Parse the binary transactionUpdate payloads into readable Solana transactions.

Stream Pump AMM Data

Real-world example: monitor Pump AMM trades with reconnect-safe filters.
The @triton-one/yellowstone-grpc client works against the same endpoints if you prefer the raw Yellowstone protocol. See the Yellowstone gRPC reference for protocol-level details.

Subscribe Request

In the subscribe request, you need to include the following general parameters:
Historical Replay: You can optionally include a fromSlot field (a u64 number) in the main SubscribeRequest object to replay data from a specific slot onwards. Replay is currently limited to the last ~48 hours (~691,200 slots at current network speed); note that replays older than ~20 minutes return finalized-only data.
enum
Specifies the commitment level, which can be processed, confirmed, or finalized.
array
An array of objects { offset: uint64, length: uint64 } that allows you to receive only the required data slices from accounts.
boolean
Some cloud providers (like Cloudflare) may close idle streams after a period of inactivity. To prevent this and keep the connection alive without needing to resend filters, set this to true. The server will respond with a Pong message every 15 seconds.
Next, you’ll need to specify the filters for the data you want to subscribe to, such as accounts, blocks, slots, or transactions.
Define filters for slot updates. The key you use (e.g., mySlotLabel) is a user-defined label for this specific filter configuration, allowing you to potentially define multiple named configurations if needed (though typically one is sufficient).
boolean
By default, slots are sent for all commitment levels. With this filter, you can choose to receive only the selected commitment level.
boolean
Enables the subscription to receive updates for changes within a slot, not just at the beginning of new slots. This is useful for more granular, low-latency slot data.
Define filters for account data updates. The key you use (e.g., tokenAccounts) is a user-defined label for this specific filter configuration.
array
Matches any public key from the provided array.
array
The account owner’s public key. Matches any public key from the provided array.
array
Similar to the filters in getProgramAccounts. This is an array of datasize and/or memcmp filters. For memcmp, the comparand goes on one of bytes, base58, or base64 directly on the memcmp object.
enum
deprecated
Deprecated — no-op as of Agave 4.2. Setting notifyOn has no effect. The field will be removed at a later date.
If all fields are empty, all accounts are broadcasted. Otherwise:
  • Fields operate as a logical AND.
  • Values within arrays act as a logical OR (except within filters, which operate as a logical AND).
Tracking more than ~10,000 accounts? Instead of an explicit pubkey list (32 bytes per account), use a compressed cuckoo filter (~3–4 bytes per account) to subscribe to hundreds of thousands of accounts in a single stream. Available in the Rust and JavaScript SDKs.
Define filters for transaction updates. The key you use (e.g., myTxSubscription) is a user-defined label for this specific filter configuration.
boolean
Enable or disable the broadcast of vote transactions.
boolean
Enable or disable the broadcast of failed transactions.
string
Broadcast only transactions matching the specified signature.
array
Filter transactions that involve any account from the provided list.
array
Exclude transactions that involve any account from the provided list (opposite of accountInclude).
array
Filter transactions that involve all accounts from the provided list (all accounts must be used).
string
Optional tokenAccounts (associated token account) expansion. When set, an accountInclude wallet also matches transactions where it owns an SPL token balance — e.g. incoming token transfers that touch the wallet’s token account rather than its pubkey. Accepts "balanceChanged" (balance-delta matches), "all" (any reference, higher volume), or "none" (no expansion, the default). The SDK converts the string to the wire-level TokenAccountExpansionControlFlag enum (part of yellowstone-grpc-proto 12.5.0+). See Token Account (ATA) Filtering for what it does and how it works.
boolean
Optional matchMints flag (default false). When true, the accountInclude, accountExclude, and accountRequired lists are also matched against the mints in the transaction’s pre/post token balances, not just its account keys. Put a mint in accountInclude to receive every transaction that touches that token, including plain SPL transfers that never reference the mint in their account keys. Opt-in with no effect on existing filters. Requires helius-laserstream 0.8.5+ (JS), 0.6.4+ (Rust), or go/v0.3.0+ (Go). See Token Mint Filtering for semantics and examples.
If all fields are left empty, all transactions are broadcasted. Otherwise:
  • Fields operate as a logical AND.
  • Values within arrays are treated as a logical OR (except for accountRequired, where all must match).
Define filters for block updates. The key you use (e.g., myBlockLabel) is a user-defined label for this specific filter configuration.
array
Filters transactions and accounts that involve any account from the provided list.
boolean
Includes all transactions in the broadcast.
boolean
Includes all account updates in the broadcast.
boolean
Includes all entries in the broadcast.
This functions similarly to Blocks but excludes transactions, accounts, and entries. The key you use (e.g., blockmetadata) is a user-defined label for this subscription. Currently, no filters are available for block metadata—all messages are broadcasted by default.
Subscribe to ledger entries. The key you use (e.g., entrySubscribe) is a user-defined label for this subscription. Currently, there are no filters available for entries; all entries are broadcasted.

Code Examples (LaserStream SDK)

SDK Options

We provide official SDKs for multiple programming languages: For other languages or custom implementations, you can use the Yellowstone gRPC proto files directly to generate gRPC clients for your preferred language.

Troubleshooting / FAQ

A: Performance issues with LaserStream connections are typically caused by:
  • Javascript Client Slowness: The JavaScript client may lag behind when processing too many messages or consuming too much bandwidth. Consider filtering your subscriptions more narrowly to reduce message volume, switch to the LaserStream JavaScript SDK, or try using another language.
  • Limited local bandwidth: Heavy subscriptions can overwhelm clients with limited network bandwidth. Monitor your network usage and consider upgrading your connection or reducing subscription scope.
  • Geographic distance: Long network routes increase latency and packet loss. Use the endpoint closest to your server. For high-latency connections, increase your network read buffer sizes (can improve bandwidth by 5x+):
    To persist across reboots, add to /etc/sysctl.conf:
    Increase the HTTP/2 stream and connection window sizes to 64MB to prevent flow control bottlenecks. Both are required — raising only the stream window leaves the connection-level window as the binding constraint:
  • Client-side processing bottlenecks: Ensure your message processing logic is optimized and doesn’t block the main thread for extended periods.
Debugging Client Lag: To help you debug client, we built a tool to test for the max bandwidth from your node to a Laserstream gRPC server. To use it run:
The output returns the max network capacity between your server and the Laserstream server. At a minimum, you need 10MB/s to subscribe to all transaction data and 80MB/s to subscribe to all account data. We recommend having at least 2x the required capacity for optimal performance.
A: Verify your API key and endpoint are correct and that your network allows outbound gRPC connections to the specified endpoint. Check the Helius status page for any ongoing incidents.
A: Double-check the logical operators (AND/OR) described in the filter sections. Ensure public keys are correct. Review the commitment level specified in your request.
A: Yes, you can define filter configurations under multiple keys (e.g., accounts, transactions) within the same SubscribeRequest object.
A: We don’t implement consumer groups. Instead, LaserStream delivers the same outcomes teams want: resume, replay, and multi-node reliability without a coordination layer (and the latency/overhead that comes with it). We believe consumer groups are not needed for most workloads and they add latency and operational overhead. As an example a single LaserStream gRPC connection can emit up to 10× Solana’s transaction + account data, and most clients subscribe to a small, filtered slice. Using consumer groups in this case burns performance headroom and introduces another point of failure.
A: LaserStream truncates transaction log messages to 10 KB by default for better speed and performance. If you need full logs, connect to a dedicated untruncated endpoint — see Log Truncation for the list.
A: Including a ping field in your initial SubscribeRequest causes LaserStream to silently ignore all subscription filters — only a Pong is returned with zero account, transaction, or slot data. To fix this, remove ping from the initial subscribe request and instead send pings separately via the stream’s sink after the subscription is established. This keeps the connection alive without interfering with your filters.