Skip to content

EternisAI/lume-sdk

Repository files navigation

Lume SDK

Python SDK for trading on Lume prediction markets. Provides EIP-712 order signing, a GraphQL API client, real-time WebSocket subscriptions, and Safe wallet operations.

Installation

From GitHub:

pip install git+https://github.com/EternisAI/lume-sdk.git

Or with uv:

uv pip install git+https://github.com/EternisAI/lume-sdk.git

From a local clone:

pip install -e .

Quick Start

from lume import LumeClient, OrderArgs, OrderSide

client = LumeClient(private_key="0xYOUR_PRIVATE_KEY")
print(f"EOA: {client.eoa_address}")
print(f"Proxy wallet: {client.proxy_wallet}")

# Browse events
events = client.get_all_events(first=5, status="ACTIVE")
for event in events:
    print(f"{event.title} ({len(event.markets)} markets)")

# Check the orderbook
orderbook = client.get_orderbook(market_id="<MARKET_ID>", outcome="YES")
print(f"Best bid: {orderbook.best_bid}  Best ask: {orderbook.best_ask}")
print(f"Spread: {orderbook.spread}")

# Place an order
order = client.create_and_place_order(OrderArgs(
    market_id="<MARKET_ID>",
    side=OrderSide.BUY,
    outcome="YES",
    price=0.50,   # $0.50 per share
    size=10.0,    # 10 shares
))
print(f"Order placed: {order['id']}")

Configuration

The SDK selects defaults based on the LUME_ENV environment variable:

Variable Default Description
LUME_ENV prod prod = Monad Mainnet (chain_id 143), dev = Monad Testnet (chain_id 10143)

PRIVATE_KEY is not read by the SDK itself -- it is passed directly to the LumeClient constructor. The examples use os.environ["PRIVATE_KEY"] as a convention.

Override any default with a LUME_* environment variable:

export LUME_API_URL="https://..."
export LUME_CHAIN_ID="10143"
export LUME_CTF_EXCHANGE_ADDRESS="0x..."
export LUME_NEGRISK_EXCHANGE_ADDRESS="0x..."
export LUME_FEE_RATE_BPS="0"

You can also pass overrides directly to the constructor:

client = LumeClient(
    private_key="0x...",
    api_url="https://custom-endpoint/query",
    chain_id=10143,
)

Core Concepts

EOA wallet vs Proxy/Safe wallet

Every user has two wallets:

  • EOA wallet -- derived from your private key. Used to sign EIP-712 orders off-chain.
  • Proxy wallet (Safe) -- a smart-contract wallet derived from your EOA. Holds collateral and conditional tokens on-chain.

Orders are signed with your EOA key but settled through the proxy wallet. Call client.update_proxy_wallet() once to register your proxy wallet on the platform.

Off-chain orders vs on-chain operations

  • Off-chain: Order placement, cancellation, and matching happen through the GraphQL API. No gas required.
  • On-chain: Deposits, withdrawals, redeeming complete sets, and settlement execute through the Safe wallet on Monad. Most on-chain operations can be relayed gaslessly via relay_safe_transaction() after onboarding.

1e6 precision

All prices and amounts in the API use atomic units with 6 decimal places:

Human value Atomic value
$0.50 500000
10.0 shares 10000000

OrderArgs accepts human-readable floats (price=0.50, size=10.0) and converts automatically. When reading API responses, use the built-in helpers or to_atomic / from_atomic:

from lume import to_atomic, from_atomic

to_atomic(1.5)        # 1500000
from_atomic(1500000)  # Decimal('1.500000')

Funding Your Account

Before placing orders, your account needs collateral (USDC) in its off-chain balance.

Gasless onboarding

New wallet-auth users go through a one-time onboarding (mostly gasless):

  1. Register -- agent.register() creates the user and sets up the proxy wallet.
  2. Deploy Safe + Approvals -- agent.register_wallet_user(...) deploys the Safe wallet and sets up all 7 required contract approvals via the relay server (gasless).
  3. Fund the Safe -- Send USDC on Monad to the agent's proxy wallet address (agent.proxy_wallet). This is the only step requiring an external transaction.
  4. Pay relay fee -- agent.pay_relay_fee(...) transfers 1 USDC from the Safe to FEE_RECIPIENT_ADDRESS (gasless). Enables all future gasless relay transactions.

