For the complete documentation index, see llms.txt. This page is also available as Markdown.

Overview

On-chain limit orders with partial fills, searcher execution, and configurable time-in-force.

Titan's Limit Orders are designed to thrive in a competitive environment where searchers play a central role. By participating as a searcher, you gain access to a marketplace of on-chain limit orders.

Limit orders are resting on-chain and can be partially or completely filled. Fees are charged to takers and are charged as output_mint tokens.

Program address: TitanLozLMhczcwrioEguG2aAmiATAPXdYpBg3DbeKK


Order structure

Each limit order is a PDA derived from the maker's public key, input mint, output mint, and an order ID.

use pinocchio::pubkey::{create_program_address, Pubkey};
use bytemuck::{Pod, Zeroable};

/// Limit order structure
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct LimitOrder {
    // The public key of the order,
    pub maker: Pubkey,
    // Input mint of the limit order
    pub input_mint: Pubkey,
    // Output mint of the limit order
    pub output_mint: Pubkey,
    // Slot which the order was created
    pub creation_slot: u64,
    // The slot at which the order expires
    pub expiration_slot: u64,
    // The amount of input tokens to be exchanged
    pub amount: u64,
    // The amount of input tokens that have been filled
    pub amount_filled: u64,
    // The amount of output tokens that have been exchanged.
    pub out_amount_filled: u64,
    // The amount of output tokens that the maker has withdrawn.
    pub out_amount_withdrawn: u64,
    // The amount of fees paid in the smallest unit of from_token mint.
    pub fees_paid: u64,
    // Price base in the order, in the smallest unit of output token
    pub price_base: u64,
    // Price exponent, price is calculated as price_base * 10^(-price_exponent)
    pub price_exponent: u8,
    // The status of the order
    pub status: u8,
    // Bump seed for the limit order PDA
    pub bump: u8,
    // Unique identifier for the order, used to differentiate orders for same
    // (owner, input_mint, output_mint) tuple
    pub id: u8,
    // Bump seed for the input mint vault PDA
    pub input_mint_vault_bump: u8,
    // Bump seed for the output mint vault PDA
    pub output_mint_vault_bump: u8,
    // Time in order
    pub time_in_force: u8,
    // Fees ticks rate for the order from takers.
    pub fee_ticks: u8,
}

PDA seeds: ["order", maker, input_mint, output_mint, id, bump]

Account size: 168 bytes.

PDA derivation


Price calculation

Price is stored as price_base * 10^(-price_exponent). For example, a 100 USDC → 1 SOL order uses price_base = 1 and price_exponent = 2, giving a price of 0.01 output tokens per input token.


Fees

Fees are charged to takers in the output token. The fee rate is stored as fee_ticks on the order.

The minimum fee is always 1 unit of the output token.

Fee receiver address: Bq5ZzfiU3vTiJPrBJFcr98BnUy9Wc1dg9ASeycB2tX1C


Time-in-force

Each order carries a time-in-force policy that controls fill behavior.

  • GoodTillCancelled (0) — Remains open until fully filled or cancelled. Partial fills allowed.

  • TakeCancelsOrder (1) — Closes after any take, regardless of fill amount.

  • AllOrNothing (2) — Takes must completely fill the remaining amount.

  • ImmediateOrCancel (3) — Same as TakeCancelsOrder, but must be filled in the same slot as creation.

  • FillOrKill (4) — Same as AllOrNothing, but must be filled in the same slot as creation.


Order status

  • Open (0) — Can be partially filled, fully filled, or cancelled.

  • PartiallyFilled (1) — Some amount filled. Can still be filled or cancelled.

  • Filled (2) — Fully filled. Terminal state.

  • Cancelled (3) — Cancelled by maker. Terminal state.


Last updated