Skip to main content

Introduction

The DLOB (Decentralized Limit Order Book) is a high-performance, event-driven orderbook aggregator for Drift Protocol. It maintains live orderbook state across multiple markets by consuming incremental updates from the blockchain.

Key Features

  • Event-Driven Architecture: Incrementally built from user account updates and slot changes
  • Multi-Market Support: Aggregates orderbooks for multiple perpetual and spot markets
  • L2 and L3 Snapshots: Provides both aggregated (L2) and order-level (L3) orderbook views
  • Lock-Free Reads: Optimized for high-throughput concurrent access
  • Order Matching: Built-in logic for finding crosses and matching orders
  • Auction Support: Handles Drift’s unique auction mechanisms for limit and market orders

DLOB Structure

The DLOB struct aggregates orderbooks for multiple markets:
pub struct DLOB {
    markets: DashMap<MarketId, Orderbook>,
    order_events: OrderEventMap,
    metadata: MetadataMap,
    program_data: &'static ProgramData,
    last_modified_slot: AtomicU64,
    enable_l2_snapshot: AtomicBool,
    enable_l3_snapshot: AtomicBool,
}

Order Types

The DLOB organizes orders into different categories based on their semantics:

Maker Orders (Resting)

  • Limit Orders: Orders with fixed prices that rest on the book
  • Floating Limit Orders: Orders with prices offset from the oracle price

Taker Orders (Auction)

  • Market Orders: Auction orders with fixed price bounds that change by slot
  • Oracle Orders: Auction orders with dynamic price bounds relative to oracle price

Conditional Orders

  • Trigger Orders: Orders that activate when a trigger condition is met

Basic Usage

Initialization

use drift_rs::dlob::DLOB;

let dlob = Box::leak(Box::new(DLOB::default()));
let notifier = dlob.spawn_notifier();

Getting Orderbook Snapshots

use drift_rs::types::{MarketId, MarketType};

// Get L3 snapshot (order-level detail)
let l3_book = dlob.get_l3_snapshot(0, MarketType::Perp);

// Get L2 snapshot (aggregated by price level)
dlob.enable_l2_snapshot();
let l2_book = dlob.get_l2_snapshot(0, MarketType::Perp);

Accessing Bids and Asks

// Get top bids and asks
let oracle_price = 50_000_000_000; // $50,000 in 6 decimals
let bids = l3_book.top_bids(10, Some(oracle_price), None, None);
let asks = l3_book.top_asks(10, Some(oracle_price), None, None);

for bid in bids {
    println!("Bid: {} @ {}", bid.size, bid.price);
}

Core Methods

Snapshot Methods

get_l3_snapshot
fn
Get an L3 (order-level) snapshot of the orderbookParameters:
  • market_index: u16 - Market index
  • market_type: MarketType - Perp or Spot market
Returns: Arc<L3Book>Panics: If orderbook doesn’t exist for the market
get_l3_snapshot_safe
fn
Get an L3 snapshot, returning None if orderbook doesn’t existReturns: Option<Arc<L3Book>>
get_l2_snapshot
fn
Get an L2 (aggregated) snapshot of the orderbookNote: L2 snapshots must be enabled via enable_l2_snapshot()Returns: Arc<L2Book>

Order Matching Methods

find_crosses_for_taker_order
fn
Find all maker orders that would cross with a given taker orderParameters:
  • current_slot: u64 - Current blockchain slot
  • oracle_price: u64 - Current oracle price
  • taker_order: TakerOrder - The taker order to match
  • perp_market: Option<&PerpMarket> - Market info for vAMM calculations
  • depth: Option<usize> - Max order depth to consider (default: 32)
Returns: MakerCrosses - Matched maker orders and fill info
find_crosses_for_auctions
fn
Find all auction orders crossing resting limit orders at the current slotParameters:
  • market_index: u16
  • market_type: MarketType
  • slot: u64
  • oracle_price: u64
  • perp_market: Option<&PerpMarket>
  • trigger_price: u64
  • depth: Option<usize>
