Skip to main content

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 markets
  • orderbook — Orderbook changes (CLOB markets)
  • positions — Position updates (requires authentication)
  • system — System messages
  • exception — 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_limitless-0.1.1.tar.gz (176.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_limitless-0.1.1-py3-none-any.whl (34.7 kB view details)

Uploaded Python 3

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

Hashes for py_limitless-0.1.1.tar.gz
Algorithm Hash digest
SHA256 33f39d2591d48e9b0d7b9dca0fc594394987056d5c9883a96b2c4933166aa596
MD5 a8bf66be8e1d42aabada32151de7f3ce
BLAKE2b-256 b74e157034b9dea3515c7cd87b07ca4bf3754e05bd55db988512d1fc034c50cc

See more details on using hashes here.

File details

Details for the file py_limitless-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for py_limitless-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 32fb140675384e2ab2100a2cf8fc3ed43d77104f9f44df0d65cfcb6795d53fd5
MD5 84ac6a571dcfa20d44258c4b9d3bf14e
BLAKE2b-256 bf14ae2f16086bdab1c942a52d53b7124dd33fb11f5931627ed5cac57daee89a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page