Skip to main content

Yellowstone and Vixen: Monitor Real-Time Jupiter Limit Orders in Rust

Updated on
Apr 14, 2026

19 min read

Overviewโ€‹

This guide builds a real-time Jupiter Limit Order monitor in Rust using Yellowstone gRPC and Vixen, a Rust-based Solana data parsing toolkit. The application streams confirmed limit order transactions and logs order placements, fills, and cancellations with human-readable token amounts and symbols. Along the way, the guide demonstrates three Vixen v0.6.1 features: IDL-based parser codegen via proc-macro, the failed field in TransactionPrefilter for filtering out failed transactions, and structured tracing for observability.


TL;DR
  • Build a real-time Jupiter Limit Order v2 monitor in Rust using Yellowstone gRPC and Vixen
  • Generate a type-safe parser directly from the Jupiter Limit Order IDL using Vixen's include_vixen_parser! proc-macro
  • Stream only confirmed (non-failed) transactions using Vixen v0.6.1's TransactionPrefilter
  • Log order placements, fills, and cancellations with human-readable token symbols and amounts
  • Run on Quicknode's Yellowstone gRPC add-on (Solana mainnet)

What You Will Doโ€‹


  • Set up a Rust project with Vixen v0.6.1 dependencies
  • Fetch and convert the Jupiter Limit Order v2 IDL to Codama format
  • Generate a type-safe instruction parser using Vixen's proc-macro
  • Implement a handler that logs limit order events with human-readable output
  • Build and run a Vixen runtime connected to Quicknode's Yellowstone gRPC endpoint

What You Will Needโ€‹


This guide also uses the following packages:

DependencyVersion
rustc1.85.0
yellowstone-vixen0.6.1
yellowstone-vixen-core0.6.1
yellowstone-vixen-parser0.6.1
yellowstone-vixen-proc-macro0.6.1
yellowstone-vixen-yellowstone-grpc-source0.6.1
borsh1
bs580.5
chrono0.4
reqwest0.12
serde1
clap4
rustls0.23
toml0.8
tracing0.1
tracing-subscriber0.3

What is Yellowstone gRPC?โ€‹

Yellowstone gRPC is a high-performance data streaming solution for Solana built on the Geyser plugin system. Rather than polling an RPC endpoint for new data or managing WebSocket reconnections, Yellowstone gRPC pushes account updates, transactions, and slot notifications to your application as a continuous stream. This provides lower latency and higher throughput compared to traditional approaches.

Quicknode exposes Yellowstone gRPC through the Yellowstone gRPC add-on. You can enable it on any Solana endpoint from the Quicknode dashboard. The paid add-on provides a dedicated gRPC endpoint and authentication token for your application.

Key filtering capabilities include:


  • Filter by program address to receive only transactions involving a specific program
  • Filter out failed transactions so only confirmed onchain events are processed
  • Filter out vote transactions to reduce noise

What is Vixen?โ€‹

Vixen is an open-source Rust framework for building Solana data pipelines on top of Yellowstone gRPC. It handles gRPC subscriptions, transaction filtering, and deserialization automatically, so application code receives typed Rust structs instead of raw bytes.

Vixen uses a Parser + Handler architecture to separate data extraction from business logic:


  • Parser: Deserializes raw transaction data into typed Rust structs
  • Handler: Receives the parsed data and implements your application logic
  • Pipeline: Connects a parser to one or more handlers
  • Runtime: Manages the gRPC connection, stream subscription, and pipeline execution

According to the Vixen v0.6.1 release notes, this release introduces three production-focused improvements that this guide demonstrates:


  1. IDL-based codegen via proc-macro: Generate a type-safe parser directly from a program's IDL using include_vixen_parser!, eliminating manual deserialization code
  2. failed field in TransactionPrefilter: Exclude failed transactions from the stream so only confirmed onchain events reach your handler
  3. Tracing spans for observability: Structured, filterable log output via the tracing crate instead of plain log/env_logger

Vixen vs Carbonโ€‹

Vixen and Carbon are both Rust frameworks for parsing Solana program data. They share the same core approach: stream transactions via Yellowstone gRPC, decode instruction data into typed structs, and process events in handlers, but differ in how they generate parsers and what data sources they support:

