Skip to main content

Overview

The OrderClient handles order creation, EIP-712 signing, and order management. It supports both Good-Till-Cancelled (GTC) limit orders and Fill-or-Kill (FOK) market orders.

Prerequisites

Before placing orders, you need four components:
import asyncio
from eth_account import Account
from limitless_sdk.api import HttpClient
from limitless_sdk.markets import MarketFetcher
from limitless_sdk.orders import OrderClient
from limitless_sdk.types import Side, OrderType

http_client = HttpClient()  # loads LIMITLESS_API_KEY from env
account = Account.from_key("0xYOUR_PRIVATE_KEY")
market_fetcher = MarketFetcher(http_client)
order_client = OrderClient(http_client, account)
ComponentPurpose
HttpClientAuthenticated HTTP client for API requests
Accounteth-account wallet for EIP-712 order signing
MarketFetcherFetches market data and caches venue addresses
OrderClientCreates, signs, and submits orders
The OrderClient constructor automatically fetches your user profile data (userData) from the API. This is used to populate the ownerId field on submitted orders.

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.
For standard CLOB markets, approve USDC and Conditional Tokens to the exchange contract:
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://mainnet.base.org"))

USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
CT_ADDRESS = "0xC9c98965297Bc527861c898329Ee280632B76e18"  # Conditional Token framework address

market = await market_fetcher.get_market("your-market-slug")
exchange = market.venue.exchange

# Approve USDC for BUY orders
usdc_contract = w3.eth.contract(
    address=Web3.to_checksum_address(USDC_ADDRESS),
    abi=[{
        "name": "approve",
        "type": "function",
        "inputs": [
            {"name": "spender", "type": "address"},
            {"name": "amount", "type": "uint256"},
        ],
        "outputs": [{"name": "", "type": "bool"}],
    }],
)
tx = usdc_contract.functions.approve(
    Web3.to_checksum_address(exchange),
    2**256 - 1,  # max approval
).build_transaction({
    "from": account.address,
    "nonce": w3.eth.get_transaction_count(account.address),
})
signed = w3.eth.account.sign_transaction(tx, account.key)
w3.eth.send_raw_transaction(signed.raw_transaction)

# Approve Conditional Tokens for SELL orders
ct_contract = w3.eth.contract(
    address=Web3.to_checksum_address(CT_ADDRESS),
    abi=[{
        "name": "setApprovalForAll",
        "type": "function",
        "inputs": [
            {"name": "operator", "type": "address"},
            {"name": "approved", "type": "bool"},
        ],
        "outputs": [],
    }],
)
tx = ct_contract.functions.setApprovalForAll(
    Web3.to_checksum_address(exchange),
    True,
).build_transaction({
    "from": account.address,
    "nonce": w3.eth.get_transaction_count(account.address),
})
signed = w3.eth.account.sign_transaction(tx, account.key)
w3.eth.send_raw_transaction(signed.raw_transaction)
Approvals are on-chain transactions that cost gas. You only need to perform them once per venue. Use venue.exchange for both CLOB and NegRisk, and additionally venue.adapter for NegRisk markets.

GTC Orders (Good-Till-Cancelled)

GTC orders remain on the orderbook until filled or explicitly cancelled. Specify price (in dollars) and size (number of shares):
market = await market_fetcher.get_market("btc-above-100k-march-2025")

result = await order_client.create_order(
    token_id=market.tokens.yes,
    price=0.65,
    size=10.0,
    side=Side.BUY,
    order_type=OrderType.GTC,
    market_slug="btc-above-100k-march-2025",
)
print("Order placed:", result)
ParameterTypeDescription
token_idstrToken ID from market.tokens.yes or market.tokens.no
pricefloatPrice per share in dollars (0.01 to 0.99)
sizefloatNumber of shares to buy or sell
sideSideSide.BUY or Side.SELL
order_typeOrderTypeOrderType.GTC
market_slugstrMarket slug for venue lookup

FOK Orders (Fill-or-Kill)

FOK orders execute immediately and fully, or are rejected entirely. Instead of price and size, you specify maker_amount:
When buying, maker_amount is the total USDC you want to spend. The exchange fills as many shares as possible at the best available price:
result = await order_client.create_order(
    token_id=market.tokens.yes,
    maker_amount=10.0,  # spend 10 USDC
    side=Side.BUY,
    order_type=OrderType.FOK,
    market_slug="btc-above-100k-march-2025",
)

Cancelling Orders

Cancel a specific order by its ID:
await order_client.cancel(order_id="abc123-def456")

Enums Reference

Side

ValueDescription
Side.BUYBuy shares with USDC
Side.SELLSell shares for USDC

OrderType

ValueDescription
OrderType.GTCGood-Till-Cancelled limit order (rests on the book)
OrderType.FOKFill-or-Kill market order (fills immediately or rejects)

Error Handling

The SDK raises APIError for non-2xx responses. Always wrap order calls in try/except:
from limitless_sdk.api import APIError

try:
    result = await order_client.create_order(
        token_id=market.tokens.yes,
        price=0.65,
        size=10.0,
        side=Side.BUY,
        order_type=OrderType.GTC,
        market_slug="btc-above-100k-march-2025",
    )
except APIError as e:
    print(f"Order failed — status {e.status_code}: {e.message}")
See Error Handling & Retry for details on APIError fields and the @retry_on_errors decorator.

Complete Example

import asyncio
from eth_account import Account
from limitless_sdk.api import HttpClient, APIError
from limitless_sdk.markets import MarketFetcher
from limitless_sdk.orders import OrderClient
from limitless_sdk.types import Side, OrderType

async def main():
    http_client = HttpClient()
    account = Account.from_key("0xYOUR_PRIVATE_KEY")
    market_fetcher = MarketFetcher(http_client)
    order_client = OrderClient(http_client, account)

    try:
        # Fetch market (caches venue automatically)
        market = await market_fetcher.get_market("btc-above-100k-march-2025")

        # Place a GTC BUY order for 10 YES shares at $0.65
        result = await order_client.create_order(
            token_id=market.tokens.yes,
            price=0.65,
            size=10.0,
            side=Side.BUY,
            order_type=OrderType.GTC,
            market_slug="btc-above-100k-march-2025",
        )
        print("GTC order placed:", result)

        # Place a FOK BUY order spending 5 USDC
        fok_result = await order_client.create_order(
            token_id=market.tokens.yes,
            maker_amount=5.0,
            side=Side.BUY,
            order_type=OrderType.FOK,
            market_slug="btc-above-100k-march-2025",
        )
        print("FOK order placed:", fok_result)

        # Cancel all orders on this market
        await order_client.cancel_all(market_slug="btc-above-100k-march-2025")
        print("All orders cancelled")

    except APIError as e:
        print(f"API error — status {e.status_code}: {e.message}")
    finally:
        await http_client.close()

asyncio.run(main())
Always call await http_client.close() when finished. Failing to close the client can leave open connections and cause resource leaks.