Creating Orders

Step-by-step guide for creating, signing, submitting, and managing orders programmatically with the Python SDK.

Prerequisites

Install the SDK and have your credentials ready:

pip install turbine-py-client

You need a wallet private key and API credentials. If you don't have API credentials yet, the SDK can register them for you (see Auto-Registration below).

Initialize the Client

import os
import time
from dotenv import load_dotenv
from turbine_client import TurbineClient, Outcome, Side, OrderArgs

load_dotenv()

client = TurbineClient(
    host=os.environ["TURBINE_HOST"],       # https://api.turbinefi.com
    chain_id=int(os.environ.get("CHAIN_ID", "137")),
    private_key=os.environ["TURBINE_PRIVATE_KEY"],
    api_key_id=os.environ["TURBINE_API_KEY_ID"],
    api_private_key=os.environ["TURBINE_API_PRIVATE_KEY"],
)

Auto-Registration

If you don't have TURBINE_API_KEY_ID and TURBINE_API_PRIVATE_KEY yet, register them first:

credentials = TurbineClient.request_api_credentials(
    host="https://api.turbinefi.com",
    private_key=os.environ["TURBINE_PRIVATE_KEY"],
)

# Save these — the private key is not recoverable
print(f"TURBINE_API_KEY_ID={credentials['api_key_id']}")
print(f"TURBINE_API_PRIVATE_KEY={credentials['api_private_key']}")

Check the Orderbook

Before placing an order, inspect the current orderbook to find appropriate prices:

market_id = "0x..."  # Get from client.get_markets() or client.get_quick_market()

ob = client.get_orderbook(market_id, outcome=Outcome.YES)

print("YES Orderbook:")
print("  Bids (buy orders):")
for level in ob.bids[:5]:
    print(f"    {level.price} (${level.price / 1e6:.4f}) x {level.size / 1e6:.2f} shares")

print("  Asks (sell orders):")
for level in ob.asks[:5]:
    print(f"    {level.price} (${level.price / 1e6:.4f}) x {level.size / 1e6:.2f} shares")

# Calculate mid price
if ob.bids and ob.asks:
    mid = (ob.bids[0].price + ob.asks[0].price) // 2
    print(f"\n  Mid: {mid} (${mid / 1e6:.4f})")
    print(f"  Spread: {ob.asks[0].price - ob.bids[0].price}")

Create and Submit an Order

Using create_limit_buy / create_limit_sell

The simplest approach. The client handles signing and nonce generation:

# Buy 10 YES shares at $0.45
signed = client.create_limit_buy(
    market_id=market_id,
    outcome=Outcome.YES,
    price=450000,       # $0.45
    size=10000000,      # 10 shares
    expiration=int(time.time()) + 3600,  # 1 hour
)

print(f"Order hash: {signed.order_hash}")
print(f"Cost if filled: {450000 * 10000000 / 1e6 / 1e6:.2f} USDC")  # $4.50

# Submit to the orderbook
result = client.post_order(signed)
print(f"Result: {result}")
# Sell 5 NO shares at $0.60
signed = client.create_limit_sell(
    market_id=market_id,
    outcome=Outcome.NO,
    price=600000,       # $0.60
    size=5000000,       # 5 shares
    expiration=int(time.time()) + 3600,
)

result = client.post_order(signed)

Using OrderArgs

For more control, construct OrderArgs explicitly:

args = OrderArgs(
    market_id=market_id,
    side=Side.BUY,
    outcome=Outcome.YES,
    price=500000,       # $0.50
    size=1000000,       # 1 share
    expiration=int(time.time()) + 3600,  # 1 hour
    nonce=0,            # auto-generated
    maker_fee_recipient="0x0000000000000000000000000000000000000000",
)

signed = client.create_order(args)
result = client.post_order(signed)

Price and Size Encoding

All prices and sizes are integers with 6 decimal places:

TypeValueMeaning
Price500000$0.50 (50% probability)
Price100000$0.10 (10% probability)
Price900000$0.90 (90% probability)
Size10000001 share
Size1000000010 shares
Size5000000.5 shares

Valid prices: 1 to 999999 (exclusive of 0 and 1,000,000).

Cost to buy: price * size / 1,000,000. For example, buying 10 shares at 450000 ($0.45) costs 450000 * 10000000 / 1000000 = 4500000 = $4.50 USDC.

Payout if you win: size. So 10 shares pay 10000000 = $10 USDC. Profit = $10 - $4.50 = $5.50.

USDC Approval

Before your first order can settle, the settlement contract needs USDC approval. Use the gasless max permit (one-time, no native gas needed):

# One-time gasless max approval per settlement contract
result = client.approve_usdc_for_settlement()
print(f"Approval TX: {result}")

This signs an EIP-2612 max permit and submits it to the relayer. All subsequent orders on that settlement contract reuse the existing allowance.

To check the current allowance:

allowance = client.get_usdc_allowance()
print(f"Current allowance: {allowance / 1e6:.2f} USDC")

