@limitless-exchange/sdk 0.0.1 → 0.0.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/logger.ts","../src/types/orders.ts","../src/types/websocket.ts","../src/auth/signer.ts","../src/auth/authenticator.ts","../src/api/errors.ts","../src/auth/authenticated-client.ts","../src/api/http.ts","../src/utils/constants.ts","../src/api/retry.ts","../src/orders/builder.ts","../src/orders/signer.ts","../src/orders/validator.ts","../src/orders/client.ts","../src/markets/fetcher.ts","../src/portfolio/fetcher.ts","../src/websocket/client.ts"],"sourcesContent":["/**\n * Limitless Exchange TypeScript SDK\n *\n * @remarks\n * A TypeScript SDK for interacting with the Limitless Exchange platform,\n * providing type-safe access to CLOB and NegRisk prediction markets.\n *\n * @packageDocumentation\n */\n\nexport * from './types';\nexport * from './auth';\nexport * from './api';\nexport * from './utils';\nexport * from './orders';\nexport * from './markets';\nexport * from './portfolio';\nexport * from './websocket';\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 * Market type enum.\n * @public\n */\nexport enum MarketType {\n CLOB = 'CLOB',\n NEGRISK = 'NEGRISK',\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 * Market type (CLOB or NEGRISK)\n * @defaultValue 'CLOB'\n */\n marketType?: MarketType;\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\n */\n contractAddress: string;\n\n /**\n * Market type (CLOB or NEGRISK)\n */\n marketType: MarketType;\n}\n","/**\n * WebSocket types for real-time data streaming.\n * @module types/websocket\n */\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 * Session cookie for authentication\n */\n sessionCookie?: 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\n/**\n * Orderbook update event.\n * @public\n */\nexport interface OrderbookUpdate {\n marketSlug: string;\n bids: Array<{ price: number; size: number }>;\n asks: Array<{ price: number; size: number }>;\n timestamp: number;\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.\n * @public\n */\nexport interface PriceUpdate {\n marketSlug: string;\n price: number;\n timestamp: number;\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\n */\n orderbook: (data: OrderbookUpdate) => 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 * Price updates\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 */\n marketSlug?: string;\n\n /**\n * Market address to subscribe to (for AMM markets)\n */\n marketAddress?: string;\n\n /**\n * Additional filters\n */\n filters?: Record<string, any>;\n}\n","import { ethers } from 'ethers';\nimport type { SignatureHeaders } from '../types/auth';\n\n/**\n * Message signer for authentication.\n *\n * @remarks\n * This class handles signing messages with an Ethereum wallet and\n * creating authentication headers required by the Limitless Exchange API.\n *\n * @public\n */\nexport class MessageSigner {\n private wallet: ethers.Wallet;\n\n /**\n * Creates a new message signer instance.\n *\n * @param wallet - Ethers wallet instance for signing\n */\n constructor(wallet: ethers.Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Creates authentication headers for API requests.\n *\n * @param signingMessage - Message to sign from the API\n * @returns Promise resolving to signature headers\n *\n * @example\n * ```typescript\n * const signer = new MessageSigner(wallet);\n * const headers = await signer.createAuthHeaders(message);\n * ```\n */\n async createAuthHeaders(signingMessage: string): Promise<SignatureHeaders> {\n const hexMessage = this.stringToHex(signingMessage);\n const signature = await this.wallet.signMessage(signingMessage);\n const address = this.wallet.address;\n\n const recoveredAddress = ethers.verifyMessage(signingMessage, signature);\n if (address.toLowerCase() !== recoveredAddress.toLowerCase()) {\n throw new Error('Signature verification failed: address mismatch');\n }\n\n return {\n 'x-account': address,\n 'x-signing-message': hexMessage,\n 'x-signature': signature,\n };\n }\n\n /**\n * Signs EIP-712 typed data.\n *\n * @param domain - EIP-712 domain\n * @param types - EIP-712 types\n * @param value - Value to sign\n * @returns Promise resolving to signature string\n *\n * @example\n * ```typescript\n * const signature = await signer.signTypedData(domain, types, order);\n * ```\n */\n async signTypedData(\n domain: ethers.TypedDataDomain,\n types: Record<string, ethers.TypedDataField[]>,\n value: Record<string, any>\n ): Promise<string> {\n return await this.wallet.signTypedData(domain, types, value);\n }\n\n /**\n * Gets the wallet address.\n *\n * @returns Ethereum address\n */\n getAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Converts a string to hex format.\n *\n * @param text - String to convert\n * @returns Hex string with 0x prefix\n * @internal\n */\n private stringToHex(text: string): string {\n return ethers.hexlify(ethers.toUtf8Bytes(text));\n }\n}\n","import { AxiosResponse } from 'axios';\nimport { HttpClient } from '../api/http';\nimport { MessageSigner } from './signer';\nimport type { AuthResult, LoginOptions, UserProfile } from '../types/auth';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Authenticator for Limitless Exchange API.\n *\n * @remarks\n * This class handles the complete authentication flow:\n * 1. Get signing message from API\n * 2. Sign message with wallet\n * 3. Login and obtain session cookie\n * 4. Verify authentication status\n *\n * @public\n */\nexport class Authenticator {\n private httpClient: HttpClient;\n private signer: MessageSigner;\n private logger: ILogger;\n\n /**\n * Creates a new authenticator instance.\n *\n * @param httpClient - HTTP client for API requests\n * @param signer - Message signer for wallet operations\n * @param logger - Optional logger for debugging and monitoring (default: no logging)\n *\n * @example\n * ```typescript\n * // Without logging (default)\n * const authenticator = new Authenticator(httpClient, signer);\n *\n * // With logging\n * import { ConsoleLogger } from '@limitless-exchange/sdk';\n * const logger = new ConsoleLogger('debug');\n * const authenticator = new Authenticator(httpClient, signer, logger);\n * ```\n */\n constructor(httpClient: HttpClient, signer: MessageSigner, logger?: ILogger) {\n this.httpClient = httpClient;\n this.signer = signer;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets a signing message from the API.\n *\n * @returns Promise resolving to signing message string\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const message = await authenticator.getSigningMessage();\n * console.log(message);\n * ```\n */\n async getSigningMessage(): Promise<string> {\n this.logger.debug('Requesting signing message from API');\n const message = await this.httpClient.get<string>('/auth/signing-message');\n this.logger.debug('Received signing message', { length: message.length });\n return message;\n }\n\n /**\n * Authenticates with the API and obtains session cookie.\n *\n * @param options - Login options including client type and smart wallet\n * @returns Promise resolving to authentication result\n * @throws Error if authentication fails or smart wallet is required but not provided\n *\n * @example\n * ```typescript\n * // EOA authentication\n * const result = await authenticator.authenticate({ client: 'eoa' });\n *\n * // ETHERSPOT with smart wallet\n * const result = await authenticator.authenticate({\n * client: 'etherspot',\n * smartWallet: '0x...'\n * });\n * ```\n */\n async authenticate(options: LoginOptions = {}): Promise<AuthResult> {\n const client = options.client || 'eoa';\n\n this.logger.info('Starting authentication', {\n client,\n hasSmartWallet: !!options.smartWallet,\n });\n\n if (client === 'etherspot' && !options.smartWallet) {\n this.logger.error('Smart wallet address required for ETHERSPOT client');\n throw new Error('Smart wallet address is required for ETHERSPOT client');\n }\n\n try {\n const signingMessage = await this.getSigningMessage();\n\n this.logger.debug('Creating signature headers');\n const headers = await this.signer.createAuthHeaders(signingMessage);\n\n this.logger.debug('Sending authentication request', { client });\n const response = await this.httpClient.postWithResponse<UserProfile>(\n '/auth/login',\n { client, smartWallet: options.smartWallet },\n {\n headers: headers as any,\n validateStatus: (status) => status < 500,\n }\n );\n\n this.logger.debug('Extracting session cookie from response');\n const cookies = this.httpClient.extractCookies(response);\n\n const sessionCookie = cookies['limitless_session'];\n if (!sessionCookie) {\n this.logger.error('Session cookie not found in response headers');\n throw new Error('Failed to obtain session cookie from response');\n }\n\n this.httpClient.setSessionCookie(sessionCookie);\n\n this.logger.info('Authentication successful', {\n account: response.data.account,\n client: response.data.client,\n });\n\n return {\n sessionCookie,\n profile: response.data,\n };\n } catch (error) {\n this.logger.error('Authentication failed', error as Error, {\n client,\n });\n throw error;\n }\n }\n\n /**\n * Verifies the current authentication status.\n *\n * @param sessionCookie - Session cookie to verify\n * @returns Promise resolving to user's Ethereum address\n * @throws Error if session is invalid\n *\n * @example\n * ```typescript\n * const address = await authenticator.verifyAuth(sessionCookie);\n * console.log(`Authenticated as: ${address}`);\n * ```\n */\n async verifyAuth(sessionCookie: string): Promise<string> {\n this.logger.debug('Verifying authentication session');\n const originalCookie = this.httpClient['sessionCookie'];\n this.httpClient.setSessionCookie(sessionCookie);\n\n try {\n const address = await this.httpClient.get<string>('/auth/verify-auth');\n this.logger.info('Session verified', { address });\n return address;\n } catch (error) {\n this.logger.error('Session verification failed', error as Error);\n throw error;\n } finally {\n if (originalCookie) {\n this.httpClient.setSessionCookie(originalCookie);\n } else {\n this.httpClient.clearSessionCookie();\n }\n }\n }\n\n /**\n * Logs out and clears the session.\n *\n * @param sessionCookie - Session cookie to invalidate\n * @throws Error if logout request fails\n *\n * @example\n * ```typescript\n * await authenticator.logout(sessionCookie);\n * console.log('Logged out successfully');\n * ```\n */\n async logout(sessionCookie: string): Promise<void> {\n this.logger.debug('Logging out session');\n const originalCookie = this.httpClient['sessionCookie'];\n this.httpClient.setSessionCookie(sessionCookie);\n\n try {\n await this.httpClient.post('/auth/logout', {});\n this.logger.info('Logout successful');\n } catch (error) {\n this.logger.error('Logout failed', error as Error);\n throw error;\n } finally {\n if (originalCookie) {\n this.httpClient.setSessionCookie(originalCookie);\n } else {\n this.httpClient.clearSessionCookie();\n }\n }\n }\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 * Optional helper for automatic authentication retry on token expiration.\n * @module auth/authenticated-client\n */\n\nimport { HttpClient } from '../api/http';\nimport { APIError } from '../api/errors';\nimport { Authenticator } from './authenticator';\nimport { MessageSigner } from './signer';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Configuration for authenticated client with auto-retry.\n * @public\n */\nexport interface AuthenticatedClientConfig {\n /**\n * HTTP client instance\n */\n httpClient: HttpClient;\n\n /**\n * Authenticator instance\n */\n authenticator: Authenticator;\n\n /**\n * Authentication client type ('eoa' or 'etherspot')\n */\n client: 'eoa' | 'etherspot';\n\n /**\n * Optional smart wallet address (required for 'etherspot')\n */\n smartWallet?: string;\n\n /**\n * Optional logger for debugging\n */\n logger?: ILogger;\n\n /**\n * Maximum retry attempts for auth errors (default: 1)\n */\n maxRetries?: number;\n}\n\n/**\n * Optional helper class that automatically re-authenticates on token expiration.\n *\n * @remarks\n * This is an optional convenience wrapper. Users can choose to handle\n * authentication retry manually or use this helper for automatic retry logic.\n *\n * @example\n * ```typescript\n * // Create authenticated client with auto-retry\n * const authClient = new AuthenticatedClient({\n * httpClient,\n * authenticator,\n * client: 'eoa'\n * });\n *\n * // Use withRetry for automatic re-authentication\n * const portfolioFetcher = new PortfolioFetcher(httpClient);\n * const positions = await authClient.withRetry(() =>\n * portfolioFetcher.getPositions()\n * );\n * ```\n *\n * @public\n */\nexport class AuthenticatedClient {\n private httpClient: HttpClient;\n private authenticator: Authenticator;\n private client: 'eoa' | 'etherspot';\n private smartWallet?: string;\n private logger: ILogger;\n private maxRetries: number;\n\n /**\n * Creates a new authenticated client with auto-retry capability.\n *\n * @param config - Configuration for authenticated client\n */\n constructor(config: AuthenticatedClientConfig) {\n this.httpClient = config.httpClient;\n this.authenticator = config.authenticator;\n this.client = config.client;\n this.smartWallet = config.smartWallet;\n this.logger = config.logger || new NoOpLogger();\n this.maxRetries = config.maxRetries ?? 1;\n }\n\n /**\n * Executes a function with automatic retry on authentication errors.\n *\n * @param fn - Function to execute with auth retry\n * @returns Promise resolving to the function result\n * @throws Error if max retries exceeded or non-auth error occurs\n *\n * @example\n * ```typescript\n * // Automatic retry on 401/403\n * const positions = await authClient.withRetry(() =>\n * portfolioFetcher.getPositions()\n * );\n *\n * // Works with any async operation\n * const order = await authClient.withRetry(() =>\n * orderClient.createOrder({ ... })\n * );\n * ```\n */\n async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let attempts = 0;\n\n while (attempts <= this.maxRetries) {\n try {\n return await fn();\n } catch (error) {\n // Check if it's an auth error and we have retries left\n if (error instanceof APIError && error.isAuthError() && attempts < this.maxRetries) {\n this.logger.info('Authentication expired, re-authenticating...', {\n attempt: attempts + 1,\n maxRetries: this.maxRetries,\n });\n\n // Re-authenticate\n await this.reauthenticate();\n\n // Increment attempts and retry\n attempts++;\n continue;\n }\n\n // Not an auth error or no retries left - throw\n throw error;\n }\n }\n\n // Should never reach here, but TypeScript needs this\n throw new Error('Unexpected error: exceeded max retries');\n }\n\n /**\n * Re-authenticates with the API.\n *\n * @internal\n */\n private async reauthenticate(): Promise<void> {\n this.logger.debug('Re-authenticating with API');\n\n await this.authenticator.authenticate({\n client: this.client,\n smartWallet: this.smartWallet,\n });\n\n this.logger.info('Re-authentication successful');\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport { DEFAULT_API_URL } from '../utils/constants';\nimport { APIError } 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 * Session cookie for authenticated requests\n */\n sessionCookie?: string;\n\n /**\n * Optional logger for debugging\n * @defaultValue NoOpLogger (no logging)\n */\n logger?: ILogger;\n}\n\n/**\n * HTTP client wrapper for Limitless Exchange API.\n *\n * @remarks\n * This class provides a centralized HTTP client with cookie management,\n * error handling, and request/response interceptors.\n *\n * @public\n */\nexport class HttpClient {\n private client: AxiosInstance;\n private sessionCookie?: 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.sessionCookie = config.sessionCookie;\n this.logger = config.logger || new NoOpLogger();\n\n this.client = axios.create({\n baseURL: config.baseURL || DEFAULT_API_URL,\n timeout: config.timeout || 30000,\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\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.sessionCookie) {\n config.headers['Cookie'] = `limitless_session=${this.sessionCookie}`;\n }\n\n // Log outgoing request - concise format\n const fullUrl = `${config.baseURL || ''}${config.url || ''}`;\n const method = config.method?.toUpperCase() || 'GET';\n\n this.logger.debug(`→ ${method} ${fullUrl}`, {\n headers: config.headers,\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 APIError with original data preserved\n throw new APIError(message, status, data, url, method);\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 session cookie for authenticated requests.\n *\n * @param cookie - Session cookie value\n */\n setSessionCookie(cookie: string): void {\n this.sessionCookie = cookie;\n }\n\n /**\n * Clears the session cookie.\n */\n clearSessionCookie(): void {\n this.sessionCookie = 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 POST request and returns the full response object.\n * Useful when you need access to response headers (e.g., for cookie extraction).\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the full AxiosResponse object\n * @internal\n */\n async postWithResponse<T = any>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig\n ): Promise<AxiosResponse<T>> {\n return await this.client.post(url, data, config);\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 * Extracts cookies from response headers.\n *\n * @param response - Axios response object\n * @returns Object containing parsed cookies\n * @internal\n */\n extractCookies(response: AxiosResponse): Record<string, string> {\n const setCookie = response.headers['set-cookie'];\n if (!setCookie) return {};\n\n const cookies: Record<string, string> = {};\n const cookieStrings = Array.isArray(setCookie) ? setCookie : [setCookie];\n\n for (const cookieString of cookieStrings) {\n const parts = cookieString.split(';')[0].split('=');\n if (parts.length === 2) {\n cookies[parts[0].trim()] = parts[1].trim();\n }\n }\n\n return cookies;\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 * @public\n */\nexport const CONTRACT_ADDRESSES = {\n // Base mainnet (chainId: 8453)\n 8453: {\n CLOB: '0xa4409D988CA2218d956BeEFD3874100F444f0DC3',\n NEGRISK: '0x5a38afc17F7E97ad8d6C547ddb837E40B4aEDfC6',\n },\n // Base Sepolia testnet (chainId: 84532)\n 84532: {\n CLOB: '0x...', // Add testnet addresses when available\n NEGRISK: '0x...',\n },\n} as const;\n\n/**\n * Get contract address for a specific market type and chain\n *\n * @param marketType - Market type (CLOB or NEGRISK)\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 marketType: 'CLOB' | 'NEGRISK',\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 return addresses[marketType];\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, MarketType, 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 * marketType: MarketType.CLOB\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 * marketType: MarketType.CLOB\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 'amount' 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 < 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 {\n UnsignedOrder,\n OrderSigningConfig,\n MarketType,\n} 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 * marketType: MarketType.CLOB\n * });\n * ```\n */\n async signOrder(\n order: UnsignedOrder,\n config: OrderSigningConfig\n ): Promise<string> {\n this.logger.debug('Signing order with EIP-712', {\n tokenId: order.tokenId,\n side: order.side,\n marketType: config.marketType,\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 console.log('[OrderSigner] Full signing payload:', JSON.stringify({\n domain,\n types: this.getTypes(),\n value: orderValue,\n }, null, 2));\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 * Validation error class.\n * @public\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\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 ValidationError 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 ValidationError('TokenId is required');\n }\n\n if (args.tokenId === '0') {\n throw new ValidationError('TokenId cannot be zero');\n }\n\n // Validate tokenId format (should be numeric string)\n if (!/^\\d+$/.test(args.tokenId)) {\n throw new ValidationError(`Invalid tokenId format: ${args.tokenId}`);\n }\n\n // Validate taker address if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new ValidationError(`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 ValidationError(`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 ValidationError(`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 ValidationError('Amount must be a valid number');\n }\n\n if (args.makerAmount <= 0) {\n throw new ValidationError(`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 ValidationError(\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 ValidationError('Price must be a valid number');\n }\n\n if (args.price < 0 || args.price > 1) {\n throw new ValidationError(`Price must be between 0 and 1, got: ${args.price}`);\n }\n\n if (typeof args.size !== 'number' || isNaN(args.size)) {\n throw new ValidationError('Size must be a valid number');\n }\n\n if (args.size <= 0) {\n throw new ValidationError(`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 ValidationError 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 ValidationError(`Invalid maker address: ${order.maker}`);\n }\n\n if (!ethers.isAddress(order.signer)) {\n throw new ValidationError(`Invalid signer address: ${order.signer}`);\n }\n\n if (!ethers.isAddress(order.taker)) {\n throw new ValidationError(`Invalid taker address: ${order.taker}`);\n }\n\n // Validate amounts\n if (!order.makerAmount || order.makerAmount === 0) {\n throw new ValidationError('MakerAmount must be greater than zero');\n }\n\n if (!order.takerAmount || order.takerAmount === 0) {\n throw new ValidationError('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 ValidationError(`Invalid makerAmount: ${order.makerAmount}`);\n }\n\n if (typeof order.takerAmount !== 'number' || order.takerAmount <= 0) {\n throw new ValidationError(`Invalid takerAmount: ${order.takerAmount}`);\n }\n\n if (!/^\\d+$/.test(order.tokenId)) {\n throw new ValidationError(`Invalid tokenId format: ${order.tokenId}`);\n }\n\n if (!/^\\d+$/.test(order.expiration)) {\n throw new ValidationError(`Invalid expiration format: ${order.expiration}`);\n }\n\n // Validate salt\n if (!Number.isInteger(order.salt) || order.salt <= 0) {\n throw new ValidationError(`Invalid salt: ${order.salt}`);\n }\n\n // Validate nonce\n if (!Number.isInteger(order.nonce) || order.nonce < 0) {\n throw new ValidationError(`Invalid nonce: ${order.nonce}`);\n }\n\n // Validate feeRateBps\n if (!Number.isInteger(order.feeRateBps) || order.feeRateBps < 0) {\n throw new ValidationError(`Invalid feeRateBps: ${order.feeRateBps}`);\n }\n\n // Validate side (0 or 1)\n if (order.side !== 0 && order.side !== 1) {\n throw new ValidationError(`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 ValidationError(`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 ValidationError('Price must be a valid number');\n }\n\n if (order.price < 0 || order.price > 1) {\n throw new ValidationError(`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 ValidationError 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 ValidationError('Signature is required');\n }\n\n if (!order.signature.startsWith('0x')) {\n throw new ValidationError('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 ValidationError(\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 ValidationError('Signature must be valid hex string');\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, MarketType } from '../types/orders';\nimport { OrderBuilder } from './builder';\nimport { OrderSigner } from './signer';\nimport type { ethers } from 'ethers';\nimport type { UserData } from '../types/auth';\nimport { getContractAddress } from '../utils/constants';\n\n/**\n * Configuration for the order client.\n *\n * @remarks\n * The order client supports two configuration modes:\n * 1. Simple mode: Provide userData and marketType (auto-configures signing)\n * 2. Advanced mode: Provide userData and custom signingConfig\n *\n * @public\n */\nexport interface OrderClientConfig {\n /**\n * HTTP client for API requests\n */\n httpClient: HttpClient;\n\n /**\n * Wallet for signing orders\n */\n wallet: ethers.Wallet;\n\n /**\n * User data containing userId and feeRateBps\n *\n * @example\n * ```typescript\n * {\n * userId: 123, // From auth result\n * feeRateBps: 300 // User's fee rate (3%)\n * }\n * ```\n */\n userData: UserData;\n\n /**\n * Market type for auto-configuration (optional if signingConfig provided)\n *\n * @remarks\n * When provided without signingConfig, automatically loads contract address\n * from environment variables or SDK defaults.\n *\n * @defaultValue MarketType.CLOB\n */\n marketType?: MarketType;\n\n /**\n * Custom signing configuration (optional)\n *\n * @remarks\n * If not provided, SDK will auto-configure based on marketType.\n * Useful for custom deployments or testing.\n */\n signingConfig?: OrderSigningConfig;\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 * @example\n * ```typescript\n * const orderClient = new OrderClient({\n * httpClient,\n * wallet,\n * ownerId: 123,\n * feeRateBps: 100,\n * signingConfig: {\n * chainId: 8453,\n * contractAddress: '0x...',\n * marketType: MarketType.CLOB\n * }\n * });\n *\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 orderBuilder: OrderBuilder;\n private orderSigner: OrderSigner;\n private ownerId: number;\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 * @throws Error if neither marketType nor signingConfig is provided\n */\n constructor(config: OrderClientConfig) {\n this.httpClient = config.httpClient;\n this.logger = config.logger || new NoOpLogger();\n\n // Extract user data\n this.ownerId = config.userData.userId;\n const feeRateBps = config.userData.feeRateBps;\n\n // Initialize order builder with default price tick (0.001 = 3 decimals)\n this.orderBuilder = new OrderBuilder(config.wallet.address, feeRateBps, 0.001);\n\n // Initialize order signer\n this.orderSigner = new OrderSigner(config.wallet, this.logger);\n\n // Configure signing: use provided config or auto-configure from marketType\n if (config.signingConfig) {\n // Use custom signing configuration\n this.signingConfig = config.signingConfig;\n } else if (config.marketType) {\n // Auto-configure from market type\n const chainId = parseInt(process.env.CHAIN_ID || '8453'); // Base mainnet default\n\n // Check for market-type specific env var first, then fall back to SDK defaults\n const contractAddress = config.marketType === MarketType.NEGRISK\n ? (process.env.NEGRISK_CONTRACT_ADDRESS || getContractAddress('NEGRISK', chainId))\n : (process.env.CLOB_CONTRACT_ADDRESS || getContractAddress('CLOB', chainId));\n\n this.signingConfig = {\n chainId,\n contractAddress,\n marketType: config.marketType,\n };\n\n this.logger.info('Auto-configured signing', {\n chainId,\n contractAddress,\n marketType: config.marketType,\n });\n } else {\n // Default to CLOB if neither provided\n const chainId = parseInt(process.env.CHAIN_ID || '8453');\n const contractAddress = process.env.CLOB_CONTRACT_ADDRESS ||\n getContractAddress('CLOB', chainId);\n\n this.signingConfig = {\n chainId,\n contractAddress,\n marketType: MarketType.CLOB,\n };\n\n this.logger.debug('Using default CLOB configuration', {\n chainId,\n contractAddress,\n });\n }\n }\n\n /**\n * Creates and submits a new order.\n *\n * @remarks\n * This method handles the complete order creation flow:\n * 1. Build unsigned order\n * 2. Sign with EIP-712\n * 3. Submit to API\n *\n * @param params - Order parameters\n * @returns Promise resolving to order response\n *\n * @throws Error if order creation fails\n *\n * @example\n * ```typescript\n * const order = await orderClient.createOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'market-slug'\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 this.logger.info('Creating order', {\n side: params.side,\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n });\n\n // Step 1: Build unsigned order\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 // Step 2: Sign order with EIP-712\n const signature = await this.orderSigner.signOrder(\n unsignedOrder,\n this.signingConfig\n );\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: this.ownerId,\n };\n\n // Step 4: Submit to API\n this.logger.debug('Submitting order to API');\n console.log('[OrderClient] Full API request payload:', JSON.stringify(payload, null, 2));\n const apiResponse = await this.httpClient.post<any>(\n '/orders',\n payload\n );\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 }>(\n `/orders/${orderId}`\n );\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 }>(\n `/orders/all/${marketSlug}`\n );\n\n this.logger.info('All orders cancellation response', {\n marketSlug,\n message: response.message\n });\n\n return response;\n }\n\n /**\n * @deprecated Use `cancel()` instead\n */\n async cancelOrder(orderId: string): Promise<void> {\n await this.cancel(orderId);\n }\n\n /**\n * Gets an order by ID.\n *\n * @param orderId - Order ID to fetch\n * @returns Promise resolving to order details\n *\n * @throws Error if order not found\n *\n * @example\n * ```typescript\n * const order = await orderClient.getOrder('order-id-123');\n * console.log(order.order.side);\n * ```\n */\n async getOrder(orderId: string): Promise<OrderResponse> {\n this.logger.debug('Fetching order', { orderId });\n\n const response = await this.httpClient.get<OrderResponse>(\n `/orders/${orderId}`\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 Unsigned order\n *\n * @example\n * ```typescript\n * const unsignedOrder = orderClient.buildUnsignedOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY\n * });\n * ```\n */\n buildUnsignedOrder(params: OrderArgs): UnsignedOrder {\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 * Market data fetcher for Limitless Exchange.\n * @module markets/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport type {\n Market,\n MarketsResponse,\n OrderBook,\n MarketPrice,\n ActiveMarketsParams,\n ActiveMarketsResponse,\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 * @public\n */\nexport class MarketFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\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 }\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<ActiveMarketsResponse>(endpoint);\n\n this.logger.info('Active markets fetched successfully', {\n count: response.data.length,\n total: response.totalMarketsCount,\n sortBy: params?.sortBy,\n page: params?.page,\n });\n\n return response;\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 * @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 * const market = await fetcher.getMarket('bitcoin-price-2024');\n * console.log(`Market: ${market.title}`);\n * ```\n */\n async getMarket(slug: string): Promise<Market> {\n this.logger.debug('Fetching market', { slug });\n\n try {\n const market = await this.httpClient.get<Market>(`/markets/${slug}`);\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 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 * Gets the current price for a token.\n *\n * @param tokenId - Token ID\n * @returns Promise resolving to price information\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const price = await fetcher.getPrice('123456');\n * console.log(`Current price: ${price.price}`);\n * ```\n */\n async getPrice(tokenId: string): Promise<MarketPrice> {\n this.logger.debug('Fetching price', { tokenId });\n\n try {\n const price = await this.httpClient.get<MarketPrice>(`/prices/${tokenId}`);\n\n this.logger.info('Price fetched successfully', {\n tokenId,\n price: price.price,\n });\n return price;\n } catch (error) {\n this.logger.error('Failed to fetch price', error as Error, { tokenId });\n throw error;\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} 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 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 = await this.httpClient.get<PortfolioPositionsResponse>(\n '/portfolio/positions'\n );\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 * Flattens positions into a unified format for easier consumption.\n *\n * @remarks\n * Converts CLOB positions (which have YES/NO sides) and AMM positions\n * into a unified Position array. Only includes positions with non-zero values.\n *\n * @returns Promise resolving to array of flattened positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const positions = await portfolioFetcher.getFlattenedPositions();\n * positions.forEach(pos => {\n * const pnlPercent = (pos.unrealizedPnl / pos.costBasis) * 100;\n * console.log(`${pos.market.title} (${pos.side}): ${pnlPercent.toFixed(2)}% P&L`);\n * });\n * ```\n */\n async getFlattenedPositions(): Promise<Position[]> {\n const response = await this.getPositions();\n const positions: Position[] = [];\n\n // Flatten CLOB positions\n for (const clobPos of response.clob || []) {\n // Add YES position if it has value\n const yesCost = parseFloat(clobPos.positions.yes.cost);\n const yesValue = parseFloat(clobPos.positions.yes.marketValue);\n if (yesCost > 0 || yesValue > 0) {\n positions.push({\n type: 'CLOB',\n market: clobPos.market,\n side: 'YES',\n costBasis: yesCost,\n marketValue: yesValue,\n unrealizedPnl: parseFloat(clobPos.positions.yes.unrealizedPnl),\n realizedPnl: parseFloat(clobPos.positions.yes.realisedPnl),\n currentPrice: clobPos.latestTrade?.latestYesPrice ?? 0,\n avgPrice: yesCost > 0 ? parseFloat(clobPos.positions.yes.fillPrice) / 1e6 : 0,\n tokenBalance: parseFloat(clobPos.tokensBalance.yes),\n });\n }\n\n // Add NO position if it has value\n const noCost = parseFloat(clobPos.positions.no.cost);\n const noValue = parseFloat(clobPos.positions.no.marketValue);\n if (noCost > 0 || noValue > 0) {\n positions.push({\n type: 'CLOB',\n market: clobPos.market,\n side: 'NO',\n costBasis: noCost,\n marketValue: noValue,\n unrealizedPnl: parseFloat(clobPos.positions.no.unrealizedPnl),\n realizedPnl: parseFloat(clobPos.positions.no.realisedPnl),\n currentPrice: clobPos.latestTrade?.latestNoPrice ?? 0,\n avgPrice: noCost > 0 ? parseFloat(clobPos.positions.no.fillPrice) / 1e6 : 0,\n tokenBalance: parseFloat(clobPos.tokensBalance.no),\n });\n }\n }\n\n // Flatten AMM positions\n for (const ammPos of response.amm || []) {\n const cost = parseFloat(ammPos.totalBuysCost);\n const value = parseFloat(ammPos.collateralAmount);\n\n if (cost > 0 || value > 0) {\n positions.push({\n type: 'AMM',\n market: ammPos.market,\n side: ammPos.outcomeIndex === 0 ? 'YES' : 'NO',\n costBasis: cost,\n marketValue: value,\n unrealizedPnl: parseFloat(ammPos.unrealizedPnl),\n realizedPnl: parseFloat(ammPos.realizedPnl),\n currentPrice: ammPos.latestTrade ? parseFloat(ammPos.latestTrade.outcomeTokenPrice) : 0,\n avgPrice: parseFloat(ammPos.averageFillPrice),\n tokenBalance: parseFloat(ammPos.outcomeTokenAmount),\n });\n }\n }\n\n this.logger.debug('Flattened positions', { count: positions.length });\n\n return positions;\n }\n\n /**\n * Calculates portfolio summary statistics from raw API response.\n *\n * @param response - Portfolio positions response from API\n * @returns Portfolio summary with totals and statistics\n *\n * @example\n * ```typescript\n * const response = await portfolioFetcher.getPositions();\n * const summary = portfolioFetcher.calculateSummary(response);\n *\n * console.log(`Total Portfolio Value: $${(summary.totalValue / 1e6).toFixed(2)}`);\n * console.log(`Total P&L: ${summary.totalUnrealizedPnlPercent.toFixed(2)}%`);\n * console.log(`CLOB Positions: ${summary.breakdown.clob.positions}`);\n * console.log(`AMM Positions: ${summary.breakdown.amm.positions}`);\n * ```\n */\n calculateSummary(response: PortfolioPositionsResponse): PortfolioSummary {\n this.logger.debug('Calculating portfolio summary', {\n clobCount: response.clob?.length || 0,\n ammCount: response.amm?.length || 0,\n });\n\n let totalValue = 0;\n let totalCostBasis = 0;\n let totalUnrealizedPnl = 0;\n let totalRealizedPnl = 0;\n\n let clobPositions = 0;\n let clobValue = 0;\n let clobPnl = 0;\n\n let ammPositions = 0;\n let ammValue = 0;\n let ammPnl = 0;\n\n // Process CLOB positions\n for (const clobPos of response.clob || []) {\n // YES side\n const yesCost = parseFloat(clobPos.positions.yes.cost);\n const yesValue = parseFloat(clobPos.positions.yes.marketValue);\n const yesUnrealizedPnl = parseFloat(clobPos.positions.yes.unrealizedPnl);\n const yesRealizedPnl = parseFloat(clobPos.positions.yes.realisedPnl);\n\n if (yesCost > 0 || yesValue > 0) {\n clobPositions++;\n totalCostBasis += yesCost;\n totalValue += yesValue;\n totalUnrealizedPnl += yesUnrealizedPnl;\n totalRealizedPnl += yesRealizedPnl;\n clobValue += yesValue;\n clobPnl += yesUnrealizedPnl;\n }\n\n // NO side\n const noCost = parseFloat(clobPos.positions.no.cost);\n const noValue = parseFloat(clobPos.positions.no.marketValue);\n const noUnrealizedPnl = parseFloat(clobPos.positions.no.unrealizedPnl);\n const noRealizedPnl = parseFloat(clobPos.positions.no.realisedPnl);\n\n if (noCost > 0 || noValue > 0) {\n clobPositions++;\n totalCostBasis += noCost;\n totalValue += noValue;\n totalUnrealizedPnl += noUnrealizedPnl;\n totalRealizedPnl += noRealizedPnl;\n clobValue += noValue;\n clobPnl += noUnrealizedPnl;\n }\n }\n\n // Process AMM positions\n for (const ammPos of response.amm || []) {\n const cost = parseFloat(ammPos.totalBuysCost);\n const value = parseFloat(ammPos.collateralAmount);\n const unrealizedPnl = parseFloat(ammPos.unrealizedPnl);\n const realizedPnl = parseFloat(ammPos.realizedPnl);\n\n if (cost > 0 || value > 0) {\n ammPositions++;\n totalCostBasis += cost;\n totalValue += value;\n totalUnrealizedPnl += unrealizedPnl;\n totalRealizedPnl += realizedPnl;\n ammValue += value;\n ammPnl += unrealizedPnl;\n }\n }\n\n // Calculate P&L percentage\n const totalUnrealizedPnlPercent =\n totalCostBasis > 0 ? (totalUnrealizedPnl / totalCostBasis) * 100 : 0;\n\n // Count unique markets\n const uniqueMarkets = new Set<number | string>();\n for (const pos of response.clob || []) {\n uniqueMarkets.add(pos.market.id);\n }\n for (const pos of response.amm || []) {\n uniqueMarkets.add(pos.market.id);\n }\n\n const summary: PortfolioSummary = {\n totalValue,\n totalCostBasis,\n totalUnrealizedPnl,\n totalRealizedPnl,\n totalUnrealizedPnlPercent,\n positionCount: clobPositions + ammPositions,\n marketCount: uniqueMarkets.size,\n breakdown: {\n clob: {\n positions: clobPositions,\n value: clobValue,\n pnl: clobPnl,\n },\n amm: {\n positions: ammPositions,\n value: ammValue,\n pnl: ammPnl,\n },\n },\n };\n\n this.logger.debug('Portfolio summary calculated', summary);\n\n return summary;\n }\n\n /**\n * Gets positions and calculates summary in a single call.\n *\n * @returns Promise resolving to response and summary\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const { response, summary } = await portfolioFetcher.getPortfolio();\n *\n * console.log('Portfolio Summary:');\n * console.log(` Total Value: $${(summary.totalValue / 1e6).toFixed(2)}`);\n * console.log(` Total P&L: $${(summary.totalUnrealizedPnl / 1e6).toFixed(2)}`);\n * console.log(` P&L %: ${summary.totalUnrealizedPnlPercent.toFixed(2)}%`);\n * console.log(`\\nCLOB Positions: ${response.clob.length}`);\n * console.log(`AMM Positions: ${response.amm.length}`);\n * ```\n */\n async getPortfolio(): Promise<{\n response: PortfolioPositionsResponse;\n summary: PortfolioSummary;\n }> {\n this.logger.debug('Fetching portfolio with summary');\n\n const response = await this.getPositions();\n const summary = this.calculateSummary(response);\n\n this.logger.info('Portfolio fetched with summary', {\n positionCount: summary.positionCount,\n totalValueUSDC: summary.totalValue / 1e6,\n pnlPercent: summary.totalUnrealizedPnlPercent,\n });\n\n return { response, summary };\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 type OrderbookUpdate,\n type TradeEvent,\n type OrderUpdate,\n type FillEvent,\n type MarketUpdate,\n type PriceUpdate,\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 * @example\n * ```typescript\n * // Create client\n * const wsClient = new WebSocketClient({\n * sessionCookie: 'your-session-cookie',\n * autoReconnect: true,\n * });\n *\n * // Subscribe to orderbook updates\n * wsClient.on('orderbook', (data) => {\n * console.log('Orderbook update:', data);\n * });\n *\n * // Connect and subscribe\n * await wsClient.connect();\n * await wsClient.subscribe('orderbook', { marketSlug: 'market-123' });\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 sessionCookie: config.sessionCookie || '',\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 session cookie for authentication.\n *\n * @param sessionCookie - Session cookie value\n */\n setSessionCookie(sessionCookie: string): void {\n this.config.sessionCookie = sessionCookie;\n\n // If already connected, reconnect with new auth\n if (this.socket?.connected) {\n this.logger.info('Session cookie updated, reconnecting...');\n this.disconnect();\n this.connect();\n }\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 if (this.socket?.connected) {\n this.logger.info('Already connected');\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 // Authentication via cookie header (required by WsJwtAuthGuard)\n const wsUrl = this.config.url.endsWith('/markets')\n ? this.config.url\n : `${this.config.url}/markets`;\n\n this.socket = io(wsUrl, {\n transports: ['websocket'], // Use WebSocket transport only\n extraHeaders: {\n cookie: `limitless_session=${this.config.sessionCookie}`\n },\n reconnection: this.config.autoReconnect,\n reconnectionDelay: this.config.reconnectDelay,\n reconnectionAttempts: this.config.maxReconnectAttempts,\n timeout: this.config.timeout,\n });\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 * @example\n * ```typescript\n * wsClient.disconnect();\n * ```\n */\n disconnect(): 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 when subscribed\n * @throws Error if not connected\n *\n * @example\n * ```typescript\n * // Subscribe to orderbook for a specific market\n * await wsClient.subscribe('orderbook', { marketSlug: '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 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 return new Promise((resolve, reject) => {\n this.socket!.emit(channel, options, (response: any) => {\n if (response?.error) {\n this.logger.error('Subscription failed', response.error);\n this.subscriptions.delete(subscriptionKey);\n reject(new Error(response.error));\n } else {\n this.logger.info('Subscribed successfully', { channel, options });\n resolve();\n }\n });\n });\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 *\n * @example\n * ```typescript\n * await wsClient.unsubscribe('orderbook', { marketSlug: 'market-123' });\n * ```\n */\n async unsubscribe(channel: SubscriptionChannel, options: SubscriptionOptions = {}): 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 // Pass raw unsubscribe event with channel and options\n return new Promise((resolve, reject) => {\n this.socket!.emit('unsubscribe', { channel, ...options }, (response: any) => {\n if (response?.error) {\n this.logger.error('Unsubscribe failed', response.error);\n reject(new Error(response.error));\n } else {\n this.logger.info('Unsubscribed successfully', { channel, options });\n resolve();\n }\n });\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>(\n event: K,\n handler: WebSocketEvents[K]\n ): 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>(\n event: K,\n handler: WebSocketEvents[K]\n ): 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\n * @returns This client for chaining\n */\n off<K extends keyof WebSocketEvents>(\n event: K,\n handler: WebSocketEvents[K]\n ): this {\n if (!this.socket) {\n return this;\n }\n\n // Pass raw event names, no transformation\n this.socket.off(event as string, handler as any);\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","MarketType","SignatureType","WebSocketState","axios","import_ethers","ZERO_ADDRESS","import_ethers"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/logger.ts","../src/types/orders.ts","../src/types/websocket.ts","../src/auth/signer.ts","../src/auth/authenticator.ts","../src/api/errors.ts","../src/auth/authenticated-client.ts","../src/api/http.ts","../src/utils/constants.ts","../src/api/retry.ts","../src/orders/builder.ts","../src/orders/signer.ts","../src/orders/validator.ts","../src/orders/client.ts","../src/markets/fetcher.ts","../src/portfolio/fetcher.ts","../src/websocket/client.ts"],"sourcesContent":["/**\n * Limitless Exchange TypeScript SDK\n *\n * @remarks\n * A TypeScript SDK for interacting with the Limitless Exchange platform,\n * providing type-safe access to CLOB and NegRisk prediction markets.\n *\n * @packageDocumentation\n */\n\nexport * from './types';\nexport * from './auth';\nexport * from './api';\nexport * from './utils';\nexport * from './orders';\nexport * from './markets';\nexport * from './portfolio';\nexport * from './websocket';\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 * Market type enum.\n * @public\n */\nexport enum MarketType {\n CLOB = 'CLOB',\n NEGRISK = 'NEGRISK',\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 * Market type (CLOB or NEGRISK)\n * @defaultValue 'CLOB'\n */\n marketType?: MarketType;\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\n */\n contractAddress: string;\n\n /**\n * Market type (CLOB or NEGRISK)\n */\n marketType: MarketType;\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 * Session cookie for authentication\n */\n sessionCookie?: 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 */\n marketSlug?: string;\n\n /**\n * Market address to subscribe to (for AMM markets)\n */\n marketAddress?: string;\n\n /**\n * Additional filters\n */\n filters?: Record<string, any>;\n}\n","import { ethers } from 'ethers';\nimport type { SignatureHeaders } from '../types/auth';\n\n/**\n * Message signer for authentication.\n *\n * @remarks\n * This class handles signing messages with an Ethereum wallet and\n * creating authentication headers required by the Limitless Exchange API.\n *\n * @public\n */\nexport class MessageSigner {\n private wallet: ethers.Wallet;\n\n /**\n * Creates a new message signer instance.\n *\n * @param wallet - Ethers wallet instance for signing\n */\n constructor(wallet: ethers.Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Creates authentication headers for API requests.\n *\n * @param signingMessage - Message to sign from the API\n * @returns Promise resolving to signature headers\n *\n * @example\n * ```typescript\n * const signer = new MessageSigner(wallet);\n * const headers = await signer.createAuthHeaders(message);\n * ```\n */\n async createAuthHeaders(signingMessage: string): Promise<SignatureHeaders> {\n const hexMessage = this.stringToHex(signingMessage);\n const signature = await this.wallet.signMessage(signingMessage);\n const address = this.wallet.address;\n\n const recoveredAddress = ethers.verifyMessage(signingMessage, signature);\n if (address.toLowerCase() !== recoveredAddress.toLowerCase()) {\n throw new Error('Signature verification failed: address mismatch');\n }\n\n return {\n 'x-account': address,\n 'x-signing-message': hexMessage,\n 'x-signature': signature,\n };\n }\n\n /**\n * Signs EIP-712 typed data.\n *\n * @param domain - EIP-712 domain\n * @param types - EIP-712 types\n * @param value - Value to sign\n * @returns Promise resolving to signature string\n *\n * @example\n * ```typescript\n * const signature = await signer.signTypedData(domain, types, order);\n * ```\n */\n async signTypedData(\n domain: ethers.TypedDataDomain,\n types: Record<string, ethers.TypedDataField[]>,\n value: Record<string, any>\n ): Promise<string> {\n return await this.wallet.signTypedData(domain, types, value);\n }\n\n /**\n * Gets the wallet address.\n *\n * @returns Ethereum address\n */\n getAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Converts a string to hex format.\n *\n * @param text - String to convert\n * @returns Hex string with 0x prefix\n * @internal\n */\n private stringToHex(text: string): string {\n return ethers.hexlify(ethers.toUtf8Bytes(text));\n }\n}\n","import { AxiosResponse } from 'axios';\nimport { HttpClient } from '../api/http';\nimport { MessageSigner } from './signer';\nimport type { AuthResult, LoginOptions, UserProfile } from '../types/auth';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Authenticator for Limitless Exchange API.\n *\n * @remarks\n * This class handles the complete authentication flow:\n * 1. Get signing message from API\n * 2. Sign message with wallet\n * 3. Login and obtain session cookie\n * 4. Verify authentication status\n *\n * @public\n */\nexport class Authenticator {\n private httpClient: HttpClient;\n private signer: MessageSigner;\n private logger: ILogger;\n\n /**\n * Creates a new authenticator instance.\n *\n * @param httpClient - HTTP client for API requests\n * @param signer - Message signer for wallet operations\n * @param logger - Optional logger for debugging and monitoring (default: no logging)\n *\n * @example\n * ```typescript\n * // Without logging (default)\n * const authenticator = new Authenticator(httpClient, signer);\n *\n * // With logging\n * import { ConsoleLogger } from '@limitless-exchange/sdk';\n * const logger = new ConsoleLogger('debug');\n * const authenticator = new Authenticator(httpClient, signer, logger);\n * ```\n */\n constructor(httpClient: HttpClient, signer: MessageSigner, logger?: ILogger) {\n this.httpClient = httpClient;\n this.signer = signer;\n this.logger = logger || new NoOpLogger();\n }\n\n /**\n * Gets a signing message from the API.\n *\n * @returns Promise resolving to signing message string\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const message = await authenticator.getSigningMessage();\n * console.log(message);\n * ```\n */\n async getSigningMessage(): Promise<string> {\n this.logger.debug('Requesting signing message from API');\n const message = await this.httpClient.get<string>('/auth/signing-message');\n this.logger.debug('Received signing message', { length: message.length });\n return message;\n }\n\n /**\n * Authenticates with the API and obtains session cookie.\n *\n * @param options - Login options including client type and smart wallet\n * @returns Promise resolving to authentication result\n * @throws Error if authentication fails or smart wallet is required but not provided\n *\n * @example\n * ```typescript\n * // EOA authentication\n * const result = await authenticator.authenticate({ client: 'eoa' });\n *\n * // ETHERSPOT with smart wallet\n * const result = await authenticator.authenticate({\n * client: 'etherspot',\n * smartWallet: '0x...'\n * });\n * ```\n */\n async authenticate(options: LoginOptions = {}): Promise<AuthResult> {\n const client = options.client || 'eoa';\n\n this.logger.info('Starting authentication', {\n client,\n hasSmartWallet: !!options.smartWallet,\n });\n\n if (client === 'etherspot' && !options.smartWallet) {\n this.logger.error('Smart wallet address required for ETHERSPOT client');\n throw new Error('Smart wallet address is required for ETHERSPOT client');\n }\n\n try {\n const signingMessage = await this.getSigningMessage();\n\n this.logger.debug('Creating signature headers');\n const headers = await this.signer.createAuthHeaders(signingMessage);\n\n this.logger.debug('Sending authentication request', { client });\n const response = await this.httpClient.postWithResponse<UserProfile>(\n '/auth/login',\n { client, smartWallet: options.smartWallet },\n {\n headers: headers as any,\n validateStatus: (status) => status < 500,\n }\n );\n\n this.logger.debug('Extracting session cookie from response');\n const cookies = this.httpClient.extractCookies(response);\n\n const sessionCookie = cookies['limitless_session'];\n if (!sessionCookie) {\n this.logger.error('Session cookie not found in response headers');\n throw new Error('Failed to obtain session cookie from response');\n }\n\n this.httpClient.setSessionCookie(sessionCookie);\n\n this.logger.info('Authentication successful', {\n account: response.data.account,\n client: response.data.client,\n });\n\n return {\n sessionCookie,\n profile: response.data,\n };\n } catch (error) {\n this.logger.error('Authentication failed', error as Error, {\n client,\n });\n throw error;\n }\n }\n\n /**\n * Verifies the current authentication status.\n *\n * @param sessionCookie - Session cookie to verify\n * @returns Promise resolving to user's Ethereum address\n * @throws Error if session is invalid\n *\n * @example\n * ```typescript\n * const address = await authenticator.verifyAuth(sessionCookie);\n * console.log(`Authenticated as: ${address}`);\n * ```\n */\n async verifyAuth(sessionCookie: string): Promise<string> {\n this.logger.debug('Verifying authentication session');\n const originalCookie = this.httpClient['sessionCookie'];\n this.httpClient.setSessionCookie(sessionCookie);\n\n try {\n const address = await this.httpClient.get<string>('/auth/verify-auth');\n this.logger.info('Session verified', { address });\n return address;\n } catch (error) {\n this.logger.error('Session verification failed', error as Error);\n throw error;\n } finally {\n if (originalCookie) {\n this.httpClient.setSessionCookie(originalCookie);\n } else {\n this.httpClient.clearSessionCookie();\n }\n }\n }\n\n /**\n * Logs out and clears the session.\n *\n * @param sessionCookie - Session cookie to invalidate\n * @throws Error if logout request fails\n *\n * @example\n * ```typescript\n * await authenticator.logout(sessionCookie);\n * console.log('Logged out successfully');\n * ```\n */\n async logout(sessionCookie: string): Promise<void> {\n this.logger.debug('Logging out session');\n const originalCookie = this.httpClient['sessionCookie'];\n this.httpClient.setSessionCookie(sessionCookie);\n\n try {\n await this.httpClient.post('/auth/logout', {});\n this.logger.info('Logout successful');\n } catch (error) {\n this.logger.error('Logout failed', error as Error);\n throw error;\n } finally {\n if (originalCookie) {\n this.httpClient.setSessionCookie(originalCookie);\n } else {\n this.httpClient.clearSessionCookie();\n }\n }\n }\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 * Optional helper for automatic authentication retry on token expiration.\n * @module auth/authenticated-client\n */\n\nimport { HttpClient } from '../api/http';\nimport { APIError } from '../api/errors';\nimport { Authenticator } from './authenticator';\nimport { MessageSigner } from './signer';\nimport type { ILogger } from '../types/logger';\nimport { NoOpLogger } from '../types/logger';\n\n/**\n * Configuration for authenticated client with auto-retry.\n * @public\n */\nexport interface AuthenticatedClientConfig {\n /**\n * HTTP client instance\n */\n httpClient: HttpClient;\n\n /**\n * Authenticator instance\n */\n authenticator: Authenticator;\n\n /**\n * Authentication client type ('eoa' or 'etherspot')\n */\n client: 'eoa' | 'etherspot';\n\n /**\n * Optional smart wallet address (required for 'etherspot')\n */\n smartWallet?: string;\n\n /**\n * Optional logger for debugging\n */\n logger?: ILogger;\n\n /**\n * Maximum retry attempts for auth errors (default: 1)\n */\n maxRetries?: number;\n}\n\n/**\n * Optional helper class that automatically re-authenticates on token expiration.\n *\n * @remarks\n * This is an optional convenience wrapper. Users can choose to handle\n * authentication retry manually or use this helper for automatic retry logic.\n *\n * @example\n * ```typescript\n * // Create authenticated client with auto-retry\n * const authClient = new AuthenticatedClient({\n * httpClient,\n * authenticator,\n * client: 'eoa'\n * });\n *\n * // Use withRetry for automatic re-authentication\n * const portfolioFetcher = new PortfolioFetcher(httpClient);\n * const positions = await authClient.withRetry(() =>\n * portfolioFetcher.getPositions()\n * );\n * ```\n *\n * @public\n */\nexport class AuthenticatedClient {\n private httpClient: HttpClient;\n private authenticator: Authenticator;\n private client: 'eoa' | 'etherspot';\n private smartWallet?: string;\n private logger: ILogger;\n private maxRetries: number;\n\n /**\n * Creates a new authenticated client with auto-retry capability.\n *\n * @param config - Configuration for authenticated client\n */\n constructor(config: AuthenticatedClientConfig) {\n this.httpClient = config.httpClient;\n this.authenticator = config.authenticator;\n this.client = config.client;\n this.smartWallet = config.smartWallet;\n this.logger = config.logger || new NoOpLogger();\n this.maxRetries = config.maxRetries ?? 1;\n }\n\n /**\n * Executes a function with automatic retry on authentication errors.\n *\n * @param fn - Function to execute with auth retry\n * @returns Promise resolving to the function result\n * @throws Error if max retries exceeded or non-auth error occurs\n *\n * @example\n * ```typescript\n * // Automatic retry on 401/403\n * const positions = await authClient.withRetry(() =>\n * portfolioFetcher.getPositions()\n * );\n *\n * // Works with any async operation\n * const order = await authClient.withRetry(() =>\n * orderClient.createOrder({ ... })\n * );\n * ```\n */\n async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let attempts = 0;\n\n while (attempts <= this.maxRetries) {\n try {\n return await fn();\n } catch (error) {\n // Check if it's an auth error and we have retries left\n if (error instanceof APIError && error.isAuthError() && attempts < this.maxRetries) {\n this.logger.info('Authentication expired, re-authenticating...', {\n attempt: attempts + 1,\n maxRetries: this.maxRetries,\n });\n\n // Re-authenticate\n await this.reauthenticate();\n\n // Increment attempts and retry\n attempts++;\n continue;\n }\n\n // Not an auth error or no retries left - throw\n throw error;\n }\n }\n\n // Should never reach here, but TypeScript needs this\n throw new Error('Unexpected error: exceeded max retries');\n }\n\n /**\n * Re-authenticates with the API.\n *\n * @internal\n */\n private async reauthenticate(): Promise<void> {\n this.logger.debug('Re-authenticating with API');\n\n await this.authenticator.authenticate({\n client: this.client,\n smartWallet: this.smartWallet,\n });\n\n this.logger.info('Re-authentication successful');\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 } 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 * Session cookie for authenticated requests\n */\n sessionCookie?: 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 cookie management,\n * error handling, and request/response interceptors.\n *\n * @public\n */\nexport class HttpClient {\n private client: AxiosInstance;\n private sessionCookie?: 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.sessionCookie = config.sessionCookie;\n this.logger = config.logger || new NoOpLogger();\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.sessionCookie) {\n config.headers['Cookie'] = `limitless_session=${this.sessionCookie}`;\n }\n\n // Log outgoing request - concise format\n const fullUrl = `${config.baseURL || ''}${config.url || ''}`;\n const method = config.method?.toUpperCase() || 'GET';\n\n this.logger.debug(`→ ${method} ${fullUrl}`, {\n headers: config.headers,\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 APIError with original data preserved\n throw new APIError(message, status, data, url, method);\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 session cookie for authenticated requests.\n *\n * @param cookie - Session cookie value\n */\n setSessionCookie(cookie: string): void {\n this.sessionCookie = cookie;\n }\n\n /**\n * Clears the session cookie.\n */\n clearSessionCookie(): void {\n this.sessionCookie = 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 POST request and returns the full response object.\n * Useful when you need access to response headers (e.g., for cookie extraction).\n *\n * @param url - Request URL\n * @param data - Request body data\n * @param config - Additional request configuration\n * @returns Promise resolving to the full AxiosResponse object\n * @internal\n */\n async postWithResponse<T = any>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig\n ): Promise<AxiosResponse<T>> {\n return await this.client.post(url, data, config);\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 * Extracts cookies from response headers.\n *\n * @param response - Axios response object\n * @returns Object containing parsed cookies\n * @internal\n */\n extractCookies(response: AxiosResponse): Record<string, string> {\n const setCookie = response.headers['set-cookie'];\n if (!setCookie) return {};\n\n const cookies: Record<string, string> = {};\n const cookieStrings = Array.isArray(setCookie) ? setCookie : [setCookie];\n\n for (const cookieString of cookieStrings) {\n const parts = cookieString.split(';')[0].split('=');\n if (parts.length === 2) {\n cookies[parts[0].trim()] = parts[1].trim();\n }\n }\n\n return cookies;\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 * @public\n */\nexport const CONTRACT_ADDRESSES = {\n // Base mainnet (chainId: 8453)\n 8453: {\n CLOB: '0xa4409D988CA2218d956BeEFD3874100F444f0DC3',\n NEGRISK: '0x5a38afc17F7E97ad8d6C547ddb837E40B4aEDfC6',\n },\n // Base Sepolia testnet (chainId: 84532)\n 84532: {\n CLOB: '0x...', // Add testnet addresses when available\n NEGRISK: '0x...',\n },\n} as const;\n\n/**\n * Get contract address for a specific market type and chain\n *\n * @param marketType - Market type (CLOB or NEGRISK)\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 marketType: 'CLOB' | 'NEGRISK',\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 return addresses[marketType];\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, MarketType, 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 * marketType: MarketType.CLOB\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 * marketType: MarketType.CLOB\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 'amount' 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 < 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 {\n UnsignedOrder,\n OrderSigningConfig,\n MarketType,\n} 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 * marketType: MarketType.CLOB\n * });\n * ```\n */\n async signOrder(\n order: UnsignedOrder,\n config: OrderSigningConfig\n ): Promise<string> {\n this.logger.debug('Signing order with EIP-712', {\n tokenId: order.tokenId,\n side: order.side,\n marketType: config.marketType,\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 console.log('[OrderSigner] Full signing payload:', JSON.stringify({\n domain,\n types: this.getTypes(),\n value: orderValue,\n }, null, 2));\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 * Validation error class.\n * @public\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\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 ValidationError 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 ValidationError('TokenId is required');\n }\n\n if (args.tokenId === '0') {\n throw new ValidationError('TokenId cannot be zero');\n }\n\n // Validate tokenId format (should be numeric string)\n if (!/^\\d+$/.test(args.tokenId)) {\n throw new ValidationError(`Invalid tokenId format: ${args.tokenId}`);\n }\n\n // Validate taker address if provided\n if (args.taker && !ethers.isAddress(args.taker)) {\n throw new ValidationError(`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 ValidationError(`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 ValidationError(`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 ValidationError('Amount must be a valid number');\n }\n\n if (args.makerAmount <= 0) {\n throw new ValidationError(`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 ValidationError(\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 ValidationError('Price must be a valid number');\n }\n\n if (args.price < 0 || args.price > 1) {\n throw new ValidationError(`Price must be between 0 and 1, got: ${args.price}`);\n }\n\n if (typeof args.size !== 'number' || isNaN(args.size)) {\n throw new ValidationError('Size must be a valid number');\n }\n\n if (args.size <= 0) {\n throw new ValidationError(`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 ValidationError 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 ValidationError(`Invalid maker address: ${order.maker}`);\n }\n\n if (!ethers.isAddress(order.signer)) {\n throw new ValidationError(`Invalid signer address: ${order.signer}`);\n }\n\n if (!ethers.isAddress(order.taker)) {\n throw new ValidationError(`Invalid taker address: ${order.taker}`);\n }\n\n // Validate amounts\n if (!order.makerAmount || order.makerAmount === 0) {\n throw new ValidationError('MakerAmount must be greater than zero');\n }\n\n if (!order.takerAmount || order.takerAmount === 0) {\n throw new ValidationError('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 ValidationError(`Invalid makerAmount: ${order.makerAmount}`);\n }\n\n if (typeof order.takerAmount !== 'number' || order.takerAmount <= 0) {\n throw new ValidationError(`Invalid takerAmount: ${order.takerAmount}`);\n }\n\n if (!/^\\d+$/.test(order.tokenId)) {\n throw new ValidationError(`Invalid tokenId format: ${order.tokenId}`);\n }\n\n if (!/^\\d+$/.test(order.expiration)) {\n throw new ValidationError(`Invalid expiration format: ${order.expiration}`);\n }\n\n // Validate salt\n if (!Number.isInteger(order.salt) || order.salt <= 0) {\n throw new ValidationError(`Invalid salt: ${order.salt}`);\n }\n\n // Validate nonce\n if (!Number.isInteger(order.nonce) || order.nonce < 0) {\n throw new ValidationError(`Invalid nonce: ${order.nonce}`);\n }\n\n // Validate feeRateBps\n if (!Number.isInteger(order.feeRateBps) || order.feeRateBps < 0) {\n throw new ValidationError(`Invalid feeRateBps: ${order.feeRateBps}`);\n }\n\n // Validate side (0 or 1)\n if (order.side !== 0 && order.side !== 1) {\n throw new ValidationError(`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 ValidationError(`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 ValidationError('Price must be a valid number');\n }\n\n if (order.price < 0 || order.price > 1) {\n throw new ValidationError(`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 ValidationError 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 ValidationError('Signature is required');\n }\n\n if (!order.signature.startsWith('0x')) {\n throw new ValidationError('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 ValidationError(\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 ValidationError('Signature must be valid hex string');\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, MarketType } from '../types/orders';\nimport { OrderBuilder } from './builder';\nimport { OrderSigner } from './signer';\nimport type { ethers } from 'ethers';\nimport type { UserData } from '../types/auth';\nimport { getContractAddress } from '../utils/constants';\n\n/**\n * Configuration for the order client.\n *\n * @remarks\n * The order client supports two configuration modes:\n * 1. Simple mode: Provide userData and marketType (auto-configures signing)\n * 2. Advanced mode: Provide userData and custom signingConfig\n *\n * @public\n */\nexport interface OrderClientConfig {\n /**\n * HTTP client for API requests\n */\n httpClient: HttpClient;\n\n /**\n * Wallet for signing orders\n */\n wallet: ethers.Wallet;\n\n /**\n * User data containing userId and feeRateBps\n *\n * @example\n * ```typescript\n * {\n * userId: 123, // From auth result\n * feeRateBps: 300 // User's fee rate (3%)\n * }\n * ```\n */\n userData: UserData;\n\n /**\n * Market type for auto-configuration (optional if signingConfig provided)\n *\n * @remarks\n * When provided without signingConfig, automatically loads contract address\n * from environment variables or SDK defaults.\n *\n * @defaultValue MarketType.CLOB\n */\n marketType?: MarketType;\n\n /**\n * Custom signing configuration (optional)\n *\n * @remarks\n * If not provided, SDK will auto-configure based on marketType.\n * Useful for custom deployments or testing.\n */\n signingConfig?: OrderSigningConfig;\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 * @example\n * ```typescript\n * const orderClient = new OrderClient({\n * httpClient,\n * wallet,\n * ownerId: 123,\n * feeRateBps: 100,\n * signingConfig: {\n * chainId: 8453,\n * contractAddress: '0x...',\n * marketType: MarketType.CLOB\n * }\n * });\n *\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 orderBuilder: OrderBuilder;\n private orderSigner: OrderSigner;\n private ownerId: number;\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 * @throws Error if neither marketType nor signingConfig is provided\n */\n constructor(config: OrderClientConfig) {\n this.httpClient = config.httpClient;\n this.logger = config.logger || new NoOpLogger();\n\n // Extract user data\n this.ownerId = config.userData.userId;\n const feeRateBps = config.userData.feeRateBps;\n\n // Initialize order builder with default price tick (0.001 = 3 decimals)\n this.orderBuilder = new OrderBuilder(config.wallet.address, feeRateBps, 0.001);\n\n // Initialize order signer\n this.orderSigner = new OrderSigner(config.wallet, this.logger);\n\n // Configure signing: use provided config or auto-configure from marketType\n if (config.signingConfig) {\n // Use custom signing configuration\n this.signingConfig = config.signingConfig;\n } else if (config.marketType) {\n // Auto-configure from market type\n const chainId = parseInt(process.env.CHAIN_ID || '8453'); // Base mainnet default\n\n // Check for market-type specific env var first, then fall back to SDK defaults\n const contractAddress = config.marketType === MarketType.NEGRISK\n ? (process.env.NEGRISK_CONTRACT_ADDRESS || getContractAddress('NEGRISK', chainId))\n : (process.env.CLOB_CONTRACT_ADDRESS || getContractAddress('CLOB', chainId));\n\n this.signingConfig = {\n chainId,\n contractAddress,\n marketType: config.marketType,\n };\n\n this.logger.info('Auto-configured signing', {\n chainId,\n contractAddress,\n marketType: config.marketType,\n });\n } else {\n // Default to CLOB if neither provided\n const chainId = parseInt(process.env.CHAIN_ID || '8453');\n const contractAddress = process.env.CLOB_CONTRACT_ADDRESS ||\n getContractAddress('CLOB', chainId);\n\n this.signingConfig = {\n chainId,\n contractAddress,\n marketType: MarketType.CLOB,\n };\n\n this.logger.debug('Using default CLOB configuration', {\n chainId,\n contractAddress,\n });\n }\n }\n\n /**\n * Creates and submits a new order.\n *\n * @remarks\n * This method handles the complete order creation flow:\n * 1. Build unsigned order\n * 2. Sign with EIP-712\n * 3. Submit to API\n *\n * @param params - Order parameters\n * @returns Promise resolving to order response\n *\n * @throws Error if order creation fails\n *\n * @example\n * ```typescript\n * const order = await orderClient.createOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY,\n * orderType: OrderType.GTC,\n * marketSlug: 'market-slug'\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 this.logger.info('Creating order', {\n side: params.side,\n orderType: params.orderType,\n marketSlug: params.marketSlug,\n });\n\n // Step 1: Build unsigned order\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 // Step 2: Sign order with EIP-712\n const signature = await this.orderSigner.signOrder(\n unsignedOrder,\n this.signingConfig\n );\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: this.ownerId,\n };\n\n // Step 4: Submit to API\n this.logger.debug('Submitting order to API');\n console.log('[OrderClient] Full API request payload:', JSON.stringify(payload, null, 2));\n const apiResponse = await this.httpClient.post<any>(\n '/orders',\n payload\n );\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 }>(\n `/orders/${orderId}`\n );\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 }>(\n `/orders/all/${marketSlug}`\n );\n\n this.logger.info('All orders cancellation response', {\n marketSlug,\n message: response.message\n });\n\n return response;\n }\n\n /**\n * @deprecated Use `cancel()` instead\n */\n async cancelOrder(orderId: string): Promise<void> {\n await this.cancel(orderId);\n }\n\n /**\n * Gets an order by ID.\n *\n * @param orderId - Order ID to fetch\n * @returns Promise resolving to order details\n *\n * @throws Error if order not found\n *\n * @example\n * ```typescript\n * const order = await orderClient.getOrder('order-id-123');\n * console.log(order.order.side);\n * ```\n */\n async getOrder(orderId: string): Promise<OrderResponse> {\n this.logger.debug('Fetching order', { orderId });\n\n const response = await this.httpClient.get<OrderResponse>(\n `/orders/${orderId}`\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 Unsigned order\n *\n * @example\n * ```typescript\n * const unsignedOrder = orderClient.buildUnsignedOrder({\n * tokenId: '123456',\n * price: 0.65,\n * size: 100,\n * side: Side.BUY\n * });\n * ```\n */\n buildUnsignedOrder(params: OrderArgs): UnsignedOrder {\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 * Market data fetcher for Limitless Exchange.\n * @module markets/fetcher\n */\n\nimport { HttpClient } from '../api/http';\nimport type {\n Market,\n MarketsResponse,\n OrderBook,\n MarketPrice,\n ActiveMarketsParams,\n ActiveMarketsResponse,\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 * @public\n */\nexport class MarketFetcher {\n private httpClient: HttpClient;\n private logger: ILogger;\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 }\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<ActiveMarketsResponse>(endpoint);\n\n this.logger.info('Active markets fetched successfully', {\n count: response.data.length,\n total: response.totalMarketsCount,\n sortBy: params?.sortBy,\n page: params?.page,\n });\n\n return response;\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 * @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 * const market = await fetcher.getMarket('bitcoin-price-2024');\n * console.log(`Market: ${market.title}`);\n * ```\n */\n async getMarket(slug: string): Promise<Market> {\n this.logger.debug('Fetching market', { slug });\n\n try {\n const market = await this.httpClient.get<Market>(`/markets/${slug}`);\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 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 * Gets the current price for a token.\n *\n * @param tokenId - Token ID\n * @returns Promise resolving to price information\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const price = await fetcher.getPrice('123456');\n * console.log(`Current price: ${price.price}`);\n * ```\n */\n async getPrice(tokenId: string): Promise<MarketPrice> {\n this.logger.debug('Fetching price', { tokenId });\n\n try {\n const price = await this.httpClient.get<MarketPrice>(`/prices/${tokenId}`);\n\n this.logger.info('Price fetched successfully', {\n tokenId,\n price: price.price,\n });\n return price;\n } catch (error) {\n this.logger.error('Failed to fetch price', error as Error, { tokenId });\n throw error;\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} 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 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 = await this.httpClient.get<PortfolioPositionsResponse>(\n '/portfolio/positions'\n );\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 * Flattens positions into a unified format for easier consumption.\n *\n * @remarks\n * Converts CLOB positions (which have YES/NO sides) and AMM positions\n * into a unified Position array. Only includes positions with non-zero values.\n *\n * @returns Promise resolving to array of flattened positions\n * @throws Error if API request fails\n *\n * @example\n * ```typescript\n * const positions = await portfolioFetcher.getFlattenedPositions();\n * positions.forEach(pos => {\n * const pnlPercent = (pos.unrealizedPnl / pos.costBasis) * 100;\n * console.log(`${pos.market.title} (${pos.side}): ${pnlPercent.toFixed(2)}% P&L`);\n * });\n * ```\n */\n async getFlattenedPositions(): Promise<Position[]> {\n const response = await this.getPositions();\n const positions: Position[] = [];\n\n // Flatten CLOB positions\n for (const clobPos of response.clob || []) {\n // Add YES position if it has value\n const yesCost = parseFloat(clobPos.positions.yes.cost);\n const yesValue = parseFloat(clobPos.positions.yes.marketValue);\n if (yesCost > 0 || yesValue > 0) {\n positions.push({\n type: 'CLOB',\n market: clobPos.market,\n side: 'YES',\n costBasis: yesCost,\n marketValue: yesValue,\n unrealizedPnl: parseFloat(clobPos.positions.yes.unrealizedPnl),\n realizedPnl: parseFloat(clobPos.positions.yes.realisedPnl),\n currentPrice: clobPos.latestTrade?.latestYesPrice ?? 0,\n avgPrice: yesCost > 0 ? parseFloat(clobPos.positions.yes.fillPrice) / 1e6 : 0,\n tokenBalance: parseFloat(clobPos.tokensBalance.yes),\n });\n }\n\n // Add NO position if it has value\n const noCost = parseFloat(clobPos.positions.no.cost);\n const noValue = parseFloat(clobPos.positions.no.marketValue);\n if (noCost > 0 || noValue > 0) {\n positions.push({\n type: 'CLOB',\n market: clobPos.market,\n side: 'NO',\n costBasis: noCost,\n marketValue: noValue,\n unrealizedPnl: parseFloat(clobPos.positions.no.unrealizedPnl),\n realizedPnl: parseFloat(clobPos.positions.no.realisedPnl),\n currentPrice: clobPos.latestTrade?.latestNoPrice ?? 0,\n avgPrice: noCost > 0 ? parseFloat(clobPos.positions.no.fillPrice) / 1e6 : 0,\n tokenBalance: parseFloat(clobPos.tokensBalance.no),\n });\n }\n }\n\n // Flatten AMM positions\n for (const ammPos of response.amm || []) {\n const cost = parseFloat(ammPos.totalBuysCost);\n const value = parseFloat(ammPos.collateralAmount);\n\n if (cost > 0 || value > 0) {\n positions.push({\n type: 'AMM',\n market: ammPos.market,\n side: ammPos.outcomeIndex === 0 ? 'YES' : 'NO',\n costBasis: cost,\n marketValue: value,\n unrealizedPnl: parseFloat(ammPos.unrealizedPnl),\n realizedPnl: parseFloat(ammPos.realizedPnl),\n currentPrice: ammPos.latestTrade ? parseFloat(ammPos.latestTrade.outcomeTokenPrice) : 0,\n avgPrice: parseFloat(ammPos.averageFillPrice),\n tokenBalance: parseFloat(ammPos.outcomeTokenAmount),\n });\n }\n }\n\n this.logger.debug('Flattened positions', { count: positions.length });\n\n return positions;\n }\n\n /**\n * Calculates portfolio summary statistics from raw API response.\n *\n * @param response - Portfolio positions response from API\n * @returns Portfolio summary with totals and statistics\n *\n * @example\n * ```typescript\n * const response = await portfolioFetcher.getPositions();\n * const summary = portfolioFetcher.calculateSummary(response);\n *\n * console.log(`Total Portfolio Value: $${(summary.totalValue / 1e6).toFixed(2)}`);\n * console.log(`Total P&L: ${summary.totalUnrealizedPnlPercent.toFixed(2)}%`);\n * console.log(`CLOB Positions: ${summary.breakdown.clob.positions}`);\n * console.log(`AMM Positions: ${summary.breakdown.amm.positions}`);\n * ```\n */\n calculateSummary(response: PortfolioPositionsResponse): PortfolioSummary {\n this.logger.debug('Calculating portfolio summary', {\n clobCount: response.clob?.length || 0,\n ammCount: response.amm?.length || 0,\n });\n\n let totalValue = 0;\n let totalCostBasis = 0;\n let totalUnrealizedPnl = 0;\n let totalRealizedPnl = 0;\n\n let clobPositions = 0;\n let clobValue = 0;\n let clobPnl = 0;\n\n let ammPositions = 0;\n let ammValue = 0;\n let ammPnl = 0;\n\n // Process CLOB positions\n for (const clobPos of response.clob || []) {\n // YES side\n const yesCost = parseFloat(clobPos.positions.yes.cost);\n const yesValue = parseFloat(clobPos.positions.yes.marketValue);\n const yesUnrealizedPnl = parseFloat(clobPos.positions.yes.unrealizedPnl);\n const yesRealizedPnl = parseFloat(clobPos.positions.yes.realisedPnl);\n\n if (yesCost > 0 || yesValue > 0) {\n clobPositions++;\n totalCostBasis += yesCost;\n totalValue += yesValue;\n totalUnrealizedPnl += yesUnrealizedPnl;\n totalRealizedPnl += yesRealizedPnl;\n clobValue += yesValue;\n clobPnl += yesUnrealizedPnl;\n }\n\n // NO side\n const noCost = parseFloat(clobPos.positions.no.cost);\n const noValue = parseFloat(clobPos.positions.no.marketValue);\n const noUnrealizedPnl = parseFloat(clobPos.positions.no.unrealizedPnl);\n const noRealizedPnl = parseFloat(clobPos.positions.no.realisedPnl);\n\n if (noCost > 0 || noValue > 0) {\n clobPositions++;\n totalCostBasis += noCost;\n totalValue += noValue;\n totalUnrealizedPnl += noUnrealizedPnl;\n totalRealizedPnl += noRealizedPnl;\n clobValue += noValue;\n clobPnl += noUnrealizedPnl;\n }\n }\n\n // Process AMM positions\n for (const ammPos of response.amm || []) {\n const cost = parseFloat(ammPos.totalBuysCost);\n const value = parseFloat(ammPos.collateralAmount);\n const unrealizedPnl = parseFloat(ammPos.unrealizedPnl);\n const realizedPnl = parseFloat(ammPos.realizedPnl);\n\n if (cost > 0 || value > 0) {\n ammPositions++;\n totalCostBasis += cost;\n totalValue += value;\n totalUnrealizedPnl += unrealizedPnl;\n totalRealizedPnl += realizedPnl;\n ammValue += value;\n ammPnl += unrealizedPnl;\n }\n }\n\n // Calculate P&L percentage\n const totalUnrealizedPnlPercent =\n totalCostBasis > 0 ? (totalUnrealizedPnl / totalCostBasis) * 100 : 0;\n\n // Count unique markets\n const uniqueMarkets = new Set<number | string>();\n for (const pos of response.clob || []) {\n uniqueMarkets.add(pos.market.id);\n }\n for (const pos of response.amm || []) {\n uniqueMarkets.add(pos.market.id);\n }\n\n const summary: PortfolioSummary = {\n totalValue,\n totalCostBasis,\n totalUnrealizedPnl,\n totalRealizedPnl,\n totalUnrealizedPnlPercent,\n positionCount: clobPositions + ammPositions,\n marketCount: uniqueMarkets.size,\n breakdown: {\n clob: {\n positions: clobPositions,\n value: clobValue,\n pnl: clobPnl,\n },\n amm: {\n positions: ammPositions,\n value: ammValue,\n pnl: ammPnl,\n },\n },\n };\n\n this.logger.debug('Portfolio summary calculated', summary);\n\n return summary;\n }\n\n /**\n * Gets positions and calculates summary in a single call.\n *\n * @returns Promise resolving to response and summary\n * @throws Error if API request fails or user is not authenticated\n *\n * @example\n * ```typescript\n * const { response, summary } = await portfolioFetcher.getPortfolio();\n *\n * console.log('Portfolio Summary:');\n * console.log(` Total Value: $${(summary.totalValue / 1e6).toFixed(2)}`);\n * console.log(` Total P&L: $${(summary.totalUnrealizedPnl / 1e6).toFixed(2)}`);\n * console.log(` P&L %: ${summary.totalUnrealizedPnlPercent.toFixed(2)}%`);\n * console.log(`\\nCLOB Positions: ${response.clob.length}`);\n * console.log(`AMM Positions: ${response.amm.length}`);\n * ```\n */\n async getPortfolio(): Promise<{\n response: PortfolioPositionsResponse;\n summary: PortfolioSummary;\n }> {\n this.logger.debug('Fetching portfolio with summary');\n\n const response = await this.getPositions();\n const summary = this.calculateSummary(response);\n\n this.logger.info('Portfolio fetched with summary', {\n positionCount: summary.positionCount,\n totalValueUSDC: summary.totalValue / 1e6,\n pnlPercent: summary.totalUnrealizedPnlPercent,\n });\n\n return { response, summary };\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 type OrderbookUpdate,\n type TradeEvent,\n type OrderUpdate,\n type FillEvent,\n type MarketUpdate,\n type PriceUpdate,\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 * @example\n * ```typescript\n * // Create client\n * const wsClient = new WebSocketClient({\n * sessionCookie: 'your-session-cookie',\n * autoReconnect: true,\n * });\n *\n * // Subscribe to orderbook updates\n * wsClient.on('orderbook', (data) => {\n * console.log('Orderbook update:', data);\n * });\n *\n * // Connect and subscribe\n * await wsClient.connect();\n * await wsClient.subscribe('orderbook', { marketSlug: 'market-123' });\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 sessionCookie: config.sessionCookie || '',\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 session cookie for authentication.\n *\n * @param sessionCookie - Session cookie value\n */\n setSessionCookie(sessionCookie: string): void {\n this.config.sessionCookie = sessionCookie;\n\n // If already connected, reconnect with new auth\n if (this.socket?.connected) {\n this.logger.info('Session cookie updated, reconnecting...');\n this.disconnect();\n this.connect();\n }\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 if (this.socket?.connected) {\n this.logger.info('Already connected');\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 // Authentication via cookie header (required by WsJwtAuthGuard)\n const wsUrl = this.config.url.endsWith('/markets')\n ? this.config.url\n : `${this.config.url}/markets`;\n\n this.socket = io(wsUrl, {\n transports: ['websocket'], // Use WebSocket transport only\n extraHeaders: {\n cookie: `limitless_session=${this.config.sessionCookie}`\n },\n reconnection: this.config.autoReconnect,\n reconnectionDelay: this.config.reconnectDelay,\n reconnectionAttempts: this.config.maxReconnectAttempts,\n timeout: this.config.timeout,\n });\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 * @example\n * ```typescript\n * wsClient.disconnect();\n * ```\n */\n disconnect(): 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 when subscribed\n * @throws Error if not connected\n *\n * @example\n * ```typescript\n * // Subscribe to orderbook for a specific market\n * await wsClient.subscribe('orderbook', { marketSlug: '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 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 return new Promise((resolve, reject) => {\n this.socket!.emit(channel, options, (response: any) => {\n if (response?.error) {\n this.logger.error('Subscription failed', response.error);\n this.subscriptions.delete(subscriptionKey);\n reject(new Error(response.error));\n } else {\n this.logger.info('Subscribed successfully', { channel, options });\n resolve();\n }\n });\n });\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 *\n * @example\n * ```typescript\n * await wsClient.unsubscribe('orderbook', { marketSlug: 'market-123' });\n * ```\n */\n async unsubscribe(channel: SubscriptionChannel, options: SubscriptionOptions = {}): 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 // Pass raw unsubscribe event with channel and options\n return new Promise((resolve, reject) => {\n this.socket!.emit('unsubscribe', { channel, ...options }, (response: any) => {\n if (response?.error) {\n this.logger.error('Unsubscribe failed', response.error);\n reject(new Error(response.error));\n } else {\n this.logger.info('Unsubscribed successfully', { channel, options });\n resolve();\n }\n });\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>(\n event: K,\n handler: WebSocketEvents[K]\n ): 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>(\n event: K,\n handler: WebSocketEvents[K]\n ): 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\n * @returns This client for chaining\n */\n off<K extends keyof WebSocketEvents>(\n event: K,\n handler: WebSocketEvents[K]\n ): this {\n if (!this.socket) {\n return this;\n }\n\n // Pass raw event names, no transformation\n this.socket.off(event as string, handler as any);\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","MarketType","SignatureType","WebSocketState","http","https","axios","import_ethers","ZERO_ADDRESS","import_ethers"]}