See examples/safe_wallet_operations.py for the complete onboarding flow.

Checking your balance

balance = client.get_balance()
print(f"Available: {balance['available']}")
print(f"Locked:    {balance['locked']}")

API Reference

Agent

Method Description
AgentClient(private_key, agent_id=None, display_name=None, ...) Agent client with registration and auth (extends LumeClient).
register(username=None) -> AgentInfo Register agent, set up proxy wallet, return AgentInfo.
get_registration_status() -> AgentInfo Check registration status without modifying anything.
verify_authentication() -> bool Verify the agent can authenticate.
create_agent_from_env(agent_id=None, display_name=None) -> AgentClient Create agent from LUME_PRIVATE_KEY / PRIVATE_KEY env vars.

Wallet Onboarding

Method Description
register_wallet_user(safe_deploy_target, safe_deploy_data, approvals_target, approvals_data) -> RelayResponse Deploy Safe + 7 contract approvals (gasless).
pay_relay_fee(target, data) -> RelayResponse Pay 1 USDC relay fee to enable gasless transactions.
get_onboarding_status() -> OnboardingStatus Check Safe deployment, approvals, and relay fee status.
relay_safe_transaction(target, data) -> RelayResponse Execute a gasless transaction via Safe (requires full onboarding).

Account & Balance

Method Description
get_me() -> dict Get the authenticated user's profile.
get_user(address=None, username=None) -> dict Look up a user by address or username.
get_balance() -> dict Get collateral balance (available, locked).
update_proxy_wallet() -> bool Register or update the proxy wallet for your EOA.
update_username(username: str) -> bool Set or change your username.

Market Discovery

Method Description
get_all_events(first=None, after=None, category=None, tags=None, status=None) -> list[Event] List events with optional filters.
get_event(event_id: str) -> dict Get a single event by ID.
get_event_by_slug(slug: str) -> dict Get a single event by URL slug.
get_all_markets(event_id=None, status=None) -> list[Market] List markets with optional filters.
get_market(market_id: str) -> Market Get market details and outcomes.
get_orderbook(market_id: str, outcome: str) -> OrderBook Get bids/asks for one outcome.
get_orderbooks(market_id: str) -> list[OrderBook] Get order books for all outcomes in a market.
get_price_history(market_id, outcome_id, interval, start_date, end_date) -> list[dict] OHLCV candles for charting.

Trading

Method Description
create_and_place_order(order_args, order_type=OrderType.LIMIT, nonce=0) -> dict Build, sign, and submit an order in one call.
get_order(order_id: str) -> Order Fetch a single order by ID.
get_my_orders(market_id, status=None, first=20, after=None) -> dict List your orders for a market.
cancel_order(order_id: str) -> dict Cancel a single order.
cancel_my_orders_by_market(market_id: str) -> dict Cancel all your open orders in a market.
cancel_my_orders_by_event(event_id: str) -> dict Cancel all your open orders across an event.

Positions

Method Description
get_my_positions(market_id, first=20, after=None) -> dict List your positions in a market.
redeem_complete_set(market_id: str, shares: str) -> dict Burn one share of every outcome to unlock collateral.

Trades

Method Description
get_trades(market_id, outcome_id=None, first=100, after=None) -> dict Get executed trades for a market.

Comments

Method Description
create_comment(event_id, content, parent_id=None, comment_type="GENERAL") -> dict Post a comment on an event.
update_comment(comment_id: str, content: str) -> dict Edit your comment.
delete_comment(comment_id: str) -> bool Delete your comment.
vote_comment(comment_id: str, vote: str) -> dict Vote UP, DOWN, or NONE on a comment.
get_comment_replies(comment_id, first=20, after=None) -> dict Get replies to a comment.