Per-Order Permit (Alternative)

You can attach a permit to an individual order instead:

permit = client.sign_usdc_permit(value=5000000)  # $5 USDC
signed.permit_signature = permit
result = client.post_order(signed)

Order Lifecycle

  1. Createdcreate_limit_buy() or create_order() signs the order locally and returns a SignedOrder.
  2. Submittedpost_order() sends it to the API. The matching engine checks for compatible counter-orders.
  3. Matched — If a compatible order exists, a trade is created. Both orders are matched at the maker's price.
  4. Settled — The matched trade is settled on-chain via the settlement contract.
  5. Failed / Pending — Check get_failed_trades() / get_pending_trades() for settlement status.

Cancel Orders

Cancel a Single Order

result = client.cancel_order(
    order_hash="0xOrderHash...",
    market_id=market_id,  # optional validation
    side=Side.BUY,        # optional validation
)
print(f"Cancelled: {result}")

Cancel All Orders for a Market

result = client.cancel_market_orders(market_id=market_id)
print(f"Cancelled all: {result}")

Monitor Order Status

Check Your Open Orders

orders = client.get_orders(market_id=market_id, status="open")

for o in orders:
    side = "BUY" if o.side == 0 else "SELL"
    outcome = "YES" if o.outcome == 0 else "NO"
    filled_pct = o.filled_size / o.size * 100 if o.size > 0 else 0
    print(
        f"{side} {outcome}: {o.remaining_size / 1e6:.2f} remaining "
        f"@ {o.price} (${o.price / 1e6:.4f}) | "
        f"filled: {filled_pct:.1f}% | {o.status}"
    )

Check a Specific Order

order = client.get_order("0xOrderHash...")
print(f"Status: {order.status}")
print(f"Filled: {order.filled_size / 1e6:.2f} / {order.size / 1e6:.2f}")
print(f"Remaining: {order.remaining_size / 1e6:.2f}")

Monitor Failed and Pending Trades

After orders match, trades go through on-chain settlement. Monitor the pipeline:

# Trades waiting for settlement TX
pending = client.get_pending_trades()
for t in pending:
    print(f"Pending: {t.fill_size / 1e6:.2f} @ {t.fill_price} (${t.fill_price / 1e6:.4f}) | tx={t.tx_hash}")

# Trades that failed settlement
failed = client.get_failed_trades()
for t in failed:
    print(f"Failed: {t.fill_size / 1e6:.2f} @ {t.fill_price} (${t.fill_price / 1e6:.4f}) | reason={t.reason}")

# Check a specific settlement TX
status = client.get_settlement_status("0xTxHash...")
print(f"Found: {status.found}, Status: {status.status}, Error: {status.error}")

Complete Example

A script that checks the orderbook, places a buy order, and monitors it:

import os
import time
from dotenv import load_dotenv
from turbine_client import TurbineClient, Outcome, Side

load_dotenv()

client = TurbineClient(
    host=os.environ["TURBINE_HOST"],
    chain_id=int(os.environ.get("CHAIN_ID", "137")),
    private_key=os.environ["TURBINE_PRIVATE_KEY"],
    api_key_id=os.environ["TURBINE_API_KEY_ID"],
    api_private_key=os.environ["TURBINE_API_PRIVATE_KEY"],
)

# Get active BTC quick market
qm = client.get_quick_market("BTC")
market_id = qm.market_id
print(f"Market: Will BTC be above ${qm.start_price / 1e8:,.2f}?")
print(f"Market ID: {market_id}")

# Ensure USDC approval (gasless, one-time)
allowance = client.get_usdc_allowance()
if allowance < 2**128:
    print("Approving USDC (gasless)...")
    client.approve_usdc_for_settlement()

# Check orderbook
ob = client.get_orderbook(market_id, outcome=Outcome.YES)
if ob.asks:
    best_ask = ob.asks[0]
    print(f"Best YES ask: {best_ask.price} (${best_ask.price / 1e6:.4f}) x {best_ask.size / 1e6:.2f}")

# Place a limit buy for YES at $0.45
signed = client.create_limit_buy(
    market_id=market_id,
    outcome=Outcome.YES,
    price=450000,       # $0.45
    size=2000000,       # 2 shares
    expiration=int(time.time()) + 900,  # 15 minutes
)

print(f"\nSubmitting order: BUY 2 YES @ 450000 ($0.45)")
print(f"Order hash: {signed.order_hash}")
print(f"Cost if filled: $0.90 USDC")

result = client.post_order(signed)
print(f"Response: {result}")

# Wait and check status
time.sleep(5)
order = client.get_order(signed.order_hash)
print(f"\nOrder status: {order.status}")
print(f"Filled: {order.filled_size / 1e6:.2f} / {order.size / 1e6:.2f}")

if order.status == "open" and order.remaining_size > 0:
    print("Order still open. Cancelling...")
    client.cancel_order(signed.order_hash)
    print("Cancelled.")