FeatureVixenCarbon
Parser generationIDL codegen via include_vixen_parser! proc-macro at compile timePre-built decoder crates + CLI codegen from IDL
Data sourcesYellowstone gRPCYellowstone gRPC, JITO Shredstream, JSON RPC
Built-in program supportNone โ€” generate from any Anchor IDL60+ pre-built decoders for popular programs
Setup for a supported programFetch IDL โ†’ convert to Codama โ†’ macro invocationAdd a single Cargo crate dependency
Observabilitytracing crate with structured spansPrometheus metrics + logging
Pipeline modelRuntime โ†’ Pipeline โ†’ Parser โ†’ HandlerPipeline โ†’ Datasource โ†’ Decoder โ†’ Processor

For a Carbon-based guide, see Yellowstone and Carbon: Parse Real-time Solana Program Data.

The Sample App: Jupiter Limit Order Monitorโ€‹

Jupiter Limit Orders is an onchain order book that lets traders place orders that execute automatically when the market reaches a specified price. Unlike instant swaps, limit orders sit onchain until a keeper (referred to as taker in the program's accounts) fills them at or better than the requested price. The maker can also cancel an unfilled order at any time to reclaim their tokens.

Jupiter Limit Orders is used for this guide for three reasons:


  1. All activity flows through a single Anchor program (j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X), which maps cleanly to Vixen's single-pipeline model.
  2. The program publishes an onchain IDL, which lets us demonstrate Vixen's IDL codegen feature end-to-end.
  3. The program emits three discrete, semantically distinct instruction types (one per lifecycle event) which makes the handler logic straightforward to read and extend.

The three instructions this guide monitors are:


  • InitializeOrder: A maker creates a new limit order specifying input/output tokens and amounts
  • FillOrder: A keeper fills an existing order at or better than the requested price
  • CancelOrder: A maker cancels their unfilled order and reclaims their tokens

For each event, the handler resolves human-readable token symbols from Jupiter's token API and formats raw token amounts using the decimal precision from the transaction's token balance metadata.

Set Up the Projectโ€‹

Create the project directory and an idls folder to store the Jupiter Limit Order IDL:

cargo new jupiter-lo-vixen
cd jupiter-lo-vixen
mkdir idls

Replace the contents of Cargo.toml with the following. All Vixen crates are pinned to v0.6.1:

Cargo.toml
[package]
name = "jupiter-lo-vixen"
version = "0.1.0"
edition = "2021"

[dependencies]
yellowstone-vixen = "0.6.1"
yellowstone-vixen-core = "0.6.1"
yellowstone-vixen-parser = "0.6.1"
yellowstone-vixen-proc-macro = "0.6.1"
yellowstone-vixen-yellowstone-grpc-source = "0.6.1"
borsh = { version = "1", features = ["derive"] }
bs58 = "0.5"
chrono = { version = "0.4", features = ["clock"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
serde = { version = "1", features = ["derive"] }
clap = { version = "4", features = ["derive"] }
rustls = { version = "0.23", features = ["ring"] }
toml = "0.8"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

Note that yellowstone-vixen-core must be a direct dependency (not just transitive through yellowstone-vixen) because the proc-macro generates code that references it by crate name.

Here is what the key dependencies do:


  • yellowstone-vixen / yellowstone-vixen-core: The Vixen runtime and core traits (Parser, Handler, Pipeline)
  • yellowstone-vixen-proc-macro: The include_vixen_parser! macro for IDL-based codegen
  • yellowstone-vixen-yellowstone-grpc-source: Connects the Vixen runtime to a Yellowstone gRPC endpoint
  • borsh: Serialization format used by Solana programs (required by the generated parser)
  • bs58: Base58 encoding for transaction signatures
  • chrono: Timestamp formatting for log output
  • reqwest: HTTP client for fetching token symbols from the Jupiter API
  • clap: Command-line argument parsing for the --config flag
  • rustls: TLS provider required by the gRPC connection
  • tracing / tracing-subscriber: Structured logging with environment-based filtering

Create Vixen.toml at the project root. This is the only config file the application needs:

Vixen.toml
[source]
endpoint = "YOUR_QN_ENDPOINT:10000"
x-token = "YOUR_X_TOKEN"
timeout = 120
commitment-level = "confirmed"
accept-compression = "zstd"

You can find these values in the Quicknode dashboard under your Solana mainnet endpoint's Yellowstone gRPC add-on settings. The dashboard displays your endpoint URL in the format https://your-endpoint-name.solana-mainnet.quiknode.pro/abc123. Append :10000 to the hostname for the endpoint field, and use the trailing token (abc123) as your x-token. For more details, see the Yellowstone gRPC documentation.

Generate Parser from Limit Order IDLโ€‹

Instead of writing manual deserialization code for each instruction, you provide a program's IDL in Codama format and the include_vixen_parser! macro generates a complete type-safe parser at compile time. This section walks through the full flow so you can apply it to any Anchor program.

Fetch the Jupiter Limit Order v2 IDL:

The Vixen repo already includes a ready-to-use Codama IDL for Jupiter Limit Order v2 at tests/idls/lo_v2.json. You can copy it directly into your idls/ folder and skip straight to Invoke the Proc-Macro. The steps below walk through the full fetch-and-convert flow so you can apply the same process to any Anchor program that doesn't already have a Codama IDL available.

Use the Anchor CLI to fetch the onchain IDL for the Jupiter Limit Order v2 program. Replace YOUR_QN_RPC_URL with your Quicknode Solana mainnet RPC endpoint:

anchor idl fetch j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X \
--provider.cluster YOUR_QN_RPC_URL \
-o idls/lo_v2_raw.json

The IDL contains the full program interface definition: instruction names, account structures, argument types, and the program address. This is what Vixen uses to generate typed Rust code.


An Anchor IDL Gotcha

When you downloaded the IDL using the anchor idl command, it came with a small inconsistency that trips up Codama's converter. In the initialize_order instruction, a PDA seed references an argument called unique_id, but in this IDL, unique_id is actually nested inside a params struct, not a top-level argument. Codama looks for it at the top level, can't find it, and errors out.

This is something you may run into when using Codama with other programs' IDLs where the IDL is technically valid Anchor output, but the path reference doesn't match the actual argument structure. You may have to manually troubleshoot issues like these when using an IDL that doesn't already have a Codama format IDL when using Vixen.

To fix this issue, open idls/lo_v2_raw.json and find this line (around #621) in the initialize_order instruction's account seeds:

idls/lo_v2_raw.json
{ 
"kind": "arg",
"path": "unique_id"
}

Change it to:

idls/lo_v2_raw.json
{ 
"kind": "arg",
"path": "params.unique_id"
}

Convert to Codama Format:

Initialize the root project folder as a Node.js project so we can run Codama commands:

npm init -y
npm install -g @codama/cli
npm install @codama/nodes-from-anchor

@codama/nodes-from-anchor is required to understand Anchor's IDL format during the conversion.

Convert the raw Anchor IDL to Codama format:

codama convert idls/lo_v2_raw.json idls/lo_v2.json

This one-time conversion step is what unlocks Vixen's compile-time codegen for any Anchor program.

Invoke the Proc-Macroโ€‹

Create src/parser.rs with the following:

src/parser.rs
use yellowstone_vixen_proc_macro::include_vixen_parser;

include_vixen_parser!("idls/lo_v2.json");

This single macro call generates at compile time:


  • A limit_order2 module containing all generated types
  • A typed Instructions enum with variants for every instruction in the IDL (InitializeOrder, FillOrder, CancelOrder, and others)
  • Typed account and argument structs for each instruction
  • An InstructionParser that implements Vixen's parser trait
  • A TransactionPrefilter configured with three filters: program address (Jupiter LO v2 only), failed: Some(false) (new in v0.6.1) to exclude failed transactions, and vote: Some(false) to exclude vote transactions

Implement the Monitorโ€‹

Vixen v0.6.1 uses the tracing crate for structured, filterable log output, replacing the older log/env_logger pattern used in previous versions of Vixen.

The tracing subscriber respects the RUST_LOG environment variable, so you control verbosity at runtime without recompiling:


  • RUST_LOG=info: Shows handler output and Vixen lifecycle events
  • RUST_LOG=debug: Adds gRPC connection details and stream subscription activity
  • RUST_LOG=warn: Shows only warnings and errors

The initialization happens in main() before any other code runs, ensuring all Vixen internals and your handler code benefit from structured logging.

Implement the Limit Order Handlerโ€‹

Create src/handlers.rs. The handler receives parsed instructions from the generated parser and logs the three order events: placements, fills, and cancellations.

The handler includes helpers that fetch human-readable token symbols from Jupiter's token API and cache them to avoid repeated lookups. It also extracts decimal precision from the transaction's token balance metadata to display amounts in human-readable form (e.g., 1.5 USDC instead of 1500000).

src/handlers.rs
use std::{collections::HashMap, sync::Mutex};

use yellowstone_vixen::vixen_core::instruction::InstructionUpdate;

use crate::parser::limit_order2;

fn fmt_amount(raw: u64, decimals: u32) -> String {
if decimals == 0 {
return raw.to_string();
}
let s = format!("{:.prec$}", raw as f64 / 10f64.powi(decimals as i32), prec = decimals as usize);
s.trim_end_matches('0').trim_end_matches('.').to_string()
}

fn fmt_token(amount: &str, symbol: &str, mint: &str) -> String {
if symbol == mint {
format!("{amount} {mint}")
} else {
format!("{amount} {symbol} ({mint})")
}
}

async fn fetch_symbol(mint: &str) -> String {
#[derive(serde::Deserialize)]
struct Token {
id: String,
symbol: String,
}

let url = format!("https://api.jup.ag/tokens/v2/search?query={mint}");
let fallback = mint.to_string();

let Ok(resp) = reqwest::get(&url).await else {
return fallback;
};
let Ok(tokens) = resp.json::<Vec<Token>>().await else {
return fallback;
};
tokens
.into_iter()
.find(|t| t.id == mint)
.map(|t| t.symbol)
.unwrap_or(fallback)
}

#[derive(Debug, Default)]
pub struct LimitOrderHandler {
symbol_cache: Mutex<HashMap<String, String>>,
}

impl LimitOrderHandler {
async fn get_symbol(&self, mint: &str) -> String {
{
let cache = self.symbol_cache.lock().unwrap();
if let Some(sym) = cache.get(mint) {
return sym.clone();
}
}
let symbol = fetch_symbol(mint).await;
self.symbol_cache
.lock()
.unwrap()
.insert(mint.to_string(), symbol.clone());
symbol
}
}

impl yellowstone_vixen::Handler<limit_order2::Instructions, InstructionUpdate>
for LimitOrderHandler
{
async fn handle(
&self,
value: &limit_order2::Instructions,
raw: &InstructionUpdate,
) -> yellowstone_vixen::HandlerResult<()> {
use limit_order2::instruction::Instruction;

let sig = bs58::encode(&raw.shared.signature).into_string();
let ts = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.6fZ");

let pre = &raw.shared.pre_token_balances;
let post = &raw.shared.post_token_balances;
let find_decimals = |mint: &str| {
pre.iter()
.chain(post.iter())
.find(|b| b.mint == mint)
.and_then(|b| b.ui_token_amount.as_ref())
.map(|u| u.decimals)
};

match &value.instruction {
Instruction::InitializeOrder { accounts, args } => {
let input_mint_str = accounts.input_mint.to_string();
let output_mint_str = accounts.output_mint.to_string();

let input_symbol = self.get_symbol(&input_mint_str).await;
let output_symbol = self.get_symbol(&output_mint_str).await;

let making_amount = find_decimals(&input_mint_str)
.map(|d| fmt_amount(args.making_amount, d))
.unwrap_or_else(|| args.making_amount.to_string());
let taking_amount = find_decimals(&output_mint_str)
.map(|d| fmt_amount(args.taking_amount, d))
.unwrap_or_else(|| args.taking_amount.to_string());

let expired_at = args.expired_at
.and_then(|t| chrono::DateTime::from_timestamp(t, 0))
.map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
.unwrap_or_else(|| "None".to_string());

let making = fmt_token(&making_amount, &input_symbol, &input_mint_str);
let taking = fmt_token(&taking_amount, &output_symbol, &output_mint_str);
tracing::info!(
tx = %sig,
maker = %accounts.maker,
making_amount = %making,
taking_amount = %taking,
expired_at = %expired_at,
"New limit order placed - {ts}",
);
},
Instruction::FillOrder { accounts, args } => {
let input_mint_str = accounts.input_mint.to_string();
let output_mint_str = accounts.output_mint.to_string();

let input_symbol = self.get_symbol(&input_mint_str).await;

let input_amount = find_decimals(&input_mint_str)
.map(|d| fmt_amount(args.input_amount, d))
.unwrap_or_else(|| args.input_amount.to_string());

let input = fmt_token(&input_amount, &input_symbol, &input_mint_str);
tracing::info!(
tx = %sig,
taker = %accounts.taker,
output_mint = %output_mint_str,
input_amount = %input,
"Limit order filled - {ts}",
);
},
Instruction::CancelOrder { accounts, .. } => {
tracing::info!(
tx = %sig,
maker = %accounts.maker,
order = %accounts.order,
"Limit order cancelled - {ts}",
);
},
_ => {},
}

Ok(())
}
}

The handler implements Vixen's Handler trait for the generated limit_order2::Instructions type. It pattern-matches on three instruction variants:


  • InitializeOrder: Logs the maker's address, input/output tokens with human-readable amounts, and the order's expiration timestamp
  • FillOrder: Logs the taker's address, the output mint, and the input amount being filled
  • CancelOrder: Logs the maker's address and the order account being cancelled
  • _ (wildcard): Silently ignores all other instructions (fee updates, admin operations, etc.)

The handler also includes user-friendly formatting such as decimal conversion for token amounts and ticker symbol lookups via Jupiter's token API. For an ultra-high-performance application, these outbound API calls could impact performance.

Build the Vixen Runtimeโ€‹

Replace the generated src/main.rs with the following code. This ties everything together: tracing initialization, the TLS crypto provider, config loading, and the Vixen runtime with the instruction pipeline.

src/main.rs
use std::path::PathBuf;

use clap::Parser as _;
use yellowstone_vixen::Pipeline;
use yellowstone_vixen_yellowstone_grpc_source::YellowstoneGrpcSource;

mod handlers;
mod parser;

use handlers::LimitOrderHandler;
use parser::limit_order2;

#[derive(clap::Parser)]
#[command(version, author, about = "Monitor Jupiter Limit Order v2 events via Yellowstone Vixen")]
struct Opts {
#[arg(long, short)]
config: PathBuf,
}

fn main() {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.init();

rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install rustls crypto provider");

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");

yellowstone_vixen::Runtime::<YellowstoneGrpcSource>::builder()
.instruction(Pipeline::new(limit_order2::InstructionParser, [LimitOrderHandler::default()]))
.build(config)
.run();
}

The runtime setup performs four steps:


  1. Tracing: Initializes tracing-subscriber with EnvFilter so the RUST_LOG environment variable controls log verbosity at runtime without recompiling
  2. TLS: Installs the rustls crypto provider, which is required by the gRPC TLS connection to Quicknode
  3. Config: Reads and parses Vixen.toml for the endpoint, token, and stream settings
  4. Runtime: Builds a Vixen Runtime with a single instruction Pipeline that connects the generated InstructionParser to the LimitOrderHandler, then starts streaming

The Pipeline::new call wires the parser to the handler. The generated InstructionParser handles subscription filtering (program address, failed transactions, vote transactions) and deserialization. Your handler receives only parsed, typed instruction data for the Jupiter Limit Order v2 program.

Build and Run the Applicationโ€‹

Build the project:

cargo build

Run it with the config flag. Set RUST_LOG=info to see handler output and Vixen lifecycle events:

RUST_LOG=info cargo run -- --config ./Vixen.toml

Expected Outputโ€‹

Once connected, you will see Vixen lifecycle log lines followed by limit order events as they occur on mainnet. Here is example output for each of the three event types:

2026-04-08T14:32:01.123456Z  INFO jupiter_lo_vixen: New limit order placed - 2026-04-08T14:32:01.123456Z tx=5UjQ...abc maker=7xKm...def making_amount="100 USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v)" taking_amount="1.5 SOL (So11111111111111111111111111111111111111112)" expired_at=2026-04-15T00:00:00Z
2026-04-08T14:33:15.654321Z INFO jupiter_lo_vixen: Limit order filled - 2026-04-08T14:33:15.654321Z tx=3Kpx...ghi taker=9mRv...jkl output_mint=So11111111111111111111111111111111111111112 input_amount="100 USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v)"
2026-04-08T14:35:42.789012Z INFO jupiter_lo_vixen: Limit order cancelled - 2026-04-08T14:35:42.789012Z tx=8FnY...mno maker=7xKm...def order=4vTq...pqr

Each entry includes an ISO 8601 timestamp, the transaction signature, and the relevant accounts and amounts for the event type. Token amounts are displayed in human-readable form with ticker symbols resolved from Jupiter's token API.

Expand Your Monitorโ€‹

The architecture you built is flexible. Here are some ways to extend it:


  • Monitor a different Jupiter program: Swap in the IDL for Jupiter DCA, Perps, or any other Anchor program. The pipeline structure stays the same; only the IDL file and handler logic change.
  • Watch multiple programs simultaneously: Vixen v0.6.1 supports multiple program subscriptions. Add a second instruction pipeline to monitor both Limit Order v1 and v2 in the same runtime.
  • Add account monitoring: Alongside instruction monitoring, add an account pipeline to track changes to specific limit order account states.
  • Persist events to a database: Extend the handler to write parsed events to PostgreSQL, ClickHouse, or another datastore for historical analysis.

Frequently Asked Questionsโ€‹

What is Yellowstone gRPC and how does it enable real-time monitoring on Solana?

Yellowstone gRPC is a high-performance gRPC interface for streaming Solana blockchain data, including transactions and account updates, in real time. It allows Rust applications to subscribe to specific programs like Jupiter for low-latency limit order feeds without polling.

What is Vixen in the context of Solana development?

Vixen is an open-source Rust framework for building typed data pipelines on top of Yellowstone gRPC. It handles the gRPC connection, stream filtering, and instruction deserialization automatically, so you write business logic against typed Rust structs rather than raw bytes. Its core abstractions are a Parser, which decodes instructions, a Handler, which processes them, and a Pipeline, which connects the two inside a managed Runtime.

Can I use Vixen to monitor programs other than Jupiter Limit Orders?

Yes. Vixen's proc-macro works with any Anchor program that publishes an IDL. Fetch the IDL with the Anchor CLI, convert it to Codama format, and pass it to include_vixen_parser!. The generated parser and pipeline structure remain the same. Only the IDL file and your handler logic change.

Why does the TransactionPrefilter exclude failed transactions?

Vixen v0.6.1 introduced a failed field in its TransactionPrefilter. Setting it to exclude failed transactions ensures only confirmed, successfully executed transactions reach your handler. For a limit order monitor, this prevents logging events like failed fill attempts that never actually executed onchain.

Do I need a Quicknode account to use Vixen?

Vixen itself is an open-source framework. However, it requires a Yellowstone gRPC endpoint to stream data. Quicknode's Yellowstone gRPC add-on provides a managed gRPC endpoint for Solana mainnet that you can enable on any Quicknode Solana endpoint from the dashboard.

What is Codama and why is a conversion step needed?

Codama is an IDL format that provides richer type information than Anchor's native IDL format. Vixen's proc-macro requires Codama format to generate accurate typed structs and enums. The codama convert command bridges the two formats. This one-time conversion step is what unlocks Vixen's compile-time codegen for any Anchor program.

Wrapping Upโ€‹

You have built a real-time Jupiter Limit Order monitor that streams confirmed transactions via Yellowstone gRPC, parses them into typed Rust structs using Vixen's IDL codegen, and logs order placements, fills, and cancellations with human-readable token output. From here, you can apply the same pattern to any Anchor program by swapping in its IDL, making Vixen a versatile foundation for building Solana data pipelines.

Resourcesโ€‹


Have questions? Join the Quicknode Discord or follow @quicknode for updates.

We โค๏ธ Feedback!

Let us know if you have any feedback or requests for new topics. We'd love to hear from you.

Share this guide