Skip to content

ego-errante/limitless-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

About

Python SDK for trading on Limitless Exchange

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages