"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { AuthenticationError: () => AuthenticationError, InsufficientFundsError: () => InsufficientFundsError, InvoicesEndpoint: () => InvoicesEndpoint, KlingEx: () => KlingEx, KlingExError: () => KlingExError, KlingExWebSocket: () => KlingExWebSocket, MarketsEndpoint: () => MarketsEndpoint, OrdersEndpoint: () => OrdersEndpoint, RateLimitError: () => RateLimitError, ValidationError: () => ValidationError, WalletEndpoint: () => WalletEndpoint, default: () => KlingEx }); module.exports = __toCommonJS(index_exports); // src/types/index.ts var KlingExError = class extends Error { constructor(message, code, statusCode, details) { super(message); this.code = code; this.statusCode = statusCode; this.details = details; this.name = "KlingExError"; } }; var AuthenticationError = class extends KlingExError { constructor(message = "Authentication failed") { super(message, "AUTH_ERROR", 401); this.name = "AuthenticationError"; } }; var RateLimitError = class extends KlingExError { constructor(message = "Rate limit exceeded", retryAfter) { super(message, "RATE_LIMIT", 429); this.retryAfter = retryAfter; this.name = "RateLimitError"; } }; var ValidationError = class extends KlingExError { constructor(message, details) { super(message, "VALIDATION_ERROR", 400, details); this.name = "ValidationError"; } }; var InsufficientFundsError = class extends KlingExError { constructor(message = "Insufficient funds") { super(message, "INSUFFICIENT_FUNDS", 400); this.name = "InsufficientFundsError"; } }; // src/http.ts var HttpClient = class { constructor(config) { this.config = config; } /** * Update authentication credentials */ setAuth(auth) { if (auth.apiKey) this.config.apiKey = auth.apiKey; if (auth.jwt) this.config.jwt = auth.jwt; } /** * Make an HTTP request to the API */ async request(endpoint, options = {}) { const { method = "GET", body, params, headers = {} } = options; let url = `${this.config.baseUrl}${endpoint}`; if (params) { const searchParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== void 0 && value !== null) { searchParams.append(key, String(value)); } } const queryString = searchParams.toString(); if (queryString) { url += `?${queryString}`; } } const requestHeaders = { "Content-Type": "application/json", ...headers }; if (this.config.apiKey) { requestHeaders["X-API-Key"] = this.config.apiKey; } else if (this.config.jwt) { requestHeaders["Authorization"] = `Bearer ${this.config.jwt}`; } const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.config.timeout); try { const response = await fetch(url, { method, headers: requestHeaders, body: body ? JSON.stringify(body) : void 0, signal: controller.signal }); clearTimeout(timeoutId); const contentType = response.headers.get("content-type"); let data; if (contentType?.includes("application/json")) { data = await response.json(); } else if (contentType?.includes("application/pdf")) { data = await response.blob(); } else { data = await response.text(); } if (!response.ok) { this.handleError(response.status, data); } return data; } catch (error) { clearTimeout(timeoutId); if (error instanceof KlingExError) { throw error; } if (error instanceof Error) { if (error.name === "AbortError") { throw new KlingExError("Request timeout", "TIMEOUT", 408); } throw new KlingExError(error.message, "NETWORK_ERROR"); } throw new KlingExError("Unknown error occurred", "UNKNOWN"); } } /** * Handle HTTP error responses */ handleError(status, data) { const errorMessage = this.extractErrorMessage(data); switch (status) { case 401: throw new AuthenticationError(errorMessage); case 429: const retryAfter = this.extractRetryAfter(data); throw new RateLimitError(errorMessage, retryAfter); case 400: if (errorMessage.toLowerCase().includes("insufficient")) { throw new InsufficientFundsError(errorMessage); } throw new ValidationError(errorMessage, data); default: throw new KlingExError(errorMessage, "API_ERROR", status, data); } } /** * Extract error message from response */ extractErrorMessage(data) { if (typeof data === "string") return data; if (typeof data === "object" && data !== null) { const obj = data; return String(obj.error || obj.message || obj.detail || "Unknown error"); } return "Unknown error"; } /** * Extract retry-after value from rate limit response */ extractRetryAfter(data) { if (typeof data === "object" && data !== null) { const obj = data; if (typeof obj.retry_after === "number") { return obj.retry_after; } } return void 0; } // Convenience methods async get(endpoint, params) { return this.request(endpoint, { method: "GET", params }); } async post(endpoint, body) { return this.request(endpoint, { method: "POST", body }); } async put(endpoint, body) { return this.request(endpoint, { method: "PUT", body }); } async delete(endpoint, body) { return this.request(endpoint, { method: "DELETE", body }); } }; // src/websocket.ts var KlingExWebSocket = class { constructor(url, auth, options = {}) { this.ws = null; this.subscriptions = /* @__PURE__ */ new Map(); this.reconnectAttempts = 0; this.reconnectTimeout = null; this.pingInterval = null; this.isConnecting = false; this.url = url; this.apiKey = auth.apiKey; this.jwt = auth.jwt; this.options = { reconnect: options.reconnect ?? true, reconnectInterval: options.reconnectInterval ?? 5e3, maxReconnectAttempts: options.maxReconnectAttempts ?? 10 }; } /** * Connect to WebSocket server */ async connect() { if (this.ws?.readyState === WebSocket.OPEN || this.isConnecting) { return; } this.isConnecting = true; return new Promise((resolve, reject) => { try { const wsUrl = new URL(this.url); if (this.apiKey) { wsUrl.searchParams.set("apiKey", this.apiKey); } else if (this.jwt) { wsUrl.searchParams.set("token", this.jwt); } this.ws = new WebSocket(wsUrl.toString()); this.ws.onopen = () => { this.isConnecting = false; this.reconnectAttempts = 0; this.startPingInterval(); this.resubscribeAll(); resolve(); }; this.ws.onclose = (event) => { this.isConnecting = false; this.stopPingInterval(); if (this.options.reconnect && !event.wasClean) { this.scheduleReconnect(); } }; this.ws.onerror = (_event) => { this.isConnecting = false; const err = new Error("WebSocket error"); this.errorHandler?.(err); reject(err); }; this.ws.onmessage = (event) => { this.handleMessage(event.data); }; } catch (error) { this.isConnecting = false; reject(error); } }); } /** * Disconnect from WebSocket server */ disconnect() { this.options.reconnect = false; this.stopPingInterval(); if (this.reconnectTimeout) { clearTimeout(this.reconnectTimeout); this.reconnectTimeout = null; } if (this.ws) { this.ws.close(1e3, "Client disconnect"); this.ws = null; } this.subscriptions.clear(); } /** * Set error handler */ onError(handler) { this.errorHandler = handler; } /** * Subscribe to orderbook updates * @param symbol - Trading pair symbol * @param handler - Callback for orderbook updates */ orderbook(symbol, handler) { return this.subscribe("orderbook", symbol, handler); } /** * Subscribe to trade updates * @param symbol - Trading pair symbol * @param handler - Callback for trade updates */ trades(symbol, handler) { return this.subscribe("trades", symbol, handler); } /** * Subscribe to ticker updates * @param symbol - Trading pair symbol * @param handler - Callback for ticker updates */ ticker(symbol, handler) { return this.subscribe("ticker", symbol, handler); } /** * Subscribe to user order updates (requires auth) * @param handler - Callback for order updates */ userOrders(handler) { return this.subscribe("user.orders", void 0, handler); } /** * Subscribe to user balance updates (requires auth) * @param handler - Callback for balance updates */ userBalances(handler) { return this.subscribe("user.balances", void 0, handler); } // ========================================================================= // Private methods // ========================================================================= subscribe(channel, symbol, handler) { const key = symbol ? `${channel}:${symbol}` : channel; this.subscriptions.set(key, { channel, symbol, handler }); if (this.ws?.readyState === WebSocket.OPEN) { this.sendSubscribe(channel, symbol); } return () => { this.subscriptions.delete(key); if (this.ws?.readyState === WebSocket.OPEN) { this.sendUnsubscribe(channel, symbol); } }; } sendSubscribe(channel, symbol) { this.send({ action: "subscribe", channel, symbol }); } sendUnsubscribe(channel, symbol) { this.send({ action: "unsubscribe", channel, symbol }); } send(data) { if (this.ws?.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify(data)); } } handleMessage(data) { try { const message = JSON.parse(data); if (message.type === "pong") { return; } const key = message.data && typeof message.data === "object" && "symbol" in message.data ? `${message.channel}:${message.data.symbol}` : message.channel; const subscription = this.subscriptions.get(key) || this.subscriptions.get(message.channel); if (subscription) { subscription.handler(message.data); } } catch (error) { this.errorHandler?.(error instanceof Error ? error : new Error("Failed to parse message")); } } resubscribeAll() { for (const [, subscription] of this.subscriptions) { this.sendSubscribe(subscription.channel, subscription.symbol); } } scheduleReconnect() { if (this.reconnectAttempts >= this.options.maxReconnectAttempts) { this.errorHandler?.(new Error("Max reconnection attempts reached")); return; } this.reconnectAttempts++; const delay = this.options.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1); this.reconnectTimeout = setTimeout(() => { this.connect().catch((error) => { this.errorHandler?.(error instanceof Error ? error : new Error("Reconnection failed")); }); }, delay); } startPingInterval() { this.pingInterval = setInterval(() => { this.send({ type: "ping" }); }, 3e4); } stopPingInterval() { if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } } }; // src/endpoints/markets.ts var MarketsEndpoint = class { constructor(http) { this.http = http; } /** * Get all available markets/trading pairs * @example * const markets = await client.markets.list(); * // Returns full market info including: * // - base_asset_symbol, quote_asset_symbol * // - maker_fee_rate, taker_fee_rate * // - last_price, volume_24h, priceChange24h */ async list() { return this.http.get("/api/markets"); } /** * Get a specific market by ID * @param marketId - The market/trading pair ID */ async get(marketId) { const markets = await this.list(); return markets.find((m) => m.id === marketId); } /** * Find a market by symbol pair * @param baseSymbol - Base asset symbol (e.g., "BTC") * @param quoteSymbol - Quote asset symbol (e.g., "USDT") */ async findBySymbols(baseSymbol, quoteSymbol) { const markets = await this.list(); return markets.find( (m) => m.base_asset_symbol.toUpperCase() === baseSymbol.toUpperCase() && m.quote_asset_symbol.toUpperCase() === quoteSymbol.toUpperCase() ); } /** * Get all tickers with 24h price data (CMC format) * @example * const tickers = await client.markets.tickers(); * // Returns ticker_id as "BTC_USDT" format */ async tickers() { return this.http.get("/api/tickers"); } /** * Get ticker for a specific symbol pair * @param tickerId - Ticker ID in CMC format (e.g., "BTC_USDT") */ async ticker(tickerId) { const tickers = await this.tickers(); return tickers.find((t) => t.ticker_id === tickerId); } /** * Get ticker by base and quote currency * @param baseCurrency - Base currency symbol (e.g., "BTC") * @param targetCurrency - Target/quote currency symbol (e.g., "USDT") */ async tickerByPair(baseCurrency, targetCurrency) { const tickers = await this.tickers(); return tickers.find( (t) => t.base_currency.toUpperCase() === baseCurrency.toUpperCase() && t.target_currency.toUpperCase() === targetCurrency.toUpperCase() ); } /** * Get orderbook for a trading pair * @param marketId - The market/trading pair ID * @param options - Options for the orderbook request * @example * const orderbook = await client.markets.orderbook(1); * console.log('Best bid:', orderbook.bids[0]); * console.log('Best ask:', orderbook.asks[0]); */ async orderbook(marketId, options = {}) { const response = await this.http.get("/api/orderbook", { marketId, isCmc: options.isCmc ?? false }); return { trading_pair_id: response.trading_pair_id, base_symbol: response.base_symbol, quote_symbol: response.quote_symbol, bids: (response.bids || []).map(([price, quantity]) => ({ price, quantity })), asks: (response.asks || []).map(([price, quantity]) => ({ price, quantity })) }; } /** * Get raw orderbook (original API format with arrays) * @param marketId - The market/trading pair ID */ async orderbookRaw(marketId, options = {}) { return this.http.get("/api/orderbook", { marketId, isCmc: options.isCmc ?? false }); } /** * Get OHLCV (candlestick) data * @param marketId - Trading pair ID * @param timeframe - Candle timeframe (e.g., "1h", "1d") * @param options - Additional options * @example * const candles = await client.markets.ohlcv(1, '1h'); */ async ohlcv(marketId, timeframe, options = {}) { return this.http.get("/api/ohlcv", { marketId, timeframe, limit: options.limit, startDate: options.startDate, endDate: options.endDate }); } /** * Get all available assets * @example * const assets = await client.markets.assets(); */ async assets() { const response = await this.http.get("/api/assets"); return response.assets || []; } /** * Get a specific asset by symbol * @param symbol - Asset symbol (e.g., "BTC") */ async asset(symbol) { const assets = await this.assets(); return assets.find((a) => a.symbol.toUpperCase() === symbol.toUpperCase()); } /** * Get recent trades for a trading pair * @param marketId - Trading pair ID * @param limit - Number of trades to return */ async trades(marketId, limit = 50) { return this.http.get("/api/trades", { marketId, limit }); } }; // src/endpoints/orders.ts var OrdersEndpoint = class { constructor(http, humanReadableDefault = true) { this.http = http; this.humanReadableDefault = humanReadableDefault; } /** * Submit a new order * @param params - Order parameters * @example * // Buy 1.5 BTC at $50,000 (human-readable values) * const order = await client.orders.submit({ * symbol: 'BTC-USDT', * tradingPairId: 1, * side: 'BUY', * quantity: '1.5', * price: '50000.00' * }); * * @example * // Market order (price = 0) * const order = await client.orders.submit({ * symbol: 'BTC-USDT', * tradingPairId: 1, * side: 'BUY', * quantity: '1.0', * price: '0', * slippage: 0.01 // 1% slippage tolerance * }); */ async submit(params) { const rawValues = params.rawValues ?? !this.humanReadableDefault; return this.http.post("/api/submit-order", { symbol: params.symbol, tradingPairId: params.tradingPairId, side: params.side.toUpperCase(), quantity: params.quantity, price: params.price, rawValues, slippage: params.slippage }); } /** * Cancel an existing order * @param params - Order ID and trading pair ID * @example * const result = await client.orders.cancel({ * orderId: '7c9e6679-7425-40de-944b-e07fc1f90ae7', * tradingPairId: 1 * }); * console.log(`Released balance: ${result.released_balance}`); */ async cancel(params) { return this.http.post("/api/cancel-order", { orderId: params.orderId, tradingPairId: params.tradingPairId }); } /** * Cancel all open orders for a trading pair * @param tradingPairId - Trading pair ID * @example * const result = await client.orders.cancelAll(1); * console.log(`Cancelled ${result.cancelledCount} orders`); */ async cancelAll(tradingPairId) { return this.http.post("/api/cancel-all-orders", { tradingPairId }); } /** * Get your open orders * @param params - Filter parameters * @example * // Get all open orders * const orders = await client.orders.list(); * * // Get orders for specific trading pair * const orders = await client.orders.list({ tradingPairId: 1 }); */ async list(params = {}) { const response = await this.http.get("/api/user-orders", { tradingPairId: params.tradingPairId, status: params.status, limit: params.limit || 50 }); return response.orders || []; } /** * Get order history (including filled/cancelled orders) * @param params - Filter and pagination parameters */ async history(params = {}) { return this.http.get("/api/orders-history", { tradingPairId: params.tradingPairId, status: params.status, limit: params.limit || 50, offset: params.offset || 0 }); } /** * Get a specific order by ID * @param orderId - Order UUID */ async get(orderId) { const orders = await this.list(); return orders.find((o) => o.id === orderId); } // ========================================================================= // Convenience methods for common order types // ========================================================================= /** * Place a limit buy order (human-readable values) * @param symbol - Trading pair symbol (e.g., "BTC-USDT") * @param tradingPairId - Trading pair ID * @param quantity - Amount to buy * @param price - Price per unit */ async limitBuy(symbol, tradingPairId, quantity, price) { return this.submit({ symbol, tradingPairId, side: "BUY", quantity, price }); } /** * Place a limit sell order (human-readable values) * @param symbol - Trading pair symbol (e.g., "BTC-USDT") * @param tradingPairId - Trading pair ID * @param quantity - Amount to sell * @param price - Price per unit */ async limitSell(symbol, tradingPairId, quantity, price) { return this.submit({ symbol, tradingPairId, side: "SELL", quantity, price }); } /** * Place a market buy order * @param symbol - Trading pair symbol (e.g., "BTC-USDT") * @param tradingPairId - Trading pair ID * @param quantity - Amount to buy * @param slippage - Slippage tolerance (0-1, e.g., 0.01 for 1%) */ async marketBuy(symbol, tradingPairId, quantity, slippage = 0.01) { return this.submit({ symbol, tradingPairId, side: "BUY", quantity, price: "0", slippage }); } /** * Place a market sell order * @param symbol - Trading pair symbol (e.g., "BTC-USDT") * @param tradingPairId - Trading pair ID * @param quantity - Amount to sell * @param slippage - Slippage tolerance (0-1, e.g., 0.01 for 1%) */ async marketSell(symbol, tradingPairId, quantity, slippage = 0.01) { return this.submit({ symbol, tradingPairId, side: "SELL", quantity, price: "0", slippage }); } }; // src/endpoints/wallet.ts var WalletEndpoint = class { constructor(http) { this.http = http; } /** * Get all wallet balances * Each balance includes: * - balance: Total balance (raw value) * - locked_balance: Locked in orders (raw value) * - wallet_id: UUID of the wallet * - deposit_address: Deposit address for this asset * - id, symbol, name, decimals: Asset info * - min_deposit, min_withdrawal, withdrawal_fee: Limits * * @example * const balances = await client.wallet.balances(); * const ethBalance = balances.find(b => b.symbol === 'ETH'); * console.log(`ETH Balance: ${ethBalance?.balance}`); * console.log(`Deposit Address: ${ethBalance?.deposit_address}`); */ async balances() { const balances = await this.http.get("/api/user-balances"); return balances.map((b) => { const balance = BigInt(b.balance); const locked = BigInt(b.locked_balance); const available = balance - locked; const decimals = b.decimals; return { ...b, available_balance: available.toString(), human_balance: this.formatUnits(b.balance, decimals), human_locked: this.formatUnits(b.locked_balance, decimals), human_available: this.formatUnits(available.toString(), decimals) }; }); } /** * Get balance for a specific asset * @param symbol - Asset symbol (e.g., "BTC", "ETH", "USDT") */ async balance(symbol) { const balances = await this.balances(); return balances.find((b) => b.symbol.toUpperCase() === symbol.toUpperCase()); } /** * Get deposit address for an asset (from balance data) * The deposit_address is included in the balance response * @param symbol - Asset symbol (e.g., "BTC") * @example * const address = await client.wallet.depositAddress('ETH'); * console.log(`Send ETH to: ${address.address}`); */ async depositAddress(symbol) { const balances = await this.http.get("/api/user-balances"); const balance = balances.find((b) => b.symbol.toUpperCase() === symbol.toUpperCase()); if (!balance) { return void 0; } return { address: balance.deposit_address }; } /** * Generate a new deposit address (if supported) * @param assetId - Asset ID */ async generateDepositAddress(assetId) { const response = await this.http.post("/api/generate-deposit-address", { assetId }); return { address: response.address, memo: response.memo }; } /** * Submit a withdrawal request * @param params - Withdrawal parameters * @example * const result = await client.wallet.withdraw({ * assetId: 2, * symbol: 'ETH', * address: '0x...', * amount: '0.1' * }); * * if (result.requires_2fa) { * // Need to complete 2FA verification * await client.wallet.confirm2FA(result.session_token, '123456'); * } */ async withdraw(params) { return this.http.post("/api/submit-withdraw", { assetId: params.assetId, symbol: params.symbol, address: params.address, amount: params.amount, destinationTag: params.memo }); } /** * Complete withdrawal 2FA verification * @param sessionToken - Session token from withdraw response * @param code - 2FA code from authenticator app */ async confirm2FA(sessionToken, code) { return this.http.post("/api/withdrawal/complete-2fa", { sessionToken, code }); } /** * Get deposit history * @param options - Pagination options */ async deposits(options = {}) { return this.http.get("/api/deposits", { limit: options.limit || 50, offset: options.offset || 0 }); } /** * Get withdrawal history * @param options - Pagination options */ async withdrawals(options = {}) { return this.http.get("/api/withdrawals", { limit: options.limit || 50, offset: options.offset || 0 }); } /** * Get transaction history (deposits + withdrawals + trades) */ async history() { return this.http.get("/api/history"); } /** * Format raw units to human-readable decimal string * @param value - Raw value as string * @param decimals - Number of decimals */ formatUnits(value, decimals) { if (decimals === 0) return value; const str = value.padStart(decimals + 1, "0"); const intPart = str.slice(0, -decimals) || "0"; const decPart = str.slice(-decimals); const trimmedDec = decPart.replace(/0+$/, ""); return trimmedDec ? `${intPart}.${trimmedDec}` : intPart; } }; // src/endpoints/invoices.ts var InvoicesEndpoint = class { constructor(http) { this.http = http; } /** * Create a new payment invoice * @param params - Invoice parameters * @example * const invoice = await client.invoices.create({ * amount: '100.00', * asset: 'USDT', * description: 'Order #12345', * external_id: 'order-12345', * webhook_url: 'https://yoursite.com/webhook' * }); * * console.log(`Payment address: ${invoice.payment_address}`); * console.log(`Expires: ${invoice.expires_at}`); */ async create(params) { const response = await this.http.post("/api/invoices", { amount: params.amount, asset: params.asset, description: params.description, external_id: params.external_id, webhook_url: params.webhook_url, redirect_url: params.redirect_url, expires_in: params.expires_in }); if (!response.data) { throw new Error("Failed to create invoice"); } return response.data; } /** * Get all invoices * @param options - Pagination and filter options */ async list(options = {}) { return this.http.get("/api/invoices", { limit: options.limit || 50, offset: options.offset || 0, status: options.status }); } /** * Get a specific invoice by ID * @param invoiceId - Invoice UUID */ async get(invoiceId) { const response = await this.http.get(`/api/invoices/${invoiceId}`); if (!response.data) { throw new Error("Invoice not found"); } return response.data; } /** * Get invoice status (for polling) * @param invoiceId - Invoice UUID */ async status(invoiceId) { return this.http.get(`/api/invoices/${invoiceId}/status`); } /** * Cancel a pending invoice * @param invoiceId - Invoice UUID */ async cancel(invoiceId) { return this.http.post(`/api/invoices/${invoiceId}/cancel`); } /** * Get invoice PDF * @param invoiceId - Invoice UUID * @returns PDF blob */ async pdf(invoiceId) { return this.http.get(`/api/invoices/${invoiceId}/pdf`); } /** * Get estimated fees for an invoice * @param asset - Asset symbol * @param amount - Invoice amount */ async fees(asset, amount) { const response = await this.http.get("/api/invoices/fees", { asset, amount }); if (!response.data) { return { network_fee: "0", service_fee: "0", total_fee: "0" }; } return response.data; } /** * Get public invoice payment page data (no auth required) * @param invoiceId - Invoice UUID */ async paymentPage(invoiceId) { return this.http.get(`/api/invoices/${invoiceId}/pay`); } }; // src/client.ts var DEFAULT_BASE_URL = "https://api.klingex.io"; var DEFAULT_WS_URL = "wss://api.klingex.io/ws"; var DEFAULT_TIMEOUT = 3e4; var KlingEx = class { constructor(config = {}) { this._ws = null; this.config = { apiKey: config.apiKey, jwt: config.jwt, baseUrl: config.baseUrl || DEFAULT_BASE_URL, wsUrl: config.wsUrl || DEFAULT_WS_URL, timeout: config.timeout || DEFAULT_TIMEOUT, humanReadable: config.humanReadable ?? true }; this.http = new HttpClient({ baseUrl: this.config.baseUrl, apiKey: this.config.apiKey, jwt: this.config.jwt, timeout: this.config.timeout }); this.markets = new MarketsEndpoint(this.http); this.orders = new OrdersEndpoint(this.http, this.config.humanReadable); this.wallet = new WalletEndpoint(this.http); this.invoices = new InvoicesEndpoint(this.http); } /** * WebSocket client for real-time data * Note: Call ws.connect() before subscribing to channels */ get ws() { if (!this._ws) { this._ws = new KlingExWebSocket( this.config.wsUrl, { apiKey: this.config.apiKey, jwt: this.config.jwt } ); } return this._ws; } /** * Create WebSocket connection with custom options */ createWebSocket(options) { return new KlingExWebSocket( this.config.wsUrl, { apiKey: this.config.apiKey, jwt: this.config.jwt }, options ); } /** * Update authentication credentials */ setAuth(auth) { if (auth.apiKey) this.config.apiKey = auth.apiKey; if (auth.jwt) this.config.jwt = auth.jwt; this.http.setAuth(auth); } /** * Check if client has authentication configured */ get isAuthenticated() { return !!(this.config.apiKey || this.config.jwt); } /** * Get the configured base URL */ get baseUrl() { return this.config.baseUrl; } // ========================================================================= // Account endpoints (directly on client for convenience) // ========================================================================= /** * Get current user profile */ async getProfile() { return this.http.get("/api/profile"); } /** * Get current user info */ async getUser() { return this.http.get("/api/user"); } /** * Get API key statistics */ async getApiKeyStats() { return this.http.get("/api/api-keys/stats"); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AuthenticationError, InsufficientFundsError, InvoicesEndpoint, KlingEx, KlingExError, KlingExWebSocket, MarketsEndpoint, OrdersEndpoint, RateLimitError, ValidationError, WalletEndpoint });