Python SDK for trading on Limitless Exchange
Project description
py-limitless
A Python SDK for trading on Limitless Exchange — a prediction market on Base.
Features
- Authentication — Sign in with your Ethereum wallet (EOA or Smart Wallet)
- Trading — Place buy/sell orders (GTC and FOK), cancel orders, view orderbook
- Real-time data — WebSocket subscriptions for price updates and orderbook changes
- Portfolio management — View positions, open orders, and P&L
- Position redemption — Claim winnings from resolved markets
- Token approvals — Approve USDC and conditional tokens for trading
Installation
pip install py-limitless
Or with uv:
uv add py-limitless
Quick Start
EOA Mode (Simple)
Use your Ethereum wallet's private key directly:
from limitless_sdk import Limitless
# Initialize client
client = Limitless(private_key="0x...")
client.authenticate()
# Get market data
market = client.get_market("my-market-slug")
yes_token_id = market.get("tokens", {}).get("yes")
# Place a buy order: 10 shares of YES at 65¢
result = client.buy(
market_slug="my-market-slug",
token_id=yes_token_id,
price_cents=65,
amount=10,
token_type="YES",
)
print(f"Order placed: {result['order']['id']}")
Smart Wallet Mode
For accounts using Limitless's embedded smart wallet:
from limitless_sdk import Limitless
client = Limitless(
private_key="0x...", # Auth key (your EOA)
signing_wallet_pk="0x...", # Signing key (embedded account)
wallet_type="smart_wallet"
)
client.authenticate()
# Trading works the same way
client.buy(market_slug="...", token_id="...", price_cents=50, amount=5, token_type="YES")
Core Concepts
Market Data
Every market has a slug (URL identifier) and two tokens: YES and NO. Get market details:
market = client.get_market("my-market-slug")
tokens = market.get("tokens", {})
yes_token_id = tokens.get("yes")
no_token_id = tokens.get("no")
title = market.get("title")
Order Types
- GTC (Good Till Cancelled) — Limit order that stays open until filled or cancelled
- FOK (Fill Or Kill) — Market order that fills immediately or fails
# Limit order at specific price
client.buy(market_slug="...", token_id="...", price_cents=65, amount=10, token_type="YES", order_type="GTC")
# Market order - fills at best available price
client.buy(market_slug="...", token_id="...", price_cents=70, amount=10, token_type="YES", order_type="FOK")
Token Approvals
Before trading, you need to approve the exchange to spend your tokens:
# For buying: approve USDC
client.ensure_usdc_approved_for_market("my-market-slug")
# For selling: approve conditional tokens (YES/NO positions)
client.ensure_ctf_approved_for_market("my-market-slug")
API Reference
Limitless Client
The main client for interacting with Limitless Exchange.
Constructor
Limitless(
private_key: str, # Your wallet's private key
signing_wallet_pk: str = None, # Signing key (smart_wallet mode only)
wallet_type: str = "eoa", # "eoa" or "smart_wallet"
api_base_url: str = "https://api.limitless.exchange",
referral_code: str = None # Optional referral code
)
Authentication
client.authenticate() # Returns user data dict
client.is_authenticated # bool
client.address # Your wallet address
client.smart_wallet # Smart wallet address (after auth)
Trading
# Place orders
client.buy(market_slug, token_id, price_cents, amount, token_type="YES", order_type="GTC")
client.sell(market_slug, token_id, price_cents, amount, token_type="YES", order_type="GTC")
# Cancel orders
client.cancel_order(order_id)
client.cancel_all_orders(market_slug)
client.cancel_all_user_orders() # Cancel across all markets
# View orders
client.get_user_orders(market_slug)
Market Data
client.get_market(market_slug) # Market details
client.get_active_markets(category_id) # Browse markets by category
client.get_categories() # List all categories
# Orderbook returns bids/asks for YES and NO tokens
orderbook = client.get_orderbook(market_slug)
yes_bids = orderbook.get("yes", {}).get("bids", [])
yes_asks = orderbook.get("yes", {}).get("asks", [])
no_bids = orderbook.get("no", {}).get("bids", [])
Portfolio
client.get_portfolio_positions() # All positions
client.get_usdc_balance() # USDC balance
Position Redemption
Claim winnings from resolved markets:
# Get redeemable positions
redeemable = client.get_redeemable_positions()
for pos in redeemable:
print(f"{pos.market_title}: ${pos.balance}")
# Redeem a single position
result = client.redeem_position(condition_id="0x...")
# Redeem all winning positions
results = client.redeem_all_positions()
Token Approvals
# USDC (for buying)
client.check_usdc_allowance_for_market(market_slug)
client.approve_usdc_for_market(market_slug)
client.ensure_usdc_approved_for_market(market_slug)
# CTF/Conditional Tokens (for selling)
client.check_ctf_approval_for_market(market_slug)
client.approve_ctf_for_market(market_slug)
client.ensure_ctf_approved_for_market(market_slug)
WebSocket Client
Real-time market data via Socket.IO:
import asyncio
from limitless_sdk import LimitlessWebSocket
async def main():
ws = LimitlessWebSocket(auth_private_key="0x...")
await ws.connect()
# Register event handlers
ws.on("price", lambda data: print(f"Price update: {data}"))
ws.on("orderbook", lambda data: print(f"Orderbook: {data}"))
# Subscribe to markets
await ws.subscribe_markets(market_slugs=["my-market-slug"])
# Keep connection alive
await ws.wait()
asyncio.run(main())
Events
price— Price updates for subscribed marketsorderbook— Orderbook changes (CLOB markets)positions— Position updates (requires authentication)system— System messagesexception— Error messages
Constants
from limitless_sdk import (
# Trade sides
SIDE_BUY, # 0
SIDE_SELL, # 1
# Order types
ORDER_TYPE_GTC, # "GTC"
ORDER_TYPE_FOK, # "FOK"
# Market categories
CATEGORY_IDS, # {2: "Crypto", 5: "Other", ...}
# Contract addresses (Base chain)
USDC_ADDRESS,
BASE_CTF_ADDRESS,
)
Utility Functions
from limitless_sdk import (
scale_amount, # Convert to 6-decimal USDC units
unscale_amount, # Convert from 6-decimal units
cents_to_dollars, # 65 → 0.65
dollars_to_cents, # 0.65 → 65
)
Configuration
Environment Variables
# Your wallet's private key
PRIVATE_KEY=0x...
# Optional: Custom RPC URL (defaults to https://mainnet.base.org)
BASE_RPC_URL=https://your-rpc-url.com
Custom RPC
Pass a custom RPC URL for blockchain operations:
client.get_usdc_balance(rpc_url="https://your-rpc.com")
client.approve_usdc_for_market(market_slug, rpc_url="https://your-rpc.com")
client.redeem_position(condition_id, rpc_url="https://your-rpc.com")
Examples
Market Making Bot
from limitless_sdk import Limitless
client = Limitless(private_key="0x...")
client.authenticate()
market_slug = "my-market-slug"
market = client.get_market(market_slug)
yes_token = market.get("tokens", {}).get("yes")
# Ensure approvals
client.ensure_usdc_approved_for_market(market_slug)
client.ensure_ctf_approved_for_market(market_slug)
# Place bid and ask
client.buy(market_slug, yes_token, price_cents=48, amount=100, token_type="YES") # Bid
client.sell(market_slug, yes_token, price_cents=52, amount=100, token_type="YES") # Ask
Portfolio Monitor
from limitless_sdk import Limitless
client = Limitless(private_key="0x...")
client.authenticate()
portfolio = client.get_portfolio_positions()
for position in portfolio.get("clob", []):
market = position["market"]
print(f"{market['title']}")
print(f" Value: ${position.get('value', 0):.2f}")
print(f" P&L: ${position.get('pnl', 0):.2f}")
Claim All Winnings
from limitless_sdk import Limitless
client = Limitless(private_key="0x...")
client.authenticate()
redeemable = client.get_redeemable_positions()
if redeemable:
print(f"Found {len(redeemable)} positions to redeem")
results = client.redeem_all_positions()
for r in results:
status = "✓" if r["success"] else "✗"
print(f"{status} {r['market_title']}: ${r['balance']}")
Requirements
- Python 3.10+
- An Ethereum wallet with Base ETH for gas (redemptions only)
- USDC on Base for trading
Links
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_limitless-0.1.1.tar.gz.
File metadata
- Download URL: py_limitless-0.1.1.tar.gz
- Upload date:
- Size: 176.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33f39d2591d48e9b0d7b9dca0fc594394987056d5c9883a96b2c4933166aa596
|
|
| MD5 |
a8bf66be8e1d42aabada32151de7f3ce
|
|
| BLAKE2b-256 |
b74e157034b9dea3515c7cd87b07ca4bf3754e05bd55db988512d1fc034c50cc
|
File details
Details for the file py_limitless-0.1.1-py3-none-any.whl.
File metadata
- Download URL: py_limitless-0.1.1-py3-none-any.whl
- Upload date:
- Size: 34.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32fb140675384e2ab2100a2cf8fc3ed43d77104f9f44df0d65cfcb6795d53fd5
|
|
| MD5 |
84ac6a571dcfa20d44258c4b9d3bf14e
|
|
| BLAKE2b-256 |
bf14ae2f16086bdab1c942a52d53b7124dd33fb11f5931627ed5cac57daee89a
|