Returns: CrossesAndTopMakers - All crosses and top maker accounts
find_crossing_region
fn
Find the crossing region where best bid >= best askReturns: Option<CrossingRegion> - Crossing orders if any exist

Configuration Methods

enable_l2_snapshot
fn
Enable live L2 snapshots for all orderbooks (disabled by default)
disable_l3_snapshot
fn
Disable live L3 snapshots for all orderbooks (enabled by default)
spawn_notifier
fn
Spawn a notifier channel for sending updates to the DLOBReturns: DLOBNotifier - Channel for sending order and slot updates

L3Book Structure

The L3Book provides order-level detail with support for:
  • Fixed price orders
  • Floating (oracle-offset) orders
  • VAMM taker orders
  • Trigger orders with dynamic post-trigger prices

L3Book Methods

impl L3Book {
    pub fn bids(
        &self,
        oracle_price: Option<u64>,
        perp_market: Option<&PerpMarket>,
        trigger_price: Option<u64>,
    ) -> impl Iterator<Item = &L3Order>;
    
    pub fn asks(
        &self,
        oracle_price: Option<u64>,
        perp_market: Option<&PerpMarket>,
        trigger_price: Option<u64>,
    ) -> impl Iterator<Item = &L3Order>;
    
    pub fn top_bids(
        &self,
        count: usize,
        oracle_price: Option<u64>,
        perp_market: Option<&PerpMarket>,
        trigger_price: Option<u64>,
    ) -> impl Iterator<Item = &L3Order>;
    
    pub fn top_asks(
        &self,
        count: usize,
        oracle_price: Option<u64>,
        perp_market: Option<&PerpMarket>,
        trigger_price: Option<u64>,
    ) -> impl Iterator<Item = &L3Order>;
    
    pub fn trigger_bids(&self, trigger_price: u64) -> impl Iterator<Item = &L3Order>;
    pub fn trigger_asks(&self, trigger_price: u64) -> impl Iterator<Item = &L3Order>;
}

L3Order Fields

pub struct L3Order {
    pub price: u64,        // Limit price at current slot & oracle price
    pub size: u64,         // Base asset amount
    pub max_ts: u64,       // Order expiry timestamp
    pub order_id: u32,     // Program-assigned order ID
    pub kind: OrderKind,   // Order type classification
    pub user: Pubkey,      // User subaccount
}

L3Order Methods

  • is_long() - True if this is a long order
  • is_reduce_only() - True if this is a reduce-only order
  • is_trigger_above() - True if trigger condition is “above”
  • is_post_only() - True if this is a post-only limit order
  • is_maker() - True if order is maker-only
  • is_taker() - True if order is taker-only
  • post_trigger_price(slot, oracle_price, perp_market) - Calculate post-trigger price for trigger orders

Order Kinds

pub enum OrderKind {
    Market,         // Auction with fixed price offset
    Oracle,         // Auction with oracle price offset
    Limit,          // Resting limit order
    FloatingLimit,  // Resting oracle-offset limit order
    TriggerMarket,  // Untriggered market order
    TriggerLimit,   // Untriggered limit order
}

Performance Considerations

Lock-Free Reads

The DLOB uses lock-free atomic operations for reading orderbook snapshots, enabling high-throughput concurrent access without contention.

Memory Management

Orderbooks are lazily initialized on first write, and snapshots use double-buffering to avoid blocking readers during updates.

Snapshot Trade-offs

  • L3 snapshots (enabled by default): Higher memory usage, full order detail
  • L2 snapshots (disabled by default): Lower memory usage, aggregated price levels
  • DLOBNotifier - Channel for sending updates to DLOB
  • DLOBBuilder - Convenience builder for constructing DLOB instances
  • OrderMetadata - Metadata about orders in the DLOB
  • TakerOrder - Minimal taker order info for matching
  • MakerCrosses - Matched maker orders for a taker
  • CrossesAndTopMakers - All auction crosses and top makers
  • CrossingRegion - Orders in a crossed book region

See Also

Build docs developers (and LLMs) love