### Usage Examples Source: https://api.limitless.exchange/api-v1/index Provides practical examples of how to use the WebSocket client for different scenarios. ```APIDOC ## Usage Examples ### Basic Connection (Public Data) This example demonstrates how to establish a basic connection to the WebSocket API in public mode to receive price data. ```python # WebSocket Client Implementation import asyncio from socket_subs import LimitlessWebSocket async def public_data_example(): client = LimitlessWebSocket() await client.connect() await client.subscribe_markets(["0x1234..."]) await client.wait() asyncio.run(public_data_example()) ``` ### Authenticated Connection (Full Data) This example shows how to connect in authenticated mode using a private key to access full market data, including positions. ```python # WebSocket Client Implementation import os import asyncio from socket_subs import LimitlessWebSocket async def authenticated_example(): private_key = os.getenv('PRIVATE_KEY') ##please define on shell level export PRIVATE_KEY='0x...' client = LimitlessWebSocket(private_key=private_key) await client.connect() await client.subscribe_markets(["0x1234..."]) # on script level is passed automatically await client.wait() asyncio.run(authenticated_example()) ``` ### Custom Event Handling This example illustrates how to create a custom WebSocket class to handle specific events like `newPriceData` and `positions` with custom logic. ```python # WebSocket Client Implementation class CustomWebSocket(LimitlessWebSocket): def _setup_handlers(self): super()._setup_handlers() @self.sio.event(namespace='/markets') async def newPriceData(data): """Custom price data handler""" market_address = data.get('marketAddress') prices = data.get('updatedPrices', {}) print(f"Market {market_address}: YES={prices.get('yes')}, NO={prices.get('no')}") @self.sio.event(namespace='/markets') async def positions(data): """Custom position handler""" account = data.get('account') positions = data.get('positions', []) print(f"User {account} has {len(positions)} positions") ``` ``` -------------------------------- ### Install Dependencies with Gradle Source: https://api.limitless.exchange/api-v1/index Installs project dependencies using Gradle. Ensure you have Java Development Kit (JDK) 11 or later installed. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example ./gradlew build ``` -------------------------------- ### Python WebSocket Real-Time Data Guide (Example) Source: https://api.limitless.exchange/api-v1/index An example Python script for educational purposes demonstrating how to connect to Limitless Exchange WebSocket for real-time market data and position updates. It outlines the steps for authentication, connection, subscription, and handling events. Users are advised to test with small amounts and understand the code before use. ```python ##### Python WebSocket Real-Time Data Guide โš ๏ธ **IMPORTANT DISCLAIMER** โš ๏ธ ``` This is an example script for educational purposes only. Limitless Labs is not responsible for any losses or mistakes. This script should be adjusted to your personal needs and risk tolerance. Always test with small amounts first and understand the code before using it. USE AT YOUR OWN RISK. ``` This guide provides a complete walkthrough of connecting to Limitless Exchange WebSocket for real-time market data and position updates using Python. #### Overview The Socket.io integration process involves: 1. **Authentication** : Get a signing message and authenticate with your wallet 2. **WebSocket Connection** : Connect to the `markets` 3. **Event Subscription** : Subscribe to market prices and position updates 4. **Real-Time Events** : Handle incoming market data and position changes #### Prerequisites ##### Required Python Packages ``` ``` -------------------------------- ### Install Node.js/TypeScript Dependencies Source: https://api.limitless.exchange/api-v1/index Installs necessary npm packages for the Node.js/TypeScript quick start guide using pnpm. These include socket.io-client, cross-fetch, ethers, and viem. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example pnpm add socket.io-client cross-fetch ethers viem ``` -------------------------------- ### Node.js/TypeScript Quick Start Source: https://api.limitless.exchange/api-v1/index Provides a quick start guide for Node.js/TypeScript developers to implement trading and WebSocket subscriptions with the Limitless Exchange API. ```APIDOC ## ๐Ÿ“ฆ Node.js/TypeScript Quick Start Complete end-to-end Node.js/TypeScript implementation for trading and WebSocket subscriptions. ### Overview This guide covers placing orders via REST (requiring EIP-712 signing) and subscribing to real-time updates via WebSocket for: * AMM price updates for specific market addresses. * CLOB order book updates for specific market slugs. **Important:** WebSocket subscriptions replace previous ones. To receive both AMM prices and CLOB order book data simultaneously, send `marketAddresses` and `marketSlugs` together in a single `subscribe_market_prices` call. * Production WS URL: `wss://ws.limitless.exchange/markets` * Production API URL: `https://api.limitless.exchange` ### Venue System for CLOB Markets CLOB markets utilize a **venue system** where each market has unique contract addresses. Before placing orders: 1. **Fetch market data once**: Use `GET /markets/:slug` to retrieve venue information. 2. **Use `venue.exchange`**: This address serves as the `verifyingContract` for EIP-712 order signing. 3. **Cache the venue**: Venue data is static per market; fetch it once and reuse it. **Required Approvals**: * **BUY orders**: Approve USDC to `venue.exchange`. * **SELL orders (simple CLOB)**: Approve conditional tokens to `venue.exchange`. * **SELL orders (NegRisk/grouped)**: Approve conditional tokens to both `venue.exchange` AND `venue.adapter`. **Checksummed Addresses**: All addresses must be in checksummed format (EIP-55). Use `getAddress()` from `viem` or similar utilities to ensure correct formatting. ### Prerequisites * Node 18+ (or any V8/Node LTS). * Packages: ```bash pnpm add socket.io-client cross-fetch ethers viem ``` * Environment variables (example): ``` PRIVATE_KEY="0x..." API_URL="https://api.limitless.exchange" ``` ``` -------------------------------- ### Limitless Exchange Trading Example Main Method (Java) Source: https://api.limitless.exchange/api-v1/index This Java `main` method serves as an entry point for an example trading application interacting with the Limitless Exchange API. It initializes trading parameters, sets the market slug, retrieves a private key from environment variables (with a security warning), and then calls the `executeTrade` function. Error handling is included for missing private keys and exceptions during trade execution. It also prints informative messages about the trade process and the final result. ```java public static void main(String[] args) { System.out.println("=" + "=".repeat(79)); System.out.println("LIMITLESS EXCHANGE TRADING EXAMPLE - JAVA"); System.out.println("=" + "=".repeat(79)); System.out.println("\nโš ๏ธ WARNING: This is an example trading application for educational purposes."); System.out.println("โš ๏ธ Limitless Labs is not responsible for any losses or mistakes."); System.out.println("โš ๏ธ Always test with small amounts first and understand the code."); System.out.println("โš ๏ธ USE AT YOUR OWN RISK.\n"); System.out.println("=" + "=".repeat(79)); try { // Example parameters - REPLACE THESE WITH YOUR ACTUAL VALUES TradingParams tradingParams = new TradingParams( 50, // Price in cents (50ยข) 2, // Number of shares "YES" // "YES" or "NO" ); // Market slug - the script will fetch market data (including venue and tokens) automatically String marketSlug = "example-market-slug"; // Replace with actual market slug // SECURITY WARNING: Never hardcode your private key! // Use environment variables or secure key management String privateKey = System.getenv("PRIVATE_KEY"); if (privateKey == null || privateKey.isEmpty()) { System.err.println("โŒ ERROR: Please set your private key in the PRIVATE_KEY environment variable"); System.err.println("Example: export PRIVATE_KEY='0x...'"); System.exit(1); } System.out.println("๐Ÿš€ Starting trading example..."); System.out.println("Trading parameters: " + tradingParams.amount + " shares at " + tradingParams.firstPrice + " cents for " + tradingParams.firstType); System.out.println("Market slug: " + marketSlug); // Execute the trade // Market data (including venue) is fetched and cached automatically JsonNode result = executeTrade(tradingParams, marketSlug, privateKey); System.out.println("\nโœ… Trade executed successfully!"); System.out.println("Result: " + objectMapper.writerWithDefaultPrettyPrinter() .writeValueAsString(result)); } catch (Exception e) { System.err.println("\nโŒ Error executing trade: " + e.getMessage()); e.printStackTrace(); } } ``` -------------------------------- ### Java Project Setup with Gradle Source: https://api.limitless.exchange/api-v1/index This snippet outlines the directory structure and Gradle initialization commands for a Java application. It includes setting up a new project, managing dependencies, and creating a fat JAR for deployment. ```bash mkdir limitless-trading-example cd limitless-trading-example gradle init --type java-application ``` -------------------------------- ### Install Python SocketIO with Async Support Source: https://api.limitless.exchange/api-v1/index This command installs the python-socketio library with asynchronous support, which is crucial for handling WebSocket connections efficiently. It resolves potential import errors when using asynchronous operations with socketio. ```shell pip install python-socketio[asyncio] ``` -------------------------------- ### End-to-end Example (TypeScript) Source: https://api.limitless.exchange/api-v1/index A comprehensive example demonstrating the typical workflow for interacting with the Limitless Exchange API, from authentication to order submission. ```APIDOC ## End-to-end Example (TypeScript) ### Description This example demonstrates the full flow of authenticating, fetching market data, subscribing to real-time updates via WebSocket, and submitting an order. ### Method N/A (Client-side script) ### Endpoint N/A (Client-side script) ### Parameters N/A ### Request Example ```typescript // main.ts import { loginWithPrivateKey } from './auth'; import { getMarketData, getVenueExchange } from './market'; import { createSignedOrder, submitOrder } from './orders'; import { connectMarkets } from './ws'; import { createWalletFromPrivateKey } from './wallet'; async function main() { const API_URL = process.env.API_URL || 'https://api.limitless.exchange'; const PRIVATE_KEY = process.env.PRIVATE_KEY || ''; const marketSlug = 'example-market-slug'; // Replace with actual market slug // 1) Authenticate const { session, user } = await loginWithPrivateKey(API_URL, PRIVATE_KEY); console.log('Authenticated as', user.account); // 2) Fetch market data const market = await getMarketData(API_URL, marketSlug); const verifyingContract = getVenueExchange(market); console.log('Using venue exchange:', verifyingContract); const tokenId = market.positionIds[0]; // YES token // 3) Connect WS and subscribe const socket = connectMarkets(session); const marketAddresses = ['0xE082AF5a25f5D3904fae514CD03dC99F9Ff39fBc']; // AMM markets array const marketSlugs = [marketSlug]; // CLOB markets array socket.emit('subscribe_market_prices', { marketAddresses, marketSlugs }); // Handlers socket.on('newPriceData', (data: unknown) => console.log('AMM price update:', data)); socket.on('orderbookUpdate', (data: unknown) => console.log('Orderbook update:', data)); // 4) Create wallet client const client = createWalletFromPrivateKey(PRIVATE_KEY as `0x${string}`); // 5) Prepare and place CLOB order const { order, signature } = await createSignedOrder(client, { amount: '1.5', side: 0, // 0 = BUY tokenId, decimals: 6, chainId: 8453, verifyingContract, }); const orderPayload = { order: { ...order, signature }, ownerId: user.id, orderType: 'FOK' as const, marketSlug, }; // 6) Submit order const result = await submitOrder(API_URL, orderPayload, { Cookie: `limitless_session=${session}`, }); console.log('Order created:', result); } main().catch((e) => { console.error(e); process.exit(1); }); ``` ### Response N/A (Client-side script) ``` -------------------------------- ### Build and Run Source: https://api.limitless.exchange/api-v1/index Instructions on how to build and run the Limitless Exchange application, including installing dependencies and creating an executable JAR. ```APIDOC ## Build and Run ### Install Dependencies ```bash ./gradlew build ``` ### Run the Application #### With environment variable ```bash export PRIVATE_KEY="0x..." ./gradlew run ``` #### Or with system property ```bash ./gradlew run -DPRIVATE_KEY="0x..." ``` ### Create Executable JAR ```bash ./gradlew fatJar java -jar build/libs/limitless-trading-example-1.0.0-all.jar ``` ``` -------------------------------- ### Simple Usage Example for WebSocket Client (Python) Source: https://api.limitless.exchange/api-v1/index Demonstrates the basic usage of the Limitless WebSocket client. It initializes the client, connects to the WebSocket, subscribes to default markets, and keeps the connection active. ```python async def simple_usage_example(): """Simple example for API docs""" # Basic usage client = LimitlessWebSocket(private_key=os.getenv('PRIVATE_KEY')) await client.connect() await client.subscribe_markets(MARKET_ADDRESSES) await client.wait() ``` -------------------------------- ### Basic WebSocket Connection Example (Python) Source: https://api.limitless.exchange/api-v1/index Provides a straightforward example of connecting to the Limitless Exchange WebSocket API in public mode. It initializes the client without a private key, connects, subscribes to a specified market, and waits for data. ```python import asyncio from socket_subs import LimitlessWebSocket async def public_data_example(): client = LimitlessWebSocket() await client.connect() await client.subscribe_markets(["0x1234..."]) await client.wait() asyncio.run(public_data_example()) ``` -------------------------------- ### Gradle Dependencies for Limitless Exchange Java Example Source: https://api.limitless.exchange/api-v1/index This `build.gradle` file specifies the necessary dependencies for the Limitless Exchange Java example. It includes libraries for Ethereum operations (Web3j), HTTP requests (OkHttp), JSON processing (Jackson), cryptography (Bouncycastle), logging (SLF4J/Logback), and testing (JUnit). It also configures the creation of a fat JAR. ```gradle plugins { id 'java' id 'application' } group = 'com.limitless.example' version = '1.0.0' sourceCompatibility = '11' repositories { mavenCentral() } dependencies { // Web3j for Ethereum operations implementation 'org.web3j:core:4.9.8' implementation 'org.web3j:crypto:4.9.8' // OkHttp for HTTP operations implementation 'com.squareup.okhttp3:okhttp:4.11.0' implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.11.0' // Jackson for JSON processing implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' // Bouncy Castle for additional crypto support implementation 'org.bouncycastle:bcprov-jdk15on:1.70' // SLF4J for logging implementation 'org.slf4j:slf4j-api:2.0.7' implementation 'ch.qos.logback:logback-classic:1.4.8' // Testing testImplementation 'junit:junit:4.13.2' } application { mainClass = 'com.limitless.example.LimitlessTradingExample' } // Create a fat JAR with all dependencies task fatJar(type: Jar) { manifest { attributes 'Main-Class': 'com.limitless.example.LimitlessTradingExample' } archiveClassifier = 'all' from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } with jar } ``` -------------------------------- ### Install Python Dependencies for Limitless Exchange API Source: https://api.limitless.exchange/api-v1/index Installs the required Python packages for the Limitless Exchange API client, including socket.io and eth-account with a specific version for compatibility. ```bash pip install python-socketio[asyncio] eth-account==0.10.0 requests asyncio ``` -------------------------------- ### Python: Install API Integration Packages Source: https://api.limitless.exchange/api-v1/index Installs essential Python packages for integrating with the Limitless Exchange API, including libraries for account management, HTTP requests, and blockchain interactions. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example pip install eth-account requests web3 ``` -------------------------------- ### LimitlessWebSocket Class Initialization and Setup (Python) Source: https://api.limitless.exchange/api-v1/index Initializes the LimitlessWebSocket client, setting up the WebSocket URL, handling private keys, and configuring event handlers using Socket.IO. It prepares the client for connection and event management. ```python class LimitlessWebSocket: """ Streamlined WebSocket client for Limitless Exchange Essential functionality: authentication, connection, subscription, events """ def __init__(self, websocket_url: str = "wss://ws.limitless.exchange", private_key: Optional[str] = None): self.websocket_url = websocket_url self.private_key = private_key self.session_cookie = None self.connected = False self.subscribed_markets: List[str] = [] # Socket.IO client with minimal logging self.sio = socketio.AsyncClient(logger=False, engineio_logger=False) self._setup_handlers() ``` -------------------------------- ### Authentication and Common Utilities Source: https://api.limitless.exchange/api-v1/index Details on installing necessary packages, setting up environment variables, and using common utility functions for authentication and message signing. ```APIDOC ## Installation ```bash pip install python-socketio[asyncio] eth-account==0.10.0 requests asyncio ``` **Important**: Ensure you use compatible package versions as specified. The script has been tested with these dependencies. ## Environment Variables ##### Required for authenticated features (positions, transactions) ```bash export PRIVATE_KEY="0x..." # Your wallet private key ``` ##### Optional: Enable debug logging ```bash export DEBUG=1 ``` ## Common Utilities (`common_utils.py`) ### Description Provides shared authentication and utility functions for interacting with the Limitless Exchange API. ### Functions - **`authenticate(private_key, signing_message)`** - Authenticates with the Limitless Exchange API using a private key. - Args: - `private_key` (str): The private key for signing. - `signing_message` (str): The message to sign, obtained from `get_signing_message()`. - Returns: - `tuple`: A tuple containing the `session_cookie` and `user_data`. - Raises: - `Exception`: If authentication fails. - **`get_signing_message()`** - Retrieves the signing message required for authentication from the Limitless Exchange API. - Returns: - `str`: The signing message. - Raises: - `Exception`: If fetching the signing message fails. - **`string_to_hex(text)`** - Converts a string to its hexadecimal representation with a '0x' prefix. - Args: - `text` (str): The input string. - Returns: - `str`: The hex representation of the string. ### Request Example (Authentication) ```python from common_utils import authenticate, get_signing_message private_key = os.environ.get("PRIVATE_KEY") if private_key: signing_message = get_signing_message() session_cookie, user_data = authenticate(private_key, signing_message) print("Authentication successful!") print(f"Session Cookie: {session_cookie}") print(f"User Data: {user_data}") else: print("PRIVATE_KEY environment variable not set.") ``` ### Response Example (Authentication Success) ```json { "limitless_session": "your_session_cookie_here", "user": { "address": "0x...", "client_id": "..." } } ``` ### Note on `encode_typed_data` The module attempts to import `encode_typed_data` from `eth_account.messages`. If this fails, it falls back to `encode_structured_data` and provides instructions for upgrading `eth-account` if necessary. `encode_typed_data` is re-exported for backward compatibility. ``` -------------------------------- ### End-to-End Trading Example with TypeScript Source: https://api.limitless.exchange/api-v1/index Demonstrates a complete trading workflow: authentication, fetching market data, subscribing to WebSocket streams, creating a wallet, signing an order, and submitting it. It uses environment variables for API URL and private key, and requires specific market slugs. Addresses should be checksummed, and market data should be cached. ```typescript // ๐ŸŽฏ Copy and customize this example // main.ts import { loginWithPrivateKey } from './auth'; import { getMarketData, getVenueExchange } from './market'; import { createSignedOrder, submitOrder } from './orders'; import { connectMarkets } from './ws'; import { createWalletFromPrivateKey } from './wallet'; async function main() { const API_URL = process.env.API_URL || 'https://api.limitless.exchange'; // Warning: storing private keys in .env files is dangerous, use proper secret management services. const PRIVATE_KEY = process.env.PRIVATE_KEY || ''; // Market slug for CLOB trading const marketSlug = 'example-market-slug'; // Replace with actual market slug // 1) Authenticate (optional for public WS; required to place orders) const { session, user } = await loginWithPrivateKey(API_URL, PRIVATE_KEY); console.log('Authenticated as', user.account); // 2) Fetch market data (cached per market) to get venue and token info const market = await getMarketData(API_URL, marketSlug); const verifyingContract = getVenueExchange(market); console.log('Using venue exchange:', verifyingContract); // Get token IDs from market data // positionIds[0] = YES token, positionIds[1] = NO token const tokenId = market.positionIds[0]; // YES token for this example // 3) Connect WS and subscribe const socket = connectMarkets(session); // Combined subscription (send both arrays together to avoid replacing previous subscriptions) const marketAddresses = ['0xE082AF5a25f5D3904fae514CD03dC99F9Ff39fBc']; // AMM markets array const marketSlugs = [marketSlug]; // CLOB markets array socket.emit('subscribe_market_prices', { marketAddresses, marketSlugs }); // Handlers socket.on('newPriceData', (data: unknown) => console.log('AMM price update:', data)); // AMM markets only socket.on('orderbookUpdate', (data: unknown) => console.log('Orderbook update:', data)); // CLOB markets only // 4) Create wallet client from private key const client = createWalletFromPrivateKey(PRIVATE_KEY as `0x${string}`); // 5) Prepare and place CLOB order using venue's exchange address const { order, signature } = await createSignedOrder(client, { amount: '1.5', side: 0, // 0 = BUY tokenId, decimals: 6, chainId: 8453, verifyingContract, // From venue data }); const orderPayload = { order: { ...order, signature }, ownerId: user.id, orderType: 'FOK' as const, marketSlug, }; // 6) Submit order const result = await submitOrder(API_URL, orderPayload, { Cookie: `limitless_session=${session}`, }); console.log('Order created:', result); } main().catch((e) => { console.error(e); process.exit(1); }); ``` -------------------------------- ### LimitlessWebSocket Event Handlers Setup (Python) Source: https://api.limitless.exchange/api-v1/index Sets up various event handlers for the WebSocket connection, including connect, disconnect, authentication, and data reception events like newPriceData, positions, system, and exceptions. These handlers manage the client's state and process incoming messages. ```python def _setup_handlers(self): """Setup essential event handlers""" @self.sio.event(namespace='/markets') async def connect(): self.connected = True print("โœ… Connected to /markets") # Send authentication if available if self.session_cookie: await self.sio.emit('authenticate', f'Bearer {self.session_cookie}', namespace='/markets') # Re-subscribe to markets after reconnection if self.subscribed_markets: await asyncio.sleep(1) await self._resubscribe() @self.sio.event(namespace='/markets') async def disconnect(): self.connected = False print("โŒ Disconnected from /markets") @self.sio.event(namespace='/markets') async def authenticated(data): print(f"Received packet MESSAGE data 2/markets, ["authenticated", {json.dumps(data)}]") @self.sio.event(namespace='/markets') async def newPriceData(data): """Print raw newPriceData packet""" print(f"Received packet MESSAGE data 2/markets, ["newPriceData", {json.dumps(data)}]") @self.sio.event(namespace='/markets') async def positions(data): """Print raw positions packet""" print(f"Received packet MESSAGE data 2/markets, ["positions", {json.dumps(data)}]") @self.sio.event(namespace='/markets') async def system(data): print(f"Received packet MESSAGE data 2/markets, ["system", {json.dumps(data)}]") @self.sio.event(namespace='/markets') async def exception(data): """Print raw exception packet""" print(f"Received packet MESSAGE data 2/markets, ["exception", {json.dumps(data)}]") ``` -------------------------------- ### Configure Environment Variables for API Limitless Exchange API v1 Source: https://api.limitless.exchange/api-v1/index This example demonstrates how to configure essential environment variables for interacting with the Limitless Exchange API v1. It requires setting a PRIVATE_KEY for wallet authentication and API_URL for the endpoint. Storing private keys directly in the environment is suitable for development and testing only. ```shell export PRIVATE_KEY="0x..." export API_URL="https://api.limitless.exchange" ``` -------------------------------- ### Authenticated WebSocket Connection Example (Python) Source: https://api.limitless.exchange/api-v1/index Illustrates how to establish an authenticated connection to the Limitless Exchange WebSocket API using a private key. This allows access to full market data, including positions and transactions. ```python import os import asyncio from socket_subs import LimitlessWebSocket async def authenticated_example(): private_key = os.getenv('PRIVATE_KEY') ##please define on shell level export PRIVATE_KEY='0x...' client = LimitlessWebSocket(private_key=private_key) await client.connect() await client.subscribe_markets(["0x1234..."]) # on script level is passed automatically await client.wait() asyncio.run(authenticated_example()) ``` -------------------------------- ### Run Application with Gradle Source: https://api.limitless.exchange/api-v1/index Runs the application using Gradle. Supports setting the PRIVATE_KEY environment variable either as an environment variable or a system property. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example #### With environment variable export PRIVATE_KEY="0x..." ./gradlew run #### Or with system property ./gradlew run -DPRIVATE_KEY="0x..." ``` -------------------------------- ### Create Executable JAR with Gradle Source: https://api.limitless.exchange/api-v1/index Builds an executable fat JAR file using Gradle and then runs it. This command bundles all dependencies into a single JAR. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example ./gradlew fatJar java -jar build/libs/limitless-trading-example-1.0.0-all.jar ``` -------------------------------- ### Get Signing Message Source: https://api.limitless.exchange/api-v1/index Returns a signing message with a randomly generated nonce for authentication purposes. ```APIDOC ## GET /auth/signing-message ### Description Returns a signing message with a randomly generated nonce for authentication purposes. ### Method GET ### Endpoint /auth/signing-message ### Parameters ### Request Example ```json { "example": "curl https://api.limitless.exchange/auth/signing-message" } ``` ### Response #### Success Response (200) - **message** (string) - A signing message containing a nonce has been successfully generated - **nonce** (string) - The randomly generated nonce #### Response Example ```json { "message": "Welcome to Limitless.exchange! Please sign this message to verify your identity.", "nonce": "0xa1b2c3d4e5f67890..." } ``` ``` -------------------------------- ### GET /markets/:slug Source: https://api.limitless.exchange/api-v1/index Fetches dynamic venue information for a given market slug, crucial for CLOB markets. ```APIDOC ## GET /markets/:slug ### Description Fetches market data, including venue information (exchange and adapter contract addresses), for a specific market slug. This is essential for CLOB markets as it provides the necessary contract addresses for EIP-712 order signing and approvals. ### Method GET ### Endpoint `/markets/:slug` ### Parameters #### Path Parameters - **slug** (string) - Required - The unique identifier for the market. ### Response #### Success Response (200) - **venue** (object) - Contains venue details. - **exchange** (string) - The exchange contract address for the venue. - **adapter** (string) - The adapter contract address for the venue (used for NegRisk/grouped markets). #### Response Example ```json { "venue": { "exchange": "0x...", "adapter": "0x..." } } ``` ``` -------------------------------- ### GET Market Data Source: https://api.limitless.exchange/api-v1/index Fetches market data for a given market slug, including venue information required for EIP-712 signing. ```APIDOC ## GET /markets/{marketSlug} ### Description Fetches detailed market data for a specified market, including its associated venue. This information is essential for constructing EIP-712 compliant signatures. ### Method GET ### Endpoint /markets/{marketSlug} ### Parameters #### Path Parameters - **marketSlug** (String) - Required - The unique identifier for the market. #### Query Parameters None #### Request Body None ### Request Example ```bash GET /markets/some_market_slug ``` ### Response #### Success Response (200) - **positionIds** (Array) - An array containing the IDs for the 'YES' and 'NO' tokens. - **venue** (Object) - Information about the trading venue. - **exchange** (String) - The name of the exchange venue. #### Response Example ```json { "positionIds": ["yes_token_id", "no_token_id"], "venue": { "exchange": "limitless_exchange" } } ``` #### Error Response (e.g., 404) - **error** (String) - A message indicating that the market was not found. ``` -------------------------------- ### GET /auth/signing-message Source: https://api.limitless.exchange/api-v1/index Fetches a unique signing message from the API, which is required for user authentication. This message needs to be signed with the user's private key. ```APIDOC ## GET /auth/signing-message ### Description Fetches the signing message required for authentication. This message must be signed by the user's private key to prove ownership. ### Method GET ### Endpoint /auth/signing-message ### Parameters None ### Request Example None ### Response #### Success Response (200) - **message** (string) - The signing message to be signed. ``` -------------------------------- ### Wallet Creation Source: https://api.limitless.exchange/api-v1/index Creates a Viem wallet client from a private key for signing transactions on the Base network. ```APIDOC ## Wallet Client Creation ### Description Creates a `viem` wallet client using a provided private key. This client can be used for signing transactions and messages on the Base mainnet. ### Method Function Call ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **privateKey** (`0x${string}`) - Required - The private key of the wallet. ### Request Example ```javascript import { createWalletFromPrivateKey } from './wallet'; // Assuming the function is in wallet.ts const privateKey = '0x...your_private_key_here...'; const walletClient = createWalletFromPrivateKey(privateKey); console.log('Wallet client created:', walletClient); ``` ### Response #### Success Response - **walletClient** (object) - A `viem` wallet client instance configured for the Base network. #### Response Example (Returns a `viem` wallet client object, no specific JSON example) ``` ``` -------------------------------- ### Get Default Market Addresses (Python) Source: https://api.limitless.exchange/api-v1/index A helper function designed to retrieve a predefined list of market addresses. This is typically used to fetch default market data when no specific markets are provided. ```python def get_default_markets(): """Helper function to access global market addresses""" return MARKET_ADDRESSES ``` -------------------------------- ### Create Viem Wallet Client from Private Key (TypeScript) Source: https://api.limitless.exchange/api-v1/index Creates a viem wallet client instance from a private key, configured for the Base mainnet. This client can then be used for signing transactions and other EIP-712 operations. ```typescript // wallet.ts import { createWalletClient, http } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; import { base } from 'viem/chains'; export function createWalletFromPrivateKey(privateKey: `0x${string}`) { const account = privateKeyToAccount(privateKey); const client = createWalletClient({ account, chain: base, // Base mainnet (chain ID 8453) transport: http(), }); return client; } ``` -------------------------------- ### Set Environment Variables for Production Source: https://api.limitless.exchange/api-v1/index Configures required and optional environment variables for production use. PRIVATE_KEY is mandatory for authentication, and API_URL specifies the API endpoint. ```bash # ๐Ÿ’ป Run in your terminal // ๐ŸŽฏ Copy and customize this example #### Required export PRIVATE_KEY="0x..." # Your wallet private key #### Optional (defaults shown) export API_URL="https://api.limitless.exchange" ``` -------------------------------- ### Fetch Signing Message from API (Java) Source: https://api.limitless.exchange/api-v1/index Fetches a signing message required for authentication from the API. It constructs an HTTP GET request to the '/auth/signing-message' endpoint using an OkHttp client. The function returns the signing message as a string and throws an IOException if the request fails. ```java private static String getSigningMessage() throws IOException { logger.info("Fetching signing message from API..."); Request request = new Request.Builder() .url(API_BASE_URL + "/auth/signing-message") .get() .build(); try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("Failed to get signing message: " + response.code()); } String signingMessage = response.body().string(); logger.info("Signing message received: {}", signingMessage); return signingMessage; } ``` -------------------------------- ### Python: Fetch Signing Message from Limitless Exchange API Source: https://api.limitless.exchange/api-v1/index Retrieves the necessary signing message from the Limitless Exchange API to initiate the authentication process. This function makes a GET request to the '/auth/signing-message' endpoint. It requires the 'requests' library and assumes API_BASE_URL is defined. ```python import requests API_BASE_URL = "YOUR_API_BASE_URL" # Replace with your actual API base URL def get_signing_message(): """ Fetch the signing message from the API. Returns: str: The signing message to be signed """ response = requests.get(f"{API_BASE_URL}/auth/signing-message") if response.status_code == 200: return response.text else: raise Exception(f"Failed to get signing message: {response.status_code}") ``` -------------------------------- ### Get Signing Message - Shell Curl Source: https://api.limitless.exchange/api-v1/index Retrieves a unique signing message with a nonce for user authentication. This message must be signed by the user's wallet to verify their identity before proceeding with other authenticated actions. No specific dependencies are required beyond a standard curl client. ```Shell curl https://api.limitless.exchange/auth/signing-message ``` -------------------------------- ### Set Private Key and Debug Environment Variables Source: https://api.limitless.exchange/api-v1/index These commands export environment variables required for authenticated API access and enhanced debugging. PRIVATE_KEY should be set to your wallet's private key, and DEBUG=1 enables detailed logging for troubleshooting. ```shell export PRIVATE_KEY="0x..." export DEBUG=1 ``` -------------------------------- ### Get Venue Exchange Address for a Market (Java) Source: https://api.limitless.exchange/api-v1/index Retrieves the venue exchange address associated with a given market slug. This function relies on the getMarketData method and expects the market data to contain nested 'venue' and 'exchange' fields. It throws an IOException if market or venue data is missing. ```java private static String getVenueExchange(String slug) throws IOException { JsonNode market = getMarketData(slug); JsonNode venue = market.get("venue"); if (venue == null || venue.get("exchange") == null) { throw new IOException("Market " + slug + " does not have venue data"); } return venue.get("exchange").asText(); } ``` -------------------------------- ### Create Signed Order (viem TypeScript) Source: https://api.limitless.exchange/api-v1/index Creates a signed order for CLOB trading using viem. It constructs an order message with specified details and signs it using the provided viem WalletClient. Dependencies include 'viem'. ```typescript // ๐ŸŽฏ Copy and customize this example // orders.ts (viem-based FOK market order example) import fetch from 'cross-fetch'; import { parseUnits, type WalletClient, type Account, type Transport, type Chain } from 'viem'; type OrderMessage = { salt: string; maker: `0x${string}`; signer: `0x${string}`; taker: `0x${string}`; tokenId: string; makerAmount: string; takerAmount: string; expiration: string; nonce: string; feeRateBps: string; side: number; // 0 buy, 1 sell signatureType: number; // 0 EOA }; const EIP712_DOMAIN = [ { name: 'name', type: 'string' }, { name: 'version', type: 'string' }, { name: 'chainId', type: 'uint256' }, { name: 'verifyingContract', type: 'address' }, ] as const; const ORDER_STRUCTURE = [ { name: 'salt', type: 'uint256' }, { name: 'maker', type: 'address' }, { name: 'signer', type: 'address' }, { name: 'taker', type: 'address' }, { name: 'tokenId', type: 'uint256' }, { name: 'makerAmount', type: 'uint256' }, { name: 'takerAmount', type: 'uint256' }, { name: 'expiration', type: 'uint256' }, { name: 'nonce', type: 'uint256' }, { name: 'feeRateBps', type: 'uint256' }, { name: 'side', type: 'uint8' }, { name: 'signatureType', type: 'uint8' }, ] as const; /** * Create a signed order for CLOB trading. * @param client - viem WalletClient with account * @param options.verifyingContract - The venue's exchange address from market data (GET /markets/:slug) */ export async function createSignedOrder( client: WalletClient, options: { amount: string; // USD amount in decimal, e.g., '1.5' side: 0 | 1; // 0 buy, 1 sell tokenId: string; decimals?: number; // default 6 chainId: number; // e.g., 8453 verifyingContract: `0x${string}`; // venue.exchange from market data }, ) { const maker = client.account!.address as `0x${string}`; const salt = String(Math.round(Math.random() * Date.now())); const makerAmount = parseUnits(options.amount, options.decimals ?? 6).toString(); const order: OrderMessage = { salt, maker, signer: maker, taker: '0x0000000000000000000000000000000000000000', tokenId: options.tokenId, ``` -------------------------------- ### Get EIP-712 Domain (Python) Source: https://api.limitless.exchange/api-v1/index Constructs the EIP-712 domain separator object, which is crucial for the signing process. It includes the exchange's name, version, chain ID (Base chain), and the specific verifying contract address. This object is a prerequisite for signing messages according to the EIP-712 standard. ```python def get_eip712_domain(venue_exchange_address): """ Get the EIP-712 domain for signing. Args: venue_exchange_address: The venue's exchange contract address from market data Returns: dict: EIP-712 domain object """ return { "name": "Limitless CTF Exchange", "version": "1", "chainId": 8453, # Base chain ID "verifyingContract": venue_exchange_address, } ``` -------------------------------- ### Configure Environment Variables for Limitless Exchange API Source: https://api.limitless.exchange/api-v1/index Sets up essential environment variables for authenticated API access. PRIVATE_KEY is required for transactions and positions, while DEBUG can be set to enable logging. ```bash # Connection Commands ##### Required for authenticated features (positions, transactions) export PRIVATE_KEY="0x..." # Your wallet private key ##### Optional: Enable debug logging export DEBUG=1 ``` -------------------------------- ### LimitlessWebSocket Connection Establishment (Python) Source: https://api.limitless.exchange/api-v1/index Establishes a connection to the Limitless Exchange WebSocket server. It first attempts authentication if a private key is available, then connects using the provided URL, including session cookies in headers if authenticated. It includes logic to wait for the connection to establish. ```python async def connect(self): """Connect to WebSocket with working configuration""" try: # Authenticate first if private key provided await self.authenticate() # Connect with same options as working version print(f"๐Ÿ”Œ Connecting to {self.websocket_url}...") # Prepare connection options with authentication headers if available connect_options = {'transports': ['websocket']} if self.session_cookie: connect_options['headers'] = { 'Cookie': f'limitless_session={self.session_cookie}' } print("๐Ÿช Adding session cookie to connection headers") await self.sio.connect( self.websocket_url, namespaces=['/markets'], **connect_options ) # Wait for connection to establish max_retries = 10 for _ in range(max_retries): if self.connected: break await asyncio.sleep(0.2) if self.connected: print("โœ… Successfully connected") else: print("โŒ Connection failed") except Exception as e: print(f"โŒ Connection error: {e}") raise ``` -------------------------------- ### Create and Submit Order to Limitless Exchange API (Java) Source: https://api.limitless.exchange/api-v1/index This Java code snippet demonstrates the process of creating and submitting a trading order to the Limitless Exchange API. It includes fetching fee rates, creating an order payload, signing the order using a private key, constructing the final order details, and submitting the order via an API call. It utilizes standard Java data structures like Maps and relies on external methods for payload creation, signing, and API submission. ```java int feeRateBps = authResult.userData.path("rank").path("feeRateBps").asInt(0); Map orderPayload = createOrderPayloadWithoutSignature( makerAddress, selectedToken, makerAmount, takerAmount, feeRateBps ); // Step 5: Sign the order using venue's exchange address String signature = createSignatureForOrderPayload(venueExchange, orderPayload, privateKey); // Step 6: Create final order payload Map finalOrderPayload = new LinkedHashMap<>(); Map orderWithSignature = new LinkedHashMap<>(orderPayload); orderWithSignature.put("price", priceInDollars); orderWithSignature.put("signature", signature); finalOrderPayload.put("order", orderWithSignature); finalOrderPayload.put("ownerId", authResult.userData.get("id").asInt()); finalOrderPayload.put("orderType", tradeType); finalOrderPayload.put("marketSlug", marketSlug); logger.info("Order placed for {} cents, amount: {}, share type: {}", priceInCents, amount, tradingParams.firstType); // Step 7: Submit to API return createOrderApi(finalOrderPayload, authResult.sessionCookie); } ``` -------------------------------- ### Troubleshooting Source: https://api.limitless.exchange/api-v1/index Provides solutions for common issues encountered when using the Limitless Exchange API, including build failures, authentication problems, and order creation errors. ```APIDOC ## Troubleshooting ### Common Issues 1. **Build Failures** * Ensure Java 11+ is installed. * Check internet connection for dependency downloads. * Clear Gradle cache: `./gradlew clean`. 2. **Authentication Failed** * Verify private key format (with or without '0x' prefix). * Check API endpoint accessibility. * Ensure signing message is current. 3. **Order Creation Failed** * Verify market slug and token IDs. * Check account balance. * Ensure market is still open. 4. **Signature Verification Failed** * Ensure you're using the venue's exchange address from market data (`GET /markets/:slug`). * Check chain ID (e.g., 8453 for Base). * Make sure addresses are checksummed (use `Keys.toChecksumAddress()` or equivalent). * Ensure Web3j version compatibility. ```