> For the complete documentation index, see [llms.txt](https://docs.triton.one/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.triton.one/solana/quickstart/streaming/how-to-use-shipstern-grpc.md).

# How to use Shipstern + gRPC

Build program-aware Solana data pipelines with Shipstern, fed by Triton's gRPC, Fumarole, or RPC.

Shipstern is an open-source framework for building program-aware, real-time Solana data pipelines. It provides the core components — runtime, parser definitions, and handler interfaces — needed to transform raw on-chain events into structured, actionable data.

{% hint style="info" %}
**Shipstern was formerly called Yellowstone Vixen.** It runs on your side: you use one of its built-in parsers or write your own, then connect it to a Triton data source. Triton does not operate a hosted parsed-streams service.
{% endhint %}

## How it works

Solana change events, following the Yellowstone gRPC specification, are received from a **source** and routed through pluggable **parsers**. Your **handlers** then log, store, or stream the enriched data for indexing, analytics, and downstream consumption.

Shipstern is built for four things:

* **Cost efficiency.** Share Dragon's Mouth subscriptions and filter only the data you care about.
* **Operational simplicity.** Lightweight setup, with minimal external dependencies.
* **Observability.** Built-in Prometheus metrics for lag, throughput, and error tracking.
* **Composability.** Independent, reusable parser crates that can deserialize complex cross-program interactions (CPI).

## Connect a Triton source

Each source is a Rust crate you configure in your Shipstern pipeline. These connect Shipstern to Triton infrastructure:

| Source crate                            | Triton service                                                            | Use it for                                                                                                      |
| --------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `shipstern-yellowstone-grpc-source`     | [Dragon's Mouth gRPC](/solana/real-time-streaming/dragon-s-mouth-grpc.md) | Real-time account and transaction streams via the Dragon's Mouth Geyser plugin                                  |
| `shipstern-yellowstone-fumarole-source` | [Fumarole](/solana/real-time-streaming/fumarole-persistent-streams.md)    | Persistent streams that merge data from multiple nodes, support consumer groups, and resume after interruptions |
| `shipstern-solana-rpc-source`           | [Standard RPC](/solana/readme.md)                                         | Pulling account data with `getProgramAccounts`                                                                  |
| `shipstern-jetstream-source`            | [Old Faithful](/solana/historical-data.md)                                | Replaying historical blocks over a slot or epoch range, as the same `SubscribeUpdate` messages as a live stream |

Shipstern also ships a `shipstern-solana-snapshot-source` for loading ledger snapshots offline.

{% hint style="warning" %}
**The RPC source filters on account owners only.** Its prefilter's `accounts` pubkey set and `filters` comparisons (`Memcmp`, `DataSize`, and the rest) are not translated into the RPC request, so a prefilter that narrows on those still fetches every account the owner holds. For fine-grained filtering at the source, use Dragon's Mouth gRPC.
{% endhint %}

Archives hold only finalized history, so slots replayed through `shipstern-jetstream-source` report `SLOT_FINALIZED`. Its folder in the repository is `jetstreamer-source`, but the crate is published as `shipstern-jetstream-source`.

## Built-in parsers

Shipstern ships parsers for these programs:

| Address                                       | Program                | Parser crate                            |
| --------------------------------------------- | ---------------------- | --------------------------------------- |
| `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | Token Program          | `shipstern-spl-token-parser`            |
| `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | Token Extensions       | `shipstern-spl-token-extensions-parser` |
| `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | SPL Stake Pool         | `shipstern-stake-pool-parser`           |
| `BPFLoaderUpgradeab1e11111111111111111111111` | BPF Loader Upgradeable | `shipstern-bpf-loader-parser`           |

Two more parsers read block-level updates rather than a program's accounts and instructions: `shipstern-block-meta-parser` for `BlockMeta`, and `shipstern-slot-parser` for `Slot`.

For any other program, generate a type-safe parser directly from its IDL — see [Generate parsers with Codama](/solana/quickstart/streaming/generate-parsers-with-codama.md).

## Quick start

A minimal pipeline that streams Token Program accounts and instructions from Dragon's Mouth gRPC and logs the parsed values.

{% code title="Cargo.toml" %}

```toml
[dependencies]
shipstern = "0.12"
shipstern-spl-token-parser = "0.12"
shipstern-yellowstone-grpc-source = "0.12"
clap = { version = "4", features = ["derive"] }
rustls = "0.23"
toml = "0.9"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
```

{% endcode %}

{% code title="src/main.rs" %}

```rust
use std::path::PathBuf;

use clap::Parser;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use shipstern::Pipeline;
use shipstern_spl_token_parser::{AccountParser, InstructionParser};
use shipstern_yellowstone_grpc_source::YellowstoneGrpcSource;

#[derive(clap::Parser)]
#[command(version, author, about)]
pub struct Opts {
    #[arg(long, short)]
    config: PathBuf,
}

#[derive(Debug)]
pub struct Logger;

impl<V: std::fmt::Debug + Sync, R: Sync> shipstern::Handler<V, R> for Logger {
    async fn handle(&self, value: &V, _raw: &R) -> shipstern::HandlerResult<()> {
        tracing::info!(?value);
        Ok(())
    }
}

fn main() {
    rustls::crypto::aws_lc_rs::default_provider()
        .install_default()
        .expect("Failed to install rustls crypto provider");

    tracing_subscriber::registry()
        .with(tracing_subscriber::EnvFilter::from_default_env())
        .with(tracing_subscriber::fmt::layer())
        .init();

    let Opts { config } = Opts::parse();
    let config = std::fs::read_to_string(config).expect("Error reading config file");
    let config = toml::from_str(&config).expect("Error parsing config");

    shipstern::Runtime::builder()
        .account(Pipeline::new(AccountParser, [Logger]))
        .instruction(Pipeline::new(InstructionParser, [Logger]))
        .build::<YellowstoneGrpcSource>(config)
        .run();
}
```

{% endcode %}

{% code title="Shipstern.toml" %}

```toml
[source]
endpoint = "https://<your-endpoint>.mainnet.rpcpool.com"
x-token = "<your-token>"
timeout = 60
```

{% endcode %}

Run it with that configuration:

```bash
RUST_LOG=info cargo run -- --config "./Shipstern.toml"
```

### Metrics

Metrics are collected into a `prometheus::Registry` that you hand to the runtime with `.metrics(registry)`. The runtime serves no HTTP endpoint of its own, so push the gathered metrics to a Pushgateway. The repository's `docker-compose.yaml` starts a Pushgateway on `:9091` and a Prometheus that scrapes it, so metrics appear at `http://localhost:9090`:

```bash
sudo docker-compose up
```

## Get started

Setup and configuration live in the Shipstern repository:

* [Quick start](https://github.com/solana-rpc/shipstern#quick-start) — build and run your first pipeline.
* [Example configuration](https://github.com/solana-rpc/shipstern/blob/main/Shipstern.example.toml) — a starter `Shipstern.example.toml` for pipeline configuration.
* [Usage examples](https://github.com/solana-rpc/shipstern/tree/main/examples) — example projects for each feature.
* [Generate parsers from IDL](https://github.com/solana-rpc/shipstern/blob/main/docs/codama-parser-generation.md) — the `include_shipstern_parser!` macro, including self-CPI event envelopes.

Point the source at your Triton endpoint and token from the [customer dashboard](https://customers.triton.one/). Shipstern is developed by Jupiter, ABK Labs, and Triton One.

## What's next

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Dragon's Mouth gRPC</strong></td><td>Sub-slot real-time updates for accounts, transactions, slots, and blocks — the most common Shipstern source.</td><td><a href="/solana/real-time-streaming/dragon-s-mouth-grpc.md">Dragon's Mouth gRPC</a></td></tr><tr><td><strong>Generate parsers with Codama</strong></td><td>Build a parser for your own program from its IDL.</td><td><a href="/solana/quickstart/streaming/generate-parsers-with-codama.md">Generate parsers with Codama</a></td></tr><tr><td><strong>Fumarole</strong></td><td>Persistent streams with an at-least-once delivery guarantee.</td><td><a href="/solana/real-time-streaming/fumarole-persistent-streams.md">Fumarole Persistent gRPC</a></td></tr></tbody></table>

***

<i class="fa-life-ring">:life-ring:</i> Contact support by clicking the chat icon in your [customer dashboard](https://customers.triton.one)\ <i class="fa-briefcase">:briefcase:</i> Sales questions? [Contact us](https://triton.one/contact)\ <i class="fa-sparkles">:sparkles:</i> AI agent? Read [llms.txt](https://docs.triton.one/llms.txt)\ <i class="fa-rss">:rss:</i> Follow updates: [Blog](https://blog.triton.one) · [X](https://x.com/triton_one) · [YouTube](https://www.youtube.com/@triton_one_ltd) · [Telegram](https://t.me/tritonone) · [GitHub](https://github.com/rpcpool)
