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-clientYou 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:
| Type | Value | Meaning |
|---|---|---|
| Price | 500000 | $0.50 (50% probability) |
| Price | 100000 | $0.10 (10% probability) |
| Price | 900000 | $0.90 (90% probability) |
| Size | 1000000 | 1 share |
| Size | 10000000 | 10 shares |
| Size | 500000 | 0.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
- Created —
create_limit_buy()orcreate_order()signs the order locally and returns aSignedOrder. - Submitted —
post_order()sends it to the API. The matching engine checks for compatible counter-orders. - Matched — If a compatible order exists, a trade is created. Both orders are matched at the maker's price.
- Settled — The matched trade is settled on-chain via the settlement contract.
- 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.")