Skip to main content

Overview

The Rust SDK provides OrderClient for order creation, EIP-712 signing, and order management. It supports:
  • OrderType::Gtc for resting limit orders
  • OrderType::Fak for fill-and-kill limit orders
  • OrderType::Fok for fill-or-kill market orders

Prerequisites

Before placing orders, you need:
  • an authenticated Client
  • a private key for EIP-712 signing
  • market venue data (fetched via get_market() and cached automatically)
use limitless_exchange_rust_sdk::Client;

let client = Client::new()?;
let private_key = std::env::var("PRIVATE_KEY")?;

let order_client = client.new_order_client(&private_key, None)?;
The OrderClient lazily fetches your profile on the first order to determine your owner_id and fee rate. CHAIN_ID defaults to 8453 (Base mainnet) unless you override it.

Token Approvals

Before your first trade on a given venue, you must approve the exchange contracts to spend your tokens. This is a one-time on-chain setup per venue.
Approve USDC and Conditional Tokens to the exchange contract:
let market = client.markets.get_market("your-market-slug").await?;
let exchange = market
    .venue
    .as_ref()
    .expect("venue")
    .exchange
    .clone();

println!("approve USDC and CTF to {}", exchange);
Approvals are on-chain transactions that cost gas. Use venue.exchange for both CLOB and NegRisk, and additionally venue.adapter for NegRisk markets.

GTC Orders

GTC orders remain on the book until filled or explicitly cancelled.
use limitless_exchange_rust_sdk::{CreateOrderParams, GtcOrderArgs, OrderType, Side};

let market = client.markets.get_market("btc-above-100k-march-2025").await?;
let tokens = market.tokens.as_ref().expect("market tokens");

let result = order_client
    .create_order(CreateOrderParams {
        order_type: OrderType::Gtc,
        market_slug: market.slug.clone(),
        args: GtcOrderArgs {
            token_id: tokens.yes.clone(),
            side: Side::Buy,
            price: 0.65,
            size: 10.0,
            expiration: None,
            nonce: None,
            taker: None,
            post_only: false,
        }
        .into(),
    })
    .await?;

println!("order id {}", result.order.id);

Post-only GTC order

Use post_only: true to ensure the order never crosses the spread as a taker:
let result = order_client
    .create_order(CreateOrderParams {
        order_type: OrderType::Gtc,
        market_slug: market.slug.clone(),
        args: GtcOrderArgs {
            token_id: tokens.yes.clone(),
            side: Side::Buy,
            price: 0.65,
            size: 10.0,
            expiration: None,
            nonce: None,
            taker: None,
            post_only: true,
        }
        .into(),
    })
    .await?;

GtcOrderArgs

FieldTypeDescription
token_idStringToken ID from market data
sideSideSide::Buy or Side::Sell
pricef64Price between 0 and 1, tick-aligned to 0.001
sizef64Number of shares
post_onlyboolOptional. Rejects the order if it would immediately match
expirationOption<String>Optional expiration timestamp. Defaults to "0"
nonceOption<i32>Optional nonce
takerOption<String>Optional taker address

FAK Orders

FAK orders use the same price + size inputs as GTC, but any unmatched remainder is cancelled immediately.
use limitless_exchange_rust_sdk::{CreateOrderParams, FakOrderArgs, OrderType, Side};

let response = order_client
    .create_order(CreateOrderParams {
        order_type: OrderType::Fak,
        market_slug: market.slug.clone(),
        args: FakOrderArgs {
            token_id: tokens.yes.clone(),
            side: Side::Buy,
            price: 0.45,
            size: 10.0,
            expiration: None,
            nonce: None,
            taker: None,
        }
        .into(),
    })
    .await?;

println!("order id {}", response.order.id);
println!("maker matches {}", response.maker_matches.len());
post_only is not supported for FAK orders.

FOK Orders

FOK orders execute immediately and fully, or are cancelled entirely. Instead of price and size, you pass maker_amount.
For buys, maker_amount is the total USDC to spend:
use limitless_exchange_rust_sdk::{CreateOrderParams, FokOrderArgs, OrderType, Side};

let response = order_client
    .create_order(CreateOrderParams {
        order_type: OrderType::Fok,
        market_slug: market.slug.clone(),
        args: FokOrderArgs {
            token_id: tokens.yes.clone(),
            side: Side::Buy,
            maker_amount: 10.0,
            expiration: None,
            nonce: None,
            taker: None,
        }
        .into(),
    })
    .await?;

println!("order id {}", response.order.id);

FokOrderArgs

FieldTypeDescription
token_idStringToken ID from market data
sideSideSide::Buy or Side::Sell
maker_amountf64BUY: USDC to spend. SELL: shares to sell. Max 6 decimals
expirationOption<String>Optional expiration timestamp
nonceOption<i32>Optional nonce
takerOption<String>Optional taker address

Build and Sign Separately

For advanced flows, build and sign orders without submitting them:
use limitless_exchange_rust_sdk::{GtcOrderArgs, Side};

let unsigned = order_client
    .build_unsigned_order(
        GtcOrderArgs {
            token_id: tokens.yes.clone(),
            side: Side::Buy,
            price: 0.65,
            size: 10.0,
            expiration: None,
            nonce: None,
            taker: None,
            post_only: false,
        }
        .into(),
    )
    .await?;

let signature = order_client.sign_order_for_market(&market.slug, &unsigned).await?;
println!("{}", signature);
You can also override the signing config explicitly:
use limitless_exchange_rust_sdk::OrderSigningConfig;

let signature = order_client.sign_order_with_config(
    &unsigned,
    OrderSigningConfig {
        chain_id: 8453,
        contract_address: "0xYourExchangeContract".to_string(),
    },
)?;

Cancelling Orders

Cancel a single order:
let message = order_client.cancel("abc123-def456").await?;
println!("{}", message);
Cancel all orders in a market:
let message = order_client.cancel_all(&market.slug).await?;
println!("{}", message);