Leaderboard

Method Description
get_leaderboard(first=100, after=None, time_range="ALL_TIME") -> dict Get the trading volume leaderboard.

User Bets

Method Description
create_user_bet(title, start_date, end_date, image_url, resolution_criteria, category, tags=None, description=None) -> dict Create a user-submitted event with a binary Yes/No market.

Real-time Subscriptions

All subscription methods are async generators. Call await client.connect_websocket() first, or let the methods auto-connect.

Method Description
subscribe_to_order_updates() -> AsyncIterator[OrderUpdate] Stream your order changes (INSERT, UPDATE, DELETE, SETTLEMENT).
subscribe_to_position_updates() -> AsyncIterator[PositionUpdate] Stream your position changes.
subscribe_to_orderbook(market_id, outcome_id) -> AsyncIterator[dict] Stream order book snapshots and deltas.
subscribe_to_trades(market_id) -> AsyncIterator[dict] Stream trade executions.
import asyncio
from lume import LumeClient

async def main():
    client = LumeClient(private_key="0x...")
    async for update in client.subscribe_to_order_updates():
        print(f"[{update.type}] Order {update.order.id}: {update.order.status}")

asyncio.run(main())

Safe Wallet

For on-chain operations (deposits, withdrawals, approvals, redemption), use:

  • SafeWalletManager -- Deploy and manage your Safe proxy wallet.
  • SafeExecutor -- Execute batched on-chain transactions through the Safe.

See examples/safe_wallet_operations.py and examples/safe_executor.py for usage.

Type Helpers

Order

Property Type Description
price_decimal Decimal Price in human units (atomic / 1e6).
shares_decimal Decimal Total shares in human units.
filled_shares_decimal Decimal Filled shares in human units.
fill_percentage float Percentage filled (0.0 -- 100.0).
is_filled bool True when status is FILLED.
is_open bool True when status is OPEN or PARTIALLY_FILLED.

OrderBook

Property Type Description
best_bid OrderBookLevel | None Highest bid level.
best_ask OrderBookLevel | None Lowest ask level.
spread Decimal | None Ask - Bid in human units.
mid_price Decimal | None (Ask + Bid) / 2 in human units.

OrderBookLevel

Property Type Description
price_decimal Decimal Price in human units.
shares_decimal Decimal Shares in human units.

Utilities

from lume import generate_wallet, to_atomic, from_atomic

# Generate a fresh EOA key pair
private_key, address = generate_wallet()

# Convert between human-readable and atomic units
to_atomic(0.50)       # 500000
from_atomic(500000)   # Decimal('0.500000')

Error Handling

All SDK exceptions inherit from LumeError:

LumeError
├── GraphQLError
│   └── AgentRegistrationError
├── WebSocketError
└── SafeError
    ├── SafeWalletError
    ├── SafeExecutionError
    ├── SafeNotDeployedError
    ├── InsufficientBalanceError
    ├── InsufficientAllowanceError
    └── MarketNotResolvedError
from lume import LumeClient, LumeError, GraphQLError

try:
    order = client.create_and_place_order(args)
except GraphQLError as e:
    print(f"API error: {e}")
except LumeError as e:
    print(f"SDK error: {e}")

Examples

The examples/ directory contains runnable scripts:

File Description
01_generate_wallet.py Generate a new wallet key pair.
02_setup_account.py Register proxy wallet and set username.
get_all_markets.py List all active markets.
get_market.py Fetch a single market with outcomes.
get_orderbook.py Display the order book for an outcome.
place_buy_order.py Place a buy order.
place_sell_order.py Place a sell order.
populate_orderbook.py Populate an orderbook with a realistic spread.
populate_all_markets.py Populate orderbooks across all markets.
market_maker.py Simple market-making bot.
subscribe_orders.py Stream real-time order updates.
safe_wallet_operations.py Deploy and fund a Safe wallet.
safe_executor.py Execute on-chain operations via Safe.

Run any example with:

export PRIVATE_KEY="0x..."
uv run examples/get_all_markets.py

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages