@limitless-exchange/sdk 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -38
- package/dist/index.d.mts +728 -54
- package/dist/index.d.ts +728 -54
- package/dist/index.js +773 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +761 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/logger.ts","../src/types/orders.ts","../src/types/websocket.ts","../src/types/market-class.ts","../src/api/http.ts","../src/utils/constants.ts","../src/api/errors.ts","../src/api/retry.ts","../src/orders/builder.ts","../src/orders/signer.ts","../src/orders/validator.ts","../src/markets/fetcher.ts","../src/portfolio/fetcher.ts","../src/orders/client.ts","../src/websocket/client.ts"],"sourcesContent":["/**\n * Logger interface for SDK integration.\n * Allows users to inject their own logging implementation.\n *\n * @public\n */\nexport interface ILogger {\n /**\n * Log debug information (verbose, development only)\n */\n debug(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log informational messages\n */\n info(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log warning messages\n */\n warn(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log error messages\n */\n error(message: string, error?: Error, meta?: Record<string, any>): void;\n}\n\n/**\n * No-op logger (default) - does nothing.\n * Zero performance overhead when logging is not needed.\n *\n * @internal\n */\nexport class NoOpLogger implements ILogger {\n debug(): void {}\n info(): void {}\n warn(): void {}\n error(): void {}\n}\n\n/**\n * Simple console logger for development.\n * Can be used as a starting point or for debugging.\n *\n * @example\n * ```typescript\n * import { ConsoleLogger } from '@limitless-exchange/sdk';\n *\n * const logger = new ConsoleLogger('debug');\n * const authenticator = new Authenticator(httpClient, signer, logger);\n * ```\n *\n * @public\n */\nexport class ConsoleLogger implements ILogger {\n private level: 'debug' | 'info' | 'warn' | 'error';\n\n constructor(level: 'debug' | 'info' | 'warn' | 'error' = 'info') {\n this.level = level;\n }\n\n private shouldLog(messageLevel: 'debug' | 'info' | 'warn' | 'error'): boolean {\n const levels = ['debug', 'info', 'warn', 'error'];\n return levels.indexOf(messageLevel) >= levels.indexOf(this.level);\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('debug')) {\n console.debug('[Limitless SDK]', message, meta || '');\n }\n }\n\n info(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('info')) {\n console.info('[Limitless SDK]', message, meta || '');\n }\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('warn')) {\n console.warn('[Limitless SDK]', message, meta || '');\n }\n }\n\n error(message: string, error?: Error, meta?: Record<string, any>): void {\n if (this.shouldLog('error')) {\n // Only log error message, not the full error object (which includes stack trace)\n const errorMsg = error ? error.message : '';\n console.error('[Limitless SDK]', message, errorMsg ? `- ${errorMsg}` : '', meta || '');\n }\n }\n}\n","/**\n * Order-related types for Limitless Exchange.\n * @module types/orders\n */\n\n/**\n * Order side enum.\n * @public\n */\nexport enum Side {\n BUY = 0,\n SELL = 1,\n}\n\n/**\n * Order type enum.\n * @public\n */\nexport enum OrderType {\n /** Fill-or-Kill: Execute immediately or cancel */\n FOK = 'FOK',\n /** Good-Til-Cancelled: Remain on orderbook until filled or cancelled */\n GTC = 'GTC',\n}\n\n/**\n * Signature type enum.\n * @public\n */\nexport enum SignatureType {\n /** Externally Owned Account */\n EOA = 0,\n /** Polymarket Proxy */\n POLY_PROXY = 1,\n /** Polymarket Gnosis Safe */\n POLY_GNOSIS_SAFE = 2,\n}\n\n/**\n * Base arguments shared by all order types.\n * @public\n */\nexport interface BaseOrderArgs {\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Order side (BUY or SELL)\n */\n side: Side;\n\n /**\n * Expiration timestamp (0 for no expiration)\n * @defaultValue '0'\n */\n expiration?: string;\n\n /**\n * Nonce for order replay protection\n * @defaultValue 0\n */\n nonce?: number;\n\n /**\n * Taker address (ZERO_ADDRESS for any taker)\n * @defaultValue '0x0000000000000000000000000000000000000000'\n */\n taker?: string;\n}\n\n/**\n * Arguments for FOK (Fill-or-Kill) market orders.\n *\n * @remarks\n * FOK orders are market orders that execute immediately at the best available price.\n * Specify the maker amount (human-readable, max 6 decimals).\n *\n * For BUY orders: Amount in USDC to spend (e.g., 50.0 = spend $50 USDC)\n * For SELL orders: Number of shares to sell (e.g., 18.64 = sell 18.64 shares)\n *\n * @example\n * ```typescript\n * // BUY: Spend 50 USDC\n * {\n * tokenId: '123...',\n * makerAmount: 50, // Spend $50 USDC\n * side: Side.BUY\n * }\n *\n * // SELL: Sell 18.64 shares\n * {\n * tokenId: '123...',\n * makerAmount: 18.64, // Sell 18.64 shares\n * side: Side.SELL\n * }\n * ```\n *\n * @public\n */\nexport interface FOKOrderArgs extends BaseOrderArgs {\n /**\n * Maker amount (human-readable, max 6 decimals)\n *\n * For BUY orders: Amount of USDC to spend\n * For SELL orders: Number of shares to sell\n *\n * @example\n * // BUY examples\n * 50 = Spend $50 USDC\n * 1.5 = Spend $1.50 USDC\n * 0.75 = Spend $0.75 USDC\n *\n * // SELL examples\n * 18.64 = Sell 18.64 shares\n * 44.111 = Sell 44.111 shares\n */\n makerAmount: number;\n}\n\n/**\n * Arguments for GTC (Good-Til-Cancelled) limit orders.\n *\n * @remarks\n * GTC orders are limit orders that remain on the orderbook until filled or cancelled.\n * You specify the price and number of shares.\n *\n * @example\n * ```typescript\n * // BUY: Buy 10 shares at 0.65 price\n * {\n * tokenId: '123...',\n * price: 0.65,\n * size: 10,\n * side: Side.BUY\n * }\n *\n * // SELL: Sell 5 shares at 0.75 price\n * {\n * tokenId: '123...',\n * price: 0.75,\n * size: 5,\n * side: Side.SELL\n * }\n * ```\n *\n * @public\n */\nexport interface GTCOrderArgs extends BaseOrderArgs {\n /**\n * Price per share (0.0 to 1.0)\n */\n price: number;\n\n /**\n * Number of shares to trade\n */\n size: number;\n}\n\n/**\n * Union type for all order arguments.\n * @public\n */\nexport type OrderArgs = FOKOrderArgs | GTCOrderArgs;\n\n/**\n * Unsigned order payload.\n * @public\n */\nexport interface UnsignedOrder {\n /**\n * Unique salt for order identification\n */\n salt: number;\n\n /**\n * Maker address (order creator)\n */\n maker: string;\n\n /**\n * Signer address (must match maker for EOA)\n */\n signer: string;\n\n /**\n * Taker address (ZERO_ADDRESS for any taker)\n */\n taker: string;\n\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Maker amount in USDC units (6 decimals)\n */\n makerAmount: number;\n\n /**\n * Taker amount in USDC units (6 decimals)\n */\n takerAmount: number;\n\n /**\n * Expiration timestamp (0 for no expiration)\n */\n expiration: string;\n\n /**\n * Nonce for replay protection\n */\n nonce: number;\n\n /**\n * Fee rate in basis points\n */\n feeRateBps: number;\n\n /**\n * Order side (BUY or SELL)\n */\n side: Side;\n\n /**\n * Signature type (EOA, POLY_PROXY, etc.)\n */\n signatureType: SignatureType;\n\n /**\n * Price per share (required for GTC orders)\n */\n price?: number;\n}\n\n/**\n * Signed order payload.\n * @public\n */\nexport interface SignedOrder extends UnsignedOrder {\n /**\n * EIP-712 signature\n */\n signature: string;\n}\n\n/**\n * Complete order payload for API submission.\n * @public\n */\nexport interface NewOrderPayload {\n /**\n * Signed order details\n */\n order: SignedOrder;\n\n /**\n * Order type (FOK or GTC)\n */\n orderType: OrderType;\n\n /**\n * Market slug identifier\n */\n marketSlug: string;\n\n /**\n * Owner ID from user profile\n */\n ownerId: number;\n}\n\n/**\n * Clean order data returned from API.\n *\n * @remarks\n * This is a minimal, user-friendly representation of an order\n * that excludes unnecessary API metadata.\n *\n * @public\n */\nexport interface CreatedOrder {\n /**\n * Order database ID\n */\n id: string;\n\n /**\n * Creation timestamp (ISO 8601)\n */\n createdAt: string;\n\n /**\n * Maker amount (USDC units with 6 decimals)\n */\n makerAmount: number;\n\n /**\n * Taker amount (USDC units with 6 decimals)\n */\n takerAmount: number;\n\n /**\n * Expiration timestamp (null for no expiration)\n */\n expiration: string | null;\n\n /**\n * Signature type (0 = EOA, 1 = Polymarket Proxy, 2 = Gnosis Safe)\n */\n signatureType: number;\n\n /**\n * Unique salt for order identification\n */\n salt: number;\n\n /**\n * Maker address\n */\n maker: string;\n\n /**\n * Signer address\n */\n signer: string;\n\n /**\n * Taker address (zero address for any taker)\n */\n taker: string;\n\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Order side (0 = BUY, 1 = SELL)\n */\n side: Side;\n\n /**\n * Fee rate in basis points\n */\n feeRateBps: number;\n\n /**\n * Nonce for replay protection\n */\n nonce: number;\n\n /**\n * EIP-712 signature\n */\n signature: string;\n\n /**\n * Order type (GTC or FOK)\n */\n orderType: string;\n\n /**\n * Price per share (0.0 to 1.0) - only for GTC orders\n */\n price: number | null;\n\n /**\n * Market database ID\n */\n marketId: number;\n}\n\n/**\n * Match information for filled orders.\n *\n * @remarks\n * When a FOK order is filled or a GTC order is partially matched,\n * this provides minimal information about the match.\n *\n * @public\n */\nexport interface OrderMatch {\n /**\n * Match database ID\n */\n id: string;\n\n /**\n * Creation timestamp (ISO 8601)\n */\n createdAt: string;\n\n /**\n * Matched size (USDC units with 6 decimals)\n */\n matchedSize: string;\n\n /**\n * Matched order ID\n */\n orderId: string;\n}\n\n/**\n * Clean order creation response.\n *\n * @remarks\n * This is what users receive after successfully creating an order.\n * For GTC orders, makerMatches will be undefined or empty.\n * For FOK orders, makerMatches contains the fills.\n *\n * @public\n */\nexport interface OrderResponse {\n /**\n * Created order data\n */\n order: CreatedOrder;\n\n /**\n * Matches if order was filled (FOK) or partially matched (GTC)\n */\n makerMatches?: OrderMatch[];\n}\n\n/**\n * Order signing configuration.\n * @public\n */\nexport interface OrderSigningConfig {\n /**\n * Blockchain chain ID\n */\n chainId: number;\n\n /**\n * Contract address for verification (from venue.exchange)\n */\n contractAddress: string;\n}\n","/**\n * WebSocket types for real-time data streaming.\n * @module types/websocket\n */\n\nimport type { OrderbookEntry } from './markets';\n\n// Re-export OrderbookEntry for convenience\nexport type { OrderbookEntry };\n\n/**\n * WebSocket connection configuration.\n * @public\n */\nexport interface WebSocketConfig {\n /**\n * WebSocket URL (default: wss://ws.limitless.exchange)\n */\n url?: string;\n\n /**\n * API key for authentication\n *\n * @remarks\n * **Required** for authenticated subscriptions (positions, transactions).\n * Not required for public subscriptions (market prices, orderbook).\n *\n * You can generate an API key at https://limitless.exchange\n * and the LIMITLESS_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * Auto-reconnect on connection loss (default: true)\n */\n autoReconnect?: boolean;\n\n /**\n * Reconnection delay in ms (default: 1000)\n */\n reconnectDelay?: number;\n\n /**\n * Maximum reconnection attempts (default: Infinity)\n */\n maxReconnectAttempts?: number;\n\n /**\n * Connection timeout in ms (default: 10000)\n */\n timeout?: number;\n}\n\n/**\n * WebSocket connection state.\n * @public\n */\nexport enum WebSocketState {\n DISCONNECTED = 'disconnected',\n CONNECTING = 'connecting',\n CONNECTED = 'connected',\n RECONNECTING = 'reconnecting',\n ERROR = 'error',\n}\n\n/**\n * Subscription channels for WebSocket events.\n * @public\n */\nexport type SubscriptionChannel =\n | 'orderbook'\n | 'trades'\n | 'orders'\n | 'fills'\n | 'markets'\n | 'prices'\n | 'subscribe_market_prices'\n | 'subscribe_positions'\n | 'subscribe_transactions';\n\n/**\n * Orderbook data structure (nested object in OrderbookUpdate).\n * @public\n */\nexport interface OrderbookData {\n /** List of bid orders sorted by price descending */\n bids: OrderbookEntry[];\n /** List of ask orders sorted by price ascending */\n asks: OrderbookEntry[];\n /** Token ID for the orderbook */\n tokenId: string;\n /** Adjusted midpoint price */\n adjustedMidpoint: number;\n /** Maximum spread allowed */\n maxSpread: number;\n /** Minimum order size */\n minSize: number;\n}\n\n/**\n * Orderbook update event - matches API format exactly.\n * @public\n */\nexport interface OrderbookUpdate {\n /** Market slug identifier (camelCase to match API) */\n marketSlug: string;\n /** Nested orderbook data object */\n orderbook: OrderbookData;\n /** Timestamp as Date or number after serialization */\n timestamp: Date | number | string;\n}\n\n/**\n * Trade event.\n * @public\n */\nexport interface TradeEvent {\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price: number;\n size: number;\n timestamp: number;\n tradeId: string;\n}\n\n/**\n * Order update event.\n * @public\n */\nexport interface OrderUpdate {\n orderId: string;\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price?: number;\n size: number;\n filled: number;\n status: 'OPEN' | 'FILLED' | 'CANCELLED' | 'PARTIALLY_FILLED';\n timestamp: number;\n}\n\n/**\n * Order fill event.\n * @public\n */\nexport interface FillEvent {\n orderId: string;\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price: number;\n size: number;\n timestamp: number;\n fillId: string;\n}\n\n/**\n * Market update event.\n * @public\n */\nexport interface MarketUpdate {\n marketSlug: string;\n lastPrice?: number;\n volume24h?: number;\n priceChange24h?: number;\n timestamp: number;\n}\n\n/**\n * Price update event (deprecated - use NewPriceData for AMM prices).\n *\n * Note: This type does not match the actual API response.\n * Use NewPriceData for the correct AMM price update format.\n *\n * @public\n * @deprecated\n */\nexport interface PriceUpdate {\n marketSlug: string;\n price: number;\n timestamp: number;\n}\n\n/**\n * Single AMM price entry in updatedPrices array.\n * @public\n */\nexport interface AmmPriceEntry {\n /** Market ID */\n marketId: number;\n /** Market contract address */\n marketAddress: string;\n /** YES token price (0-1 range) */\n yesPrice: number;\n /** NO token price (0-1 range) */\n noPrice: number;\n}\n\n/**\n * AMM price update event (newPriceData) - matches API format exactly.\n * @public\n */\nexport interface NewPriceData {\n /** Market contract address (camelCase to match API) */\n marketAddress: string;\n /** Array of price updates for this market */\n updatedPrices: AmmPriceEntry[];\n /** Blockchain block number */\n blockNumber: number;\n /** Timestamp as Date or number after serialization */\n timestamp: Date | number | string;\n}\n\n/**\n * Transaction event (blockchain transaction status).\n * @public\n */\nexport interface TransactionEvent {\n /** User ID (optional) */\n userId?: number;\n /** Transaction hash (optional) */\n txHash?: string;\n /** Transaction status */\n status: 'CONFIRMED' | 'FAILED';\n /** Transaction source */\n source: string;\n /** Transaction timestamp */\n timestamp: Date | string;\n /** Market address (optional) */\n marketAddress?: string;\n /** Market slug identifier (optional) */\n marketSlug?: string;\n /** Token ID (optional) */\n tokenId?: string;\n /** Condition ID (optional) */\n conditionId?: string;\n /** Amount of contracts (optional, in string format) */\n amountContracts?: string;\n /** Amount of collateral (optional, in string format) */\n amountCollateral?: string;\n /** Price (optional, in string format) */\n price?: string;\n /** Trade side (optional) */\n side?: 'BUY' | 'SELL';\n}\n\n/**\n * WebSocket event types.\n * @public\n */\nexport interface WebSocketEvents {\n /**\n * Connection established\n */\n connect: () => void;\n\n /**\n * Connection lost\n */\n disconnect: (reason: string) => void;\n\n /**\n * Connection error\n */\n error: (error: Error) => void;\n\n /**\n * Reconnection attempt\n */\n reconnecting: (attempt: number) => void;\n\n /**\n * Orderbook updates (CLOB markets) - API event name: orderbookUpdate\n */\n orderbookUpdate: (data: OrderbookUpdate) => void;\n\n /**\n * AMM price updates - API event name: newPriceData\n */\n newPriceData: (data: NewPriceData) => void;\n\n /**\n * Trade events\n */\n trade: (data: TradeEvent) => void;\n\n /**\n * Order updates\n */\n order: (data: OrderUpdate) => void;\n\n /**\n * Order fill events\n */\n fill: (data: FillEvent) => void;\n\n /**\n * Market updates\n */\n market: (data: MarketUpdate) => void;\n\n /**\n * Position updates\n */\n positions: (data: any) => void;\n\n /**\n * Transaction events (blockchain confirmations)\n */\n tx: (data: TransactionEvent) => void;\n\n /**\n * Price updates (deprecated - use newPriceData)\n * @deprecated\n */\n price: (data: PriceUpdate) => void;\n}\n\n/**\n * Subscription options.\n * @public\n */\nexport interface SubscriptionOptions {\n /**\n * Market slug to subscribe to (required for market-specific channels)\n * @deprecated Use marketSlugs (array) instead - server expects array format\n */\n marketSlug?: string;\n\n /**\n * Market slugs to subscribe to (array format - required by server)\n */\n marketSlugs?: string[];\n\n /**\n * Market address to subscribe to (for AMM markets)\n * @deprecated Use marketAddresses (array) instead - server expects array format\n */\n marketAddress?: string;\n\n /**\n * Market addresses to subscribe to (array format - required by server)\n */\n marketAddresses?: string[];\n\n /**\n * Additional filters\n */\n filters?: Record<string, any>;\n}\n","/**\n * Market class with fluent API methods.\n * @module types/market-class\n */\n\nimport type { HttpClient } from '../api/http';\nimport type {\n CollateralToken,\n MarketCreator,\n MarketMetadata,\n MarketSettings,\n MarketTokens,\n TradePrices,\n PriceOracleMetadata,\n Venue,\n MarketOutcome,\n} from './markets';\n\n/**\n * Market class with fluent API support.\n *\n * @remarks\n * This class represents a market with methods for fetching related data.\n * Instances are created by MarketFetcher and have http_client attached.\n *\n * @public\n */\nexport class Market {\n // Common fields (both single and group)\n id!: number;\n slug!: string;\n title!: string;\n proxyTitle!: string | null;\n description?: string;\n collateralToken!: CollateralToken;\n expirationDate!: string;\n expirationTimestamp!: number;\n expired?: boolean;\n createdAt!: string;\n updatedAt!: string;\n categories!: string[];\n status!: string;\n creator!: MarketCreator;\n tags!: string[];\n tradeType!: string;\n marketType!: string;\n priorityIndex!: number;\n metadata!: MarketMetadata;\n volume?: string;\n volumeFormatted?: string;\n\n // CLOB single market fields\n conditionId?: string;\n negRiskRequestId?: string | null;\n tokens?: MarketTokens;\n prices?: number[];\n tradePrices?: TradePrices;\n isRewardable?: boolean;\n settings?: MarketSettings;\n venue?: Venue;\n logo?: string | null;\n priceOracleMetadata?: PriceOracleMetadata;\n orderInGroup?: number;\n winningOutcomeIndex?: number | null;\n\n // NegRisk group market fields\n outcomeTokens?: string[];\n ogImageURI?: string;\n negRiskMarketId?: string;\n markets?: Market[];\n dailyReward?: string;\n\n // Legacy/deprecated fields\n address?: string | null;\n type?: string;\n outcomes?: MarketOutcome[];\n resolutionDate?: string;\n\n // Private http client for fluent API\n private httpClient?: HttpClient;\n\n /**\n * Creates a Market instance.\n *\n * @param data - Market data from API\n * @param httpClient - HTTP client for making requests\n */\n constructor(data: any, httpClient?: HttpClient) {\n // Copy all properties from data\n Object.assign(this, data);\n\n // Store http client for fluent API\n this.httpClient = httpClient;\n\n // Handle nested Market[] for group markets\n if (data.markets && Array.isArray(data.markets)) {\n this.markets = data.markets.map((m: any) => new Market(m, httpClient));\n }\n }\n\n /**\n * Get user's orders for this market.\n *\n * @remarks\n * Fetches all orders placed by the authenticated user for this specific market.\n * Uses the http_client from the MarketFetcher that created this Market instance.\n *\n * @returns Promise resolving to array of user orders\n * @throws Error if market wasn't fetched via MarketFetcher\n *\n * @example\n * ```typescript\n * // Clean fluent API\n * const market = await marketFetcher.getMarket(\"bitcoin-2024\");\n * const orders = await market.getUserOrders();\n * console.log(`You have ${orders.length} orders in ${market.title}`);\n * ```\n */\n async getUserOrders(): Promise<any[]> {\n if (!this.httpClient) {\n throw new Error(\n 'This Market instance has no httpClient attached. ' +\n 'Make sure to fetch the market via MarketFetcher.getMarket() to use this method.'\n );\n }\n\n const response = await this.httpClient.get<any>(`/markets/${this.slug}/user-orders`);\n\n // Handle both array response and object with orders property\n const orders = Array.isArray(response) ? response : response.orders || [];\n\n return orders;\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport http from 'http';\nimport https from 'https';\nimport { DEFAULT_API_URL } from '../utils/constants';\nimport { APIError, RateLimitError, AuthenticationError, ValidationError } from './errors';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Configuration options for the HTTP client.\n * @public\n */\nexport interface HttpClientConfig {\n /**\n * Base URL for API requests\n * @defaultValue 'https://api.limitless.exchange'\n */\n baseURL?: string;\n\n /**\n * Request timeout in milliseconds\n * @defaultValue 30000\n */\n timeout?: number;\n\n /**\n * API key for authenticated requests\n * @remarks\n * If not provided, will attempt to load from LIMITLESS_API_KEY environment variable.\n * Required for authenticated endpoints (portfolio, orders, etc.)\n */\n apiKey?: string;\n\n /**\n * Optional logger for debugging\n * @defaultValue NoOpLogger (no logging)\n */\n logger?: ILogger;\n\n /**\n * Enable HTTP connection pooling with keepAlive\n * @defaultValue true\n * @remarks\n * When enabled, HTTP connections are reused across requests, reducing latency by 30-50%.\n * Recommended for production environments with high request volume.\n */\n keepAlive?: boolean;\n\n /**\n * Maximum number of sockets to allow per host\n * @defaultValue 50\n * @remarks\n * Controls the connection pool size. Higher values allow more concurrent requests\n * but consume more system resources.\n */\n maxSockets?: number;\n\n /**\n * Maximum number of free sockets to keep open per host\n * @defaultValue 10\n * @remarks\n * Determines how many idle connections to maintain in the pool.\n * Keeping connections open reduces latency for subsequent requests.\n */\n maxFreeSockets?: number;\n\n /**\n * Socket timeout in milliseconds\n * @defaultValue 60000\n * @remarks\n * Time to wait before closing an idle socket connection.\n */\n socketTimeout?: number;\n\n /**\n * Additional headers to include in all requests\n * @remarks\n * These headers will be merged with default headers and sent with every request.\n * Can be overridden by per-request headers.\n *\n * @example\n * ```typescript\n * const client = new HttpClient({\n * additionalHeaders: {\n * 'X-Custom-Header': 'value',\n * 'X-API-Version': 'v1'\n * }\n * });\n * ```\n */\n additionalHeaders?: Record<string, string>;\n}\n\n/**\n * HTTP client wrapper for Limitless Exchange API.\n *\n * @remarks\n * This class provides a centralized HTTP client with API key authentication,\n * error handling, and request/response interceptors.\n *\n * @public\n */\nexport class HttpClient {\n private client: AxiosInstance;\n private apiKey?: string;\n private logger: ILogger;\n\n /**\n * Creates a new HTTP client instance.\n *\n * @param config - Configuration options for the HTTP client\n */\n constructor(config: HttpClientConfig = {}) {\n this.apiKey = config.apiKey || process.env.LIMITLESS_API_KEY;\n this.logger = config.logger || new NoOpLogger();\n\n if (!this.apiKey) {\n this.logger.warn(\n 'API key not set. Authenticated endpoints will fail. ' +\n 'Set LIMITLESS_API_KEY environment variable or pass apiKey parameter.'\n );\n }\n\n // Connection pooling configuration (enabled by default)\n const keepAlive = config.keepAlive !== false; // Default: true\n const maxSockets = config.maxSockets || 50;\n const maxFreeSockets = config.maxFreeSockets || 10;\n const socketTimeout = config.socketTimeout || 60000;\n\n // Create HTTP agent with connection pooling\n const httpAgent = new http.Agent({\n keepAlive,\n maxSockets,\n maxFreeSockets,\n timeout: socketTimeout,\n });\n\n // Create HTTPS agent with connection pooling\n const httpsAgent = new https.Agent({\n keepAlive,\n maxSockets,\n maxFreeSockets,\n timeout: socketTimeout,\n });\n\n this.client = axios.create({\n baseURL: config.baseURL || DEFAULT_API_URL,\n timeout: config.timeout || 30000,\n httpAgent,\n httpsAgent,\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n ...config.additionalHeaders,\n },\n });\n\n this.logger.debug('HTTP client initialized', {\n baseURL: config.baseURL || DEFAULT_API_URL,\n keepAlive,\n maxSockets,\n maxFreeSockets,\n });\n\n this.setupInterceptors();\n }\n\n /**\n * Sets up request and response interceptors.\n * @internal\n */\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (config) => {\n if (this.apiKey) {\n config.headers['X-API-Key'] = this.apiKey;\n }\n\n // Log outgoing request - concise format\n const fullUrl = `${config.baseURL || ''}${config.url || ''}`;\n const method = config.method?.toUpperCase() || 'GET';\n\n // Hide API key in logs for security\n const logHeaders = { ...config.headers };\n if (logHeaders['X-API-Key']) {\n logHeaders['X-API-Key'] = '***';\n }\n\n this.logger.debug(`→ ${method} ${fullUrl}`, {\n headers: logHeaders,\n body: config.data,\n });\n\n return config;\n },\n (error) => Promise.reject(error)\n );\n\n this.client.interceptors.response.use(\n (response) => {\n // Log successful response - concise format\n const method = response.config.method?.toUpperCase() || 'GET';\n const url = response.config.url || '';\n\n this.logger.debug(`✓ ${response.status} ${method} ${url}`, {\n data: response.data,\n });\n return response;\n },\n (error) => {\n if (error.response) {\n // Handle error response data\n const status = error.response.status;\n const data = error.response.data;\n const url = error.config?.url;\n const method = error.config?.method?.toUpperCase();\n let message = error.message;\n\n if (data) {\n // Log error response - concise format\n this.logger.debug(`✗ ${status} ${method} ${url}`, {\n error: data,\n });\n\n // If data is an object, try to extract message or stringify\n if (typeof data === 'object') {\n // Check if message is an array (validation errors)\n if (Array.isArray(data.message)) {\n const messages = data.message\n .map((err: any) => {\n // Include all error details, not just field and message\n const details = Object.entries(err)\n .filter(([_key, val]) => val !== '' && val !== null && val !== undefined)\n .map(([key, val]) => `${key}: ${val}`)\n .join(', ');\n return details || JSON.stringify(err);\n })\n .filter((msg: string) => msg.trim() !== '')\n .join(' | ');\n message = messages || data.error || JSON.stringify(data);\n } else {\n // Try multiple common error field names\n message =\n data.message ||\n data.error ||\n data.msg ||\n (data.errors && JSON.stringify(data.errors)) ||\n JSON.stringify(data);\n }\n } else {\n message = String(data);\n }\n }\n\n // Throw appropriate error type based on status code\n if (status === 429) {\n throw new RateLimitError(message, status, data, url, method);\n } else if (status === 401 || status === 403) {\n throw new AuthenticationError(message, status, data, url, method);\n } else if (status === 400) {\n throw new ValidationError(message, status, data, url, method);\n } else {\n throw new APIError(message, status, data, url, method);\n }\n } else if (error.request) {\n throw new Error('No response received from API');\n } else {\n throw new Error(`Request failed: ${error.message}`);\n }\n }\n );\n }\n\n /**\n * Sets the API key for authenticated requests.\n *\n * @param apiKey - API key value\n */\n setApiKey(apiKey: string): void {\n this.apiKey = apiKey;\n }\n\n /**\n * Clears the API key.\n */\n clearApiKey(): void {\n this.apiKey = undefined;\n }\n\n /**\n * Performs a GET request.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.get(url, config);\n return response.data;\n }\n\n /**\n * Performs a POST request.\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.post(url, data, config);\n return response.data;\n }\n\n /**\n * Performs a DELETE request.\n *\n * @remarks\n * DELETE requests typically don't have a body, so we remove the Content-Type header\n * to avoid \"Body cannot be empty\" errors from the API.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n // Remove Content-Type header for DELETE requests (no body expected)\n const deleteConfig: AxiosRequestConfig = {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': undefined,\n },\n };\n\n const response: AxiosResponse<T> = await this.client.delete(url, deleteConfig);\n return response.data;\n }\n}\n","/**\n * Default API endpoints and configuration constants.\n * @public\n */\n\n/**\n * Default Limitless Exchange API URL.\n * @public\n */\nexport const DEFAULT_API_URL = 'https://api.limitless.exchange';\n\n/**\n * Default WebSocket URL for real-time data.\n * @public\n */\nexport const DEFAULT_WS_URL = 'wss://ws.limitless.exchange';\n\n/**\n * Default chain ID (Base mainnet).\n * @public\n */\nexport const DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Base Sepolia testnet chain ID.\n * @public\n */\nexport const BASE_SEPOLIA_CHAIN_ID = 84532;\n\n/**\n * Signing message template used by the API.\n * @internal\n */\nexport const SIGNING_MESSAGE_TEMPLATE = 'Welcome to Limitless.exchange! Please sign this message to verify your identity.\\n\\nNonce: {NONCE}';\n\n/**\n * Zero address constant.\n * @public\n */\nexport const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Contract addresses by network\n *\n * @remarks\n * Note: CLOB and NegRisk exchange addresses are provided dynamically via the venue system\n * (market.venue.exchange and market.venue.adapter). These addresses vary per market and\n * should be fetched from the API rather than hardcoded.\n *\n * @public\n */\nexport const CONTRACT_ADDRESSES = {\n // Base mainnet (chainId: 8453)\n 8453: {\n USDC: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Native USDC on Base\n CTF: '0xC9c98965297Bc527861c898329Ee280632B76e18', // Conditional Token Framework\n },\n // Base Sepolia testnet (chainId: 84532)\n 84532: {\n USDC: '0x...',\n CTF: '0x...',\n },\n} as const;\n\n/**\n * Get contract address for tokens (USDC or CTF)\n *\n * @remarks\n * For CLOB and NegRisk exchange addresses, use the venue system instead:\n * - Fetch market via `marketFetcher.getMarket(slug)`\n * - Use `market.venue.exchange` for signing and approvals\n * - Use `market.venue.adapter` for NegRisk adapter approvals\n *\n * @param contractType - Contract type (USDC or CTF)\n * @param chainId - Chain ID (default: 8453 for Base mainnet)\n * @returns Contract address\n *\n * @throws Error if contract address not found for chain\n *\n * @public\n */\nexport function getContractAddress(\n contractType: 'USDC' | 'CTF',\n chainId: number = DEFAULT_CHAIN_ID\n): string {\n const addresses = CONTRACT_ADDRESSES[chainId as keyof typeof CONTRACT_ADDRESSES];\n\n if (!addresses) {\n throw new Error(\n `No contract addresses configured for chainId ${chainId}. ` +\n `Supported chains: ${Object.keys(CONTRACT_ADDRESSES).join(', ')}`\n );\n }\n\n const address = addresses[contractType];\n\n if (!address || address === '0x...') {\n throw new Error(\n `Contract address for ${contractType} not available on chainId ${chainId}. ` +\n `Please configure the address in constants.ts or use environment variables.`\n );\n }\n\n return address;\n}\n","/**\n * API error types for Limitless Exchange SDK.\n * @module api/errors\n */\n\n/**\n * Custom error class for API errors that preserves the original response data.\n *\n * @remarks\n * This error class allows users to access the raw API response for custom error handling.\n *\n * @example\n * ```typescript\n * try {\n * await orderClient.createOrder(...);\n * } catch (error) {\n * if (error instanceof APIError) {\n * console.log('Status:', error.status);\n * console.log('Raw response:', error.data);\n * console.log('Message:', error.message);\n * }\n * }\n * ```\n *\n * @public\n */\nexport class APIError extends Error {\n /**\n * HTTP status code (e.g., 400, 404, 500)\n */\n public readonly status: number;\n\n /**\n * Raw API response data (original JSON from API)\n */\n public readonly data: any;\n\n /**\n * Request URL that failed\n */\n public readonly url?: string;\n\n /**\n * Request method (GET, POST, etc.)\n */\n public readonly method?: string;\n\n /**\n * Creates a new API error.\n *\n * @param message - Human-readable error message\n * @param status - HTTP status code\n * @param data - Raw API response data\n * @param url - Request URL\n * @param method - Request method\n */\n constructor(\n message: string,\n status: number,\n data: any,\n url?: string,\n method?: string\n ) {\n super(message);\n this.name = 'APIError';\n this.status = status;\n this.data = data;\n this.url = url;\n this.method = method;\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, APIError);\n }\n }\n\n /**\n * Checks if this error is an authentication/authorization error.\n *\n * @returns True if the error is due to expired or invalid authentication\n *\n * @example\n * ```typescript\n * try {\n * await portfolioFetcher.getPositions();\n * } catch (error) {\n * if (error instanceof APIError && error.isAuthError()) {\n * // Re-authenticate and retry\n * await authenticator.authenticate({ client: 'eoa' });\n * await portfolioFetcher.getPositions();\n * }\n * }\n * ```\n */\n isAuthError(): boolean {\n return this.status === 401 || this.status === 403;\n }\n}\n\n/**\n * Rate limit error (HTTP 429).\n *\n * @remarks\n * Thrown when API rate limits are exceeded. The request should be retried after a delay.\n *\n * @example\n * ```typescript\n * try {\n * await marketFetcher.getActiveMarkets();\n * } catch (error) {\n * if (error instanceof RateLimitError) {\n * console.log('Rate limit exceeded, retry after delay');\n * }\n * }\n * ```\n *\n * @public\n */\nexport class RateLimitError extends APIError {\n constructor(\n message: string = 'Rate limit exceeded',\n status: number = 429,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'RateLimitError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, RateLimitError);\n }\n }\n}\n\n/**\n * Authentication error (HTTP 401, 403).\n *\n * @remarks\n * Thrown when authentication fails or API key is invalid/missing.\n *\n * @example\n * ```typescript\n * try {\n * await portfolioFetcher.getPositions();\n * } catch (error) {\n * if (error instanceof AuthenticationError) {\n * console.log('Authentication failed - check API key');\n * }\n * }\n * ```\n *\n * @public\n */\nexport class AuthenticationError extends APIError {\n constructor(\n message: string = 'Authentication failed',\n status: number = 401,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'AuthenticationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AuthenticationError);\n }\n }\n}\n\n/**\n * Validation error (HTTP 400).\n *\n * @remarks\n * Thrown when request validation fails (invalid parameters, missing required fields, etc.).\n *\n * @example\n * ```typescript\n * try {\n * await orderClient.createOrder({ ... });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.log('Validation failed:', error.message);\n * }\n * }\n * ```\n *\n * @public\n */\nexport class ValidationError extends APIError {\n constructor(\n message: string,\n status: number = 400,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'ValidationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n }\n}\n","/**\n * Retry mechanism for handling transient API failures.\n *\n * @remarks\n * This module provides flexible retry logic for handling rate limits (429),\n * server errors (500, 502, 503), and other transient failures.\n *\n * @example\n * ```typescript\n * // Decorator approach\n * @retryOnErrors({ statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] })\n * async function createOrder() {\n * return await orderClient.createOrder(...);\n * }\n *\n * // Wrapper approach\n * const retryConfig = new RetryConfig({ statusCodes: [429, 500], maxRetries: 3 });\n * const retryableClient = new RetryableClient(httpClient, retryConfig);\n * const markets = await retryableClient.get('/markets');\n * ```\n *\n * @module api/retry\n * @public\n */\n\nimport { APIError } from './errors';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Configuration options for retry behavior.\n *\n * @public\n */\nexport interface RetryConfigOptions {\n /**\n * HTTP status codes to retry on\n * @defaultValue [429, 500, 502, 503, 504]\n */\n statusCodes?: number[];\n\n /**\n * Maximum number of retry attempts\n * @defaultValue 3\n */\n maxRetries?: number;\n\n /**\n * List of delays in seconds for each retry attempt.\n * If not provided, exponential backoff will be used.\n * @defaultValue undefined (use exponential backoff)\n */\n delays?: number[];\n\n /**\n * Base for exponential backoff calculation (delay = base^attempt)\n * @defaultValue 2\n */\n exponentialBase?: number;\n\n /**\n * Maximum delay in seconds for exponential backoff\n * @defaultValue 60\n */\n maxDelay?: number;\n\n /**\n * Optional callback called before each retry attempt\n * @param attempt - Retry attempt number (0-based)\n * @param error - The error that triggered the retry\n * @param delay - Delay in seconds before retry\n */\n onRetry?: (attempt: number, error: Error, delay: number) => void;\n}\n\n/**\n * Configuration class for retry behavior.\n *\n * @public\n */\nexport class RetryConfig {\n /**\n * HTTP status codes to retry on\n */\n readonly statusCodes: Set<number>;\n\n /**\n * Maximum number of retry attempts\n */\n readonly maxRetries: number;\n\n /**\n * List of delays in seconds for each retry\n */\n readonly delays?: number[];\n\n /**\n * Base for exponential backoff\n */\n readonly exponentialBase: number;\n\n /**\n * Maximum delay in seconds\n */\n readonly maxDelay: number;\n\n /**\n * Optional retry callback\n */\n readonly onRetry?: (attempt: number, error: Error, delay: number) => void;\n\n /**\n * Creates a new retry configuration.\n *\n * @param options - Configuration options\n */\n constructor(options: RetryConfigOptions = {}) {\n this.statusCodes = new Set(options.statusCodes || [429, 500, 502, 503, 504]);\n this.maxRetries = options.maxRetries ?? 3;\n this.delays = options.delays;\n this.exponentialBase = options.exponentialBase ?? 2;\n this.maxDelay = options.maxDelay ?? 60;\n this.onRetry = options.onRetry;\n }\n\n /**\n * Calculates delay for a given retry attempt.\n *\n * @param attempt - Retry attempt number (0-based)\n * @returns Delay in seconds\n */\n getDelay(attempt: number): number {\n if (this.delays) {\n // Use specified delays\n return this.delays[Math.min(attempt, this.delays.length - 1)];\n } else {\n // Exponential backoff\n return Math.min(Math.pow(this.exponentialBase, attempt), this.maxDelay);\n }\n }\n}\n\n/**\n * Utility function to sleep for a given duration.\n *\n * @param seconds - Duration to sleep in seconds\n * @returns Promise that resolves after the duration\n * @internal\n */\nfunction sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n}\n\n/**\n * Decorator to add retry logic to async functions.\n *\n * @remarks\n * This decorator automatically retries failed API calls based on HTTP status codes.\n * Useful for handling transient errors like rate limits (429) or server errors (500, 502, 503).\n *\n * @param options - Retry configuration options\n * @returns Method decorator\n *\n * @example\n * ```typescript\n * class MyService {\n * @retryOnErrors({ statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] })\n * async createOrder() {\n * return await this.orderClient.createOrder(...);\n * }\n * }\n * ```\n *\n * @public\n */\nexport function retryOnErrors(options: RetryConfigOptions = {}) {\n const config = new RetryConfig(options);\n\n return function (\n _target: any,\n _propertyKey: string,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: any[]) {\n let lastError: Error | undefined;\n\n // First attempt\n try {\n return await originalMethod.apply(this, args);\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n\n // Retry attempts\n for (let attempt = 0; attempt < config.maxRetries; attempt++) {\n try {\n // Calculate delay\n const delay = config.getDelay(attempt);\n\n // Call user callback if provided\n if (config.onRetry && lastError) {\n config.onRetry(attempt, lastError, delay);\n }\n\n // Wait before retry\n await sleep(delay);\n\n // Retry the function\n return await originalMethod.apply(this, args);\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n }\n\n // All retries exhausted\n throw lastError;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Standalone retry function for wrapping async operations.\n *\n * @remarks\n * This function wraps any async operation with retry logic.\n * More flexible than the decorator approach for one-off retries.\n *\n * @param fn - Async function to execute with retry\n * @param options - Retry configuration options\n * @param logger - Optional logger for retry information\n * @returns Promise resolving to the function result\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n * async () => await orderClient.createOrder(...),\n * { statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] }\n * );\n * ```\n *\n * @public\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryConfigOptions = {},\n logger: ILogger = new NoOpLogger()\n): Promise<T> {\n const config = new RetryConfig(options);\n let lastError: Error | undefined;\n\n // First attempt\n try {\n return await fn();\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n logger.warn('API error, starting retries', { status: error.status });\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n\n // Retry attempts\n for (let attempt = 0; attempt < config.maxRetries; attempt++) {\n try {\n // Calculate delay\n const delay = config.getDelay(attempt);\n\n // Call user callback if provided\n if (config.onRetry && lastError) {\n config.onRetry(attempt, lastError, delay);\n }\n\n logger.info('Retrying operation', { attempt: attempt + 1, delay });\n\n // Wait before retry\n await sleep(delay);\n\n // Retry the function\n return await fn();\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n logger.warn('Retry failed', { attempt: attempt + 1, status: error.status });\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n }\n\n // All retries exhausted\n logger.error('All retries exhausted');\n throw lastError;\n}\n\n/**\n * HTTP client wrapper that adds retry logic to all requests.\n *\n * @remarks\n * This class wraps an HttpClient and automatically retries failed requests\n * based on configured retry settings.\n *\n * @example\n * ```typescript\n * const httpClient = new HttpClient({ logger });\n * const retryConfig = new RetryConfig({ statusCodes: [429, 500], maxRetries: 3 });\n * const retryableClient = new RetryableClient(httpClient, retryConfig);\n *\n * // All requests automatically retry on 429, 500\n * const markets = await retryableClient.get('/markets');\n * ```\n *\n * @public\n */\nexport class RetryableClient {\n /**\n * Creates a new retryable client wrapper.\n *\n * @param httpClient - HTTP client to wrap\n * @param retryConfig - Retry configuration\n * @param logger - Optional logger\n */\n constructor(\n private httpClient: any,\n private retryConfig: RetryConfig = new RetryConfig(),\n private logger: ILogger = new NoOpLogger()\n ) {}\n\n /**\n * Performs a GET request with retry logic.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async get<T = any>(url: string, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.get(url, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Performs a POST request with retry logic.\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async post<T = any>(url: string, data?: any, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.post(url, data, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Performs a DELETE request with retry logic.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async delete<T = any>(url: string, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.delete(url, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Forwards any other method calls to the wrapped HTTP client.\n *\n * @param method - Method name\n */\n [key: string]: any;\n}\n","/**\n * Order builder for constructing unsigned order payloads.\n * @module orders/builder\n */\n\nimport { ethers } from 'ethers';\nimport { OrderArgs, UnsignedOrder, Side, SignatureType } from '../types/orders';\n\n/**\n * Zero address constant for any-taker orders.\n */\nconst ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Default price tick size (0.001 = 3 decimal places).\n * This is the minimum price increment allowed by the exchange.\n */\nconst DEFAULT_PRICE_TICK = 0.001;\n\n/**\n * Order builder for constructing unsigned order payloads.\n *\n * @remarks\n * This class handles the construction of unsigned orders matching the\n * Limitless Exchange API format. It generates unique salts, calculates\n * maker/taker amounts with proper tick alignment, and validates inputs.\n *\n * **Tick Alignment Requirements**:\n * - Prices must align to tick size (default: 0.001 = 3 decimals)\n * - Size must produce takerAmount divisible by sharesStep (priceScale / tickInt = 1000 for 0.001 tick)\n * - SDK validates inputs and throws clear errors rather than auto-rounding\n * - This ensures `price * contracts` yields whole number collateral\n *\n * **Validation Strategy**:\n * - FAILS FAST: Invalid inputs throw errors with helpful suggestions\n * - NO AUTO-ROUNDING: Users maintain full control over order amounts\n * - TRANSPARENCY: Error messages show valid alternatives\n * - Example: size=22.123896 → Error: \"Try 22.123 (rounded down) or 22.124 (rounded up) instead\"\n *\n * @public\n */\nexport class OrderBuilder {\n private makerAddress: string;\n private feeRateBps: number;\n private priceTick: number;\n\n /**\n * Creates a new order builder instance.\n *\n * @param makerAddress - Ethereum address of the order maker\n * @param feeRateBps - Fee rate in basis points (e.g., 100 = 1%)\n * @param priceTick - Price tick size (default: 0.001 for 3 decimals)\n *\n * @example\n * ```typescript\n * const builder = new OrderBuilder(\n * '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',\n * 300, // 3% fee\n * 0.001 // 3 decimal price precision\n * );\n * ```\n */\n constructor(makerAddress: string, feeRateBps: number, priceTick: number = DEFAULT_PRICE_TICK) {\n this.makerAddress = makerAddress;\n this.feeRateBps = feeRateBps;\n this.priceTick = priceTick;\n }\n\n /**\n * Builds an unsigned order payload.\n *\n * @param args - Order arguments (FOK or GTC)\n * @returns Unsigned order ready for signing\n *\n * @throws Error if validation fails or tick alignment fails\n *\n * @example\n * ```typescript\n * // FOK order (market order)\n * const fokOrder = builder.buildOrder({\n * tokenId: '123456',\n * makerAmount: 50, // 50 USDC to spend\n * side: Side.BUY\n * });\n *\n * // GTC order (price + size)\n * const gtcOrder = builder.buildOrder({\n * tokenId: '123456',\n * price: 0.38,\n * size: 22.123, // Will be rounded to tick-aligned: 22.123 shares\n * side: Side.BUY\n * });\n * ```\n */\n buildOrder(args: OrderArgs): UnsignedOrder {\n this.validateOrderArgs(args);\n\n const { makerAmount, takerAmount, price } = this.isFOKOrder(args)\n ? this.calculateFOKAmounts(args.makerAmount)\n : this.calculateGTCAmountsTickAligned(args.price, args.size, args.side);\n\n const order: UnsignedOrder = {\n salt: this.generateSalt(),\n maker: this.makerAddress,\n signer: this.makerAddress,\n taker: args.taker || ZERO_ADDRESS,\n tokenId: args.tokenId,\n makerAmount: makerAmount,\n takerAmount: takerAmount,\n expiration: args.expiration || '0',\n nonce: args.nonce || 0,\n feeRateBps: this.feeRateBps,\n side: args.side,\n signatureType: SignatureType.EOA,\n };\n\n if (price !== undefined) {\n order.price = price;\n }\n\n return order;\n }\n\n /**\n * Type guard to check if order arguments are for FOK order.\n *\n * @param args - Order arguments\n * @returns True if FOK order arguments\n *\n * @internal\n */\n private isFOKOrder(args: OrderArgs): args is import('../types/orders').FOKOrderArgs {\n return 'makerAmount' in args;\n }\n\n /**\n * Generates a unique salt using timestamp + nano-offset pattern.\n *\n * @remarks\n * This follows the reference implementation pattern:\n * salt = timestamp * 1000 + nanoOffset + 24h\n *\n * This ensures uniqueness even when creating orders rapidly.\n *\n * @returns Unique salt value\n *\n * @internal\n */\n private generateSalt(): number {\n const timestamp = Date.now();\n const nanoOffset = Math.floor(performance.now() * 1000) % 1000000;\n const oneDayMs = 1000 * 60 * 60 * 24;\n return timestamp * 1000 + nanoOffset + oneDayMs;\n }\n\n /**\n * Parses decimal string to scaled BigInt.\n *\n * @param value - Decimal string (e.g., \"0.38\")\n * @param scale - Scale factor (e.g., 1_000_000n for 6 decimals)\n * @returns Scaled BigInt value\n *\n * @internal\n */\n private parseDecToInt(value: string, scale: bigint): bigint {\n const s = value.trim();\n const [intPart, fracPart = ''] = s.split('.');\n const decimals = scale.toString().length - 1;\n const frac = (fracPart + '0'.repeat(decimals)).slice(0, decimals);\n const sign = intPart.startsWith('-') ? -1n : 1n;\n const intPartAbs = intPart.replace('-', '');\n return sign * (BigInt(intPartAbs || '0') * scale + BigInt(frac || '0'));\n }\n\n /**\n * Ceiling division for BigInt.\n *\n * @param numerator - Numerator\n * @param denominator - Denominator\n * @returns Ceiling of numerator / denominator\n *\n * @internal\n */\n private divCeil(numerator: bigint, denominator: bigint): bigint {\n if (denominator === 0n) {\n throw new Error('Division by zero');\n }\n return (numerator + denominator - 1n) / denominator;\n }\n\n /**\n * Calculates maker and taker amounts for GTC orders with tick alignment validation.\n *\n * @remarks\n * Validates and calculates amounts to ensure:\n * 1. Price aligns to tick size (e.g., 0.001 for 3 decimals)\n * 2. Size produces takerAmount divisible by sharesStep\n * 3. No auto-rounding - fails fast if values are invalid\n * 4. Transparent error messages guide users to valid values\n *\n * **Algorithm**:\n * - sharesStep = priceScale / tickInt (e.g., 1000 for 0.001 tick)\n * - Validates shares are divisible by sharesStep\n * - Calculates collateral from shares × price (ceil for BUY, floor for SELL)\n * - Assigns maker/taker based on side:\n * - BUY: maker = collateral, taker = shares\n * - SELL: maker = shares, taker = collateral\n * - Throws clear error if size is not tick-aligned\n *\n * @param price - Price per share (0.0 to 1.0, max 3 decimals)\n * @param size - Number of shares (must be tick-aligned)\n * @param side - Order side (BUY or SELL)\n * @returns Object with validated makerAmount, takerAmount, and price\n *\n * @throws Error if price or size not tick-aligned\n *\n * @internal\n */\n private calculateGTCAmountsTickAligned(\n price: number,\n size: number,\n side: Side\n ): { makerAmount: number; takerAmount: number; price: number } {\n const sharesScale = 1_000_000n;\n const collateralScale = 1_000_000n;\n const priceScale = 1_000_000n;\n\n const shares = this.parseDecToInt(size.toString(), sharesScale);\n const priceInt = this.parseDecToInt(price.toString(), priceScale);\n const tickInt = this.parseDecToInt(this.priceTick.toString(), priceScale);\n\n // Validate tick and price\n if (tickInt <= 0n) {\n throw new Error(`Invalid priceTick: ${this.priceTick}`);\n }\n if (priceInt <= 0n) {\n throw new Error(`Invalid price: ${price}`);\n }\n\n // Validate price is tick-aligned\n if (priceInt % tickInt !== 0n) {\n throw new Error(\n `Price ${price} is not tick-aligned. Must be multiple of ${this.priceTick} (e.g., 0.380, 0.381, etc.)`\n );\n }\n\n // Calculate shares step (shares must be divisible by this)\n // For priceTick=0.001: sharesStep = 1_000_000 / 1_000 = 1_000\n const sharesStep = priceScale / tickInt;\n\n // Validate size produces tick-aligned shares (NO AUTO-ROUNDING)\n if (shares % sharesStep !== 0n) {\n // Calculate valid size that would work\n const validSizeDown = Number((shares / sharesStep) * sharesStep) / 1e6;\n const validSizeUp = Number(this.divCeil(shares, sharesStep) * sharesStep) / 1e6;\n\n throw new Error(\n `Invalid size: ${size}. Size must produce contracts divisible by ${sharesStep} (sharesStep). ` +\n `Try ${validSizeDown} (rounded down) or ${validSizeUp} (rounded up) instead.`\n );\n }\n\n // Calculate collateral: (shares * price * collateralScale) / (sharesScale * priceScale)\n const numerator = shares * priceInt * collateralScale;\n const denominator = sharesScale * priceScale;\n\n const collateral =\n side === Side.BUY\n ? this.divCeil(numerator, denominator) // BUY: Round UP (maker pays more)\n : numerator / denominator; // SELL: Round DOWN (maker receives less)\n\n // Assign maker/taker amounts based on side\n let makerAmount: bigint;\n let takerAmount: bigint;\n\n if (side === Side.BUY) {\n // BUY: maker provides collateral, taker provides shares\n makerAmount = collateral;\n takerAmount = shares;\n } else {\n // SELL: maker provides shares, taker provides collateral\n makerAmount = shares;\n takerAmount = collateral;\n }\n\n return {\n makerAmount: Number(makerAmount),\n takerAmount: Number(takerAmount),\n price,\n };\n }\n\n /**\n * Calculates maker and taker amounts for FOK (market) orders.\n *\n * @remarks\n * FOK orders use makerAmount for both BUY and SELL:\n * - BUY: makerAmount = USDC amount to spend (e.g., 50 = $50 USDC)\n * - SELL: makerAmount = number of shares to sell (e.g., 18.64 shares)\n *\n * takerAmount is always 1 (constant for FOK orders)\n *\n * @param makerAmount - Amount in human-readable format (max 6 decimals)\n * @returns Object with makerAmount (scaled), takerAmount (always 1), and undefined price\n *\n * @internal\n */\n private calculateFOKAmounts(makerAmount: number): {\n makerAmount: number;\n takerAmount: number;\n price: undefined;\n } {\n const DECIMALS = 6;\n\n // Validate makerAmount has max 6 decimal places\n const amountStr = makerAmount.toString();\n const decimalIndex = amountStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = amountStr.length - decimalIndex - 1;\n if (decimalPlaces > DECIMALS) {\n throw new Error(\n `Invalid makerAmount: ${makerAmount}. Can have max ${DECIMALS} decimal places. ` +\n `Try ${makerAmount.toFixed(DECIMALS)} instead.`\n );\n }\n }\n\n const amountFormatted = makerAmount.toFixed(DECIMALS);\n const amountScaled = ethers.parseUnits(amountFormatted, DECIMALS);\n const collateralAmount = Number(amountScaled);\n\n return {\n makerAmount: collateralAmount,\n takerAmount: 1,\n price: undefined,\n };\n }\n\n /**\n * Validates order arguments.\n *\n * @param args - Order arguments to validate\n * @throws Error if validation fails\n *\n * @internal\n */\n private validateOrderArgs(args: OrderArgs): void {\n // Validate tokenId\n if (!args.tokenId || args.tokenId === '0') {\n throw new Error('Invalid tokenId: tokenId is required.');\n }\n\n // Validate taker address format if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new Error(`Invalid taker address: ${args.taker}`);\n }\n\n // Type-specific validation\n if (this.isFOKOrder(args)) {\n // FOK order validation - must have makerAmount\n if (!args.makerAmount) {\n throw new Error('FOK orders require makerAmount');\n }\n if (args.makerAmount <= 0) {\n throw new Error(`Invalid makerAmount: ${args.makerAmount}. Maker amount must be positive.`);\n }\n } else {\n // GTC order validation\n if (args.price == null || args.price < 0 || args.price > 1) {\n throw new Error(`Invalid price: ${args.price}. Price must be between 0 and 1.`);\n }\n\n if (args.size <= 0) {\n throw new Error(`Invalid size: ${args.size}. Size must be positive.`);\n }\n\n // Validate price has max 3 decimals (tick alignment check)\n const priceStr = args.price.toString();\n const decimalIndex = priceStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = priceStr.length - decimalIndex - 1;\n if (decimalPlaces > 3) {\n throw new Error(\n `Invalid price: ${args.price}. Price must have max 3 decimal places (e.g., 0.380, 0.001).`\n );\n }\n }\n }\n }\n}\n","/**\n * EIP-712 order signer for Limitless Exchange.\n * @module orders/signer\n */\n\nimport { ethers } from 'ethers';\nimport type { UnsignedOrder, OrderSigningConfig } from '../types/orders';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * EIP-712 typed data field definition.\n */\ninterface TypedDataField {\n name: string;\n type: string;\n}\n\n/**\n * EIP-712 order signer.\n *\n * @remarks\n * This class handles EIP-712 signing for Limitless Exchange orders.\n * It creates signatures that match the API's verification requirements.\n *\n * Domain: \"Limitless CTF Exchange\"\n * Version: \"1\"\n *\n * @public\n */\nexport class OrderSigner {\n private wallet: ethers.Wallet;\n private logger: ILogger;\n\n /**\n * Creates a new order signer instance.\n *\n * @param wallet - Ethers wallet for signing\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * import { ethers } from 'ethers';\n * import { OrderSigner } from '@limitless-exchange/sdk';\n *\n * const wallet = new ethers.Wallet(privateKey);\n * const signer = new OrderSigner(wallet);\n * ```\n */\n constructor(wallet: ethers.Wallet, logger?: ILogger) {\n this.wallet = wallet;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Signs an order with EIP-712.\n *\n * @param order - Unsigned order to sign\n * @param config - Signing configuration (chainId, contract address, market type)\n * @returns Promise resolving to EIP-712 signature\n *\n * @throws Error if wallet address doesn't match order signer\n * @throws Error if signing fails\n *\n * @example\n * ```typescript\n * const signature = await signer.signOrder(unsignedOrder, {\n * chainId: 8453,\n * contractAddress: '0x...'\n * });\n * ```\n */\n async signOrder(order: UnsignedOrder, config: OrderSigningConfig): Promise<string> {\n this.logger.debug('Signing order with EIP-712', {\n tokenId: order.tokenId,\n side: order.side,\n verifyingContract: config.contractAddress,\n });\n\n // Verify wallet address matches signer\n const walletAddress = await this.wallet.getAddress();\n if (walletAddress.toLowerCase() !== order.signer.toLowerCase()) {\n const error = `Wallet address mismatch! Signing with: ${walletAddress}, but order signer is: ${order.signer}`;\n this.logger.error(error);\n throw new Error(error);\n }\n\n // Get EIP-712 domain\n const domain = this.getDomain(config);\n this.logger.debug('EIP-712 Domain', domain);\n\n // Get EIP-712 types\n const types = this.getTypes();\n\n // Prepare order value for signing (exclude price field)\n const orderValue = {\n salt: order.salt,\n maker: order.maker,\n signer: order.signer,\n taker: order.taker,\n tokenId: order.tokenId,\n makerAmount: order.makerAmount,\n takerAmount: order.takerAmount,\n expiration: order.expiration,\n nonce: order.nonce,\n feeRateBps: order.feeRateBps,\n side: order.side,\n signatureType: order.signatureType,\n };\n\n this.logger.debug('EIP-712 Order Value', orderValue);\n this.logger.debug('Full signing payload', {\n domain,\n types: this.getTypes(),\n value: orderValue,\n });\n try {\n // Sign with EIP-712\n const signature = await this.wallet.signTypedData(domain, types, orderValue);\n this.logger.info('Successfully generated EIP-712 signature', {\n signature: signature.slice(0, 10) + '...',\n });\n return signature;\n } catch (error) {\n this.logger.error('Failed to sign order', error as Error);\n throw error;\n }\n }\n\n /**\n * Gets the EIP-712 domain for signing.\n *\n * @param config - Signing configuration\n * @returns EIP-712 domain object\n *\n * @internal\n */\n private getDomain(config: OrderSigningConfig): {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: string;\n } {\n return {\n name: 'Limitless CTF Exchange',\n version: '1',\n chainId: config.chainId,\n verifyingContract: config.contractAddress,\n };\n }\n\n /**\n * Gets the EIP-712 type definitions.\n *\n * @remarks\n * This matches the order structure expected by the Limitless Exchange\n * smart contracts.\n *\n * @returns EIP-712 types definition\n *\n * @internal\n */\n private getTypes(): Record<string, TypedDataField[]> {\n return {\n Order: [\n { name: 'salt', type: 'uint256' },\n { name: 'maker', type: 'address' },\n { name: 'signer', type: 'address' },\n { name: 'taker', type: 'address' },\n { name: 'tokenId', type: 'uint256' },\n { name: 'makerAmount', type: 'uint256' },\n { name: 'takerAmount', type: 'uint256' },\n { name: 'expiration', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'feeRateBps', type: 'uint256' },\n { name: 'side', type: 'uint8' },\n { name: 'signatureType', type: 'uint8' },\n ],\n };\n }\n}\n","/**\n * Order validation utilities.\n * @module orders/validator\n */\n\nimport { ethers } from 'ethers';\nimport type {\n OrderArgs,\n UnsignedOrder,\n SignedOrder,\n FOKOrderArgs,\n GTCOrderArgs,\n} from '../types/orders';\n\n/**\n * Order validation error class for client-side validation.\n * @public\n */\nexport class OrderValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OrderValidationError';\n }\n}\n\n/**\n * Type guard to check if order arguments are for FOK order.\n */\nfunction isFOKOrder(args: OrderArgs): args is FOKOrderArgs {\n return 'amount' in args;\n}\n\n/**\n * Validates order arguments before building.\n *\n * @param args - Order arguments to validate (FOK or GTC)\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * try {\n * validateOrderArgs(orderArgs);\n * } catch (error) {\n * console.error('Validation failed:', error.message);\n * }\n * ```\n */\nexport function validateOrderArgs(args: OrderArgs): void {\n // Validate tokenId\n if (!args.tokenId) {\n throw new OrderValidationError('TokenId is required');\n }\n\n if (args.tokenId === '0') {\n throw new OrderValidationError('TokenId cannot be zero');\n }\n\n // Validate tokenId format (should be numeric string)\n if (!/^\\d+$/.test(args.tokenId)) {\n throw new OrderValidationError(`Invalid tokenId format: ${args.tokenId}`);\n }\n\n // Validate taker address if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new OrderValidationError(`Invalid taker address: ${args.taker}`);\n }\n\n // Validate expiration if provided\n if (args.expiration !== undefined) {\n if (!/^\\d+$/.test(args.expiration)) {\n throw new OrderValidationError(`Invalid expiration format: ${args.expiration}`);\n }\n }\n\n // Validate nonce if provided\n if (args.nonce !== undefined) {\n if (!Number.isInteger(args.nonce) || args.nonce < 0) {\n throw new OrderValidationError(`Invalid nonce: ${args.nonce}`);\n }\n }\n\n // Type-specific validation\n if (isFOKOrder(args)) {\n // FOK order validation\n if (typeof args.makerAmount !== 'number' || isNaN(args.makerAmount)) {\n throw new OrderValidationError('Amount must be a valid number');\n }\n\n if (args.makerAmount <= 0) {\n throw new OrderValidationError(`Amount must be positive, got: ${args.makerAmount}`);\n }\n\n // Validate max 2 decimal places\n // Convert to string and check decimal places\n const amountStr = args.makerAmount.toString();\n const decimalIndex = amountStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = amountStr.length - decimalIndex - 1;\n if (decimalPlaces > 2) {\n throw new OrderValidationError(\n `Amount must have max 2 decimal places, got: ${args.makerAmount} (${decimalPlaces} decimals)`\n );\n }\n }\n } else {\n // GTC order validation\n if (typeof args.price !== 'number' || isNaN(args.price)) {\n throw new OrderValidationError('Price must be a valid number');\n }\n\n if (args.price < 0 || args.price > 1) {\n throw new OrderValidationError(`Price must be between 0 and 1, got: ${args.price}`);\n }\n\n if (typeof args.size !== 'number' || isNaN(args.size)) {\n throw new OrderValidationError('Size must be a valid number');\n }\n\n if (args.size <= 0) {\n throw new OrderValidationError(`Size must be positive, got: ${args.size}`);\n }\n }\n}\n\n/**\n * Validates an unsigned order.\n *\n * @param order - Unsigned order to validate\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * validateUnsignedOrder(unsignedOrder);\n * ```\n */\nexport function validateUnsignedOrder(order: UnsignedOrder): void {\n // Validate addresses\n if (!ethers.isAddress(order.maker)) {\n throw new OrderValidationError(`Invalid maker address: ${order.maker}`);\n }\n\n if (!ethers.isAddress(order.signer)) {\n throw new OrderValidationError(`Invalid signer address: ${order.signer}`);\n }\n\n if (!ethers.isAddress(order.taker)) {\n throw new OrderValidationError(`Invalid taker address: ${order.taker}`);\n }\n\n // Validate amounts\n if (!order.makerAmount || order.makerAmount === 0) {\n throw new OrderValidationError('MakerAmount must be greater than zero');\n }\n\n if (!order.takerAmount || order.takerAmount === 0) {\n throw new OrderValidationError('TakerAmount must be greater than zero');\n }\n\n // Validate amounts are positive numbers\n if (typeof order.makerAmount !== 'number' || order.makerAmount <= 0) {\n throw new OrderValidationError(`Invalid makerAmount: ${order.makerAmount}`);\n }\n\n if (typeof order.takerAmount !== 'number' || order.takerAmount <= 0) {\n throw new OrderValidationError(`Invalid takerAmount: ${order.takerAmount}`);\n }\n\n if (!/^\\d+$/.test(order.tokenId)) {\n throw new OrderValidationError(`Invalid tokenId format: ${order.tokenId}`);\n }\n\n if (!/^\\d+$/.test(order.expiration)) {\n throw new OrderValidationError(`Invalid expiration format: ${order.expiration}`);\n }\n\n // Validate salt\n if (!Number.isInteger(order.salt) || order.salt <= 0) {\n throw new OrderValidationError(`Invalid salt: ${order.salt}`);\n }\n\n // Validate nonce\n if (!Number.isInteger(order.nonce) || order.nonce < 0) {\n throw new OrderValidationError(`Invalid nonce: ${order.nonce}`);\n }\n\n // Validate feeRateBps\n if (!Number.isInteger(order.feeRateBps) || order.feeRateBps < 0) {\n throw new OrderValidationError(`Invalid feeRateBps: ${order.feeRateBps}`);\n }\n\n // Validate side (0 or 1)\n if (order.side !== 0 && order.side !== 1) {\n throw new OrderValidationError(`Invalid side: ${order.side}. Must be 0 (BUY) or 1 (SELL)`);\n }\n\n // Validate signatureType\n if (!Number.isInteger(order.signatureType) || order.signatureType < 0) {\n throw new OrderValidationError(`Invalid signatureType: ${order.signatureType}`);\n }\n\n // Validate price if present (for GTC orders)\n if (order.price !== undefined) {\n if (typeof order.price !== 'number' || isNaN(order.price)) {\n throw new OrderValidationError('Price must be a valid number');\n }\n\n if (order.price < 0 || order.price > 1) {\n throw new OrderValidationError(`Price must be between 0 and 1, got: ${order.price}`);\n }\n }\n}\n\n/**\n * Validates a signed order.\n *\n * @param order - Signed order to validate\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * validateSignedOrder(signedOrder);\n * ```\n */\nexport function validateSignedOrder(order: SignedOrder): void {\n // Validate unsigned order fields first\n validateUnsignedOrder(order);\n\n // Validate signature\n if (!order.signature) {\n throw new OrderValidationError('Signature is required');\n }\n\n if (!order.signature.startsWith('0x')) {\n throw new OrderValidationError('Signature must start with 0x');\n }\n\n // Signature should be 132 characters (0x + 130 hex chars for 65 bytes)\n if (order.signature.length !== 132) {\n throw new OrderValidationError(\n `Invalid signature length: ${order.signature.length}. Expected 132 characters.`\n );\n }\n\n // Validate hex format\n if (!/^0x[0-9a-fA-F]{130}$/.test(order.signature)) {\n throw new OrderValidationError('Signature must be valid hex string');\n }\n}\n","/**\n * Market data fetcher for Limitless Exchange.\n * @module markets/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport { Market } from '../types/market-class';\nimport type {\n MarketsResponse,\n OrderBook,\n ActiveMarketsParams,\n ActiveMarketsResponse,\n Venue,\n} from '../types/markets';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Market data fetcher for retrieving market information and orderbooks.\n *\n * @remarks\n * This class provides methods to fetch market data, orderbooks, and prices\n * from the Limitless Exchange API.\n *\n * Venue caching: When fetching market data, venue information is automatically\n * cached for efficient order signing. This eliminates redundant API calls when\n * creating orders for the same market.\n *\n * @public\n */\nexport class MarketFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\n private venueCache: Map<string, Venue>;\n\n /**\n * Creates a new market fetcher instance.\n *\n * @param httpClient - HTTP client for API requests\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * const fetcher = new MarketFetcher(httpClient);\n * ```\n */\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n this.venueCache = new Map();\n }\n\n\n /**\n * Gets active markets with query parameters and pagination support.\n *\n * @param params - Query parameters for filtering and pagination\n * @returns Promise resolving to active markets response\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * // Get 8 markets sorted by LP rewards\n * const response = await fetcher.getActiveMarkets({\n * limit: 8,\n * sortBy: 'lp_rewards'\n * });\n * console.log(`Found ${response.data.length} of ${response.totalMarketsCount} markets`);\n *\n * // Get page 2\n * const page2 = await fetcher.getActiveMarkets({\n * limit: 8,\n * page: 2,\n * sortBy: 'ending_soon'\n * });\n * ```\n */\n async getActiveMarkets(params?: ActiveMarketsParams): Promise<ActiveMarketsResponse> {\n const queryParams = new URLSearchParams();\n\n if (params?.limit !== undefined) {\n queryParams.append('limit', params.limit.toString());\n }\n\n if (params?.page !== undefined) {\n queryParams.append('page', params.page.toString());\n }\n\n if (params?.sortBy) {\n queryParams.append('sortBy', params.sortBy);\n }\n\n const queryString = queryParams.toString();\n const endpoint = `/markets/active${queryString ? `?${queryString}` : ''}`;\n\n this.logger.debug('Fetching active markets', { params });\n\n try {\n const response = await this.httpClient.get<any>(endpoint);\n\n // Convert market data to Market instances with httpClient attached\n const markets = response.data.map((marketData: any) => new Market(marketData, this.httpClient));\n\n const result = {\n data: markets,\n totalMarketsCount: response.totalMarketsCount,\n };\n\n this.logger.info('Active markets fetched successfully', {\n count: markets.length,\n total: response.totalMarketsCount,\n sortBy: params?.sortBy,\n page: params?.page,\n });\n\n return result;\n } catch (error) {\n this.logger.error('Failed to fetch active markets', error as Error, { params });\n throw error;\n }\n }\n\n /**\n * Gets a single market by slug.\n *\n * @remarks\n * Automatically caches venue information for efficient order signing.\n * Always call this method before creating orders to ensure venue data\n * is available and avoid additional API requests.\n *\n * @param slug - Market slug identifier\n * @returns Promise resolving to market details\n * @throws Error if API request fails or market not found\n *\n * @example\n * ```typescript\n * // Get market\n * const market = await fetcher.getMarket('bitcoin-price-2024');\n * console.log(`Market: ${market.title}`);\n *\n * // Fluent API - get user orders for this market (clean!)\n * const orders = await market.getUserOrders();\n * console.log(`You have ${orders.length} orders`);\n *\n * // Venue is now cached for order signing\n * await orderClient.createOrder({\n * marketSlug: 'bitcoin-price-2024',\n * ...\n * });\n * ```\n */\n async getMarket(slug: string): Promise<Market> {\n this.logger.debug('Fetching market', { slug });\n\n try {\n const response = await this.httpClient.get<any>(`/markets/${slug}`);\n\n // Create Market instance with httpClient attached for fluent API\n const market = new Market(response, this.httpClient);\n\n if (market.venue) {\n this.venueCache.set(slug, market.venue);\n this.logger.debug('Venue cached for order signing', {\n slug,\n exchange: market.venue.exchange,\n adapter: market.venue.adapter,\n cacheSize: this.venueCache.size,\n });\n } else {\n this.logger.warn('Market has no venue data', { slug });\n }\n\n this.logger.info('Market fetched successfully', {\n slug,\n title: market.title,\n });\n return market;\n } catch (error) {\n this.logger.error('Failed to fetch market', error as Error, { slug });\n throw error;\n }\n }\n\n /**\n * Gets cached venue information for a market.\n *\n * @remarks\n * Returns venue data previously cached by getMarket() call.\n * Used internally by OrderClient for efficient order signing.\n *\n * @param slug - Market slug identifier\n * @returns Cached venue information, or undefined if not in cache\n *\n * @example\n * ```typescript\n * const venue = fetcher.getVenue('bitcoin-price-2024');\n * if (venue) {\n * console.log(`Exchange: ${venue.exchange}`);\n * }\n * ```\n */\n getVenue(slug: string): Venue | undefined {\n const venue = this.venueCache.get(slug);\n\n if (venue) {\n this.logger.debug('Venue cache hit', {\n slug,\n exchange: venue.exchange,\n });\n } else {\n this.logger.debug('Venue cache miss', { slug });\n }\n\n return venue;\n }\n\n /**\n * Gets the orderbook for a CLOB market.\n *\n * @param slug - Market slug identifier\n * @returns Promise resolving to orderbook data\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const orderbook = await fetcher.getOrderBook('bitcoin-price-2024');\n * console.log(`Bids: ${orderbook.bids.length}, Asks: ${orderbook.asks.length}`);\n * ```\n */\n async getOrderBook(slug: string): Promise<OrderBook> {\n this.logger.debug('Fetching orderbook', { slug });\n\n try {\n const orderbook = await this.httpClient.get<OrderBook>(\n `/markets/${slug}/orderbook`\n );\n\n this.logger.info('Orderbook fetched successfully', {\n slug,\n bids: orderbook.bids.length,\n asks: orderbook.asks.length,\n tokenId: orderbook.tokenId,\n });\n return orderbook;\n } catch (error) {\n this.logger.error('Failed to fetch orderbook', error as Error, { slug });\n throw error;\n }\n }\n\n}\n","/**\n * Portfolio data fetcher for Limitless Exchange.\n * @module portfolio/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport type {\n PortfolioPositionsResponse,\n CLOBPosition,\n AMMPosition,\n Position,\n PortfolioSummary,\n HistoryResponse,\n} from '../types/portfolio';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Portfolio data fetcher for retrieving user positions and portfolio information.\n *\n * @remarks\n * This class provides methods to fetch user positions and calculate portfolio statistics\n * from the Limitless Exchange API. Requires an authenticated HttpClient.\n *\n * @public\n */\nexport class PortfolioFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\n\n /**\n * Creates a new portfolio fetcher instance.\n *\n * @param httpClient - Authenticated HTTP client for API requests\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * // Create authenticated client\n * const httpClient = new HttpClient({ baseURL: API_URL });\n * await authenticator.authenticate({ client: 'eoa' });\n *\n * // Create portfolio fetcher\n * const portfolioFetcher = new PortfolioFetcher(httpClient);\n * ```\n */\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets user profile for a specific wallet address.\n *\n * @remarks\n * Returns user profile data including user ID and fee rate.\n * Used internally by OrderClient to fetch user data.\n *\n * @param address - Wallet address to fetch profile for\n * @returns Promise resolving to user profile data\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const profile = await portfolioFetcher.getProfile('0x1234...');\n * console.log(`User ID: ${profile.id}`);\n * console.log(`Account: ${profile.account}`);\n * console.log(`Fee Rate: ${profile.rank?.feeRateBps}`);\n * ```\n */\n async getProfile(address: string): Promise<any> {\n this.logger.debug('Fetching user profile', { address });\n\n try {\n const response = await this.httpClient.get<any>(`/profiles/${address}`);\n\n this.logger.info('User profile fetched successfully', { address });\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch user profile', error as Error, { address });\n throw error;\n }\n }\n\n /**\n * Gets raw portfolio positions response from API.\n *\n * @returns Promise resolving to portfolio positions response with CLOB and AMM positions\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const response = await portfolioFetcher.getPositions();\n * console.log(`CLOB positions: ${response.clob.length}`);\n * console.log(`AMM positions: ${response.amm.length}`);\n * console.log(`Total points: ${response.accumulativePoints}`);\n * ```\n */\n async getPositions(): Promise<PortfolioPositionsResponse> {\n this.logger.debug('Fetching user positions');\n\n try {\n const response =\n await this.httpClient.get<PortfolioPositionsResponse>('/portfolio/positions');\n\n this.logger.info('Positions fetched successfully', {\n clobCount: response.clob?.length || 0,\n ammCount: response.amm?.length || 0,\n });\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch positions', error as Error);\n throw error;\n }\n }\n\n /**\n * Gets CLOB positions only.\n *\n * @returns Promise resolving to array of CLOB positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const clobPositions = await portfolioFetcher.getCLOBPositions();\n * clobPositions.forEach(pos => {\n * console.log(`${pos.market.title}: YES ${pos.positions.yes.unrealizedPnl} P&L`);\n * });\n * ```\n */\n async getCLOBPositions(): Promise<CLOBPosition[]> {\n const response = await this.getPositions();\n return response.clob || [];\n }\n\n /**\n * Gets AMM positions only.\n *\n * @returns Promise resolving to array of AMM positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const ammPositions = await portfolioFetcher.getAMMPositions();\n * ammPositions.forEach(pos => {\n * console.log(`${pos.market.title}: ${pos.unrealizedPnl} P&L`);\n * });\n * ```\n */\n async getAMMPositions(): Promise<AMMPosition[]> {\n const response = await this.getPositions();\n return response.amm || [];\n }\n\n /**\n * Gets paginated history of user actions.\n *\n * Includes AMM trades, CLOB trades, Negrisk trades & conversions.\n *\n * @param page - Page number (starts at 1)\n * @param limit - Number of items per page\n * @returns Promise resolving to paginated history response\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * // Get first page\n * const response = await portfolioFetcher.getUserHistory(1, 20);\n * console.log(`Found ${response.data.length} of ${response.totalCount} entries`);\n *\n * // Process history entries\n * for (const entry of response.data) {\n * console.log(`Type: ${entry.type}`);\n * console.log(`Market: ${entry.marketSlug}`);\n * }\n *\n * // Get next page\n * const page2 = await portfolioFetcher.getUserHistory(2, 20);\n * ```\n */\n async getUserHistory(page: number = 1, limit: number = 10): Promise<HistoryResponse> {\n this.logger.debug('Fetching user history', { page, limit });\n\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n limit: limit.toString(),\n });\n\n const response = await this.httpClient.get<HistoryResponse>(\n `/portfolio/history?${params.toString()}`\n );\n\n this.logger.info('User history fetched successfully');\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch user history', error as Error, { page, limit });\n throw error;\n }\n }\n}\n","/**\n * Order client for managing orders on Limitless Exchange.\n * @module orders/client\n */\n\nimport type { HttpClient } from '../api/http';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\nimport type {\n NewOrderPayload,\n OrderResponse,\n OrderArgs,\n UnsignedOrder,\n OrderSigningConfig,\n} from '../types/orders';\nimport { OrderType } from '../types/orders';\nimport { OrderBuilder } from './builder';\nimport { OrderSigner } from './signer';\nimport type { ethers } from 'ethers';\nimport type { UserData } from '../types/auth';\nimport { ZERO_ADDRESS } from '../utils/constants';\nimport { MarketFetcher } from '../markets/fetcher';\nimport { PortfolioFetcher } from '../portfolio/fetcher';\n\n/**\n * Configuration for the order client.\n *\n * @remarks\n * The order client auto-configures signing based on venue data from the API.\n * User data (userId, feeRateBps) is automatically fetched from the profile API\n * on first order creation and cached for subsequent orders.\n *\n * Performance tip: Provide a shared marketFetcher instance to enable venue caching\n * across market fetches and order creation, avoiding redundant API calls.\n *\n * @public\n */\nexport interface OrderClientConfig {\n /**\n * HTTP client for API requests (must have API key configured)\n */\n httpClient: HttpClient;\n\n /**\n * Wallet for signing orders with EIP-712\n */\n wallet: ethers.Wallet;\n\n /**\n * Custom signing configuration (optional)\n *\n * @remarks\n * If not provided, SDK will auto-configure from venue data.\n * Useful for custom deployments or testing.\n */\n signingConfig?: OrderSigningConfig;\n\n /**\n * Shared MarketFetcher instance for venue caching (optional)\n *\n * @remarks\n * When provided, enables efficient venue caching across market fetches and order creation.\n * If not provided, OrderClient creates its own internal MarketFetcher instance.\n *\n * Best practice: Share the same MarketFetcher instance between market operations\n * and order creation for optimal performance.\n *\n * @example\n * ```typescript\n * const marketFetcher = new MarketFetcher(httpClient);\n * const orderClient = new OrderClient({\n * httpClient,\n * wallet,\n * marketFetcher // Shared instance\n * });\n *\n * // Venue is cached\n * await marketFetcher.getMarket('bitcoin-2024');\n *\n * // Uses cached venue, no extra API call\n * await orderClient.createOrder({ marketSlug: 'bitcoin-2024', ... });\n * ```\n */\n marketFetcher?: MarketFetcher;\n\n /**\n * Optional logger\n */\n logger?: ILogger;\n}\n\n/**\n * Order client for creating and managing orders.\n *\n * @remarks\n * This class provides high-level methods for order operations,\n * abstracting away HTTP details and order signing complexity.\n *\n * User data (userId, feeRateBps) is automatically fetched from profile API\n * on first order creation and cached for subsequent orders.\n *\n * Uses dynamic venue addressing for EIP-712 order signing. For best performance,\n * always call marketFetcher.getMarket() before creating orders to cache venue data.\n *\n * @example\n * ```typescript\n * import { ethers } from 'ethers';\n *\n * const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);\n * const orderClient = new OrderClient({\n * httpClient, // Must have API key configured\n * wallet, // For EIP-712 signing\n * });\n *\n * // User data automatically fetched on first order\n * const order = await orderClient.createOrder({\n * tokenId: '123...',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'market-slug'\n * });\n * ```\n *\n * @public\n */\nexport class OrderClient {\n private httpClient: HttpClient;\n private wallet: ethers.Wallet;\n private orderBuilder?: OrderBuilder;\n private orderSigner: OrderSigner;\n private marketFetcher: MarketFetcher;\n private cachedUserData?: UserData;\n private signingConfig: OrderSigningConfig;\n private logger: ILogger;\n\n /**\n * Creates a new order client instance.\n *\n * @param config - Order client configuration\n */\n constructor(config: OrderClientConfig) {\n this.httpClient = config.httpClient;\n this.wallet = config.wallet;\n this.logger = config.logger || new NoOpLogger();\n\n this.orderSigner = new OrderSigner(config.wallet, this.logger);\n\n this.marketFetcher = config.marketFetcher || new MarketFetcher(config.httpClient, this.logger);\n\n // Configure signing: use provided config or auto-configure\n if (config.signingConfig) {\n // Use custom signing configuration\n this.signingConfig = config.signingConfig;\n } else {\n // Auto-configure base settings\n const chainId = parseInt(process.env.CHAIN_ID || '8453'); // Base mainnet default\n\n // Note: contractAddress is a placeholder here and will be dynamically replaced\n // with venue.exchange in createOrder(). The actual contract address comes from\n // the venue system (market.venue.exchange).\n const contractAddress = ZERO_ADDRESS;\n\n this.signingConfig = {\n chainId,\n contractAddress,\n };\n\n this.logger.info('Auto-configured signing (contract address from venue)', {\n chainId,\n });\n }\n }\n\n /**\n * Ensures user data is loaded and cached.\n * Fetches from profile API on first call, then caches for subsequent calls.\n *\n * @returns Promise resolving to cached user data\n * @internal\n */\n private async ensureUserData(): Promise<UserData> {\n if (!this.cachedUserData) {\n this.logger.info('Fetching user profile for order client initialization...', {\n walletAddress: this.wallet.address,\n });\n\n const portfolioFetcher = new PortfolioFetcher(this.httpClient);\n const profile = await portfolioFetcher.getProfile(this.wallet.address);\n\n this.cachedUserData = {\n userId: profile.id,\n feeRateBps: profile.rank?.feeRateBps || 300,\n };\n\n this.orderBuilder = new OrderBuilder(\n this.wallet.address,\n this.cachedUserData.feeRateBps,\n 0.001\n );\n\n this.logger.info('Order Client initialized', {\n walletAddress: profile.account,\n userId: this.cachedUserData.userId,\n feeRate: `${this.cachedUserData.feeRateBps / 100}%`,\n });\n }\n\n return this.cachedUserData;\n }\n\n /**\n * Creates and submits a new order.\n *\n * @remarks\n * This method handles the complete order creation flow:\n * 1. Resolve venue address (from cache or API)\n * 2. Build unsigned order\n * 3. Sign with EIP-712 using venue.exchange as verifyingContract\n * 4. Submit to API\n *\n * Performance best practice: Always call marketFetcher.getMarket(marketSlug)\n * before createOrder() to cache venue data and avoid additional API requests.\n *\n * @param params - Order parameters\n * @returns Promise resolving to order response\n *\n * @throws Error if order creation fails or venue not found\n *\n * @example\n * ```typescript\n * // Best practice: fetch market first to cache venue\n * const market = await marketFetcher.getMarket('bitcoin-2024');\n *\n * const order = await orderClient.createOrder({\n * tokenId: market.tokens.yes,\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'bitcoin-2024'\n * });\n *\n * console.log(`Order created: ${order.order.id}`);\n * ```\n */\n async createOrder(\n params: OrderArgs & {\n orderType: OrderType;\n marketSlug: string;\n }\n ): Promise<OrderResponse> {\n // Ensure user data is loaded (lazy loading with cache)\n const userData = await this.ensureUserData();\n\n this.logger.info('Creating order', {\n side: params.side,\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n });\n\n let venue = this.marketFetcher.getVenue(params.marketSlug);\n\n if (!venue) {\n this.logger.warn(\n 'Venue not cached, fetching market details. ' +\n 'For better performance, call marketFetcher.getMarket() before createOrder().',\n { marketSlug: params.marketSlug }\n );\n\n const market = await this.marketFetcher.getMarket(params.marketSlug);\n\n if (!market.venue) {\n throw new Error(\n `Market ${params.marketSlug} does not have venue information. ` +\n 'Venue data is required for order signing.'\n );\n }\n\n venue = market.venue;\n }\n\n const dynamicSigningConfig: OrderSigningConfig = {\n ...this.signingConfig,\n contractAddress: venue.exchange,\n };\n\n this.logger.debug('Using venue for order signing', {\n marketSlug: params.marketSlug,\n exchange: venue.exchange,\n adapter: venue.adapter,\n });\n\n const unsignedOrder = this.orderBuilder!.buildOrder(params);\n\n this.logger.debug('Built unsigned order', {\n salt: unsignedOrder.salt,\n makerAmount: unsignedOrder.makerAmount,\n takerAmount: unsignedOrder.takerAmount,\n });\n\n const signature = await this.orderSigner.signOrder(unsignedOrder, dynamicSigningConfig);\n\n // Step 3: Prepare payload for API\n const payload: NewOrderPayload = {\n order: {\n ...unsignedOrder,\n signature,\n },\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n ownerId: userData.userId,\n };\n\n // Step 4: Submit to API\n this.logger.debug('Submitting order to API', payload);\n const apiResponse = await this.httpClient.post<any>('/orders', payload);\n\n this.logger.info('Order created successfully', {\n orderId: apiResponse.order.id,\n });\n\n // Step 5: Transform API response to clean DTO\n return this.transformOrderResponse(apiResponse);\n }\n\n /**\n * Transforms raw API response to clean OrderResponse DTO.\n *\n * @param apiResponse - Raw API response with nested objects\n * @returns Clean OrderResponse with only essential fields\n *\n * @internal\n */\n private transformOrderResponse(apiResponse: any): OrderResponse {\n const cleanOrder: OrderResponse = {\n order: {\n id: apiResponse.order.id,\n createdAt: apiResponse.order.createdAt,\n makerAmount: apiResponse.order.makerAmount,\n takerAmount: apiResponse.order.takerAmount,\n expiration: apiResponse.order.expiration,\n signatureType: apiResponse.order.signatureType,\n salt: apiResponse.order.salt,\n maker: apiResponse.order.maker,\n signer: apiResponse.order.signer,\n taker: apiResponse.order.taker,\n tokenId: apiResponse.order.tokenId,\n side: apiResponse.order.side,\n feeRateBps: apiResponse.order.feeRateBps,\n nonce: apiResponse.order.nonce,\n signature: apiResponse.order.signature,\n orderType: apiResponse.order.orderType,\n price: apiResponse.order.price,\n marketId: apiResponse.order.marketId,\n },\n };\n\n // Add maker matches if present (FOK or partial GTC fills)\n if (apiResponse.makerMatches && apiResponse.makerMatches.length > 0) {\n cleanOrder.makerMatches = apiResponse.makerMatches.map((match: any) => ({\n id: match.id,\n createdAt: match.createdAt,\n matchedSize: match.matchedSize,\n orderId: match.orderId,\n }));\n }\n\n return cleanOrder;\n }\n\n /**\n * Cancels an existing order by ID.\n *\n * @param orderId - Order ID to cancel\n * @returns Promise resolving to cancellation message\n *\n * @throws Error if cancellation fails\n *\n * @example\n * ```typescript\n * const result = await orderClient.cancel('order-id-123');\n * console.log(result.message); // \"Order canceled successfully\"\n * ```\n */\n async cancel(orderId: string): Promise<{ message: string }> {\n this.logger.info('Cancelling order', { orderId });\n\n const response = await this.httpClient.delete<{ message: string }>(`/orders/${orderId}`);\n\n this.logger.info('Order cancellation response', {\n orderId,\n message: response.message,\n });\n\n return response;\n }\n\n /**\n * Cancels all orders for a specific market.\n *\n * @param marketSlug - Market slug to cancel all orders for\n * @returns Promise resolving to cancellation message\n *\n * @throws Error if cancellation fails\n *\n * @example\n * ```typescript\n * const result = await orderClient.cancelAll('market-slug-123');\n * console.log(result.message); // \"Orders canceled successfully\"\n * ```\n */\n async cancelAll(marketSlug: string): Promise<{ message: string }> {\n this.logger.info('Cancelling all orders for market', { marketSlug });\n\n const response = await this.httpClient.delete<{ message: string }>(`/orders/all/${marketSlug}`);\n\n this.logger.info('All orders cancellation response', {\n marketSlug,\n message: response.message,\n });\n\n return response;\n }\n\n /**\n * Builds an unsigned order without submitting.\n *\n * @remarks\n * Useful for advanced use cases where you need the unsigned order\n * before signing and submission.\n *\n * @param params - Order parameters\n * @returns Promise resolving to unsigned order\n *\n * @example\n * ```typescript\n * const unsignedOrder = await orderClient.buildUnsignedOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY\n * });\n * ```\n */\n async buildUnsignedOrder(params: OrderArgs): Promise<UnsignedOrder> {\n // Ensure user data is loaded for order builder\n await this.ensureUserData();\n return this.orderBuilder!.buildOrder(params);\n }\n\n /**\n * Signs an unsigned order without submitting.\n *\n * @remarks\n * Useful for advanced use cases where you need to inspect\n * the signature before submission.\n *\n * @param order - Unsigned order to sign\n * @returns Promise resolving to signature\n *\n * @example\n * ```typescript\n * const signature = await orderClient.signOrder(unsignedOrder);\n * ```\n */\n async signOrder(order: UnsignedOrder): Promise<string> {\n return await this.orderSigner.signOrder(order, this.signingConfig);\n }\n\n /**\n * Gets the wallet address.\n *\n * @returns Ethereum address of the wallet\n *\n * @example\n * ```typescript\n * const address = orderClient.walletAddress;\n * console.log(`Wallet: ${address}`);\n * ```\n */\n get walletAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Gets the owner ID (user ID from profile).\n *\n * @returns Owner ID from user profile, or undefined if not yet loaded\n *\n * @example\n * ```typescript\n * const ownerId = orderClient.ownerId;\n * if (ownerId) {\n * console.log(`Owner ID: ${ownerId}`);\n * }\n * ```\n */\n get ownerId(): number | undefined {\n return this.cachedUserData?.userId;\n }\n}\n","/**\n * WebSocket client for real-time data streaming.\n * @module websocket/client\n */\n\nimport { io, Socket } from 'socket.io-client';\nimport { DEFAULT_WS_URL } from '../utils/constants';\nimport {\n WebSocketState,\n type WebSocketConfig,\n type WebSocketEvents,\n type SubscriptionChannel,\n type SubscriptionOptions,\n} from '../types/websocket';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * WebSocket client for real-time data streaming from Limitless Exchange.\n *\n * @remarks\n * This client uses Socket.IO to connect to the WebSocket server and provides\n * typed event subscriptions for orderbook, trades, orders, and market data.\n *\n * **Public Subscriptions** (no authentication required):\n * - Market prices (AMM)\n * - Orderbook updates (CLOB)\n *\n * **Authenticated Subscriptions** (require API key):\n * - User positions\n * - User transactions\n *\n * @example\n * ```typescript\n * // Public subscription (no API key needed)\n * const wsClient = new WebSocketClient({\n * autoReconnect: true,\n * });\n *\n * await wsClient.connect();\n * await wsClient.subscribe('subscribe_market_prices', {\n * marketSlugs: ['market-123']\n * });\n *\n * // Authenticated subscription (API key required)\n * const wsClientAuth = new WebSocketClient({\n * apiKey: process.env.LIMITLESS_API_KEY,\n * autoReconnect: true,\n * });\n *\n * await wsClientAuth.connect();\n * await wsClientAuth.subscribe('subscribe_positions', {\n * marketSlugs: ['market-123']\n * });\n * ```\n *\n * @public\n */\nexport class WebSocketClient {\n private socket: Socket | null = null;\n private config: Required<WebSocketConfig>;\n private logger: ILogger;\n private state: WebSocketState = WebSocketState.DISCONNECTED;\n private reconnectAttempts = 0;\n private subscriptions: Map<string, SubscriptionOptions> = new Map();\n private pendingListeners: Array<{ event: string; handler: any }> = [];\n\n /**\n * Creates a new WebSocket client.\n *\n * @param config - WebSocket configuration\n * @param logger - Optional logger for debugging\n */\n constructor(config: WebSocketConfig = {}, logger?: ILogger) {\n this.config = {\n url: config.url || DEFAULT_WS_URL,\n apiKey: config.apiKey || process.env.LIMITLESS_API_KEY || '',\n autoReconnect: config.autoReconnect ?? true,\n reconnectDelay: config.reconnectDelay || 1000,\n maxReconnectAttempts: config.maxReconnectAttempts || Infinity,\n timeout: config.timeout || 10000,\n };\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets current connection state.\n *\n * @returns Current WebSocket state\n */\n getState(): WebSocketState {\n return this.state;\n }\n\n /**\n * Checks if client is connected.\n *\n * @returns True if connected\n */\n isConnected(): boolean {\n return this.state === WebSocketState.CONNECTED && this.socket?.connected === true;\n }\n\n /**\n * Sets the API key for authentication.\n *\n * @param apiKey - API key value\n *\n * @remarks\n * API key is required for authenticated subscriptions (positions, transactions).\n * If already connected, this will trigger a reconnection with the new API key.\n */\n setApiKey(apiKey: string): void {\n this.config.apiKey = apiKey;\n\n // If already connected, reconnect with new auth\n if (this.socket?.connected) {\n this.logger.info('API key updated, reconnecting...');\n // Schedule async reconnection without blocking\n this.reconnectWithNewAuth();\n }\n }\n\n /**\n * Reconnects with new authentication credentials.\n * @internal\n */\n private async reconnectWithNewAuth(): Promise<void> {\n await this.disconnect();\n await this.connect();\n }\n\n /**\n * Connects to the WebSocket server.\n *\n * @returns Promise that resolves when connected\n * @throws Error if connection fails\n *\n * @example\n * ```typescript\n * await wsClient.connect();\n * console.log('Connected!');\n * ```\n */\n async connect(): Promise<void> {\n // Fix: Prevent race condition by checking CONNECTING state\n if (this.socket?.connected || this.state === WebSocketState.CONNECTING) {\n this.logger.info('Already connected or connecting');\n return;\n }\n\n this.logger.info('Connecting to WebSocket', { url: this.config.url });\n this.state = WebSocketState.CONNECTING;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout after ${this.config.timeout}ms`));\n }, this.config.timeout);\n\n // Create Socket.IO connection to /markets namespace\n // API key is sent via X-API-Key header for authenticated subscriptions\n const wsUrl = this.config.url;\n\n const socketOptions: any = {\n transports: ['websocket'], // Use WebSocket transport only\n reconnection: this.config.autoReconnect,\n reconnectionDelay: this.config.reconnectDelay,\n reconnectionDelayMax: Math.min(this.config.reconnectDelay * 32, 60000), // Max 60s\n reconnectionAttempts:\n this.config.maxReconnectAttempts === Infinity ? 0 : this.config.maxReconnectAttempts, // 0 = infinite\n randomizationFactor: 0.2, // Add jitter to prevent thundering herd\n timeout: this.config.timeout,\n };\n\n // Add API key to headers if provided\n // Required for authenticated subscriptions (positions, transactions)\n if (this.config.apiKey) {\n socketOptions.extraHeaders = {\n 'X-API-Key': this.config.apiKey,\n };\n }\n\n // Connect to base URL with /markets namespace\n this.socket = io(wsUrl + '/markets', socketOptions);\n\n // Attach any pending listeners that were added before connect()\n this.attachPendingListeners();\n\n // Setup event handlers\n this.setupEventHandlers();\n\n // Handle connection\n this.socket.once('connect', () => {\n clearTimeout(timeout);\n this.state = WebSocketState.CONNECTED;\n this.reconnectAttempts = 0;\n this.logger.info('WebSocket connected');\n\n // Re-subscribe to all previous subscriptions\n this.resubscribeAll();\n\n resolve();\n });\n\n // Handle connection error\n this.socket.once('connect_error', (error) => {\n clearTimeout(timeout);\n this.state = WebSocketState.ERROR;\n this.logger.error('WebSocket connection error', error);\n reject(error);\n });\n });\n }\n\n /**\n * Disconnects from the WebSocket server.\n *\n * @returns Promise that resolves when disconnected\n *\n * @example\n * ```typescript\n * await wsClient.disconnect();\n * ```\n */\n async disconnect(): Promise<void> {\n if (!this.socket) {\n return;\n }\n\n this.logger.info('Disconnecting from WebSocket');\n this.socket.disconnect();\n this.socket = null;\n this.state = WebSocketState.DISCONNECTED;\n this.subscriptions.clear();\n }\n\n /**\n * Subscribes to a channel.\n *\n * @param channel - Channel to subscribe to\n * @param options - Subscription options\n * @returns Promise that resolves immediately (kept async for API compatibility)\n * @throws Error if not connected\n *\n * @example\n * ```typescript\n * // Subscribe to orderbook for a specific market\n * await wsClient.subscribe('orderbook', { marketSlugs: ['market-123'] });\n *\n * // Subscribe to all trades\n * await wsClient.subscribe('trades');\n *\n * // Subscribe to your orders\n * await wsClient.subscribe('orders');\n * ```\n */\n async subscribe(channel: SubscriptionChannel, options: SubscriptionOptions = {}): Promise<void> {\n if (!this.isConnected()) {\n throw new Error('WebSocket not connected. Call connect() first.');\n }\n\n // Check if API key is required for authenticated channels\n const authenticatedChannels: SubscriptionChannel[] = [\n 'subscribe_positions',\n 'subscribe_transactions',\n ];\n if (authenticatedChannels.includes(channel) && !this.config.apiKey) {\n throw new Error(\n `API key is required for '${channel}' subscription. ` +\n 'Please provide an API key in the constructor or set LIMITLESS_API_KEY environment variable. ' +\n 'You can generate an API key at https://limitless.exchange'\n );\n }\n\n const subscriptionKey = this.getSubscriptionKey(channel, options);\n this.subscriptions.set(subscriptionKey, options);\n\n this.logger.info('Subscribing to channel', { channel, options });\n\n // Pass channel and options as-is to the server - no transformation\n // Note: Server returns Promise<void>, so no acknowledgment callback is used\n // This is fire-and-forget to avoid timeout issues when server doesn't send ACK\n this.socket!.emit(channel, options);\n this.logger.info('Subscription request sent', { channel, options });\n }\n\n /**\n * Unsubscribes from a channel.\n *\n * @param channel - Channel to unsubscribe from\n * @param options - Subscription options (must match subscribe call)\n * @returns Promise that resolves when unsubscribed\n * @throws Error if not connected or unsubscribe fails\n *\n * @example\n * ```typescript\n * await wsClient.unsubscribe('orderbook', { marketSlugs: ['market-123'] });\n * ```\n */\n async unsubscribe(\n channel: SubscriptionChannel,\n options: SubscriptionOptions = {}\n ): Promise<void> {\n if (!this.isConnected()) {\n throw new Error('WebSocket not connected');\n }\n\n const subscriptionKey = this.getSubscriptionKey(channel, options);\n this.subscriptions.delete(subscriptionKey);\n\n this.logger.info('Unsubscribing from channel', { channel, options });\n\n try {\n // Emit unsubscribe event with acknowledgment (waits for server response)\n const unsubscribeData = { channel, ...options };\n const response = await this.socket!.timeout(5000).emitWithAck('unsubscribe', unsubscribeData);\n\n // Check for errors in response\n if (response && typeof response === 'object' && 'error' in response) {\n const errorMsg = (response as any).error;\n this.logger.error('Unsubscribe failed', new Error(errorMsg), { error: errorMsg });\n throw new Error(`Unsubscribe failed: ${errorMsg}`);\n }\n\n this.logger.info('Unsubscribed successfully', { channel, options });\n } catch (error) {\n this.logger.error('Unsubscribe error', error as Error, { channel });\n throw error;\n }\n }\n\n /**\n * Registers an event listener.\n *\n * @param event - Event name\n * @param handler - Event handler\n * @returns This client for chaining\n *\n * @example\n * ```typescript\n * wsClient\n * .on('orderbook', (data) => console.log('Orderbook:', data))\n * .on('trade', (data) => console.log('Trade:', data))\n * .on('error', (error) => console.error('Error:', error));\n * ```\n */\n on<K extends keyof WebSocketEvents>(event: K, handler: WebSocketEvents[K]): this {\n if (!this.socket) {\n // Store listener to be attached when socket is created\n this.pendingListeners.push({ event: event as string, handler });\n return this;\n }\n\n // Pass raw event names, no transformation\n this.socket.on(event as string, handler as any);\n return this;\n }\n\n /**\n * Registers a one-time event listener.\n *\n * @param event - Event name\n * @param handler - Event handler\n * @returns This client for chaining\n */\n once<K extends keyof WebSocketEvents>(event: K, handler: WebSocketEvents[K]): this {\n if (!this.socket) {\n throw new Error('WebSocket not initialized. Call connect() first.');\n }\n\n // Pass raw event names, no transformation\n this.socket.once(event as string, handler as any);\n return this;\n }\n\n /**\n * Removes an event listener.\n *\n * @param event - Event name\n * @param handler - Event handler to remove (if undefined, removes all handlers for event)\n * @returns This client for chaining\n *\n * @example\n * ```typescript\n * // Remove specific handler\n * wsClient.off('orderbookUpdate', myHandler);\n *\n * // Remove all handlers for event\n * wsClient.off('orderbookUpdate');\n * ```\n */\n off<K extends keyof WebSocketEvents>(event: K, handler?: WebSocketEvents[K]): this {\n if (!this.socket) {\n return this;\n }\n\n if (handler === undefined) {\n // Remove all handlers for event\n this.socket.removeAllListeners(event as string);\n } else {\n // Remove specific handler\n this.socket.off(event as string, handler as any);\n }\n\n return this;\n }\n\n /**\n * Attach any pending event listeners that were added before connect().\n * @internal\n */\n private attachPendingListeners(): void {\n if (!this.socket || this.pendingListeners.length === 0) {\n return;\n }\n\n for (const { event, handler } of this.pendingListeners) {\n // Pass event names as-is, no transformation\n this.socket.on(event, handler);\n }\n\n // Clear pending listeners\n this.pendingListeners = [];\n }\n\n /**\n * Setup internal event handlers for connection management.\n * @internal\n */\n private setupEventHandlers(): void {\n if (!this.socket) {\n return;\n }\n\n // Connection events\n this.socket.on('connect', () => {\n this.state = WebSocketState.CONNECTED;\n this.reconnectAttempts = 0;\n this.logger.info('WebSocket connected');\n });\n\n this.socket.on('disconnect', (reason) => {\n this.state = WebSocketState.DISCONNECTED;\n this.logger.info('WebSocket disconnected', { reason });\n });\n\n this.socket.on('error', (error) => {\n this.state = WebSocketState.ERROR;\n this.logger.error('WebSocket error', error);\n });\n\n // Reconnection events\n this.socket.io.on('reconnect_attempt', (attempt) => {\n this.state = WebSocketState.RECONNECTING;\n this.reconnectAttempts = attempt;\n this.logger.info('Reconnecting...', { attempt });\n });\n\n this.socket.io.on('reconnect', (attempt) => {\n this.state = WebSocketState.CONNECTED;\n this.logger.info('Reconnected', { attempts: attempt });\n this.resubscribeAll();\n });\n\n this.socket.io.on('reconnect_error', (error) => {\n this.logger.error('Reconnection error', error);\n });\n\n this.socket.io.on('reconnect_failed', () => {\n this.state = WebSocketState.ERROR;\n this.logger.error('Reconnection failed');\n });\n }\n\n /**\n * Re-subscribes to all previous subscriptions after reconnection.\n * @internal\n */\n private async resubscribeAll(): Promise<void> {\n if (this.subscriptions.size === 0) {\n return;\n }\n\n this.logger.info('Re-subscribing to channels', {\n count: this.subscriptions.size,\n });\n\n for (const [key, options] of this.subscriptions.entries()) {\n const channel = this.getChannelFromKey(key);\n try {\n await this.subscribe(channel, options);\n } catch (error) {\n this.logger.error('Failed to re-subscribe', error as Error, { channel, options });\n }\n }\n }\n\n /**\n * Creates a unique subscription key.\n * @internal\n */\n private getSubscriptionKey(channel: SubscriptionChannel, options: SubscriptionOptions): string {\n return `${channel}:${options.marketSlug || 'global'}`;\n }\n\n /**\n * Extracts channel from subscription key.\n * @internal\n */\n private getChannelFromKey(key: string): SubscriptionChannel {\n return key.split(':')[0] as SubscriptionChannel;\n }\n}\n"],"mappings":"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","names":["Side","OrderType","SignatureType","WebSocketState","ZERO_ADDRESS","ethers"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/api-tokens.ts","../src/types/logger.ts","../src/types/orders.ts","../src/types/websocket.ts","../src/types/market-class.ts","../src/api/http.ts","../src/utils/constants.ts","../src/utils/sdk-tracking.ts","../src/api/errors.ts","../src/api/hmac.ts","../src/api/retry.ts","../src/api-tokens/service.ts","../src/partner-accounts/service.ts","../src/orders/builder.ts","../src/delegated-orders/service.ts","../src/utils/number-flex.ts","../src/orders/signer.ts","../src/orders/validator.ts","../src/markets/fetcher.ts","../src/portfolio/fetcher.ts","../src/orders/client.ts","../src/market-pages/fetcher.ts","../src/websocket/client.ts","../src/client.ts"],"sourcesContent":["/**\n * API token, HMAC auth, and partner capability types.\n * @public\n */\n\n/**\n * HMAC credentials for scoped API-token authentication.\n * @public\n */\nexport interface HMACCredentials {\n tokenId: string;\n secret: string;\n}\n\n/**\n * Profile reference embedded in API-token responses.\n * @public\n */\nexport interface ApiTokenProfile {\n id: number;\n account: string;\n}\n\n/**\n * Request payload for self-service token derivation.\n * `label` is token metadata only and does not affect any profile display name.\n * @public\n */\nexport interface DeriveApiTokenInput {\n label?: string;\n scopes?: string[];\n}\n\n/**\n * One-time token derivation response.\n * @public\n */\nexport interface DeriveApiTokenResponse {\n apiKey: string;\n secret: string;\n tokenId: string;\n createdAt: string;\n scopes: string[];\n profile: ApiTokenProfile;\n}\n\n/**\n * Active token list item.\n * @public\n */\nexport interface ApiToken {\n tokenId: string;\n label: string | null;\n scopes: string[];\n createdAt: string;\n lastUsedAt: string | null;\n}\n\n/**\n * Partner self-service capability config.\n * @public\n */\nexport interface PartnerCapabilities {\n partnerProfileId: number;\n tokenManagementEnabled: boolean;\n allowedScopes: string[];\n}\n\n/**\n * Update partner capabilities request.\n * @public\n */\nexport interface UpdatePartnerCapabilitiesInput {\n tokenManagementEnabled: boolean;\n allowedScopes: string[];\n}\n\n/**\n * Scope constants.\n * @public\n */\nexport const ScopeTrading = 'trading';\nexport const ScopeAccountCreation = 'account_creation';\nexport const ScopeDelegatedSigning = 'delegated_signing';\n","/**\n * Logger interface for SDK integration.\n * Allows users to inject their own logging implementation.\n *\n * @public\n */\nexport interface ILogger {\n /**\n * Log debug information (verbose, development only)\n */\n debug(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log informational messages\n */\n info(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log warning messages\n */\n warn(message: string, meta?: Record<string, any>): void;\n\n /**\n * Log error messages\n */\n error(message: string, error?: Error, meta?: Record<string, any>): void;\n}\n\n/**\n * No-op logger (default) - does nothing.\n * Zero performance overhead when logging is not needed.\n *\n * @internal\n */\nexport class NoOpLogger implements ILogger {\n debug(): void {}\n info(): void {}\n warn(): void {}\n error(): void {}\n}\n\n/**\n * Simple console logger for development.\n * Can be used as a starting point or for debugging.\n *\n * @example\n * ```typescript\n * import { ConsoleLogger } from '@limitless-exchange/sdk';\n *\n * const logger = new ConsoleLogger('debug');\n * const authenticator = new Authenticator(httpClient, signer, logger);\n * ```\n *\n * @public\n */\nexport class ConsoleLogger implements ILogger {\n private level: 'debug' | 'info' | 'warn' | 'error';\n\n constructor(level: 'debug' | 'info' | 'warn' | 'error' = 'info') {\n this.level = level;\n }\n\n private shouldLog(messageLevel: 'debug' | 'info' | 'warn' | 'error'): boolean {\n const levels = ['debug', 'info', 'warn', 'error'];\n return levels.indexOf(messageLevel) >= levels.indexOf(this.level);\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('debug')) {\n console.debug('[Limitless SDK]', message, meta || '');\n }\n }\n\n info(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('info')) {\n console.info('[Limitless SDK]', message, meta || '');\n }\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog('warn')) {\n console.warn('[Limitless SDK]', message, meta || '');\n }\n }\n\n error(message: string, error?: Error, meta?: Record<string, any>): void {\n if (this.shouldLog('error')) {\n // Only log error message, not the full error object (which includes stack trace)\n const errorMsg = error ? error.message : '';\n console.error('[Limitless SDK]', message, errorMsg ? `- ${errorMsg}` : '', meta || '');\n }\n }\n}\n","/**\n * Order-related types for Limitless Exchange.\n * @module types/orders\n */\n\n/**\n * Order side enum.\n * @public\n */\nexport enum Side {\n BUY = 0,\n SELL = 1,\n}\n\n/**\n * Order type enum.\n * @public\n */\nexport enum OrderType {\n /** Fill-or-Kill: Execute immediately or cancel */\n FOK = 'FOK',\n /** Good-Til-Cancelled: Remain on orderbook until filled or cancelled */\n GTC = 'GTC',\n}\n\n/**\n * Signature type enum.\n * @public\n */\nexport enum SignatureType {\n /** Externally Owned Account */\n EOA = 0,\n /** Polymarket Proxy */\n POLY_PROXY = 1,\n /** Polymarket Gnosis Safe */\n POLY_GNOSIS_SAFE = 2,\n}\n\n/**\n * Base arguments shared by all order types.\n * @public\n */\nexport interface BaseOrderArgs {\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Order side (BUY or SELL)\n */\n side: Side;\n\n /**\n * Expiration timestamp (0 for no expiration)\n * @defaultValue '0'\n */\n expiration?: string;\n\n /**\n * Nonce for order replay protection\n * @defaultValue 0\n */\n nonce?: number;\n\n /**\n * Taker address (ZERO_ADDRESS for any taker)\n * @defaultValue '0x0000000000000000000000000000000000000000'\n */\n taker?: string;\n}\n\n/**\n * Arguments for FOK (Fill-or-Kill) market orders.\n *\n * @remarks\n * FOK orders are market orders that execute immediately at the best available price.\n * Specify the maker amount (human-readable, max 6 decimals).\n *\n * For BUY orders: Amount in USDC to spend (e.g., 50.0 = spend $50 USDC)\n * For SELL orders: Number of shares to sell (e.g., 18.64 = sell 18.64 shares)\n *\n * @example\n * ```typescript\n * // BUY: Spend 50 USDC\n * {\n * tokenId: '123...',\n * makerAmount: 50, // Spend $50 USDC\n * side: Side.BUY\n * }\n *\n * // SELL: Sell 18.64 shares\n * {\n * tokenId: '123...',\n * makerAmount: 18.64, // Sell 18.64 shares\n * side: Side.SELL\n * }\n * ```\n *\n * @public\n */\nexport interface FOKOrderArgs extends BaseOrderArgs {\n /**\n * Maker amount (human-readable, max 6 decimals)\n *\n * For BUY orders: Amount of USDC to spend\n * For SELL orders: Number of shares to sell\n *\n * @example\n * // BUY examples\n * 50 = Spend $50 USDC\n * 1.5 = Spend $1.50 USDC\n * 0.75 = Spend $0.75 USDC\n *\n * // SELL examples\n * 18.64 = Sell 18.64 shares\n * 44.111 = Sell 44.111 shares\n */\n makerAmount: number;\n}\n\n/**\n * Arguments for GTC (Good-Til-Cancelled) limit orders.\n *\n * @remarks\n * GTC orders are limit orders that remain on the orderbook until filled or cancelled.\n * You specify the price and number of shares.\n *\n * @example\n * ```typescript\n * // BUY: Buy 10 shares at 0.65 price\n * {\n * tokenId: '123...',\n * price: 0.65,\n * size: 10,\n * side: Side.BUY\n * }\n *\n * // SELL: Sell 5 shares at 0.75 price\n * {\n * tokenId: '123...',\n * price: 0.75,\n * size: 5,\n * side: Side.SELL\n * }\n * ```\n *\n * @public\n */\nexport interface GTCOrderArgs extends BaseOrderArgs {\n /**\n * Price per share (0.0 to 1.0)\n */\n price: number;\n\n /**\n * Number of shares to trade\n */\n size: number;\n}\n\n/**\n * Union type for all order arguments.\n * @public\n */\nexport type OrderArgs = FOKOrderArgs | GTCOrderArgs;\n\n/**\n * Unsigned order payload.\n * @public\n */\nexport interface UnsignedOrder {\n /**\n * Unique salt for order identification\n */\n salt: number;\n\n /**\n * Maker address (order creator)\n */\n maker: string;\n\n /**\n * Signer address (must match maker for EOA)\n */\n signer: string;\n\n /**\n * Taker address (ZERO_ADDRESS for any taker)\n */\n taker: string;\n\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Maker amount in USDC units (6 decimals)\n */\n makerAmount: number;\n\n /**\n * Taker amount in USDC units (6 decimals)\n */\n takerAmount: number;\n\n /**\n * Expiration timestamp (0 for no expiration)\n */\n expiration: string;\n\n /**\n * Nonce for replay protection\n */\n nonce: number;\n\n /**\n * Fee rate in basis points\n */\n feeRateBps: number;\n\n /**\n * Order side (BUY or SELL)\n */\n side: Side;\n\n /**\n * Signature type (EOA, POLY_PROXY, etc.)\n */\n signatureType: SignatureType;\n\n /**\n * Price per share (required for GTC orders)\n */\n price?: number;\n}\n\n/**\n * Signed order payload.\n * @public\n */\nexport interface SignedOrder extends UnsignedOrder {\n /**\n * EIP-712 signature\n */\n signature: string;\n}\n\n/**\n * Complete order payload for API submission.\n * @public\n */\nexport interface NewOrderPayload {\n /**\n * Signed order details\n */\n order: SignedOrder;\n\n /**\n * Order type (FOK or GTC)\n */\n orderType: OrderType;\n\n /**\n * Market slug identifier\n */\n marketSlug: string;\n\n /**\n * Owner ID from user profile\n */\n ownerId: number;\n}\n\n/**\n * Clean order data returned from API.\n *\n * @remarks\n * This is a minimal, user-friendly representation of an order\n * that excludes unnecessary API metadata.\n *\n * @public\n */\nexport interface CreatedOrder {\n /**\n * Order database ID\n */\n id: string;\n\n /**\n * Creation timestamp (ISO 8601)\n */\n createdAt: string;\n\n /**\n * Maker amount (USDC units with 6 decimals)\n */\n makerAmount: number;\n\n /**\n * Taker amount (USDC units with 6 decimals)\n */\n takerAmount: number;\n\n /**\n * Expiration timestamp (null for no expiration)\n */\n expiration: string | null;\n\n /**\n * Signature type (0 = EOA, 1 = Polymarket Proxy, 2 = Gnosis Safe)\n */\n signatureType: number;\n\n /**\n * Unique salt for order identification\n *\n * @remarks\n * May be returned as a string when value exceeds JavaScript safe integer range.\n */\n salt: number | string;\n\n /**\n * Maker address\n */\n maker: string;\n\n /**\n * Signer address\n */\n signer: string;\n\n /**\n * Taker address (zero address for any taker)\n */\n taker: string;\n\n /**\n * Token ID for the outcome\n */\n tokenId: string;\n\n /**\n * Order side (0 = BUY, 1 = SELL)\n */\n side: Side;\n\n /**\n * Fee rate in basis points\n */\n feeRateBps: number;\n\n /**\n * Nonce for replay protection\n */\n nonce: number;\n\n /**\n * EIP-712 signature\n */\n signature: string;\n\n /**\n * Order type (GTC or FOK)\n */\n orderType: string;\n\n /**\n * Price per share (0.0 to 1.0) - only for GTC orders\n */\n price: number | null;\n\n /**\n * Market database ID\n */\n marketId: number;\n}\n\n/**\n * Match information for filled orders.\n *\n * @remarks\n * When a FOK order is filled or a GTC order is partially matched,\n * this provides minimal information about the match.\n *\n * @public\n */\nexport interface OrderMatch {\n /**\n * Match database ID\n */\n id: string;\n\n /**\n * Creation timestamp (ISO 8601)\n */\n createdAt: string;\n\n /**\n * Matched size (USDC units with 6 decimals)\n */\n matchedSize: string;\n\n /**\n * Matched order ID\n */\n orderId: string;\n}\n\n/**\n * Clean order creation response.\n *\n * @remarks\n * This is what users receive after successfully creating an order.\n * For GTC orders, makerMatches will be undefined or empty.\n * For FOK orders, makerMatches contains the fills.\n *\n * @public\n */\nexport interface OrderResponse {\n /**\n * Created order data\n */\n order: CreatedOrder;\n\n /**\n * Matches if order was filled (FOK) or partially matched (GTC)\n */\n makerMatches?: OrderMatch[];\n}\n\n/**\n * Order signing configuration.\n * @public\n */\nexport interface OrderSigningConfig {\n /**\n * Blockchain chain ID\n */\n chainId: number;\n\n /**\n * Contract address for verification (from venue.exchange)\n */\n contractAddress: string;\n}\n","/**\n * WebSocket types for real-time data streaming.\n * @module types/websocket\n */\n\nimport type { OrderbookEntry } from './markets';\nimport type { HMACCredentials } from './api-tokens';\n\n// Re-export OrderbookEntry for convenience\nexport type { OrderbookEntry };\n\n/**\n * WebSocket connection configuration.\n * @public\n */\nexport interface WebSocketConfig {\n /**\n * WebSocket URL (default: wss://ws.limitless.exchange)\n */\n url?: string;\n\n /**\n * API key for authentication\n *\n * @remarks\n * **Required** for authenticated subscriptions (positions, transactions).\n * Not required for public subscriptions (market prices, orderbook).\n *\n * You can generate an API key at https://limitless.exchange\n * and the LIMITLESS_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * HMAC credentials for authenticated subscriptions.\n *\n * @remarks\n * When configured alongside `apiKey`, this client uses HMAC headers for authenticated subscriptions.\n */\n hmacCredentials?: HMACCredentials;\n\n /**\n * Auto-reconnect on connection loss (default: true)\n */\n autoReconnect?: boolean;\n\n /**\n * Reconnection delay in ms (default: 1000)\n */\n reconnectDelay?: number;\n\n /**\n * Maximum reconnection attempts (default: Infinity)\n */\n maxReconnectAttempts?: number;\n\n /**\n * Connection timeout in ms (default: 10000)\n */\n timeout?: number;\n}\n\n/**\n * WebSocket connection state.\n * @public\n */\nexport enum WebSocketState {\n DISCONNECTED = 'disconnected',\n CONNECTING = 'connecting',\n CONNECTED = 'connected',\n RECONNECTING = 'reconnecting',\n ERROR = 'error',\n}\n\n/**\n * Subscription channels for WebSocket events.\n * @public\n */\nexport type SubscriptionChannel =\n | 'orderbook'\n | 'trades'\n | 'orders'\n | 'fills'\n | 'markets'\n | 'prices'\n | 'subscribe_market_prices'\n | 'subscribe_positions'\n | 'subscribe_transactions';\n\n/**\n * Orderbook data structure (nested object in OrderbookUpdate).\n * @public\n */\nexport interface OrderbookData {\n /** List of bid orders sorted by price descending */\n bids: OrderbookEntry[];\n /** List of ask orders sorted by price ascending */\n asks: OrderbookEntry[];\n /** Token ID for the orderbook */\n tokenId: string;\n /** Adjusted midpoint price */\n adjustedMidpoint: number;\n /** Maximum spread allowed */\n maxSpread: number;\n /** Minimum order size */\n minSize: number;\n}\n\n/**\n * Orderbook update event - matches API format exactly.\n * @public\n */\nexport interface OrderbookUpdate {\n /** Market slug identifier (camelCase to match API) */\n marketSlug: string;\n /** Nested orderbook data object */\n orderbook: OrderbookData;\n /** Timestamp as Date or number after serialization */\n timestamp: Date | number | string;\n}\n\n/**\n * Trade event.\n * @public\n */\nexport interface TradeEvent {\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price: number;\n size: number;\n timestamp: number;\n tradeId: string;\n}\n\n/**\n * Order update event.\n * @public\n */\nexport interface OrderUpdate {\n orderId: string;\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price?: number;\n size: number;\n filled: number;\n status: 'OPEN' | 'FILLED' | 'CANCELLED' | 'PARTIALLY_FILLED';\n timestamp: number;\n}\n\n/**\n * Order fill event.\n * @public\n */\nexport interface FillEvent {\n orderId: string;\n marketSlug: string;\n side: 'BUY' | 'SELL';\n price: number;\n size: number;\n timestamp: number;\n fillId: string;\n}\n\n/**\n * Market update event.\n * @public\n */\nexport interface MarketUpdate {\n marketSlug: string;\n lastPrice?: number;\n volume24h?: number;\n priceChange24h?: number;\n timestamp: number;\n}\n\n/**\n * Price update event (deprecated - use NewPriceData for AMM prices).\n *\n * Note: This type does not match the actual API response.\n * Use NewPriceData for the correct AMM price update format.\n *\n * @public\n * @deprecated\n */\nexport interface PriceUpdate {\n marketSlug: string;\n price: number;\n timestamp: number;\n}\n\n/**\n * Single AMM price entry in updatedPrices array.\n * @public\n */\nexport interface AmmPriceEntry {\n /** Market ID */\n marketId: number;\n /** Market contract address */\n marketAddress: string;\n /** YES token price (0-1 range) */\n yesPrice: number;\n /** NO token price (0-1 range) */\n noPrice: number;\n}\n\n/**\n * AMM price update event (newPriceData) - matches API format exactly.\n * @public\n */\nexport interface NewPriceData {\n /** Market contract address (camelCase to match API) */\n marketAddress: string;\n /** Array of price updates for this market */\n updatedPrices: AmmPriceEntry[];\n /** Blockchain block number */\n blockNumber: number;\n /** Timestamp as Date or number after serialization */\n timestamp: Date | number | string;\n}\n\n/**\n * Transaction event (blockchain transaction status).\n * @public\n */\nexport interface TransactionEvent {\n /** User ID (optional) */\n userId?: number;\n /** Transaction hash (optional) */\n txHash?: string;\n /** Transaction status */\n status: 'CONFIRMED' | 'FAILED';\n /** Transaction source */\n source: string;\n /** Transaction timestamp */\n timestamp: Date | string;\n /** Market address (optional) */\n marketAddress?: string;\n /** Market slug identifier (optional) */\n marketSlug?: string;\n /** Token ID (optional) */\n tokenId?: string;\n /** Condition ID (optional) */\n conditionId?: string;\n /** Amount of contracts (optional, in string format) */\n amountContracts?: string;\n /** Amount of collateral (optional, in string format) */\n amountCollateral?: string;\n /** Price (optional, in string format) */\n price?: string;\n /** Trade side (optional) */\n side?: 'BUY' | 'SELL';\n}\n\n/**\n * Market-created websocket event payload.\n *\n * @public\n */\nexport interface MarketCreatedEvent {\n /** Market slug identifier */\n slug: string;\n /** Human-readable market title */\n title: string;\n /** Market venue type */\n type: 'AMM' | 'CLOB';\n /** Group market slug when this market belongs to a group */\n groupSlug?: string;\n /** Category identifiers when provided by the backend */\n categoryIds?: number[];\n /** Market creation timestamp */\n createdAt: Date | number | string;\n}\n\n/**\n * Market-resolved websocket event payload.\n *\n * @public\n */\nexport interface MarketResolvedEvent {\n /** Market slug identifier */\n slug: string;\n /** Market venue type */\n type: 'AMM' | 'CLOB';\n /** Winning outcome label */\n winningOutcome: 'YES' | 'NO';\n /** Winning outcome index */\n winningIndex: 0 | 1;\n /** Resolution timestamp */\n resolutionDate: Date | number | string;\n}\n\n/**\n * WebSocket event types.\n * @public\n */\nexport interface WebSocketEvents {\n /**\n * Connection established\n */\n connect: () => void;\n\n /**\n * Connection lost\n */\n disconnect: (reason: string) => void;\n\n /**\n * Connection error\n */\n error: (error: Error) => void;\n\n /**\n * Reconnection attempt\n */\n reconnecting: (attempt: number) => void;\n\n /**\n * Orderbook updates (CLOB markets) - API event name: orderbookUpdate\n */\n orderbookUpdate: (data: OrderbookUpdate) => void;\n\n /**\n * AMM price updates - API event name: newPriceData\n */\n newPriceData: (data: NewPriceData) => void;\n\n /**\n * Trade events\n */\n trade: (data: TradeEvent) => void;\n\n /**\n * Order updates\n */\n order: (data: OrderUpdate) => void;\n\n /**\n * Order fill events\n */\n fill: (data: FillEvent) => void;\n\n /**\n * Market updates\n */\n market: (data: MarketUpdate) => void;\n\n /**\n * Market-created lifecycle events.\n */\n marketCreated: (data: MarketCreatedEvent) => void;\n\n /**\n * Market-resolved lifecycle events.\n */\n marketResolved: (data: MarketResolvedEvent) => void;\n\n /**\n * Position updates\n */\n positions: (data: any) => void;\n\n /**\n * Transaction events (blockchain confirmations)\n */\n tx: (data: TransactionEvent) => void;\n\n /**\n * Price updates (deprecated - use newPriceData)\n * @deprecated\n */\n price: (data: PriceUpdate) => void;\n}\n\n/**\n * Subscription options.\n * @public\n */\nexport interface SubscriptionOptions {\n /**\n * Market slug to subscribe to (required for market-specific channels)\n * @deprecated Use marketSlugs (array) instead - server expects array format\n */\n marketSlug?: string;\n\n /**\n * Market slugs to subscribe to (array format - required by server)\n */\n marketSlugs?: string[];\n\n /**\n * Market address to subscribe to (for AMM markets)\n * @deprecated Use marketAddresses (array) instead - server expects array format\n */\n marketAddress?: string;\n\n /**\n * Market addresses to subscribe to (array format - required by server)\n */\n marketAddresses?: string[];\n\n /**\n * Additional filters\n */\n filters?: Record<string, any>;\n}\n","/**\n * Market class with fluent API methods.\n * @module types/market-class\n */\n\nimport type { HttpClient } from '../api/http';\nimport type {\n CollateralToken,\n MarketCreator,\n MarketMetadata,\n MarketSettings,\n MarketTokens,\n TradePrices,\n PriceOracleMetadata,\n Venue,\n MarketOutcome,\n} from './markets';\n\n/**\n * Market class with fluent API support.\n *\n * @remarks\n * This class represents a market with methods for fetching related data.\n * Instances are created by MarketFetcher and have http_client attached.\n *\n * @public\n */\nexport class Market {\n // Common fields (both single and group)\n id!: number;\n slug!: string;\n title!: string;\n proxyTitle!: string | null;\n description?: string;\n collateralToken!: CollateralToken;\n expirationDate!: string;\n expirationTimestamp!: number;\n expired?: boolean;\n createdAt!: string;\n updatedAt!: string;\n categories!: string[];\n status!: string;\n creator!: MarketCreator;\n tags!: string[];\n tradeType!: string;\n marketType!: string;\n priorityIndex!: number;\n metadata!: MarketMetadata;\n volume?: string;\n volumeFormatted?: string;\n automationType?: 'manual' | 'lumy' | 'sports';\n imageUrl?: string | null;\n trends?: Record<string, unknown>;\n openInterest?: string;\n openInterestFormatted?: string;\n liquidity?: string;\n liquidityFormatted?: string;\n positionIds?: string[];\n\n // CLOB single market fields\n conditionId?: string;\n negRiskRequestId?: string | null;\n tokens?: MarketTokens;\n prices?: number[];\n tradePrices?: TradePrices;\n isRewardable?: boolean;\n settings?: MarketSettings;\n venue?: Venue;\n logo?: string | null;\n priceOracleMetadata?: PriceOracleMetadata;\n orderInGroup?: number;\n winningOutcomeIndex?: number | null;\n\n // NegRisk group market fields\n outcomeTokens?: string[];\n ogImageURI?: string;\n negRiskMarketId?: string;\n markets?: Market[];\n dailyReward?: string;\n\n // Legacy/deprecated fields\n address?: string | null;\n type?: string;\n outcomes?: MarketOutcome[];\n resolutionDate?: string;\n\n // Private http client for fluent API\n private httpClient?: HttpClient;\n\n /**\n * Creates a Market instance.\n *\n * @param data - Market data from API\n * @param httpClient - HTTP client for making requests\n */\n constructor(data: any, httpClient?: HttpClient) {\n // Copy all properties from data\n Object.assign(this, data);\n\n // Store http client for fluent API\n this.httpClient = httpClient;\n\n // Handle nested Market[] for group markets\n if (data.markets && Array.isArray(data.markets)) {\n this.markets = data.markets.map((m: any) => new Market(m, httpClient));\n }\n }\n\n /**\n * Get user's orders for this market.\n *\n * @remarks\n * Fetches all orders placed by the authenticated user for this specific market.\n * Uses the http_client from the MarketFetcher that created this Market instance.\n *\n * @returns Promise resolving to array of user orders\n * @throws Error if market wasn't fetched via MarketFetcher\n *\n * @example\n * ```typescript\n * // Clean fluent API\n * const market = await marketFetcher.getMarket(\"bitcoin-2024\");\n * const orders = await market.getUserOrders();\n * console.log(`You have ${orders.length} orders in ${market.title}`);\n * ```\n */\n async getUserOrders(): Promise<any[]> {\n if (!this.httpClient) {\n throw new Error(\n 'This Market instance has no httpClient attached. ' +\n 'Make sure to fetch the market via MarketFetcher.getMarket() to use this method.'\n );\n }\n\n const response = await this.httpClient.get<any>(`/markets/${this.slug}/user-orders`);\n\n // Handle both array response and object with orders property\n const orders = Array.isArray(response) ? response : response.orders || [];\n\n return orders;\n }\n}\n","import axios, {\n AxiosInstance,\n AxiosRequestConfig,\n AxiosResponse,\n AxiosResponseHeaders,\n InternalAxiosRequestConfig,\n RawAxiosResponseHeaders,\n} from 'axios';\nimport http from 'http';\nimport https from 'https';\nimport { DEFAULT_API_URL } from '../utils/constants';\nimport { buildSdkTrackingHeaders } from '../utils/sdk-tracking';\nimport { APIError, RateLimitError, AuthenticationError, ValidationError } from './errors';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\nimport type { HMACCredentials } from '../types/api-tokens';\nimport { computeHMACSignature } from './hmac';\n\n/**\n * Configuration options for the HTTP client.\n * @public\n */\nexport interface HttpClientConfig {\n /**\n * Base URL for API requests\n * @defaultValue 'https://api.limitless.exchange'\n */\n baseURL?: string;\n\n /**\n * Request timeout in milliseconds\n * @defaultValue 30000\n */\n timeout?: number;\n\n /**\n * API key for authenticated requests\n * @remarks\n * If not provided, will attempt to load from LIMITLESS_API_KEY environment variable.\n * Required for authenticated endpoints (portfolio, orders, etc.)\n */\n apiKey?: string;\n\n /**\n * HMAC credentials for scoped API-token authentication.\n *\n * @remarks\n * When configured alongside `apiKey`, this client uses HMAC headers for authenticated requests.\n */\n hmacCredentials?: HMACCredentials;\n\n /**\n * Optional logger for debugging\n * @defaultValue NoOpLogger (no logging)\n */\n logger?: ILogger;\n\n /**\n * Enable HTTP connection pooling with keepAlive\n * @defaultValue true\n * @remarks\n * When enabled, HTTP connections are reused across requests, reducing latency by 30-50%.\n * Recommended for production environments with high request volume.\n */\n keepAlive?: boolean;\n\n /**\n * Maximum number of sockets to allow per host\n * @defaultValue 50\n * @remarks\n * Controls the connection pool size. Higher values allow more concurrent requests\n * but consume more system resources.\n */\n maxSockets?: number;\n\n /**\n * Maximum number of free sockets to keep open per host\n * @defaultValue 10\n * @remarks\n * Determines how many idle connections to maintain in the pool.\n * Keeping connections open reduces latency for subsequent requests.\n */\n maxFreeSockets?: number;\n\n /**\n * Socket timeout in milliseconds\n * @defaultValue 60000\n * @remarks\n * Time to wait before closing an idle socket connection.\n */\n socketTimeout?: number;\n\n /**\n * Additional headers to include in all requests\n * @remarks\n * These headers will be merged with default headers and sent with every request.\n * Can be overridden by per-request headers.\n *\n * @example\n * ```typescript\n * const client = new HttpClient({\n * additionalHeaders: {\n * 'X-Custom-Header': 'value',\n * 'X-API-Version': 'v1'\n * }\n * });\n * ```\n */\n additionalHeaders?: Record<string, string>;\n}\n\n/**\n * Raw HTTP response with status and headers.\n *\n * @remarks\n * Useful for endpoints where response metadata matters (for example redirect handling).\n *\n * @public\n */\nexport interface HttpRawResponse<T = any> {\n /**\n * HTTP status code.\n */\n status: number;\n\n /**\n * Response headers.\n */\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n\n /**\n * Response body.\n */\n data: T;\n}\n\n/**\n * HTTP client wrapper for Limitless Exchange API.\n *\n * @remarks\n * This class provides a centralized HTTP client with API key authentication,\n * error handling, and request/response interceptors.\n *\n * @public\n */\nexport class HttpClient {\n private client: AxiosInstance;\n private apiKey?: string;\n private hmacCredentials?: HMACCredentials;\n private logger: ILogger;\n\n /**\n * Creates a new HTTP client instance.\n *\n * @param config - Configuration options for the HTTP client\n */\n constructor(config: HttpClientConfig = {}) {\n this.apiKey = config.apiKey || process.env.LIMITLESS_API_KEY;\n this.hmacCredentials = config.hmacCredentials\n ? {\n tokenId: config.hmacCredentials.tokenId,\n secret: config.hmacCredentials.secret,\n }\n : undefined;\n this.logger = config.logger || new NoOpLogger();\n\n if (!this.apiKey && !this.hmacCredentials) {\n this.logger.warn(\n 'Authentication not set. Authenticated endpoints will fail. ' +\n 'Set LIMITLESS_API_KEY environment variable, pass apiKey, or configure hmacCredentials.'\n );\n }\n\n // Connection pooling configuration (enabled by default)\n const keepAlive = config.keepAlive !== false; // Default: true\n const maxSockets = config.maxSockets || 50;\n const maxFreeSockets = config.maxFreeSockets || 10;\n const socketTimeout = config.socketTimeout || 60000;\n\n // Create HTTP agent with connection pooling\n const httpAgent = new http.Agent({\n keepAlive,\n maxSockets,\n maxFreeSockets,\n timeout: socketTimeout,\n });\n\n // Create HTTPS agent with connection pooling\n const httpsAgent = new https.Agent({\n keepAlive,\n maxSockets,\n maxFreeSockets,\n timeout: socketTimeout,\n });\n\n this.client = axios.create({\n baseURL: config.baseURL || DEFAULT_API_URL,\n timeout: config.timeout || 30000,\n httpAgent,\n httpsAgent,\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n ...buildSdkTrackingHeaders(),\n ...config.additionalHeaders,\n },\n });\n\n this.logger.debug('HTTP client initialized', {\n baseURL: config.baseURL || DEFAULT_API_URL,\n keepAlive,\n maxSockets,\n maxFreeSockets,\n });\n\n this.setupInterceptors();\n }\n\n /**\n * Sets up request and response interceptors.\n * @internal\n */\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (rawConfig: InternalAxiosRequestConfig & { identityToken?: string }) => {\n const config = rawConfig as InternalAxiosRequestConfig & { identityToken?: string; headers: any };\n const headers = (config.headers ||= {});\n const identityToken = config.identityToken;\n\n delete (headers as any)['X-API-Key'];\n delete (headers as any)['lmts-api-key'];\n delete (headers as any)['lmts-timestamp'];\n delete (headers as any)['lmts-signature'];\n delete (headers as any).identity;\n\n if (identityToken) {\n (headers as any).identity = `Bearer ${identityToken}`;\n } else if (this.hmacCredentials) {\n const requestPath = this.getRequestPath(config);\n const requestBody = this.getRequestBodyForSignature(config.data);\n const timestamp = new Date().toISOString();\n const signature = computeHMACSignature(\n this.hmacCredentials.secret,\n timestamp,\n config.method || 'GET',\n requestPath,\n requestBody,\n );\n\n (headers as any)['lmts-api-key'] = this.hmacCredentials.tokenId;\n (headers as any)['lmts-timestamp'] = timestamp;\n (headers as any)['lmts-signature'] = signature;\n } else if (this.apiKey) {\n (headers as any)['X-API-Key'] = this.apiKey;\n }\n\n // Log outgoing request - concise format\n const fullUrl = `${config.baseURL || ''}${config.url || ''}`;\n const method = config.method?.toUpperCase() || 'GET';\n\n const logHeaders = this.maskSensitiveHeaders(headers as Record<string, unknown>);\n\n this.logger.debug(`→ ${method} ${fullUrl}`, {\n headers: logHeaders,\n body: config.data,\n });\n\n return rawConfig;\n },\n (error) => Promise.reject(error)\n );\n\n this.client.interceptors.response.use(\n (response) => {\n // Log successful response - concise format\n const method = response.config.method?.toUpperCase() || 'GET';\n const url = response.config.url || '';\n\n this.logger.debug(`✓ ${response.status} ${method} ${url}`, {\n data: response.data,\n });\n return response;\n },\n (error) => {\n if (error.response) {\n // Handle error response data\n const status = error.response.status;\n const data = error.response.data;\n const url = error.config?.url;\n const method = error.config?.method?.toUpperCase();\n let message = error.message;\n\n if (data) {\n // Log error response - concise format\n this.logger.debug(`✗ ${status} ${method} ${url}`, {\n error: data,\n });\n\n // If data is an object, try to extract message or stringify\n if (typeof data === 'object') {\n // Check if message is an array (validation errors)\n if (Array.isArray(data.message)) {\n const messages = data.message\n .map((err: any) => {\n // Include all error details, not just field and message\n const details = Object.entries(err)\n .filter(([_key, val]) => val !== '' && val !== null && val !== undefined)\n .map(([key, val]) => `${key}: ${val}`)\n .join(', ');\n return details || JSON.stringify(err);\n })\n .filter((msg: string) => msg.trim() !== '')\n .join(' | ');\n message = messages || data.error || JSON.stringify(data);\n } else {\n // Try multiple common error field names\n message =\n data.message ||\n data.error ||\n data.msg ||\n (data.errors && JSON.stringify(data.errors)) ||\n JSON.stringify(data);\n }\n } else {\n message = String(data);\n }\n }\n\n // Throw appropriate error type based on status code\n if (status === 429) {\n throw new RateLimitError(message, status, data, url, method);\n } else if (status === 401 || status === 403) {\n throw new AuthenticationError(message, status, data, url, method);\n } else if (status === 400) {\n throw new ValidationError(message, status, data, url, method);\n } else {\n throw new APIError(message, status, data, url, method);\n }\n } else if (error.request) {\n throw new Error('No response received from API');\n } else {\n throw new Error(`Request failed: ${error.message}`);\n }\n }\n );\n }\n\n /**\n * Extracts a human-readable error message from API response payload.\n * @internal\n */\n private extractErrorMessage(data: any, fallback: string): string {\n if (!data) {\n return fallback;\n }\n\n if (typeof data === 'object') {\n if (Array.isArray(data.message)) {\n const messages = data.message\n .map((err: any) => {\n const details = Object.entries(err || {})\n .filter(([_key, val]) => val !== '' && val !== null && val !== undefined)\n .map(([key, val]) => `${key}: ${val}`)\n .join(', ');\n return details || JSON.stringify(err);\n })\n .filter((msg: string) => msg.trim() !== '')\n .join(' | ');\n\n return messages || data.error || JSON.stringify(data);\n }\n\n return data.message || data.error || data.msg || (data.errors && JSON.stringify(data.errors)) || JSON.stringify(data);\n }\n\n return String(data);\n }\n\n /**\n * Creates a typed API error class from status code.\n * @internal\n */\n private createTypedApiError(status: number, message: string, data: any, url?: string, method?: string): APIError {\n if (status === 429) {\n return new RateLimitError(message, status, data, url, method);\n }\n\n if (status === 401 || status === 403) {\n return new AuthenticationError(message, status, data, url, method);\n }\n\n if (status === 400) {\n return new ValidationError(message, status, data, url, method);\n }\n\n return new APIError(message, status, data, url, method);\n }\n\n /**\n * Sets the API key for authenticated requests.\n *\n * @param apiKey - API key value\n */\n setApiKey(apiKey: string): void {\n this.apiKey = apiKey;\n }\n\n /**\n * Returns the configured API key, if any.\n */\n getApiKey(): string | undefined {\n return this.apiKey;\n }\n\n /**\n * Clears the API key.\n */\n clearApiKey(): void {\n this.apiKey = undefined;\n }\n\n /**\n * Sets HMAC credentials for scoped API-token authentication.\n */\n setHMACCredentials(credentials: HMACCredentials): void {\n this.hmacCredentials = {\n tokenId: credentials.tokenId,\n secret: credentials.secret,\n };\n }\n\n /**\n * Clears HMAC credentials.\n */\n clearHMACCredentials(): void {\n this.hmacCredentials = undefined;\n }\n\n /**\n * Returns a copy of the configured HMAC credentials, if any.\n */\n getHMACCredentials(): HMACCredentials | undefined {\n if (!this.hmacCredentials) {\n return undefined;\n }\n\n return {\n tokenId: this.hmacCredentials.tokenId,\n secret: this.hmacCredentials.secret,\n };\n }\n\n /**\n * Returns the logger attached to this HTTP client.\n */\n getLogger(): ILogger {\n return this.logger;\n }\n\n /**\n * Returns true when cookie/header-based auth is configured on the underlying client.\n * This is primarily used for custom authenticated flows that don't use API keys or HMAC.\n */\n private hasConfiguredHeaderAuth(): boolean {\n const defaultHeaders = this.client.defaults.headers as\n | (Record<string, unknown> & { common?: Record<string, unknown> })\n | undefined;\n\n const candidates = [defaultHeaders?.common, defaultHeaders];\n\n for (const headers of candidates) {\n if (!headers) {\n continue;\n }\n\n const authValues = [\n headers.Cookie,\n headers.cookie,\n headers.Authorization,\n headers.authorization,\n headers.identity,\n ];\n\n if (authValues.some((value) => typeof value === 'string' && value.trim() !== '')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Ensures the client has some authenticated transport configured.\n */\n requireAuth(operation: string): void {\n if (this.apiKey || this.hmacCredentials || this.hasConfiguredHeaderAuth()) {\n return;\n }\n\n throw new Error(\n `Authentication is required for ${operation}; pass apiKey, hmacCredentials, cookie/auth headers, or set LIMITLESS_API_KEY.`,\n );\n }\n\n /**\n * Performs a GET request.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.get(url, config);\n return response.data;\n }\n\n /**\n * Performs a GET request with identity-token authentication.\n */\n async getWithIdentity<T = any>(url: string, identityToken: string, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.get(url, {\n ...config,\n identityToken,\n } as AxiosRequestConfig & { identityToken: string });\n return response.data;\n }\n\n /**\n * Performs a GET request and returns raw response metadata.\n *\n * @remarks\n * Use this when callers need access to status code or headers (e.g. redirect `Location`).\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to status, headers, and response data\n */\n async getRaw<T = any>(url: string, config?: AxiosRequestConfig): Promise<HttpRawResponse<T>> {\n const response: AxiosResponse<T> = await this.client.get(url, config);\n\n // Guard against callers allowing 4xx/5xx through custom validateStatus.\n // getRaw should preserve normal typed API error behavior for error responses.\n if (response.status >= 400) {\n const message = this.extractErrorMessage(response.data, `Request failed with status ${response.status}`);\n throw this.createTypedApiError(response.status, message, response.data, url, 'GET');\n }\n\n return {\n status: response.status,\n headers: response.headers,\n data: response.data,\n };\n }\n\n /**\n * Performs a POST request.\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.post(url, data, config);\n return response.data;\n }\n\n /**\n * Performs a POST request with identity-token authentication.\n */\n async postWithIdentity<T = any>(\n url: string,\n identityToken: string,\n data?: any,\n config?: AxiosRequestConfig,\n ): Promise<T> {\n const response: AxiosResponse<T> = await this.client.post(url, data, {\n ...config,\n identityToken,\n } as AxiosRequestConfig & { identityToken: string });\n return response.data;\n }\n\n /**\n * Performs a POST request with additional per-request headers.\n */\n async postWithHeaders<T = any>(\n url: string,\n data?: any,\n headers?: Record<string, string>,\n config?: AxiosRequestConfig,\n ): Promise<T> {\n const response: AxiosResponse<T> = await this.client.post(url, data, {\n ...config,\n headers: {\n ...(config?.headers || {}),\n ...(headers || {}),\n },\n });\n return response.data;\n }\n\n /**\n * Performs a PATCH request.\n */\n async patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response: AxiosResponse<T> = await this.client.patch(url, data, config);\n return response.data;\n }\n\n /**\n * Performs a DELETE request.\n *\n * @remarks\n * DELETE requests typically don't have a body, so we remove the Content-Type header\n * to avoid \"Body cannot be empty\" errors from the API.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n // Remove Content-Type header for DELETE requests (no body expected)\n const deleteConfig: AxiosRequestConfig = {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': undefined,\n },\n };\n\n const response: AxiosResponse<T> = await this.client.delete(url, deleteConfig);\n return response.data;\n }\n\n private getRequestPath(config: AxiosRequestConfig): string {\n const resolved = new URL(config.url || '', config.baseURL || this.client.defaults.baseURL || DEFAULT_API_URL);\n return `${resolved.pathname}${resolved.search}`;\n }\n\n private getRequestBodyForSignature(data: unknown): string {\n if (data === undefined || data === null || data === '') {\n return '';\n }\n\n if (typeof data === 'string') {\n return data;\n }\n\n return JSON.stringify(data);\n }\n\n private maskSensitiveHeaders(headers: Record<string, unknown>): Record<string, unknown> {\n const masked = { ...headers };\n for (const key of ['X-API-Key', 'lmts-api-key', 'lmts-timestamp', 'lmts-signature', 'identity']) {\n if (masked[key] !== undefined) {\n masked[key] = key === 'identity' ? 'Bearer ***' : '***';\n }\n }\n return masked;\n }\n}\n","/**\n * Default API endpoints and configuration constants.\n * @public\n */\n\n/**\n * Default Limitless Exchange API URL.\n * @public\n */\nexport const DEFAULT_API_URL = 'https://api.limitless.exchange';\n\n/**\n * Default WebSocket URL for real-time data.\n * @public\n */\nexport const DEFAULT_WS_URL = 'wss://ws.limitless.exchange';\n\n/**\n * Default chain ID (Base mainnet).\n * @public\n */\nexport const DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Base Sepolia testnet chain ID.\n * @public\n */\nexport const BASE_SEPOLIA_CHAIN_ID = 84532;\n\n/**\n * Signing message template used by the API.\n * @internal\n */\nexport const SIGNING_MESSAGE_TEMPLATE = 'Welcome to Limitless.exchange! Please sign this message to verify your identity.\\n\\nNonce: {NONCE}';\n\n/**\n * Zero address constant.\n * @public\n */\nexport const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Contract addresses by network\n *\n * @remarks\n * Note: CLOB and NegRisk exchange addresses are provided dynamically via the venue system\n * (market.venue.exchange and market.venue.adapter). These addresses vary per market and\n * should be fetched from the API rather than hardcoded.\n *\n * @public\n */\nexport const CONTRACT_ADDRESSES = {\n // Base mainnet (chainId: 8453)\n 8453: {\n USDC: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Native USDC on Base\n CTF: '0xC9c98965297Bc527861c898329Ee280632B76e18', // Conditional Token Framework\n },\n // Base Sepolia testnet (chainId: 84532)\n 84532: {\n USDC: '0x...',\n CTF: '0x...',\n },\n} as const;\n\n/**\n * Get contract address for tokens (USDC or CTF)\n *\n * @remarks\n * For CLOB and NegRisk exchange addresses, use the venue system instead:\n * - Fetch market via `marketFetcher.getMarket(slug)`\n * - Use `market.venue.exchange` for signing and approvals\n * - Use `market.venue.adapter` for NegRisk adapter approvals\n *\n * @param contractType - Contract type (USDC or CTF)\n * @param chainId - Chain ID (default: 8453 for Base mainnet)\n * @returns Contract address\n *\n * @throws Error if contract address not found for chain\n *\n * @public\n */\nexport function getContractAddress(\n contractType: 'USDC' | 'CTF',\n chainId: number = DEFAULT_CHAIN_ID\n): string {\n const addresses = CONTRACT_ADDRESSES[chainId as keyof typeof CONTRACT_ADDRESSES];\n\n if (!addresses) {\n throw new Error(\n `No contract addresses configured for chainId ${chainId}. ` +\n `Supported chains: ${Object.keys(CONTRACT_ADDRESSES).join(', ')}`\n );\n }\n\n const address = addresses[contractType];\n\n if (!address || address === '0x...') {\n throw new Error(\n `Contract address for ${contractType} not available on chainId ${chainId}. ` +\n `Please configure the address in constants.ts or use environment variables.`\n );\n }\n\n return address;\n}\n","const SDK_ID = 'lmts-sdk-ts';\n\nfunction isNodeRuntime(): boolean {\n return typeof process !== 'undefined' && !!process.versions?.node;\n}\n\nexport function resolveSdkVersion(): string {\n if (typeof __LMTS_SDK_VERSION__ !== 'undefined' && __LMTS_SDK_VERSION__) {\n return __LMTS_SDK_VERSION__;\n }\n\n return '0.0.0';\n}\n\nexport function resolveRuntimeToken(): string {\n if (isNodeRuntime()) {\n return `node/${process.versions.node}`;\n }\n\n return 'runtime/unknown';\n}\n\nexport function buildSdkTrackingHeaders(): Record<string, string> {\n const sdkVersion = resolveSdkVersion();\n const headers: Record<string, string> = {\n 'x-sdk-version': `${SDK_ID}/${sdkVersion}`,\n };\n\n if (isNodeRuntime()) {\n headers['user-agent'] = `${SDK_ID}/${sdkVersion} (${resolveRuntimeToken()})`;\n }\n\n return headers;\n}\n\nexport function buildWebSocketTrackingHeaders(): Record<string, string> {\n if (!isNodeRuntime()) {\n return {};\n }\n\n return buildSdkTrackingHeaders();\n}\n","/**\n * API error types for Limitless Exchange SDK.\n * @module api/errors\n */\n\n/**\n * Custom error class for API errors that preserves the original response data.\n *\n * @remarks\n * This error class allows users to access the raw API response for custom error handling.\n *\n * @example\n * ```typescript\n * try {\n * await orderClient.createOrder(...);\n * } catch (error) {\n * if (error instanceof APIError) {\n * console.log('Status:', error.status);\n * console.log('Raw response:', error.data);\n * console.log('Message:', error.message);\n * }\n * }\n * ```\n *\n * @public\n */\nexport class APIError extends Error {\n /**\n * HTTP status code (e.g., 400, 404, 500)\n */\n public readonly status: number;\n\n /**\n * Raw API response data (original JSON from API)\n */\n public readonly data: any;\n\n /**\n * Request URL that failed\n */\n public readonly url?: string;\n\n /**\n * Request method (GET, POST, etc.)\n */\n public readonly method?: string;\n\n /**\n * Creates a new API error.\n *\n * @param message - Human-readable error message\n * @param status - HTTP status code\n * @param data - Raw API response data\n * @param url - Request URL\n * @param method - Request method\n */\n constructor(\n message: string,\n status: number,\n data: any,\n url?: string,\n method?: string\n ) {\n super(message);\n this.name = 'APIError';\n this.status = status;\n this.data = data;\n this.url = url;\n this.method = method;\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, APIError);\n }\n }\n\n /**\n * Checks if this error is an authentication/authorization error.\n *\n * @returns True if the error is due to expired or invalid authentication\n *\n * @example\n * ```typescript\n * try {\n * await portfolioFetcher.getPositions();\n * } catch (error) {\n * if (error instanceof APIError && error.isAuthError()) {\n * // Re-authenticate and retry\n * await authenticator.authenticate({ client: 'eoa' });\n * await portfolioFetcher.getPositions();\n * }\n * }\n * ```\n */\n isAuthError(): boolean {\n return this.status === 401 || this.status === 403;\n }\n}\n\n/**\n * Rate limit error (HTTP 429).\n *\n * @remarks\n * Thrown when API rate limits are exceeded. The request should be retried after a delay.\n *\n * @example\n * ```typescript\n * try {\n * await marketFetcher.getActiveMarkets();\n * } catch (error) {\n * if (error instanceof RateLimitError) {\n * console.log('Rate limit exceeded, retry after delay');\n * }\n * }\n * ```\n *\n * @public\n */\nexport class RateLimitError extends APIError {\n constructor(\n message: string = 'Rate limit exceeded',\n status: number = 429,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'RateLimitError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, RateLimitError);\n }\n }\n}\n\n/**\n * Authentication error (HTTP 401, 403).\n *\n * @remarks\n * Thrown when authentication fails or API key is invalid/missing.\n *\n * @example\n * ```typescript\n * try {\n * await portfolioFetcher.getPositions();\n * } catch (error) {\n * if (error instanceof AuthenticationError) {\n * console.log('Authentication failed - check API key');\n * }\n * }\n * ```\n *\n * @public\n */\nexport class AuthenticationError extends APIError {\n constructor(\n message: string = 'Authentication failed',\n status: number = 401,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'AuthenticationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AuthenticationError);\n }\n }\n}\n\n/**\n * Validation error (HTTP 400).\n *\n * @remarks\n * Thrown when request validation fails (invalid parameters, missing required fields, etc.).\n *\n * @example\n * ```typescript\n * try {\n * await orderClient.createOrder({ ... });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.log('Validation failed:', error.message);\n * }\n * }\n * ```\n *\n * @public\n */\nexport class ValidationError extends APIError {\n constructor(\n message: string,\n status: number = 400,\n data: any = null,\n url?: string,\n method?: string\n ) {\n super(message, status, data, url, method);\n this.name = 'ValidationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n }\n}\n","import { createHmac } from 'crypto';\n\n/**\n * Builds the canonical HMAC message used by the API-token auth flow.\n * @public\n */\nexport function buildHMACMessage(timestamp: string, method: string, path: string, body: string): string {\n return `${timestamp}\\n${method.toUpperCase()}\\n${path}\\n${body}`;\n}\n\n/**\n * Computes a base64 HMAC-SHA256 request signature from a base64 secret.\n * @public\n */\nexport function computeHMACSignature(\n secret: string,\n timestamp: string,\n method: string,\n path: string,\n body: string,\n): string {\n const key = Buffer.from(secret, 'base64');\n return createHmac('sha256', key).update(buildHMACMessage(timestamp, method, path, body)).digest('base64');\n}\n","/**\n * Retry mechanism for handling transient API failures.\n *\n * @remarks\n * This module provides flexible retry logic for handling rate limits (429),\n * server errors (500, 502, 503), and other transient failures.\n *\n * @example\n * ```typescript\n * // Decorator approach\n * @retryOnErrors({ statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] })\n * async function createOrder() {\n * return await orderClient.createOrder(...);\n * }\n *\n * // Wrapper approach\n * const retryConfig = new RetryConfig({ statusCodes: [429, 500], maxRetries: 3 });\n * const retryableClient = new RetryableClient(httpClient, retryConfig);\n * const markets = await retryableClient.get('/markets');\n * ```\n *\n * @module api/retry\n * @public\n */\n\nimport { APIError } from './errors';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Configuration options for retry behavior.\n *\n * @public\n */\nexport interface RetryConfigOptions {\n /**\n * HTTP status codes to retry on\n * @defaultValue [429, 500, 502, 503, 504]\n */\n statusCodes?: number[];\n\n /**\n * Maximum number of retry attempts\n * @defaultValue 3\n */\n maxRetries?: number;\n\n /**\n * List of delays in seconds for each retry attempt.\n * If not provided, exponential backoff will be used.\n * @defaultValue undefined (use exponential backoff)\n */\n delays?: number[];\n\n /**\n * Base for exponential backoff calculation (delay = base^attempt)\n * @defaultValue 2\n */\n exponentialBase?: number;\n\n /**\n * Maximum delay in seconds for exponential backoff\n * @defaultValue 60\n */\n maxDelay?: number;\n\n /**\n * Optional callback called before each retry attempt\n * @param attempt - Retry attempt number (0-based)\n * @param error - The error that triggered the retry\n * @param delay - Delay in seconds before retry\n */\n onRetry?: (attempt: number, error: Error, delay: number) => void;\n}\n\n/**\n * Configuration class for retry behavior.\n *\n * @public\n */\nexport class RetryConfig {\n /**\n * HTTP status codes to retry on\n */\n readonly statusCodes: Set<number>;\n\n /**\n * Maximum number of retry attempts\n */\n readonly maxRetries: number;\n\n /**\n * List of delays in seconds for each retry\n */\n readonly delays?: number[];\n\n /**\n * Base for exponential backoff\n */\n readonly exponentialBase: number;\n\n /**\n * Maximum delay in seconds\n */\n readonly maxDelay: number;\n\n /**\n * Optional retry callback\n */\n readonly onRetry?: (attempt: number, error: Error, delay: number) => void;\n\n /**\n * Creates a new retry configuration.\n *\n * @param options - Configuration options\n */\n constructor(options: RetryConfigOptions = {}) {\n this.statusCodes = new Set(options.statusCodes || [429, 500, 502, 503, 504]);\n this.maxRetries = options.maxRetries ?? 3;\n this.delays = options.delays;\n this.exponentialBase = options.exponentialBase ?? 2;\n this.maxDelay = options.maxDelay ?? 60;\n this.onRetry = options.onRetry;\n }\n\n /**\n * Calculates delay for a given retry attempt.\n *\n * @param attempt - Retry attempt number (0-based)\n * @returns Delay in seconds\n */\n getDelay(attempt: number): number {\n if (this.delays) {\n // Use specified delays\n return this.delays[Math.min(attempt, this.delays.length - 1)];\n } else {\n // Exponential backoff\n return Math.min(Math.pow(this.exponentialBase, attempt), this.maxDelay);\n }\n }\n}\n\n/**\n * Utility function to sleep for a given duration.\n *\n * @param seconds - Duration to sleep in seconds\n * @returns Promise that resolves after the duration\n * @internal\n */\nfunction sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n}\n\n/**\n * Decorator to add retry logic to async functions.\n *\n * @remarks\n * This decorator automatically retries failed API calls based on HTTP status codes.\n * Useful for handling transient errors like rate limits (429) or server errors (500, 502, 503).\n *\n * @param options - Retry configuration options\n * @returns Method decorator\n *\n * @example\n * ```typescript\n * class MyService {\n * @retryOnErrors({ statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] })\n * async createOrder() {\n * return await this.orderClient.createOrder(...);\n * }\n * }\n * ```\n *\n * @public\n */\nexport function retryOnErrors(options: RetryConfigOptions = {}) {\n const config = new RetryConfig(options);\n\n return function (\n _target: any,\n _propertyKey: string,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: any[]) {\n let lastError: Error | undefined;\n\n // First attempt\n try {\n return await originalMethod.apply(this, args);\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n\n // Retry attempts\n for (let attempt = 0; attempt < config.maxRetries; attempt++) {\n try {\n // Calculate delay\n const delay = config.getDelay(attempt);\n\n // Call user callback if provided\n if (config.onRetry && lastError) {\n config.onRetry(attempt, lastError, delay);\n }\n\n // Wait before retry\n await sleep(delay);\n\n // Retry the function\n return await originalMethod.apply(this, args);\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n }\n\n // All retries exhausted\n throw lastError;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Standalone retry function for wrapping async operations.\n *\n * @remarks\n * This function wraps any async operation with retry logic.\n * More flexible than the decorator approach for one-off retries.\n *\n * @param fn - Async function to execute with retry\n * @param options - Retry configuration options\n * @param logger - Optional logger for retry information\n * @returns Promise resolving to the function result\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n * async () => await orderClient.createOrder(...),\n * { statusCodes: [429, 500], maxRetries: 3, delays: [2, 5, 10] }\n * );\n * ```\n *\n * @public\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryConfigOptions = {},\n logger: ILogger = new NoOpLogger()\n): Promise<T> {\n const config = new RetryConfig(options);\n let lastError: Error | undefined;\n\n // First attempt\n try {\n return await fn();\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n logger.warn('API error, starting retries', { status: error.status });\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n\n // Retry attempts\n for (let attempt = 0; attempt < config.maxRetries; attempt++) {\n try {\n // Calculate delay\n const delay = config.getDelay(attempt);\n\n // Call user callback if provided\n if (config.onRetry && lastError) {\n config.onRetry(attempt, lastError, delay);\n }\n\n logger.info('Retrying operation', { attempt: attempt + 1, delay });\n\n // Wait before retry\n await sleep(delay);\n\n // Retry the function\n return await fn();\n } catch (error: any) {\n // Check if we should retry this error\n if (error instanceof APIError && config.statusCodes.has(error.status)) {\n lastError = error;\n logger.warn('Retry failed', { attempt: attempt + 1, status: error.status });\n } else {\n // Not a retryable error, rethrow immediately\n throw error;\n }\n }\n }\n\n // All retries exhausted\n logger.error('All retries exhausted');\n throw lastError;\n}\n\n/**\n * HTTP client wrapper that adds retry logic to all requests.\n *\n * @remarks\n * This class wraps an HttpClient and automatically retries failed requests\n * based on configured retry settings.\n *\n * @example\n * ```typescript\n * const httpClient = new HttpClient({ logger });\n * const retryConfig = new RetryConfig({ statusCodes: [429, 500], maxRetries: 3 });\n * const retryableClient = new RetryableClient(httpClient, retryConfig);\n *\n * // All requests automatically retry on 429, 500\n * const markets = await retryableClient.get('/markets');\n * ```\n *\n * @public\n */\nexport class RetryableClient {\n /**\n * Creates a new retryable client wrapper.\n *\n * @param httpClient - HTTP client to wrap\n * @param retryConfig - Retry configuration\n * @param logger - Optional logger\n */\n constructor(\n private httpClient: any,\n private retryConfig: RetryConfig = new RetryConfig(),\n private logger: ILogger = new NoOpLogger()\n ) {}\n\n /**\n * Performs a GET request with retry logic.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async get<T = any>(url: string, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.get(url, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Performs a POST request with retry logic.\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async post<T = any>(url: string, data?: any, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.post(url, data, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Performs a DELETE request with retry logic.\n *\n * @param url - Request URL\n * @param config - Additional request configuration\n * @returns Promise resolving to the response data\n */\n async delete<T = any>(url: string, config?: any): Promise<T> {\n return withRetry(\n async () => this.httpClient.delete(url, config),\n {\n statusCodes: Array.from(this.retryConfig.statusCodes),\n maxRetries: this.retryConfig.maxRetries,\n delays: this.retryConfig.delays,\n exponentialBase: this.retryConfig.exponentialBase,\n maxDelay: this.retryConfig.maxDelay,\n onRetry: this.retryConfig.onRetry,\n },\n this.logger\n );\n }\n\n /**\n * Forwards any other method calls to the wrapped HTTP client.\n *\n * @param method - Method name\n */\n [key: string]: any;\n}\n","import { HttpClient } from '../api/http';\nimport type {\n ApiToken,\n DeriveApiTokenInput,\n DeriveApiTokenResponse,\n PartnerCapabilities,\n} from '../types/api-tokens';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\ninterface MessageResponse {\n message: string;\n}\n\n/**\n * Partner self-service API-token operations.\n * @public\n */\nexport class ApiTokenService {\n private readonly httpClient: HttpClient;\n private readonly logger: ILogger;\n\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n async deriveToken(identityToken: string, input: DeriveApiTokenInput): Promise<DeriveApiTokenResponse> {\n if (!identityToken) {\n throw new Error('Identity token is required for deriveToken');\n }\n\n this.logger.debug('Deriving API token', { scopes: input.scopes, label: input.label });\n return this.httpClient.postWithIdentity<DeriveApiTokenResponse>('/auth/api-tokens/derive', identityToken, input);\n }\n\n async listTokens(): Promise<ApiToken[]> {\n this.httpClient.requireAuth('listTokens');\n return this.httpClient.get<ApiToken[]>('/auth/api-tokens');\n }\n\n async getCapabilities(identityToken: string): Promise<PartnerCapabilities> {\n if (!identityToken) {\n throw new Error('Identity token is required for getCapabilities');\n }\n\n return this.httpClient.getWithIdentity<PartnerCapabilities>('/auth/api-tokens/capabilities', identityToken);\n }\n\n async revokeToken(tokenId: string): Promise<string> {\n this.httpClient.requireAuth('revokeToken');\n const response = await this.httpClient.delete<MessageResponse>(`/auth/api-tokens/${encodeURIComponent(tokenId)}`);\n return response.message;\n }\n}\n\n","import { HttpClient } from '../api/http';\nimport type {\n CreatePartnerAccountEOAHeaders,\n CreatePartnerAccountInput,\n PartnerAccountResponse,\n} from '../types/partner-accounts';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Partner-owned profile creation API.\n * @public\n */\nexport class PartnerAccountService {\n private static readonly DISPLAY_NAME_MAX_LENGTH = 44;\n private readonly httpClient: HttpClient;\n private readonly logger: ILogger;\n\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n async createAccount(\n input: CreatePartnerAccountInput,\n eoaHeaders?: CreatePartnerAccountEOAHeaders,\n ): Promise<PartnerAccountResponse> {\n this.httpClient.requireAuth('createPartnerAccount');\n\n const serverWalletMode = input.createServerWallet === true;\n if (!serverWalletMode && !eoaHeaders) {\n throw new Error('EOA headers are required when createServerWallet is not true');\n }\n if (input.displayName && input.displayName.length > PartnerAccountService.DISPLAY_NAME_MAX_LENGTH) {\n throw new Error(\n `displayName must be at most ${PartnerAccountService.DISPLAY_NAME_MAX_LENGTH} characters`,\n );\n }\n\n this.logger.debug('Creating partner account', {\n displayName: input.displayName,\n createServerWallet: input.createServerWallet,\n });\n\n const payload = {\n displayName: input.displayName,\n createServerWallet: input.createServerWallet,\n };\n\n return this.httpClient.postWithHeaders<PartnerAccountResponse>(\n '/profiles/partner-accounts',\n payload,\n eoaHeaders\n ? {\n 'x-account': eoaHeaders.account,\n 'x-signing-message': eoaHeaders.signingMessage,\n 'x-signature': eoaHeaders.signature,\n }\n : undefined,\n );\n }\n}\n","/**\n * Order builder for constructing unsigned order payloads.\n * @module orders/builder\n */\n\nimport { ethers } from 'ethers';\nimport { OrderArgs, UnsignedOrder, Side, SignatureType } from '../types/orders';\n\n/**\n * Zero address constant for any-taker orders.\n */\nconst ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Default price tick size (0.001 = 3 decimal places).\n * This is the minimum price increment allowed by the exchange.\n */\nconst DEFAULT_PRICE_TICK = 0.001;\n\n/**\n * Order builder for constructing unsigned order payloads.\n *\n * @remarks\n * This class handles the construction of unsigned orders matching the\n * Limitless Exchange API format. It generates unique salts, calculates\n * maker/taker amounts with proper tick alignment, and validates inputs.\n *\n * **Tick Alignment Requirements**:\n * - Prices must align to tick size (default: 0.001 = 3 decimals)\n * - Size must produce takerAmount divisible by sharesStep (priceScale / tickInt = 1000 for 0.001 tick)\n * - SDK validates inputs and throws clear errors rather than auto-rounding\n * - This ensures `price * contracts` yields whole number collateral\n *\n * **Validation Strategy**:\n * - FAILS FAST: Invalid inputs throw errors with helpful suggestions\n * - NO AUTO-ROUNDING: Users maintain full control over order amounts\n * - TRANSPARENCY: Error messages show valid alternatives\n * - Example: size=22.123896 → Error: \"Try 22.123 (rounded down) or 22.124 (rounded up) instead\"\n *\n * @public\n */\nexport class OrderBuilder {\n private makerAddress: string;\n private feeRateBps: number;\n private priceTick: number;\n\n /**\n * Creates a new order builder instance.\n *\n * @param makerAddress - Ethereum address of the order maker\n * @param feeRateBps - Fee rate in basis points (e.g., 100 = 1%)\n * @param priceTick - Price tick size (default: 0.001 for 3 decimals)\n *\n * @example\n * ```typescript\n * const builder = new OrderBuilder(\n * '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',\n * 300, // 3% fee\n * 0.001 // 3 decimal price precision\n * );\n * ```\n */\n constructor(makerAddress: string, feeRateBps: number, priceTick: number = DEFAULT_PRICE_TICK) {\n this.makerAddress = makerAddress;\n this.feeRateBps = feeRateBps;\n this.priceTick = priceTick;\n }\n\n /**\n * Builds an unsigned order payload.\n *\n * @param args - Order arguments (FOK or GTC)\n * @returns Unsigned order ready for signing\n *\n * @throws Error if validation fails or tick alignment fails\n *\n * @example\n * ```typescript\n * // FOK order (market order)\n * const fokOrder = builder.buildOrder({\n * tokenId: '123456',\n * makerAmount: 50, // 50 USDC to spend\n * side: Side.BUY\n * });\n *\n * // GTC order (price + size)\n * const gtcOrder = builder.buildOrder({\n * tokenId: '123456',\n * price: 0.38,\n * size: 22.123, // Will be rounded to tick-aligned: 22.123 shares\n * side: Side.BUY\n * });\n * ```\n */\n buildOrder(args: OrderArgs): UnsignedOrder {\n this.validateOrderArgs(args);\n\n const { makerAmount, takerAmount, price } = this.isFOKOrder(args)\n ? this.calculateFOKAmounts(args.makerAmount)\n : this.calculateGTCAmountsTickAligned(args.price, args.size, args.side);\n\n const order: UnsignedOrder = {\n salt: this.generateSalt(),\n maker: this.makerAddress,\n signer: this.makerAddress,\n taker: args.taker || ZERO_ADDRESS,\n tokenId: args.tokenId,\n makerAmount: makerAmount,\n takerAmount: takerAmount,\n expiration: args.expiration || '0',\n nonce: args.nonce || 0,\n feeRateBps: this.feeRateBps,\n side: args.side,\n signatureType: SignatureType.EOA,\n };\n\n if (price !== undefined) {\n order.price = price;\n }\n\n return order;\n }\n\n /**\n * Type guard to check if order arguments are for FOK order.\n *\n * @param args - Order arguments\n * @returns True if FOK order arguments\n *\n * @internal\n */\n private isFOKOrder(args: OrderArgs): args is import('../types/orders').FOKOrderArgs {\n return 'makerAmount' in args;\n }\n\n /**\n * Generates a unique salt using timestamp + nano-offset pattern.\n *\n * @remarks\n * This follows the reference implementation pattern:\n * salt = timestamp * 1000 + nanoOffset + 24h\n *\n * This ensures uniqueness even when creating orders rapidly.\n *\n * @returns Unique salt value\n *\n * @internal\n */\n private generateSalt(): number {\n const timestamp = Date.now();\n const nanoOffset = Math.floor(performance.now() * 1000) % 1000000;\n const oneDayMs = 1000 * 60 * 60 * 24;\n return timestamp * 1000 + nanoOffset + oneDayMs;\n }\n\n /**\n * Parses decimal string to scaled BigInt.\n *\n * @param value - Decimal string (e.g., \"0.38\")\n * @param scale - Scale factor (e.g., 1_000_000n for 6 decimals)\n * @returns Scaled BigInt value\n *\n * @internal\n */\n private parseDecToInt(value: string, scale: bigint): bigint {\n const s = value.trim();\n const [intPart, fracPart = ''] = s.split('.');\n const decimals = scale.toString().length - 1;\n const frac = (fracPart + '0'.repeat(decimals)).slice(0, decimals);\n const sign = intPart.startsWith('-') ? -1n : 1n;\n const intPartAbs = intPart.replace('-', '');\n return sign * (BigInt(intPartAbs || '0') * scale + BigInt(frac || '0'));\n }\n\n /**\n * Ceiling division for BigInt.\n *\n * @param numerator - Numerator\n * @param denominator - Denominator\n * @returns Ceiling of numerator / denominator\n *\n * @internal\n */\n private divCeil(numerator: bigint, denominator: bigint): bigint {\n if (denominator === 0n) {\n throw new Error('Division by zero');\n }\n return (numerator + denominator - 1n) / denominator;\n }\n\n /**\n * Calculates maker and taker amounts for GTC orders with tick alignment validation.\n *\n * @remarks\n * Validates and calculates amounts to ensure:\n * 1. Price aligns to tick size (e.g., 0.001 for 3 decimals)\n * 2. Size produces takerAmount divisible by sharesStep\n * 3. No auto-rounding - fails fast if values are invalid\n * 4. Transparent error messages guide users to valid values\n *\n * **Algorithm**:\n * - sharesStep = priceScale / tickInt (e.g., 1000 for 0.001 tick)\n * - Validates shares are divisible by sharesStep\n * - Calculates collateral from shares × price (ceil for BUY, floor for SELL)\n * - Assigns maker/taker based on side:\n * - BUY: maker = collateral, taker = shares\n * - SELL: maker = shares, taker = collateral\n * - Throws clear error if size is not tick-aligned\n *\n * @param price - Price per share (0.0 to 1.0, max 3 decimals)\n * @param size - Number of shares (must be tick-aligned)\n * @param side - Order side (BUY or SELL)\n * @returns Object with validated makerAmount, takerAmount, and price\n *\n * @throws Error if price or size not tick-aligned\n *\n * @internal\n */\n private calculateGTCAmountsTickAligned(\n price: number,\n size: number,\n side: Side\n ): { makerAmount: number; takerAmount: number; price: number } {\n const sharesScale = 1_000_000n;\n const collateralScale = 1_000_000n;\n const priceScale = 1_000_000n;\n\n const shares = this.parseDecToInt(size.toString(), sharesScale);\n const priceInt = this.parseDecToInt(price.toString(), priceScale);\n const tickInt = this.parseDecToInt(this.priceTick.toString(), priceScale);\n\n // Validate tick and price\n if (tickInt <= 0n) {\n throw new Error(`Invalid priceTick: ${this.priceTick}`);\n }\n if (priceInt <= 0n) {\n throw new Error(`Invalid price: ${price}`);\n }\n\n // Validate price is tick-aligned\n if (priceInt % tickInt !== 0n) {\n throw new Error(\n `Price ${price} is not tick-aligned. Must be multiple of ${this.priceTick} (e.g., 0.380, 0.381, etc.)`\n );\n }\n\n // Calculate shares step (shares must be divisible by this)\n // For priceTick=0.001: sharesStep = 1_000_000 / 1_000 = 1_000\n const sharesStep = priceScale / tickInt;\n\n // Validate size produces tick-aligned shares (NO AUTO-ROUNDING)\n if (shares % sharesStep !== 0n) {\n // Calculate valid size that would work\n const validSizeDown = Number((shares / sharesStep) * sharesStep) / 1e6;\n const validSizeUp = Number(this.divCeil(shares, sharesStep) * sharesStep) / 1e6;\n\n throw new Error(\n `Invalid size: ${size}. Size must produce contracts divisible by ${sharesStep} (sharesStep). ` +\n `Try ${validSizeDown} (rounded down) or ${validSizeUp} (rounded up) instead.`\n );\n }\n\n // Calculate collateral: (shares * price * collateralScale) / (sharesScale * priceScale)\n const numerator = shares * priceInt * collateralScale;\n const denominator = sharesScale * priceScale;\n\n const collateral =\n side === Side.BUY\n ? this.divCeil(numerator, denominator) // BUY: Round UP (maker pays more)\n : numerator / denominator; // SELL: Round DOWN (maker receives less)\n\n // Assign maker/taker amounts based on side\n let makerAmount: bigint;\n let takerAmount: bigint;\n\n if (side === Side.BUY) {\n // BUY: maker provides collateral, taker provides shares\n makerAmount = collateral;\n takerAmount = shares;\n } else {\n // SELL: maker provides shares, taker provides collateral\n makerAmount = shares;\n takerAmount = collateral;\n }\n\n return {\n makerAmount: Number(makerAmount),\n takerAmount: Number(takerAmount),\n price,\n };\n }\n\n /**\n * Calculates maker and taker amounts for FOK (market) orders.\n *\n * @remarks\n * FOK orders use makerAmount for both BUY and SELL:\n * - BUY: makerAmount = USDC amount to spend (e.g., 50 = $50 USDC)\n * - SELL: makerAmount = number of shares to sell (e.g., 18.64 shares)\n *\n * takerAmount is always 1 (constant for FOK orders)\n *\n * @param makerAmount - Amount in human-readable format (max 6 decimals)\n * @returns Object with makerAmount (scaled), takerAmount (always 1), and undefined price\n *\n * @internal\n */\n private calculateFOKAmounts(makerAmount: number): {\n makerAmount: number;\n takerAmount: number;\n price: undefined;\n } {\n const DECIMALS = 6;\n\n // Validate makerAmount has max 6 decimal places\n const amountStr = makerAmount.toString();\n const decimalIndex = amountStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = amountStr.length - decimalIndex - 1;\n if (decimalPlaces > DECIMALS) {\n throw new Error(\n `Invalid makerAmount: ${makerAmount}. Can have max ${DECIMALS} decimal places. ` +\n `Try ${makerAmount.toFixed(DECIMALS)} instead.`\n );\n }\n }\n\n const amountFormatted = makerAmount.toFixed(DECIMALS);\n const amountScaled = ethers.parseUnits(amountFormatted, DECIMALS);\n const collateralAmount = Number(amountScaled);\n\n return {\n makerAmount: collateralAmount,\n takerAmount: 1,\n price: undefined,\n };\n }\n\n /**\n * Validates order arguments.\n *\n * @param args - Order arguments to validate\n * @throws Error if validation fails\n *\n * @internal\n */\n private validateOrderArgs(args: OrderArgs): void {\n // Validate tokenId\n if (!args.tokenId || args.tokenId === '0') {\n throw new Error('Invalid tokenId: tokenId is required.');\n }\n\n // Validate taker address format if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new Error(`Invalid taker address: ${args.taker}`);\n }\n\n // Type-specific validation\n if (this.isFOKOrder(args)) {\n // FOK order validation - must have makerAmount\n if (!args.makerAmount) {\n throw new Error('FOK orders require makerAmount');\n }\n if (args.makerAmount <= 0) {\n throw new Error(`Invalid makerAmount: ${args.makerAmount}. Maker amount must be positive.`);\n }\n } else {\n // GTC order validation\n if (args.price == null || args.price < 0 || args.price > 1) {\n throw new Error(`Invalid price: ${args.price}. Price must be between 0 and 1.`);\n }\n\n if (args.size <= 0) {\n throw new Error(`Invalid size: ${args.size}. Size must be positive.`);\n }\n\n // Validate price has max 3 decimals (tick alignment check)\n const priceStr = args.price.toString();\n const decimalIndex = priceStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = priceStr.length - decimalIndex - 1;\n if (decimalPlaces > 3) {\n throw new Error(\n `Invalid price: ${args.price}. Price must have max 3 decimal places (e.g., 0.380, 0.001).`\n );\n }\n }\n }\n }\n}\n","import { HttpClient } from '../api/http';\nimport { OrderBuilder } from '../orders/builder';\nimport { ZERO_ADDRESS } from '../utils/constants';\nimport {\n type CancelResponse,\n type CreateDelegatedOrderParams,\n type CreateDelegatedOrderRequest,\n type DelegatedOrderResponse,\n} from '../types/delegated-orders';\nimport { SignatureType } from '../types/orders';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\nconst DEFAULT_DELEGATED_FEE_RATE_BPS = 300;\n\n/**\n * Delegated partner-order operations.\n * @public\n */\nexport class DelegatedOrderService {\n private readonly httpClient: HttpClient;\n private readonly logger: ILogger;\n\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n async createOrder(params: CreateDelegatedOrderParams): Promise<DelegatedOrderResponse> {\n this.httpClient.requireAuth('createDelegatedOrder');\n\n if (!Number.isInteger(params.onBehalfOf) || params.onBehalfOf <= 0) {\n throw new Error('onBehalfOf must be a positive integer');\n }\n\n const feeRateBps = params.feeRateBps && params.feeRateBps > 0\n ? params.feeRateBps\n : DEFAULT_DELEGATED_FEE_RATE_BPS;\n\n const builder = new OrderBuilder(ZERO_ADDRESS, feeRateBps);\n const unsignedOrder = builder.buildOrder(params.args);\n\n const payload: CreateDelegatedOrderRequest = {\n order: {\n salt: unsignedOrder.salt,\n maker: unsignedOrder.maker,\n signer: unsignedOrder.signer,\n taker: unsignedOrder.taker,\n tokenId: unsignedOrder.tokenId,\n makerAmount: unsignedOrder.makerAmount,\n takerAmount: unsignedOrder.takerAmount,\n expiration: unsignedOrder.expiration,\n nonce: unsignedOrder.nonce,\n feeRateBps: unsignedOrder.feeRateBps,\n side: unsignedOrder.side,\n signatureType: SignatureType.EOA,\n ...(unsignedOrder.price !== undefined ? { price: unsignedOrder.price } : {}),\n },\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n ownerId: params.onBehalfOf,\n onBehalfOf: params.onBehalfOf,\n };\n\n this.logger.debug('Creating delegated order', {\n marketSlug: params.marketSlug,\n onBehalfOf: params.onBehalfOf,\n feeRateBps,\n });\n\n return this.httpClient.post<DelegatedOrderResponse>('/orders', payload);\n }\n\n async cancel(orderId: string): Promise<string> {\n this.httpClient.requireAuth('cancelDelegatedOrder');\n const response = await this.httpClient.delete<CancelResponse>(`/orders/${encodeURIComponent(orderId)}`);\n return response.message;\n }\n\n async cancelOnBehalfOf(orderId: string, onBehalfOf: number): Promise<string> {\n this.httpClient.requireAuth('cancelDelegatedOrder');\n if (!Number.isInteger(onBehalfOf) || onBehalfOf <= 0) {\n throw new Error('onBehalfOf must be a positive integer');\n }\n\n const response = await this.httpClient.delete<CancelResponse>(\n `/orders/${encodeURIComponent(orderId)}?onBehalfOf=${onBehalfOf}`,\n );\n return response.message;\n }\n\n async cancelAll(marketSlug: string): Promise<string> {\n this.httpClient.requireAuth('cancelAllDelegatedOrders');\n const response = await this.httpClient.delete<CancelResponse>(`/orders/all/${encodeURIComponent(marketSlug)}`);\n return response.message;\n }\n\n async cancelAllOnBehalfOf(marketSlug: string, onBehalfOf: number): Promise<string> {\n this.httpClient.requireAuth('cancelAllDelegatedOrders');\n if (!Number.isInteger(onBehalfOf) || onBehalfOf <= 0) {\n throw new Error('onBehalfOf must be a positive integer');\n }\n\n const response = await this.httpClient.delete<CancelResponse>(\n `/orders/all/${encodeURIComponent(marketSlug)}?onBehalfOf=${onBehalfOf}`,\n );\n return response.message;\n }\n}\n\n","/**\n * Numeric parsing helpers for API payloads that may return numbers as strings.\n */\n\n/**\n * Converts number-like values to finite numbers.\n * Returns undefined when value is not numeric.\n */\nexport function toFiniteNumber(value: unknown): number | undefined {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : undefined;\n }\n\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return undefined;\n }\n\n const parsed = Number(trimmed);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Converts number-like values to finite integers.\n * Returns undefined when value is not a safe integer.\n */\nexport function toFiniteInteger(value: unknown): number | undefined {\n const parsed = toFiniteNumber(value);\n if (parsed === undefined) {\n return undefined;\n }\n\n return Number.isSafeInteger(parsed) ? parsed : undefined;\n}\n","/**\n * EIP-712 order signer for Limitless Exchange.\n * @module orders/signer\n */\n\nimport { ethers } from 'ethers';\nimport type { UnsignedOrder, OrderSigningConfig } from '../types/orders';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * EIP-712 typed data field definition.\n */\ninterface TypedDataField {\n name: string;\n type: string;\n}\n\n/**\n * EIP-712 order signer.\n *\n * @remarks\n * This class handles EIP-712 signing for Limitless Exchange orders.\n * It creates signatures that match the API's verification requirements.\n *\n * Domain: \"Limitless CTF Exchange\"\n * Version: \"1\"\n *\n * @public\n */\nexport class OrderSigner {\n private wallet: ethers.Wallet;\n private logger: ILogger;\n\n /**\n * Creates a new order signer instance.\n *\n * @param wallet - Ethers wallet for signing\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * import { ethers } from 'ethers';\n * import { OrderSigner } from '@limitless-exchange/sdk';\n *\n * const wallet = new ethers.Wallet(privateKey);\n * const signer = new OrderSigner(wallet);\n * ```\n */\n constructor(wallet: ethers.Wallet, logger?: ILogger) {\n this.wallet = wallet;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Signs an order with EIP-712.\n *\n * @param order - Unsigned order to sign\n * @param config - Signing configuration (chainId, contract address, market type)\n * @returns Promise resolving to EIP-712 signature\n *\n * @throws Error if wallet address doesn't match order signer\n * @throws Error if signing fails\n *\n * @example\n * ```typescript\n * const signature = await signer.signOrder(unsignedOrder, {\n * chainId: 8453,\n * contractAddress: '0x...'\n * });\n * ```\n */\n async signOrder(order: UnsignedOrder, config: OrderSigningConfig): Promise<string> {\n this.logger.debug('Signing order with EIP-712', {\n tokenId: order.tokenId,\n side: order.side,\n verifyingContract: config.contractAddress,\n });\n\n // Verify wallet address matches signer\n const walletAddress = await this.wallet.getAddress();\n if (walletAddress.toLowerCase() !== order.signer.toLowerCase()) {\n const error = `Wallet address mismatch! Signing with: ${walletAddress}, but order signer is: ${order.signer}`;\n this.logger.error(error);\n throw new Error(error);\n }\n\n // Get EIP-712 domain\n const domain = this.getDomain(config);\n this.logger.debug('EIP-712 Domain', domain);\n\n // Get EIP-712 types\n const types = this.getTypes();\n\n // Prepare order value for signing (exclude price field)\n const orderValue = {\n salt: order.salt,\n maker: order.maker,\n signer: order.signer,\n taker: order.taker,\n tokenId: order.tokenId,\n makerAmount: order.makerAmount,\n takerAmount: order.takerAmount,\n expiration: order.expiration,\n nonce: order.nonce,\n feeRateBps: order.feeRateBps,\n side: order.side,\n signatureType: order.signatureType,\n };\n\n this.logger.debug('EIP-712 Order Value', orderValue);\n this.logger.debug('Full signing payload', {\n domain,\n types: this.getTypes(),\n value: orderValue,\n });\n try {\n // Sign with EIP-712\n const signature = await this.wallet.signTypedData(domain, types, orderValue);\n this.logger.info('Successfully generated EIP-712 signature', {\n signature: signature.slice(0, 10) + '...',\n });\n return signature;\n } catch (error) {\n this.logger.error('Failed to sign order', error as Error);\n throw error;\n }\n }\n\n /**\n * Gets the EIP-712 domain for signing.\n *\n * @param config - Signing configuration\n * @returns EIP-712 domain object\n *\n * @internal\n */\n private getDomain(config: OrderSigningConfig): {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: string;\n } {\n return {\n name: 'Limitless CTF Exchange',\n version: '1',\n chainId: config.chainId,\n verifyingContract: config.contractAddress,\n };\n }\n\n /**\n * Gets the EIP-712 type definitions.\n *\n * @remarks\n * This matches the order structure expected by the Limitless Exchange\n * smart contracts.\n *\n * @returns EIP-712 types definition\n *\n * @internal\n */\n private getTypes(): Record<string, TypedDataField[]> {\n return {\n Order: [\n { name: 'salt', type: 'uint256' },\n { name: 'maker', type: 'address' },\n { name: 'signer', type: 'address' },\n { name: 'taker', type: 'address' },\n { name: 'tokenId', type: 'uint256' },\n { name: 'makerAmount', type: 'uint256' },\n { name: 'takerAmount', type: 'uint256' },\n { name: 'expiration', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'feeRateBps', type: 'uint256' },\n { name: 'side', type: 'uint8' },\n { name: 'signatureType', type: 'uint8' },\n ],\n };\n }\n}\n","/**\n * Order validation utilities.\n * @module orders/validator\n */\n\nimport { ethers } from 'ethers';\nimport type {\n OrderArgs,\n UnsignedOrder,\n SignedOrder,\n FOKOrderArgs,\n GTCOrderArgs,\n} from '../types/orders';\n\n/**\n * Order validation error class for client-side validation.\n * @public\n */\nexport class OrderValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OrderValidationError';\n }\n}\n\n/**\n * Type guard to check if order arguments are for FOK order.\n */\nfunction isFOKOrder(args: OrderArgs): args is FOKOrderArgs {\n return 'makerAmount' in args;\n}\n\n/**\n * Validates order arguments before building.\n *\n * @param args - Order arguments to validate (FOK or GTC)\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * try {\n * validateOrderArgs(orderArgs);\n * } catch (error) {\n * console.error('Validation failed:', error.message);\n * }\n * ```\n */\nexport function validateOrderArgs(args: OrderArgs): void {\n // Validate tokenId\n if (!args.tokenId) {\n throw new OrderValidationError('TokenId is required');\n }\n\n if (args.tokenId === '0') {\n throw new OrderValidationError('TokenId cannot be zero');\n }\n\n // Validate tokenId format (should be numeric string)\n if (!/^\\d+$/.test(args.tokenId)) {\n throw new OrderValidationError(`Invalid tokenId format: ${args.tokenId}`);\n }\n\n // Validate taker address if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new OrderValidationError(`Invalid taker address: ${args.taker}`);\n }\n\n // Validate expiration if provided\n if (args.expiration !== undefined) {\n if (!/^\\d+$/.test(args.expiration)) {\n throw new OrderValidationError(`Invalid expiration format: ${args.expiration}`);\n }\n }\n\n // Validate nonce if provided\n if (args.nonce !== undefined) {\n if (!Number.isInteger(args.nonce) || args.nonce < 0) {\n throw new OrderValidationError(`Invalid nonce: ${args.nonce}`);\n }\n }\n\n // Type-specific validation\n if (isFOKOrder(args)) {\n // FOK order validation\n if (typeof args.makerAmount !== 'number' || isNaN(args.makerAmount)) {\n throw new OrderValidationError('Amount must be a valid number');\n }\n\n if (args.makerAmount <= 0) {\n throw new OrderValidationError(`Amount must be positive, got: ${args.makerAmount}`);\n }\n\n // Validate max 2 decimal places\n // Convert to string and check decimal places\n const amountStr = args.makerAmount.toString();\n const decimalIndex = amountStr.indexOf('.');\n if (decimalIndex !== -1) {\n const decimalPlaces = amountStr.length - decimalIndex - 1;\n if (decimalPlaces > 2) {\n throw new OrderValidationError(\n `Amount must have max 2 decimal places, got: ${args.makerAmount} (${decimalPlaces} decimals)`\n );\n }\n }\n } else {\n // GTC order validation\n if (typeof args.price !== 'number' || isNaN(args.price)) {\n throw new OrderValidationError('Price must be a valid number');\n }\n\n if (args.price < 0 || args.price > 1) {\n throw new OrderValidationError(`Price must be between 0 and 1, got: ${args.price}`);\n }\n\n if (typeof args.size !== 'number' || isNaN(args.size)) {\n throw new OrderValidationError('Size must be a valid number');\n }\n\n if (args.size <= 0) {\n throw new OrderValidationError(`Size must be positive, got: ${args.size}`);\n }\n }\n}\n\n/**\n * Validates an unsigned order.\n *\n * @param order - Unsigned order to validate\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * validateUnsignedOrder(unsignedOrder);\n * ```\n */\nexport function validateUnsignedOrder(order: UnsignedOrder): void {\n // Validate addresses\n if (!ethers.isAddress(order.maker)) {\n throw new OrderValidationError(`Invalid maker address: ${order.maker}`);\n }\n\n if (!ethers.isAddress(order.signer)) {\n throw new OrderValidationError(`Invalid signer address: ${order.signer}`);\n }\n\n if (!ethers.isAddress(order.taker)) {\n throw new OrderValidationError(`Invalid taker address: ${order.taker}`);\n }\n\n // Validate amounts\n if (!order.makerAmount || order.makerAmount === 0) {\n throw new OrderValidationError('MakerAmount must be greater than zero');\n }\n\n if (!order.takerAmount || order.takerAmount === 0) {\n throw new OrderValidationError('TakerAmount must be greater than zero');\n }\n\n // Validate amounts are positive numbers\n if (typeof order.makerAmount !== 'number' || order.makerAmount <= 0) {\n throw new OrderValidationError(`Invalid makerAmount: ${order.makerAmount}`);\n }\n\n if (typeof order.takerAmount !== 'number' || order.takerAmount <= 0) {\n throw new OrderValidationError(`Invalid takerAmount: ${order.takerAmount}`);\n }\n\n if (!/^\\d+$/.test(order.tokenId)) {\n throw new OrderValidationError(`Invalid tokenId format: ${order.tokenId}`);\n }\n\n if (!/^\\d+$/.test(order.expiration)) {\n throw new OrderValidationError(`Invalid expiration format: ${order.expiration}`);\n }\n\n // Validate salt\n if (!Number.isInteger(order.salt) || order.salt <= 0) {\n throw new OrderValidationError(`Invalid salt: ${order.salt}`);\n }\n\n // Validate nonce\n if (!Number.isInteger(order.nonce) || order.nonce < 0) {\n throw new OrderValidationError(`Invalid nonce: ${order.nonce}`);\n }\n\n // Validate feeRateBps\n if (!Number.isInteger(order.feeRateBps) || order.feeRateBps < 0) {\n throw new OrderValidationError(`Invalid feeRateBps: ${order.feeRateBps}`);\n }\n\n // Validate side (0 or 1)\n if (order.side !== 0 && order.side !== 1) {\n throw new OrderValidationError(`Invalid side: ${order.side}. Must be 0 (BUY) or 1 (SELL)`);\n }\n\n // Validate signatureType\n if (!Number.isInteger(order.signatureType) || order.signatureType < 0) {\n throw new OrderValidationError(`Invalid signatureType: ${order.signatureType}`);\n }\n\n // Validate price if present (for GTC orders)\n if (order.price !== undefined) {\n if (typeof order.price !== 'number' || isNaN(order.price)) {\n throw new OrderValidationError('Price must be a valid number');\n }\n\n if (order.price < 0 || order.price > 1) {\n throw new OrderValidationError(`Price must be between 0 and 1, got: ${order.price}`);\n }\n }\n}\n\n/**\n * Validates a signed order.\n *\n * @param order - Signed order to validate\n * @throws OrderValidationError if validation fails\n *\n * @public\n *\n * @example\n * ```typescript\n * validateSignedOrder(signedOrder);\n * ```\n */\nexport function validateSignedOrder(order: SignedOrder): void {\n // Validate unsigned order fields first\n validateUnsignedOrder(order);\n\n // Validate signature\n if (!order.signature) {\n throw new OrderValidationError('Signature is required');\n }\n\n if (!order.signature.startsWith('0x')) {\n throw new OrderValidationError('Signature must start with 0x');\n }\n\n // Signature should be 132 characters (0x + 130 hex chars for 65 bytes)\n if (order.signature.length !== 132) {\n throw new OrderValidationError(\n `Invalid signature length: ${order.signature.length}. Expected 132 characters.`\n );\n }\n\n // Validate hex format\n if (!/^0x[0-9a-fA-F]{130}$/.test(order.signature)) {\n throw new OrderValidationError('Signature must be valid hex string');\n }\n}\n","/**\n * Market data fetcher for Limitless Exchange.\n * @module markets/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport { Market } from '../types/market-class';\nimport type {\n MarketsResponse,\n OrderBook,\n ActiveMarketsParams,\n ActiveMarketsResponse,\n Venue,\n} from '../types/markets';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Market data fetcher for retrieving market information and orderbooks.\n *\n * @remarks\n * This class provides methods to fetch market data, orderbooks, and prices\n * from the Limitless Exchange API.\n *\n * Venue caching: When fetching market data, venue information is automatically\n * cached for efficient order signing. This eliminates redundant API calls when\n * creating orders for the same market.\n *\n * @public\n */\nexport class MarketFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\n private venueCache: Map<string, Venue>;\n\n /**\n * Creates a new market fetcher instance.\n *\n * @param httpClient - HTTP client for API requests\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * const fetcher = new MarketFetcher(httpClient);\n * ```\n */\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n this.venueCache = new Map();\n }\n\n\n /**\n * Gets active markets with query parameters and pagination support.\n *\n * @param params - Query parameters for filtering and pagination\n * @returns Promise resolving to active markets response\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * // Get 8 markets sorted by LP rewards\n * const response = await fetcher.getActiveMarkets({\n * limit: 8,\n * sortBy: 'lp_rewards'\n * });\n * console.log(`Found ${response.data.length} of ${response.totalMarketsCount} markets`);\n *\n * // Get page 2\n * const page2 = await fetcher.getActiveMarkets({\n * limit: 8,\n * page: 2,\n * sortBy: 'ending_soon'\n * });\n * ```\n */\n async getActiveMarkets(params?: ActiveMarketsParams): Promise<ActiveMarketsResponse> {\n const queryParams = new URLSearchParams();\n\n if (params?.limit !== undefined) {\n queryParams.append('limit', params.limit.toString());\n }\n\n if (params?.page !== undefined) {\n queryParams.append('page', params.page.toString());\n }\n\n if (params?.sortBy) {\n queryParams.append('sortBy', params.sortBy);\n }\n\n const queryString = queryParams.toString();\n const endpoint = `/markets/active${queryString ? `?${queryString}` : ''}`;\n\n this.logger.debug('Fetching active markets', { params });\n\n try {\n const response = await this.httpClient.get<any>(endpoint);\n\n // Convert market data to Market instances with httpClient attached\n const markets = response.data.map((marketData: any) => new Market(marketData, this.httpClient));\n\n const result = {\n data: markets,\n totalMarketsCount: response.totalMarketsCount,\n };\n\n this.logger.info('Active markets fetched successfully', {\n count: markets.length,\n total: response.totalMarketsCount,\n sortBy: params?.sortBy,\n page: params?.page,\n });\n\n return result;\n } catch (error) {\n this.logger.error('Failed to fetch active markets', error as Error, { params });\n throw error;\n }\n }\n\n /**\n * Gets a single market by slug.\n *\n * @remarks\n * Automatically caches venue information for efficient order signing.\n * Always call this method before creating orders to ensure venue data\n * is available and avoid additional API requests.\n *\n * @param slug - Market slug identifier\n * @returns Promise resolving to market details\n * @throws Error if API request fails or market not found\n *\n * @example\n * ```typescript\n * // Get market\n * const market = await fetcher.getMarket('bitcoin-price-2024');\n * console.log(`Market: ${market.title}`);\n *\n * // Fluent API - get user orders for this market (clean!)\n * const orders = await market.getUserOrders();\n * console.log(`You have ${orders.length} orders`);\n *\n * // Venue is now cached for order signing\n * await orderClient.createOrder({\n * marketSlug: 'bitcoin-price-2024',\n * ...\n * });\n * ```\n */\n async getMarket(slug: string): Promise<Market> {\n this.logger.debug('Fetching market', { slug });\n\n try {\n const response = await this.httpClient.get<any>(`/markets/${slug}`);\n\n // Create Market instance with httpClient attached for fluent API\n const market = new Market(response, this.httpClient);\n\n if (market.venue) {\n this.venueCache.set(slug, market.venue);\n this.logger.debug('Venue cached for order signing', {\n slug,\n exchange: market.venue.exchange,\n adapter: market.venue.adapter,\n cacheSize: this.venueCache.size,\n });\n } else {\n this.logger.warn('Market has no venue data', { slug });\n }\n\n this.logger.info('Market fetched successfully', {\n slug,\n title: market.title,\n });\n return market;\n } catch (error) {\n this.logger.error('Failed to fetch market', error as Error, { slug });\n throw error;\n }\n }\n\n /**\n * Gets cached venue information for a market.\n *\n * @remarks\n * Returns venue data previously cached by getMarket() call.\n * Used internally by OrderClient for efficient order signing.\n *\n * @param slug - Market slug identifier\n * @returns Cached venue information, or undefined if not in cache\n *\n * @example\n * ```typescript\n * const venue = fetcher.getVenue('bitcoin-price-2024');\n * if (venue) {\n * console.log(`Exchange: ${venue.exchange}`);\n * }\n * ```\n */\n getVenue(slug: string): Venue | undefined {\n const venue = this.venueCache.get(slug);\n\n if (venue) {\n this.logger.debug('Venue cache hit', {\n slug,\n exchange: venue.exchange,\n });\n } else {\n this.logger.debug('Venue cache miss', { slug });\n }\n\n return venue;\n }\n\n /**\n * Gets the orderbook for a CLOB market.\n *\n * @param slug - Market slug identifier\n * @returns Promise resolving to orderbook data\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const orderbook = await fetcher.getOrderBook('bitcoin-price-2024');\n * console.log(`Bids: ${orderbook.bids.length}, Asks: ${orderbook.asks.length}`);\n * ```\n */\n async getOrderBook(slug: string): Promise<OrderBook> {\n this.logger.debug('Fetching orderbook', { slug });\n\n try {\n const orderbook = await this.httpClient.get<OrderBook>(\n `/markets/${slug}/orderbook`\n );\n\n this.logger.info('Orderbook fetched successfully', {\n slug,\n bids: orderbook.bids.length,\n asks: orderbook.asks.length,\n tokenId: orderbook.tokenId,\n });\n return orderbook;\n } catch (error) {\n this.logger.error('Failed to fetch orderbook', error as Error, { slug });\n throw error;\n }\n }\n\n}\n","/**\n * Portfolio data fetcher for Limitless Exchange.\n * @module portfolio/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport type {\n PortfolioPositionsResponse,\n CLOBPosition,\n AMMPosition,\n Position,\n PortfolioSummary,\n HistoryResponse,\n} from '../types/portfolio';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Portfolio data fetcher for retrieving user positions and portfolio information.\n *\n * @remarks\n * This class provides methods to fetch user positions and calculate portfolio statistics\n * from the Limitless Exchange API. Requires an authenticated HttpClient.\n *\n * @public\n */\nexport class PortfolioFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\n\n /**\n * Creates a new portfolio fetcher instance.\n *\n * @param httpClient - Authenticated HTTP client for API requests\n * @param logger - Optional logger for debugging (default: no logging)\n *\n * @example\n * ```typescript\n * // Create authenticated client\n * const httpClient = new HttpClient({ baseURL: API_URL });\n * await authenticator.authenticate({ client: 'eoa' });\n *\n * // Create portfolio fetcher\n * const portfolioFetcher = new PortfolioFetcher(httpClient);\n * ```\n */\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets user profile for a specific wallet address.\n *\n * @remarks\n * Returns user profile data including user ID and fee rate.\n * Used internally by OrderClient to fetch user data.\n *\n * @param address - Wallet address to fetch profile for\n * @returns Promise resolving to user profile data\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const profile = await portfolioFetcher.getProfile('0x1234...');\n * console.log(`User ID: ${profile.id}`);\n * console.log(`Account: ${profile.account}`);\n * console.log(`Fee Rate: ${profile.rank?.feeRateBps}`);\n * ```\n */\n async getProfile(address: string): Promise<any> {\n this.logger.debug('Fetching user profile', { address });\n\n try {\n const response = await this.httpClient.get<any>(`/profiles/${address}`);\n\n this.logger.info('User profile fetched successfully', { address });\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch user profile', error as Error, { address });\n throw error;\n }\n }\n\n /**\n * Gets raw portfolio positions response from API.\n *\n * @returns Promise resolving to portfolio positions response with CLOB and AMM positions\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const response = await portfolioFetcher.getPositions();\n * console.log(`CLOB positions: ${response.clob.length}`);\n * console.log(`AMM positions: ${response.amm.length}`);\n * console.log(`Total points: ${response.accumulativePoints}`);\n * ```\n */\n async getPositions(): Promise<PortfolioPositionsResponse> {\n this.logger.debug('Fetching user positions');\n\n try {\n const response =\n await this.httpClient.get<PortfolioPositionsResponse>('/portfolio/positions');\n\n this.logger.info('Positions fetched successfully', {\n clobCount: response.clob?.length || 0,\n ammCount: response.amm?.length || 0,\n });\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch positions', error as Error);\n throw error;\n }\n }\n\n /**\n * Gets CLOB positions only.\n *\n * @returns Promise resolving to array of CLOB positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const clobPositions = await portfolioFetcher.getCLOBPositions();\n * clobPositions.forEach(pos => {\n * console.log(`${pos.market.title}: YES ${pos.positions.yes.unrealizedPnl} P&L`);\n * });\n * ```\n */\n async getCLOBPositions(): Promise<CLOBPosition[]> {\n const response = await this.getPositions();\n return response.clob || [];\n }\n\n /**\n * Gets AMM positions only.\n *\n * @returns Promise resolving to array of AMM positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const ammPositions = await portfolioFetcher.getAMMPositions();\n * ammPositions.forEach(pos => {\n * console.log(`${pos.market.title}: ${pos.unrealizedPnl} P&L`);\n * });\n * ```\n */\n async getAMMPositions(): Promise<AMMPosition[]> {\n const response = await this.getPositions();\n return response.amm || [];\n }\n\n /**\n * Gets paginated history of user actions.\n *\n * Includes AMM trades, CLOB trades, Negrisk trades & conversions.\n *\n * @param page - Page number (starts at 1)\n * @param limit - Number of items per page\n * @returns Promise resolving to paginated history response\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * // Get first page\n * const response = await portfolioFetcher.getUserHistory(1, 20);\n * console.log(`Found ${response.data.length} of ${response.totalCount} entries`);\n *\n * // Process history entries\n * for (const entry of response.data) {\n * console.log(`Type: ${entry.type}`);\n * console.log(`Market: ${entry.marketSlug}`);\n * }\n *\n * // Get next page\n * const page2 = await portfolioFetcher.getUserHistory(2, 20);\n * ```\n */\n async getUserHistory(page: number = 1, limit: number = 10): Promise<HistoryResponse> {\n this.logger.debug('Fetching user history', { page, limit });\n\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n limit: limit.toString(),\n });\n\n const response = await this.httpClient.get<HistoryResponse>(\n `/portfolio/history?${params.toString()}`\n );\n\n this.logger.info('User history fetched successfully');\n\n return response;\n } catch (error) {\n this.logger.error('Failed to fetch user history', error as Error, { page, limit });\n throw error;\n }\n }\n}\n","/**\n * Order client for managing orders on Limitless Exchange.\n * @module orders/client\n */\n\nimport type { HttpClient } from '../api/http';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\nimport type {\n NewOrderPayload,\n OrderResponse,\n OrderArgs,\n UnsignedOrder,\n OrderSigningConfig,\n} from '../types/orders';\nimport { OrderType } from '../types/orders';\nimport { OrderBuilder } from './builder';\nimport { OrderSigner } from './signer';\nimport type { ethers } from 'ethers';\nimport type { UserData } from '../types/auth';\nimport { ZERO_ADDRESS } from '../utils/constants';\nimport { toFiniteInteger, toFiniteNumber } from '../utils/number-flex';\nimport { MarketFetcher } from '../markets/fetcher';\nimport { PortfolioFetcher } from '../portfolio/fetcher';\n\n/**\n * Configuration for the order client.\n *\n * @remarks\n * The order client auto-configures signing based on venue data from the API.\n * User data (userId, feeRateBps) is automatically fetched from the profile API\n * on first order creation and cached for subsequent orders.\n *\n * Performance tip: Provide a shared marketFetcher instance to enable venue caching\n * across market fetches and order creation, avoiding redundant API calls.\n *\n * @public\n */\nexport interface OrderClientConfig {\n /**\n * HTTP client for API requests (must have API key configured)\n */\n httpClient: HttpClient;\n\n /**\n * Wallet for signing orders with EIP-712\n */\n wallet: ethers.Wallet;\n\n /**\n * Custom signing configuration (optional)\n *\n * @remarks\n * If not provided, SDK will auto-configure from venue data.\n * Useful for custom deployments or testing.\n */\n signingConfig?: OrderSigningConfig;\n\n /**\n * Shared MarketFetcher instance for venue caching (optional)\n *\n * @remarks\n * When provided, enables efficient venue caching across market fetches and order creation.\n * If not provided, OrderClient creates its own internal MarketFetcher instance.\n *\n * Best practice: Share the same MarketFetcher instance between market operations\n * and order creation for optimal performance.\n *\n * @example\n * ```typescript\n * const marketFetcher = new MarketFetcher(httpClient);\n * const orderClient = new OrderClient({\n * httpClient,\n * wallet,\n * marketFetcher // Shared instance\n * });\n *\n * // Venue is cached\n * await marketFetcher.getMarket('bitcoin-2024');\n *\n * // Uses cached venue, no extra API call\n * await orderClient.createOrder({ marketSlug: 'bitcoin-2024', ... });\n * ```\n */\n marketFetcher?: MarketFetcher;\n\n /**\n * Optional logger\n */\n logger?: ILogger;\n}\n\n/**\n * Order client for creating and managing orders.\n *\n * @remarks\n * This class provides high-level methods for order operations,\n * abstracting away HTTP details and order signing complexity.\n *\n * User data (userId, feeRateBps) is automatically fetched from profile API\n * on first order creation and cached for subsequent orders.\n *\n * Uses dynamic venue addressing for EIP-712 order signing. For best performance,\n * always call marketFetcher.getMarket() before creating orders to cache venue data.\n *\n * @example\n * ```typescript\n * import { ethers } from 'ethers';\n *\n * const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);\n * const orderClient = new OrderClient({\n * httpClient, // Must have API key configured\n * wallet, // For EIP-712 signing\n * });\n *\n * // User data automatically fetched on first order\n * const order = await orderClient.createOrder({\n * tokenId: '123...',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'market-slug'\n * });\n * ```\n *\n * @public\n */\nexport class OrderClient {\n private httpClient: HttpClient;\n private wallet: ethers.Wallet;\n private orderBuilder?: OrderBuilder;\n private orderSigner: OrderSigner;\n private marketFetcher: MarketFetcher;\n private cachedUserData?: UserData;\n private signingConfig: OrderSigningConfig;\n private logger: ILogger;\n\n /**\n * Creates a new order client instance.\n *\n * @param config - Order client configuration\n */\n constructor(config: OrderClientConfig) {\n this.httpClient = config.httpClient;\n this.wallet = config.wallet;\n this.logger = config.logger || new NoOpLogger();\n\n this.orderSigner = new OrderSigner(config.wallet, this.logger);\n\n this.marketFetcher = config.marketFetcher || new MarketFetcher(config.httpClient, this.logger);\n\n // Configure signing: use provided config or auto-configure\n if (config.signingConfig) {\n // Use custom signing configuration\n this.signingConfig = config.signingConfig;\n } else {\n // Auto-configure base settings\n const chainId = parseInt(process.env.CHAIN_ID || '8453'); // Base mainnet default\n\n // Note: contractAddress is a placeholder here and will be dynamically replaced\n // with venue.exchange in createOrder(). The actual contract address comes from\n // the venue system (market.venue.exchange).\n const contractAddress = ZERO_ADDRESS;\n\n this.signingConfig = {\n chainId,\n contractAddress,\n };\n\n this.logger.info('Auto-configured signing (contract address from venue)', {\n chainId,\n });\n }\n }\n\n /**\n * Ensures user data is loaded and cached.\n * Fetches from profile API on first call, then caches for subsequent calls.\n *\n * @returns Promise resolving to cached user data\n * @internal\n */\n private async ensureUserData(): Promise<UserData> {\n if (!this.cachedUserData) {\n this.logger.info('Fetching user profile for order client initialization...', {\n walletAddress: this.wallet.address,\n });\n\n const portfolioFetcher = new PortfolioFetcher(this.httpClient);\n const profile = await portfolioFetcher.getProfile(this.wallet.address);\n\n const userId = toFiniteInteger(profile.id);\n const feeRateBps = toFiniteInteger(profile.rank?.feeRateBps) ?? 300;\n if (userId === undefined) {\n throw new Error(`Invalid user profile id: ${profile.id}`);\n }\n\n this.cachedUserData = {\n userId,\n feeRateBps,\n };\n\n this.orderBuilder = new OrderBuilder(\n this.wallet.address,\n this.cachedUserData.feeRateBps,\n 0.001\n );\n\n this.logger.info('Order Client initialized', {\n walletAddress: profile.account,\n userId: this.cachedUserData.userId,\n feeRate: `${this.cachedUserData.feeRateBps / 100}%`,\n });\n }\n\n return this.cachedUserData;\n }\n\n /**\n * Creates and submits a new order.\n *\n * @remarks\n * This method handles the complete order creation flow:\n * 1. Resolve venue address (from cache or API)\n * 2. Build unsigned order\n * 3. Sign with EIP-712 using venue.exchange as verifyingContract\n * 4. Submit to API\n *\n * Performance best practice: Always call marketFetcher.getMarket(marketSlug)\n * before createOrder() to cache venue data and avoid additional API requests.\n *\n * @param params - Order parameters\n * @returns Promise resolving to order response\n *\n * @throws Error if order creation fails or venue not found\n *\n * @example\n * ```typescript\n * // Best practice: fetch market first to cache venue\n * const market = await marketFetcher.getMarket('bitcoin-2024');\n *\n * const order = await orderClient.createOrder({\n * tokenId: market.tokens.yes,\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'bitcoin-2024'\n * });\n *\n * console.log(`Order created: ${order.order.id}`);\n * ```\n */\n async createOrder(\n params: OrderArgs & {\n orderType: OrderType;\n marketSlug: string;\n }\n ): Promise<OrderResponse> {\n // Ensure user data is loaded (lazy loading with cache)\n const userData = await this.ensureUserData();\n\n this.logger.info('Creating order', {\n side: params.side,\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n });\n\n let venue = this.marketFetcher.getVenue(params.marketSlug);\n\n if (!venue) {\n this.logger.warn(\n 'Venue not cached, fetching market details. ' +\n 'For better performance, call marketFetcher.getMarket() before createOrder().',\n { marketSlug: params.marketSlug }\n );\n\n const market = await this.marketFetcher.getMarket(params.marketSlug);\n\n if (!market.venue) {\n throw new Error(\n `Market ${params.marketSlug} does not have venue information. ` +\n 'Venue data is required for order signing.'\n );\n }\n\n venue = market.venue;\n }\n\n const dynamicSigningConfig: OrderSigningConfig = {\n ...this.signingConfig,\n contractAddress: venue.exchange,\n };\n\n this.logger.debug('Using venue for order signing', {\n marketSlug: params.marketSlug,\n exchange: venue.exchange,\n adapter: venue.adapter,\n });\n\n const unsignedOrder = this.orderBuilder!.buildOrder(params);\n\n this.logger.debug('Built unsigned order', {\n salt: unsignedOrder.salt,\n makerAmount: unsignedOrder.makerAmount,\n takerAmount: unsignedOrder.takerAmount,\n });\n\n const signature = await this.orderSigner.signOrder(unsignedOrder, dynamicSigningConfig);\n\n // Step 3: Prepare payload for API\n const payload: NewOrderPayload = {\n order: {\n ...unsignedOrder,\n signature,\n },\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n ownerId: userData.userId,\n };\n\n // Step 4: Submit to API\n this.logger.debug('Submitting order to API', payload);\n const apiResponse = await this.httpClient.post<any>('/orders', payload);\n\n this.logger.info('Order created successfully', {\n orderId: apiResponse.order.id,\n });\n\n // Step 5: Transform API response to clean DTO\n return this.transformOrderResponse(apiResponse);\n }\n\n /**\n * Transforms raw API response to clean OrderResponse DTO.\n *\n * @param apiResponse - Raw API response with nested objects\n * @returns Clean OrderResponse with only essential fields\n *\n * @internal\n */\n private transformOrderResponse(apiResponse: any): OrderResponse {\n const order = apiResponse.order;\n\n const cleanOrder: OrderResponse = {\n order: {\n id: order.id,\n createdAt: order.createdAt,\n makerAmount: toFiniteNumber(order.makerAmount) ?? order.makerAmount,\n takerAmount: toFiniteNumber(order.takerAmount) ?? order.takerAmount,\n expiration: order.expiration,\n signatureType: order.signatureType,\n salt: toFiniteInteger(order.salt) ?? order.salt,\n maker: order.maker,\n signer: order.signer,\n taker: order.taker,\n tokenId: order.tokenId,\n side: order.side,\n feeRateBps: order.feeRateBps,\n nonce: order.nonce,\n signature: order.signature,\n orderType: order.orderType,\n price: order.price === undefined || order.price === null ? order.price : toFiniteNumber(order.price) ?? order.price,\n marketId: order.marketId,\n },\n };\n\n // Add maker matches if present (FOK or partial GTC fills)\n if (apiResponse.makerMatches && apiResponse.makerMatches.length > 0) {\n cleanOrder.makerMatches = apiResponse.makerMatches.map((match: any) => ({\n id: match.id,\n createdAt: match.createdAt,\n matchedSize: match.matchedSize,\n orderId: match.orderId,\n }));\n }\n\n return cleanOrder;\n }\n\n /**\n * Cancels an existing order by ID.\n *\n * @param orderId - Order ID to cancel\n * @returns Promise resolving to cancellation message\n *\n * @throws Error if cancellation fails\n *\n * @example\n * ```typescript\n * const result = await orderClient.cancel('order-id-123');\n * console.log(result.message); // \"Order canceled successfully\"\n * ```\n */\n async cancel(orderId: string): Promise<{ message: string }> {\n this.logger.info('Cancelling order', { orderId });\n\n const response = await this.httpClient.delete<{ message: string }>(`/orders/${orderId}`);\n\n this.logger.info('Order cancellation response', {\n orderId,\n message: response.message,\n });\n\n return response;\n }\n\n /**\n * Cancels all orders for a specific market.\n *\n * @param marketSlug - Market slug to cancel all orders for\n * @returns Promise resolving to cancellation message\n *\n * @throws Error if cancellation fails\n *\n * @example\n * ```typescript\n * const result = await orderClient.cancelAll('market-slug-123');\n * console.log(result.message); // \"Orders canceled successfully\"\n * ```\n */\n async cancelAll(marketSlug: string): Promise<{ message: string }> {\n this.logger.info('Cancelling all orders for market', { marketSlug });\n\n const response = await this.httpClient.delete<{ message: string }>(`/orders/all/${marketSlug}`);\n\n this.logger.info('All orders cancellation response', {\n marketSlug,\n message: response.message,\n });\n\n return response;\n }\n\n /**\n * Builds an unsigned order without submitting.\n *\n * @remarks\n * Useful for advanced use cases where you need the unsigned order\n * before signing and submission.\n *\n * @param params - Order parameters\n * @returns Promise resolving to unsigned order\n *\n * @example\n * ```typescript\n * const unsignedOrder = await orderClient.buildUnsignedOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY\n * });\n * ```\n */\n async buildUnsignedOrder(params: OrderArgs): Promise<UnsignedOrder> {\n // Ensure user data is loaded for order builder\n await this.ensureUserData();\n return this.orderBuilder!.buildOrder(params);\n }\n\n /**\n * Signs an unsigned order without submitting.\n *\n * @remarks\n * Useful for advanced use cases where you need to inspect\n * the signature before submission.\n *\n * @param order - Unsigned order to sign\n * @returns Promise resolving to signature\n *\n * @example\n * ```typescript\n * const signature = await orderClient.signOrder(unsignedOrder);\n * ```\n */\n async signOrder(order: UnsignedOrder): Promise<string> {\n return await this.orderSigner.signOrder(order, this.signingConfig);\n }\n\n /**\n * Gets the wallet address.\n *\n * @returns Ethereum address of the wallet\n *\n * @example\n * ```typescript\n * const address = orderClient.walletAddress;\n * console.log(`Wallet: ${address}`);\n * ```\n */\n get walletAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Gets the owner ID (user ID from profile).\n *\n * @returns Owner ID from user profile, or undefined if not yet loaded\n *\n * @example\n * ```typescript\n * const ownerId = orderClient.ownerId;\n * if (ownerId) {\n * console.log(`Owner ID: ${ownerId}`);\n * }\n * ```\n */\n get ownerId(): number | undefined {\n return this.cachedUserData?.userId;\n }\n}\n","import type { AxiosRequestConfig } from 'axios';\nimport { HttpClient } from '../api/http';\nimport { Market } from '../types/market-class';\nimport type {\n MarketPage,\n MarketPageMarketsParams,\n MarketPageMarketsResponse,\n NavigationNode,\n PropertyKey,\n PropertyOption,\n} from '../types/market-pages';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\nconst MAX_REDIRECT_DEPTH = 3;\n\n/**\n * Fetcher for market-pages and property-keys APIs.\n *\n * @remarks\n * This class provides access to the new navigation-driven market discovery API.\n *\n * @public\n */\nexport class MarketPageFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\n\n /**\n * Creates a new market-pages fetcher.\n *\n * @param httpClient - HTTP client for API calls\n * @param logger - Optional logger\n */\n constructor(httpClient: HttpClient, logger?: ILogger) {\n this.httpClient = httpClient;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets the navigation tree.\n */\n async getNavigation(): Promise<NavigationNode[]> {\n this.logger.debug('Fetching navigation tree');\n return this.httpClient.get<NavigationNode[]>('/navigation');\n }\n\n /**\n * Resolves a market page by path.\n *\n * @remarks\n * Handles 301 redirects manually by re-requesting `/market-pages/by-path` with the\n * redirected path value from `Location` header.\n */\n async getMarketPageByPath(path: string): Promise<MarketPage> {\n return this.getMarketPageByPathInternal(path, 0);\n }\n\n private async getMarketPageByPathInternal(path: string, depth: number): Promise<MarketPage> {\n const query = new URLSearchParams({ path }).toString();\n const endpoint = `/market-pages/by-path?${query}`;\n\n const requestConfig: AxiosRequestConfig = {\n maxRedirects: 0,\n validateStatus: (status) => status === 200 || status === 301,\n };\n\n this.logger.debug('Resolving market page by path', { path, depth });\n\n const response = await this.httpClient.getRaw<MarketPage>(endpoint, requestConfig);\n\n if (response.status === 200) {\n return response.data;\n }\n\n if (response.status !== 301) {\n throw new Error(`Unexpected response status: ${response.status}`);\n }\n\n if (depth >= MAX_REDIRECT_DEPTH) {\n throw new Error(\n `Too many redirects while resolving market page path '${path}' (max ${MAX_REDIRECT_DEPTH})`\n );\n }\n\n const locationHeader = response.headers?.location;\n const location = Array.isArray(locationHeader) ? locationHeader[0] : locationHeader;\n\n if (!location || typeof location !== 'string') {\n throw new Error('Redirect response missing valid Location header');\n }\n\n const redirectedPath = this.extractRedirectPath(location);\n\n this.logger.info('Following market page redirect', {\n from: path,\n to: redirectedPath,\n depth: depth + 1,\n });\n\n return this.getMarketPageByPathInternal(redirectedPath, depth + 1);\n }\n\n private extractRedirectPath(location: string): string {\n const directByPathPrefix = '/market-pages/by-path';\n\n // Already in by-path format\n if (location.startsWith(directByPathPrefix)) {\n const url = new URL(location, 'https://api.limitless.exchange');\n const path = url.searchParams.get('path');\n if (!path) {\n throw new Error(\"Redirect location '/market-pages/by-path' is missing required 'path' query parameter\");\n }\n return path;\n }\n\n // Absolute URL\n if (/^https?:\\/\\//i.test(location)) {\n const url = new URL(location);\n if (url.pathname === directByPathPrefix) {\n const path = url.searchParams.get('path');\n if (!path) {\n throw new Error(\"Redirect location '/market-pages/by-path' is missing required 'path' query parameter\");\n }\n return path;\n }\n return url.pathname || '/';\n }\n\n // Path redirect as documented by backend (e.g. /sports/nba)\n return location;\n }\n\n /**\n * Gets markets for a market page with optional filtering and pagination.\n */\n async getMarkets(\n pageId: string,\n params: MarketPageMarketsParams = {}\n ): Promise<MarketPageMarketsResponse> {\n if (params.cursor !== undefined && params.page !== undefined) {\n throw new Error('Parameters `cursor` and `page` are mutually exclusive');\n }\n\n const query = new URLSearchParams();\n\n if (params.page !== undefined) {\n query.append('page', String(params.page));\n }\n\n if (params.limit !== undefined) {\n query.append('limit', String(params.limit));\n }\n\n if (params.sort) {\n query.append('sort', params.sort);\n }\n\n if (params.cursor !== undefined) {\n query.append('cursor', params.cursor);\n }\n\n if (params.filters) {\n for (const [key, value] of Object.entries(params.filters)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n query.append(key, this.stringifyFilterValue(item));\n }\n } else {\n query.append(key, this.stringifyFilterValue(value));\n }\n }\n }\n\n const queryString = query.toString();\n const endpoint = `/market-pages/${pageId}/markets${queryString ? `?${queryString}` : ''}`;\n\n this.logger.debug('Fetching market-page markets', { pageId, params });\n\n const response = await this.httpClient.get<any>(endpoint);\n const markets = (response.data || []).map((marketData: any) => new Market(marketData, this.httpClient));\n\n if (response.pagination) {\n return {\n data: markets,\n pagination: response.pagination,\n };\n }\n\n if (response.cursor) {\n return {\n data: markets,\n cursor: response.cursor,\n };\n }\n\n throw new Error('Invalid market-page response: expected `pagination` or `cursor` metadata');\n }\n\n /**\n * Lists all property keys with options.\n */\n async getPropertyKeys(): Promise<PropertyKey[]> {\n return this.httpClient.get<PropertyKey[]>('/property-keys');\n }\n\n /**\n * Gets a single property key by ID.\n */\n async getPropertyKey(id: string): Promise<PropertyKey> {\n return this.httpClient.get<PropertyKey>(`/property-keys/${id}`);\n }\n\n /**\n * Lists options for a property key, optionally filtered by parent option ID.\n */\n async getPropertyOptions(keyId: string, parentId?: string): Promise<PropertyOption[]> {\n const query = new URLSearchParams();\n if (parentId) {\n query.append('parentId', parentId);\n }\n\n const queryString = query.toString();\n const endpoint = `/property-keys/${keyId}/options${queryString ? `?${queryString}` : ''}`;\n\n return this.httpClient.get<PropertyOption[]>(endpoint);\n }\n\n private stringifyFilterValue(value: string | number | boolean): string {\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n return String(value);\n }\n}\n","/**\n * WebSocket client for real-time data streaming.\n * @module websocket/client\n */\n\nimport { io, Socket } from 'socket.io-client';\nimport { DEFAULT_WS_URL } from '../utils/constants';\nimport { buildWebSocketTrackingHeaders } from '../utils/sdk-tracking';\nimport { computeHMACSignature } from '../api/hmac';\nimport {\n WebSocketState,\n type WebSocketConfig,\n type WebSocketEvents,\n type SubscriptionChannel,\n type SubscriptionOptions,\n} from '../types/websocket';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\ninterface ResolvedWebSocketConfig {\n url: string;\n apiKey: string;\n hmacCredentials?: WebSocketConfig['hmacCredentials'];\n autoReconnect: boolean;\n reconnectDelay: number;\n maxReconnectAttempts: number;\n timeout: number;\n}\n\n/**\n * WebSocket client for real-time data streaming from Limitless Exchange.\n *\n * @remarks\n * This client uses Socket.IO to connect to the WebSocket server and provides\n * typed event subscriptions for orderbook, trades, orders, and market data.\n *\n * **Public Subscriptions** (no authentication required):\n * - Market prices (AMM)\n * - Orderbook updates (CLOB)\n *\n * **Authenticated Subscriptions** (require API key):\n * - User positions\n * - User transactions\n *\n * @example\n * ```typescript\n * // Public subscription (no API key needed)\n * const wsClient = new WebSocketClient({\n * autoReconnect: true,\n * });\n *\n * await wsClient.connect();\n * await wsClient.subscribe('subscribe_market_prices', {\n * marketSlugs: ['market-123']\n * });\n *\n * // Authenticated subscription (API key required)\n * const wsClientAuth = new WebSocketClient({\n * apiKey: process.env.LIMITLESS_API_KEY,\n * autoReconnect: true,\n * });\n *\n * await wsClientAuth.connect();\n * await wsClientAuth.subscribe('subscribe_positions', {\n * marketSlugs: ['market-123']\n * });\n * ```\n *\n * @public\n */\nexport class WebSocketClient {\n private socket: Socket | null = null;\n private config: ResolvedWebSocketConfig;\n private logger: ILogger;\n private state: WebSocketState = WebSocketState.DISCONNECTED;\n private reconnectAttempts = 0;\n private subscriptions: Map<string, SubscriptionOptions> = new Map();\n private pendingListeners: Array<{ event: string; handler: any }> = [];\n\n /**\n * Creates a new WebSocket client.\n *\n * @param config - WebSocket configuration\n * @param logger - Optional logger for debugging\n */\n constructor(config: WebSocketConfig = {}, logger?: ILogger) {\n this.config = {\n url: config.url || DEFAULT_WS_URL,\n apiKey: config.apiKey || process.env.LIMITLESS_API_KEY || '',\n hmacCredentials: config.hmacCredentials,\n autoReconnect: config.autoReconnect ?? true,\n reconnectDelay: config.reconnectDelay || 1000,\n maxReconnectAttempts: config.maxReconnectAttempts || Infinity,\n timeout: config.timeout || 10000,\n };\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets current connection state.\n *\n * @returns Current WebSocket state\n */\n getState(): WebSocketState {\n return this.state;\n }\n\n /**\n * Checks if client is connected.\n *\n * @returns True if connected\n */\n isConnected(): boolean {\n return this.state === WebSocketState.CONNECTED && this.socket?.connected === true;\n }\n\n /**\n * Sets the API key for authentication.\n *\n * @param apiKey - API key value\n *\n * @remarks\n * API key is required for authenticated subscriptions (positions, transactions).\n * If already connected, this will trigger a reconnection with the new API key.\n */\n setApiKey(apiKey: string): void {\n this.config.apiKey = apiKey;\n\n // If already connected, reconnect with new auth\n if (this.socket?.connected) {\n this.logger.info('API key updated, reconnecting...');\n // Schedule async reconnection without blocking\n this.reconnectWithNewAuth();\n }\n }\n\n /**\n * Sets HMAC credentials for authenticated subscriptions.\n *\n * @remarks\n * When configured alongside `apiKey`, this client uses HMAC headers for authenticated subscriptions.\n */\n setHMACCredentials(hmacCredentials: NonNullable<WebSocketConfig['hmacCredentials']>): void {\n this.config.hmacCredentials = {\n tokenId: hmacCredentials.tokenId,\n secret: hmacCredentials.secret,\n };\n\n if (this.socket?.connected) {\n this.logger.info('HMAC credentials updated, reconnecting...');\n this.reconnectWithNewAuth();\n }\n }\n\n /**\n * Clears HMAC credentials.\n */\n clearHMACCredentials(): void {\n this.config.hmacCredentials = undefined;\n\n if (this.socket?.connected) {\n this.logger.info('HMAC credentials cleared, reconnecting...');\n this.reconnectWithNewAuth();\n }\n }\n\n /**\n * Reconnects with new authentication credentials.\n * @internal\n */\n private async reconnectWithNewAuth(): Promise<void> {\n await this.disconnect();\n await this.connect();\n }\n\n /**\n * Connects to the WebSocket server.\n *\n * @returns Promise that resolves when connected\n * @throws Error if connection fails\n *\n * @example\n * ```typescript\n * await wsClient.connect();\n * console.log('Connected!');\n * ```\n */\n async connect(): Promise<void> {\n // Fix: Prevent race condition by checking CONNECTING state\n if (this.socket?.connected || this.state === WebSocketState.CONNECTING) {\n this.logger.info('Already connected or connecting');\n return;\n }\n\n this.logger.info('Connecting to WebSocket', { url: this.config.url });\n this.state = WebSocketState.CONNECTING;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout after ${this.config.timeout}ms`));\n }, this.config.timeout);\n\n // Create Socket.IO connection to /markets namespace\n // API key is sent via X-API-Key header for authenticated subscriptions\n const wsUrl = this.config.url;\n\n const socketOptions: any = {\n transports: ['websocket'], // Use WebSocket transport only\n reconnection: this.config.autoReconnect,\n reconnectionDelay: this.config.reconnectDelay,\n reconnectionDelayMax: Math.min(this.config.reconnectDelay * 32, 60000), // Max 60s\n reconnectionAttempts:\n this.config.maxReconnectAttempts === Infinity ? 0 : this.config.maxReconnectAttempts, // 0 = infinite\n randomizationFactor: 0.2, // Add jitter to prevent thundering herd\n timeout: this.config.timeout,\n };\n const extraHeaders = buildWebSocketTrackingHeaders();\n\n if (this.config.hmacCredentials) {\n const timestamp = new Date().toISOString();\n const signature = computeHMACSignature(\n this.config.hmacCredentials.secret,\n timestamp,\n 'GET',\n '/socket.io/?EIO=4&transport=websocket',\n '',\n );\n\n socketOptions.extraHeaders = {\n ...extraHeaders,\n 'lmts-api-key': this.config.hmacCredentials.tokenId,\n 'lmts-timestamp': timestamp,\n 'lmts-signature': signature,\n };\n } else if (this.config.apiKey) {\n // Add API key to headers if provided\n // Required for authenticated subscriptions (positions, transactions)\n socketOptions.extraHeaders = {\n ...extraHeaders,\n 'X-API-Key': this.config.apiKey,\n };\n } else if (Object.keys(extraHeaders).length > 0) {\n socketOptions.extraHeaders = extraHeaders;\n }\n\n // Connect to base URL with /markets namespace\n this.socket = io(wsUrl + '/markets', socketOptions);\n\n // Attach any pending listeners that were added before connect()\n this.attachPendingListeners();\n\n // Setup event handlers\n this.setupEventHandlers();\n\n // Handle connection\n this.socket.once('connect', () => {\n clearTimeout(timeout);\n this.state = WebSocketState.CONNECTED;\n this.reconnectAttempts = 0;\n this.logger.info('WebSocket connected');\n\n // Re-subscribe to all previous subscriptions\n this.resubscribeAll();\n\n resolve();\n });\n\n // Handle connection error\n this.socket.once('connect_error', (error) => {\n clearTimeout(timeout);\n this.state = WebSocketState.ERROR;\n this.logger.error('WebSocket connection error', error);\n reject(error);\n });\n });\n }\n\n /**\n * Disconnects from the WebSocket server.\n *\n * @returns Promise that resolves when disconnected\n *\n * @example\n * ```typescript\n * await wsClient.disconnect();\n * ```\n */\n async disconnect(): Promise<void> {\n if (!this.socket) {\n return;\n }\n\n this.logger.info('Disconnecting from WebSocket');\n this.socket.disconnect();\n this.socket = null;\n this.state = WebSocketState.DISCONNECTED;\n this.subscriptions.clear();\n }\n\n /**\n * Subscribes to a channel.\n *\n * @param channel - Channel to subscribe to\n * @param options - Subscription options\n * @returns Promise that resolves immediately (kept async for API compatibility)\n * @throws Error if not connected\n *\n * @example\n * ```typescript\n * // Subscribe to orderbook for a specific market\n * await wsClient.subscribe('orderbook', { marketSlugs: ['market-123'] });\n *\n * // Subscribe to all trades\n * await wsClient.subscribe('trades');\n *\n * // Subscribe to your orders\n * await wsClient.subscribe('orders');\n * ```\n */\n async subscribe(channel: SubscriptionChannel, options: SubscriptionOptions = {}): Promise<void> {\n if (!this.isConnected()) {\n throw new Error('WebSocket not connected. Call connect() first.');\n }\n\n // Check if API key is required for authenticated channels\n const authenticatedChannels: SubscriptionChannel[] = [\n 'subscribe_positions',\n 'subscribe_transactions',\n ];\n if (authenticatedChannels.includes(channel) && !this.config.apiKey && !this.config.hmacCredentials) {\n throw new Error(\n `Authentication is required for '${channel}' subscription. ` +\n 'Please provide either apiKey or hmacCredentials when creating the WebSocket client.'\n );\n }\n\n const subscriptionKey = this.getSubscriptionKey(channel, options);\n this.subscriptions.set(subscriptionKey, options);\n\n this.logger.info('Subscribing to channel', { channel, options });\n\n // Pass channel and options as-is to the server - no transformation\n // Note: Server returns Promise<void>, so no acknowledgment callback is used\n // This is fire-and-forget to avoid timeout issues when server doesn't send ACK\n this.socket!.emit(channel, options);\n this.logger.info('Subscription request sent', { channel, options });\n }\n\n /**\n * Unsubscribes from a channel.\n *\n * @param channel - Channel to unsubscribe from\n * @param options - Subscription options (must match subscribe call)\n * @returns Promise that resolves when unsubscribed\n * @throws Error if not connected or unsubscribe fails\n *\n * @example\n * ```typescript\n * await wsClient.unsubscribe('orderbook', { marketSlugs: ['market-123'] });\n * ```\n */\n async unsubscribe(\n channel: SubscriptionChannel,\n options: SubscriptionOptions = {}\n ): Promise<void> {\n if (!this.isConnected()) {\n throw new Error('WebSocket not connected');\n }\n\n const subscriptionKey = this.getSubscriptionKey(channel, options);\n this.subscriptions.delete(subscriptionKey);\n\n this.logger.info('Unsubscribing from channel', { channel, options });\n\n try {\n // Emit unsubscribe event with acknowledgment (waits for server response)\n const unsubscribeData = { channel, ...options };\n const response = await this.socket!.timeout(5000).emitWithAck('unsubscribe', unsubscribeData);\n\n // Check for errors in response\n if (response && typeof response === 'object' && 'error' in response) {\n const errorMsg = (response as any).error;\n this.logger.error('Unsubscribe failed', new Error(errorMsg), { error: errorMsg });\n throw new Error(`Unsubscribe failed: ${errorMsg}`);\n }\n\n this.logger.info('Unsubscribed successfully', { channel, options });\n } catch (error) {\n this.logger.error('Unsubscribe error', error as Error, { channel });\n throw error;\n }\n }\n\n /**\n * Registers an event listener.\n *\n * @param event - Event name\n * @param handler - Event handler\n * @returns This client for chaining\n *\n * @example\n * ```typescript\n * wsClient\n * .on('orderbook', (data) => console.log('Orderbook:', data))\n * .on('trade', (data) => console.log('Trade:', data))\n * .on('error', (error) => console.error('Error:', error));\n * ```\n */\n on<K extends keyof WebSocketEvents>(event: K, handler: WebSocketEvents[K]): this {\n if (!this.socket) {\n // Store listener to be attached when socket is created\n this.pendingListeners.push({ event: event as string, handler });\n return this;\n }\n\n // Pass raw event names, no transformation\n this.socket.on(event as string, handler as any);\n return this;\n }\n\n /**\n * Registers a one-time event listener.\n *\n * @param event - Event name\n * @param handler - Event handler\n * @returns This client for chaining\n */\n once<K extends keyof WebSocketEvents>(event: K, handler: WebSocketEvents[K]): this {\n if (!this.socket) {\n throw new Error('WebSocket not initialized. Call connect() first.');\n }\n\n // Pass raw event names, no transformation\n this.socket.once(event as string, handler as any);\n return this;\n }\n\n /**\n * Removes an event listener.\n *\n * @param event - Event name\n * @param handler - Event handler to remove (if undefined, removes all handlers for event)\n * @returns This client for chaining\n *\n * @example\n * ```typescript\n * // Remove specific handler\n * wsClient.off('orderbookUpdate', myHandler);\n *\n * // Remove all handlers for event\n * wsClient.off('orderbookUpdate');\n * ```\n */\n off<K extends keyof WebSocketEvents>(event: K, handler?: WebSocketEvents[K]): this {\n if (!this.socket) {\n return this;\n }\n\n if (handler === undefined) {\n // Remove all handlers for event\n this.socket.removeAllListeners(event as string);\n } else {\n // Remove specific handler\n this.socket.off(event as string, handler as any);\n }\n\n return this;\n }\n\n /**\n * Attach any pending event listeners that were added before connect().\n * @internal\n */\n private attachPendingListeners(): void {\n if (!this.socket || this.pendingListeners.length === 0) {\n return;\n }\n\n for (const { event, handler } of this.pendingListeners) {\n // Pass event names as-is, no transformation\n this.socket.on(event, handler);\n }\n\n // Clear pending listeners\n this.pendingListeners = [];\n }\n\n /**\n * Setup internal event handlers for connection management.\n * @internal\n */\n private setupEventHandlers(): void {\n if (!this.socket) {\n return;\n }\n\n // Connection events\n this.socket.on('connect', () => {\n this.state = WebSocketState.CONNECTED;\n this.reconnectAttempts = 0;\n this.logger.info('WebSocket connected');\n });\n\n this.socket.on('disconnect', (reason) => {\n this.state = WebSocketState.DISCONNECTED;\n this.logger.info('WebSocket disconnected', { reason });\n });\n\n this.socket.on('error', (error) => {\n this.state = WebSocketState.ERROR;\n this.logger.error('WebSocket error', error);\n });\n\n // Reconnection events\n this.socket.io.on('reconnect_attempt', (attempt) => {\n this.state = WebSocketState.RECONNECTING;\n this.reconnectAttempts = attempt;\n this.logger.info('Reconnecting...', { attempt });\n });\n\n this.socket.io.on('reconnect', (attempt) => {\n this.state = WebSocketState.CONNECTED;\n this.logger.info('Reconnected', { attempts: attempt });\n this.resubscribeAll();\n });\n\n this.socket.io.on('reconnect_error', (error) => {\n this.logger.error('Reconnection error', error);\n });\n\n this.socket.io.on('reconnect_failed', () => {\n this.state = WebSocketState.ERROR;\n this.logger.error('Reconnection failed');\n });\n }\n\n /**\n * Re-subscribes to all previous subscriptions after reconnection.\n * @internal\n */\n private async resubscribeAll(): Promise<void> {\n if (this.subscriptions.size === 0) {\n return;\n }\n\n this.logger.info('Re-subscribing to channels', {\n count: this.subscriptions.size,\n });\n\n for (const [key, options] of this.subscriptions.entries()) {\n const channel = this.getChannelFromKey(key);\n try {\n await this.subscribe(channel, options);\n } catch (error) {\n this.logger.error('Failed to re-subscribe', error as Error, { channel, options });\n }\n }\n }\n\n /**\n * Creates a unique subscription key.\n * @internal\n */\n private getSubscriptionKey(channel: SubscriptionChannel, options: SubscriptionOptions): string {\n return `${channel}:${options.marketSlug || 'global'}`;\n }\n\n /**\n * Extracts channel from subscription key.\n * @internal\n */\n private getChannelFromKey(key: string): SubscriptionChannel {\n return key.split(':')[0] as SubscriptionChannel;\n }\n}\n","import { ethers } from 'ethers';\nimport { HttpClient, type HttpClientConfig } from './api/http';\nimport { MarketFetcher } from './markets/fetcher';\nimport { PortfolioFetcher } from './portfolio/fetcher';\nimport { MarketPageFetcher } from './market-pages/fetcher';\nimport { ApiTokenService } from './api-tokens/service';\nimport { PartnerAccountService } from './partner-accounts/service';\nimport { DelegatedOrderService } from './delegated-orders/service';\nimport { OrderClient, type OrderClientConfig } from './orders/client';\nimport { WebSocketClient } from './websocket/client';\nimport type { WebSocketConfig } from './types/websocket';\nimport { NoOpLogger } from './types/logger';\n\n/**\n * Root OOP entrypoint for the SDK.\n *\n * @remarks\n * This mirrors the Go SDK shape: one shared transport plus composed domain services.\n *\n * @public\n */\nexport class Client {\n http: HttpClient;\n markets: MarketFetcher;\n portfolio: PortfolioFetcher;\n pages: MarketPageFetcher;\n apiTokens: ApiTokenService;\n partnerAccounts: PartnerAccountService;\n delegatedOrders: DelegatedOrderService;\n\n constructor(config: HttpClientConfig = {}) {\n this.http = new HttpClient(config);\n const logger = this.http.getLogger?.() || new NoOpLogger();\n\n this.markets = new MarketFetcher(this.http, logger);\n this.portfolio = new PortfolioFetcher(this.http, logger);\n this.pages = new MarketPageFetcher(this.http, logger);\n this.apiTokens = new ApiTokenService(this.http, logger);\n this.partnerAccounts = new PartnerAccountService(this.http, logger);\n this.delegatedOrders = new DelegatedOrderService(this.http, logger);\n }\n\n /**\n * Creates a root client around an existing shared HTTP client.\n */\n static fromHttpClient(httpClient: HttpClient): Client {\n const client = Object.create(Client.prototype) as Client;\n const logger = httpClient.getLogger?.() || new NoOpLogger();\n\n client.http = httpClient;\n client.markets = new MarketFetcher(httpClient, logger);\n client.portfolio = new PortfolioFetcher(httpClient, logger);\n client.pages = new MarketPageFetcher(httpClient, logger);\n client.apiTokens = new ApiTokenService(httpClient, logger);\n client.partnerAccounts = new PartnerAccountService(httpClient, logger);\n client.delegatedOrders = new DelegatedOrderService(httpClient, logger);\n\n return client;\n }\n\n /**\n * Creates a regular EIP-712 order client reusing the shared transport and market cache.\n */\n newOrderClient(\n walletOrPrivateKey: ethers.Wallet | string,\n config: Omit<OrderClientConfig, 'httpClient' | 'wallet'> = {},\n ): OrderClient {\n const wallet =\n typeof walletOrPrivateKey === 'string' ? new ethers.Wallet(walletOrPrivateKey) : walletOrPrivateKey;\n\n return new OrderClient({\n httpClient: this.http,\n wallet,\n marketFetcher: this.markets,\n logger: this.http.getLogger(),\n ...config,\n });\n }\n\n /**\n * Creates a WebSocket client reusing shared auth where possible.\n */\n newWebSocketClient(config: WebSocketConfig = {}): WebSocketClient {\n return new WebSocketClient(\n {\n apiKey: config.apiKey || this.http.getApiKey(),\n hmacCredentials: config.hmacCredentials || this.http.getHMACCredentials(),\n ...config,\n },\n this.http.getLogger(),\n );\n }\n}\n"],"mappings":"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","names":["Side","OrderType","SignatureType","WebSocketState","ZERO_ADDRESS","ethers","ethers","ethers"]}
|