# Helius LaserStream (Carbon 2.0)

> Stream accounts, transactions and blocks from Helius LaserStream gRPC, with automatic slot replay after a reconnect.

`LaserStreamGeyserClient` subscribes to Helius LaserStream, a hosted gRPC service that speaks the Yellowstone protocol, and emits account and transaction updates. Unlike the [Yellowstone datasource](https://carbon.sevenlabs.org/datasources/yellowstone-grpc.md), it tracks the last slot it saw and asks LaserStream to replay from that slot after a reconnect. Use it for real-time indexing on Helius when gaps after a disconnect are not acceptable.

|          |                                                                                                                                                        |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Crate    | `carbon-helius-laserstream-datasource` 2.0.0                                                                                                           |
| Install  | `cargo add carbon-helius-laserstream-datasource@2.0.0`                                                                                                 |
| Emits    | `AccountUpdate`, `AccountDeletion`, `Transaction`                                                                                                      |
| Mode     | Live, with replay from a recent slot. Runs until cancelled or until reconnects keep failing.                                                           |
| Provider | A Helius API key on a plan that includes LaserStream, and a regional LaserStream endpoint such as `https://laserstream-mainnet-ewr.helius-rpc.com`.    |
| API docs | [docs.rs](https://docs.rs/carbon-helius-laserstream-datasource/2.0.0/carbon_helius_laserstream_datasource/)                                            |
| Source   | [`datasources/helius-laserstream-datasource`](https://github.com/sevenlabs-hq/carbon/blob/v2.0.0/datasources/helius-laserstream-datasource/src/lib.rs) |

## Quick example

This program streams confirmed, successful Orca Whirlpool transactions and prints each `swapV2`. It compiles as shown; to run it, set `LASERSTREAM_URL` and `HELIUS_API_KEY`.

```sh
cargo new laserstream && cd laserstream
cargo add carbon-core@2.0.0 carbon-log-metrics@2.0.0 carbon-orca-whirlpool-decoder@2.0.0 carbon-helius-laserstream-datasource@2.0.0
cargo add yellowstone-grpc-proto@=12.7.0
cargo add tokio@1 --features full
cargo add env_logger@0.11 log@0.4
```

`src/main.rs`:

```rust
use {
    carbon_core::{
        error::CarbonResult, instruction::InstructionProcessorInputType, pipeline::Pipeline,
        processor::Processor,
    },
    carbon_helius_laserstream_datasource::{
        BlockFilters, LaserStreamClientConfig, LaserStreamGeyserClient,
    },
    carbon_log_metrics::LogMetrics,
    carbon_orca_whirlpool_decoder::{
        instructions::OrcaWhirlpoolInstruction, OrcaWhirlpoolDecoder, PROGRAM_ID,
    },
    std::{collections::HashMap, env, sync::Arc},
    yellowstone_grpc_proto::geyser::{CommitmentLevel, SubscribeRequestFilterTransactions},
};

#[tokio::main]
async fn main() -> CarbonResult<()> {
    env_logger::init();

    let mut transaction_filters = HashMap::new();
    transaction_filters.insert(
        "orca_whirlpool".to_string(),
        SubscribeRequestFilterTransactions {
            vote: Some(false),
            failed: Some(false),
            account_include: vec![PROGRAM_ID.to_string()],
            ..Default::default()
        },
    );

    let datasource = LaserStreamGeyserClient::new(
        env::var("LASERSTREAM_URL").expect("LASERSTREAM_URL must be set"),
        Some(env::var("HELIUS_API_KEY").expect("HELIUS_API_KEY must be set")),
        Some(CommitmentLevel::Confirmed),
        HashMap::new(), // account filters
        transaction_filters,
        BlockFilters::default(),
        LaserStreamClientConfig::default(), // replay_enabled: true
    );

    Pipeline::builder()
        .datasource(datasource)
        .metrics(Arc::new(LogMetrics::new()))
        .instruction(OrcaWhirlpoolDecoder, SwapLogger)
        .build()?
        .run()
        .await
}

struct SwapLogger;

impl Processor<InstructionProcessorInputType<'_, OrcaWhirlpoolInstruction>> for SwapLogger {
    async fn process(
        &mut self,
        input: &InstructionProcessorInputType<'_, OrcaWhirlpoolInstruction>,
    ) -> CarbonResult<()> {
        let tx = &input.metadata.transaction_metadata;
        if let OrcaWhirlpoolInstruction::SwapV2 { data, accounts, .. } = input.decoded_instruction {
            println!("slot {} swapV2 pool={} amount={}", tx.slot, accounts.whirlpool, data.amount);
        }
        Ok(())
    }
}
```

```sh
LASERSTREAM_URL=https://laserstream-mainnet-ewr.helius-rpc.com HELIUS_API_KEY=your-helius-api-key RUST_LOG=info cargo run
```

Each matching swap prints one `slot … swapV2 pool=… amount=…` line. The [Stream with LaserStream](https://carbon.sevenlabs.org/guides/stream-with-laserstream.md) guide covers endpoints and keys.

## Configuration

### `LaserStreamGeyserClient::new`

```rust
pub const fn new(
    endpoint: String,
    x_token: Option<String>,
    commitment: Option<CommitmentLevel>,
    account_filters: HashMap<String, SubscribeRequestFilterAccounts>,
    transaction_filters: HashMap<String, SubscribeRequestFilterTransactions>,
    block_filters: BlockFilters,
    geyser_config: LaserStreamClientConfig,
) -> Self
```

| Parameter             | Type                                                  | Meaning                                                                                                                                          |
| --------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `endpoint`            | `String`                                              | LaserStream gRPC URL for your region.                                                                                                            |
| `x_token`             | `Option<String>`                                      | Your Helius API key, sent as `x-token`.                                                                                                          |
| `commitment`          | `Option<CommitmentLevel>`                             | `Processed`, `Confirmed` or `Finalized`. Also decides how far back replay starts (see below).                                                    |
| `account_filters`     | `HashMap<String, SubscribeRequestFilterAccounts>`     | Named account filters, as for [Yellowstone](https://carbon.sevenlabs.org/datasources/yellowstone-grpc.md#configuration).                         |
| `transaction_filters` | `HashMap<String, SubscribeRequestFilterTransactions>` | Named transaction filters, as for Yellowstone.                                                                                                   |
| `block_filters`       | `BlockFilters`                                        | `filters: HashMap<String, SubscribeRequestFilterBlocks>` and `failed_transactions: Option<bool>` (`None` keeps failed transactions from blocks). |
| `geyser_config`       | `LaserStreamClientConfig`                             | Connection and replay settings.                                                                                                                  |

There is no disconnect notifier or stream timeout on this datasource.

### `LaserStreamClientConfig`

```rust
pub const fn new(
    compression: Option<CompressionEncoding>,
    connect_timeout: Option<Duration>,
    timeout: Option<Duration>,
    max_decoding_message_size: Option<usize>,
    tls_config: Option<ClientTlsConfig>,
    tcp_nodelay: Option<bool>,
    replay_enabled: bool,
    from_slot: Option<u64>,
) -> Self
```

| Field                       | Type                          | Default                          | Meaning                                                                                                                                   |
| --------------------------- | ----------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `compression`               | `Option<CompressionEncoding>` | `None`                           | Send and accept compressed messages.                                                                                                      |
| `connect_timeout`           | `Option<Duration>`            | 15 s                             | Connection timeout.                                                                                                                       |
| `timeout`                   | `Option<Duration>`            | 15 s                             | Request timeout.                                                                                                                          |
| `max_decoding_message_size` | `Option<usize>`               | `None` (client default)          | Raise it if large messages fail to decode.                                                                                                |
| `tls_config`                | `Option<ClientTlsConfig>`     | `None` (system and webpki roots) | Custom TLS configuration.                                                                                                                 |
| `tcp_nodelay`               | `Option<bool>`                | `None`                           | Set `TCP_NODELAY`.                                                                                                                        |
| `replay_enabled`            | `bool`                        | `true`                           | Track slots and resume from the last one after a reconnect.                                                                               |
| `from_slot`                 | `Option<u64>`                 | `None`                           | Start the first subscription at this past slot. **Only honoured when `replay_enabled` is `true`**; with replay off it is reset to `None`. |

To start from a recent past slot:

```rust
let geyser_config = LaserStreamClientConfig {
    from_slot: Some(467_000_000),
    ..LaserStreamClientConfig::default()
};
```

## Behaviour

- **Connecting.** `consume` connects first and returns `FailedToConsumeDatasource` if that fails, which stops a pipeline that has no other datasource.
- **Replay.** With `replay_enabled`, the datasource adds an internal slot subscription and remembers the last slot it saw. On reconnect it sets `from_slot` to that slot for `Confirmed` and `Finalized`, or to 31 slots earlier for `Processed` (and when `commitment` is `None`). Messages from the resumed slot can arrive twice; add a [deduplication filter](https://carbon.sevenlabs.org/concepts/filters.md) if your processor isn't idempotent.
- **Updates.** Same mapping as [Yellowstone](https://carbon.sevenlabs.org/datasources/yellowstone-grpc.md#behaviour): account messages become `AccountUpdate` or `AccountDeletion`, transaction messages become `Transaction` with `is_vote` and `index` from Geyser, and block messages expand into transactions and accounts. Failed and vote transactions pass unless your filter excludes them. No `BlockDetails` are emitted.
- **Reconnects.** After the stream ends, errors or fails to subscribe, the datasource waits 3 seconds and subscribes again. After 10 consecutive failed attempts it logs `Max reconnection attempts reached: 10` and stops, which shuts down a pipeline that has no other datasource. A successful subscription resets the count. There is no inactivity timeout: a connection that stays open but silent is not detected.
- **Backpressure.** Updates use `try_send` and are dropped with `Failed to send … ` when the pipeline channel is full.
- **Metrics.** Counters `laserstream_account_updates_received_total`, `laserstream_account_deletions_received_total`, `laserstream_transaction_updates_received_total`; histograms `laserstream_account_process_time_nanoseconds`, `laserstream_account_deletion_process_time_nanoseconds`, `laserstream_transaction_process_time_nanoseconds`.

## Troubleshooting

### The pipeline exits with `FailedToConsumeDatasource("gRPC transport error: …")`

The first connection failed. Check the regional endpoint URL, including `https://`, and your network.

### `Failed to subscribe, will retry after 5s delay`

The subscription was rejected, usually because the API key is wrong or the plan doesn't include LaserStream. The actual delay is 3 seconds; after 10 failures the datasource stops.

### `from_slot` has no effect

You set `replay_enabled: false`. The datasource only sends `from_slot` when replay is enabled.

### Duplicate transactions after a reconnect

Expected with replay. Deduplicate by signature, or make writes idempotent (for example, upserts keyed by signature).

### The stream stops without an error

There is no inactivity timeout. Monitor `laserstream_transaction_updates_received_total` (see [Prometheus](https://carbon.sevenlabs.org/guides/prometheus.md)) and restart the process if it stops growing.

## See also

- [Stream with LaserStream](https://carbon.sevenlabs.org/guides/stream-with-laserstream.md)
- [Yellowstone gRPC](https://carbon.sevenlabs.org/datasources/yellowstone-grpc.md) for filter types and the full update mapping
- [Filters](https://carbon.sevenlabs.org/concepts/filters.md) for deduplication
- [Datasources concept](https://carbon.sevenlabs.org/concepts/datasources.md) and [update types](https://carbon.sevenlabs.org/concepts/updates.md)

---

Carbon 2.0.0 documentation · Web: https://carbon.sevenlabs.org/datasources/helius-laserstream · Last updated 2026-11-09 · Index of all pages: https://carbon.sevenlabs.org/llms.txt
