@lynx-crypto/kraken-api 0.1.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/base/errors.ts","../src/base/restBase.ts","../src/spot/rest/market-data/getServerTime.ts","../src/spot/rest/market-data/getSystemStatus.ts","../src/spot/rest/market-data/getAssetInfo.ts","../src/spot/rest/market-data/getTradableAssetPairs.ts","../src/spot/rest/market-data/getTickerInformation.ts","../src/spot/rest/market-data/getOhlcData.ts","../src/spot/rest/market-data/getOrderBook.ts","../src/spot/rest/market-data/getRecentTrades.ts","../src/spot/rest/market-data/getRecentSpreads.ts","../src/spot/rest/market-data/index.ts","../src/spot/rest/account-data/getAccountBalance.ts","../src/spot/rest/account-data/getExtendedBalance.ts","../src/spot/rest/account-data/getCreditLines.ts","../src/spot/rest/account-data/getTradeBalance.ts","../src/spot/rest/account-data/getOpenOrders.ts","../src/spot/rest/account-data/getClosedOrders.ts","../src/spot/rest/account-data/queryOrdersInfo.ts","../src/spot/rest/account-data/getOrderAmends.ts","../src/spot/rest/account-data/getTradesHistory.ts","../src/spot/rest/account-data/queryTradesInfo.ts","../src/spot/rest/account-data/getOpenPositions.ts","../src/spot/rest/account-data/getLedgersInfo.ts","../src/spot/rest/account-data/queryLedgers.ts","../src/spot/rest/account-data/getTradeVolume.ts","../src/spot/rest/account-data/requestExportReport.ts","../src/spot/rest/account-data/getExportReportStatus.ts","../src/spot/rest/account-data/retrieveExportReport.ts","../src/spot/rest/account-data/deleteExportReport.ts","../src/spot/rest/account-data/index.ts","../src/spot/rest/trading/addOrder.ts","../src/spot/rest/trading/amendOrder.ts","../src/spot/rest/trading/cancelOrder.ts","../src/spot/rest/trading/cancelAllOrders.ts","../src/spot/rest/trading/cancelAllOrdersAfter.ts","../src/spot/rest/trading/getWebSocketsToken.ts","../src/spot/rest/trading/addOrderBatch.ts","../src/spot/rest/trading/cancelOrderBatch.ts","../src/spot/rest/trading/editOrder.ts","../src/spot/rest/trading/index.ts","../src/spot/rest/funding/getDepositMethods.ts","../src/spot/rest/funding/getDepositAddresses.ts","../src/spot/rest/funding/getDepositStatus.ts","../src/spot/rest/funding/getWithdrawMethods.ts","../src/spot/rest/funding/getWithdrawAddresses.ts","../src/spot/rest/funding/getWithdrawInfo.ts","../src/spot/rest/funding/withdrawFunds.ts","../src/spot/rest/funding/getWithdrawStatus.ts","../src/spot/rest/funding/withdrawCancel.ts","../src/spot/rest/funding/walletTransfer.ts","../src/spot/rest/funding/index.ts","../src/spot/rest/subaccounts/createSubaccount.ts","../src/spot/rest/subaccounts/accountTransfer.ts","../src/spot/rest/subaccounts/index.ts","../src/spot/rest/earn/allocateEarnFunds.ts","../src/spot/rest/earn/deallocateEarnFunds.ts","../src/spot/rest/earn/getAllocationStatus.ts","../src/spot/rest/earn/getDeallocationStatus.ts","../src/spot/rest/earn/listStrategies.ts","../src/spot/rest/earn/listAllocations.ts","../src/spot/rest/earn/index.ts","../src/spot/rest/transparency/getPreTradeData.ts","../src/spot/rest/transparency/getPostTradeData.ts","../src/spot/rest/transparency/index.ts","../src/spot/rest/spotRestClient.ts","../src/base/websocketBase.ts","../src/spot/websocket-v2/admin/status.ts","../src/spot/websocket-v2/admin/ping.ts","../src/spot/websocket-v2/admin/heartbeat.ts","../src/spot/websocket-v2/admin/index.ts","../src/spot/websocket-v2/market-data/ticker.ts","../src/spot/websocket-v2/market-data/book.ts","../src/spot/websocket-v2/market-data/level3.ts","../src/spot/websocket-v2/market-data/ohlc.ts","../src/spot/websocket-v2/market-data/trade.ts","../src/spot/websocket-v2/market-data/instrument.ts","../src/spot/websocket-v2/market-data/index.ts","../src/spot/websocket-v2/user-data/executions.ts","../src/spot/websocket-v2/user-data/balances.ts","../src/spot/websocket-v2/user-data/index.ts","../src/spot/websocket-v2/user-trading/addOrder.ts","../src/spot/websocket-v2/user-trading/amendOrder.ts","../src/spot/websocket-v2/user-trading/editOrder.ts","../src/spot/websocket-v2/user-trading/cancelOrder.ts","../src/spot/websocket-v2/user-trading/cancelAll.ts","../src/spot/websocket-v2/user-trading/cancelAllOrdersAfter.ts","../src/spot/websocket-v2/user-trading/batchAdd.ts","../src/spot/websocket-v2/user-trading/batchCancel.ts","../src/spot/websocket-v2/user-trading/index.ts","../src/spot/websocket-v2/spotWebsocketV2Client.ts"],"names":["KrakenApiError","message","details","KrakenRestBase","options","nowMs","path","query","url","key","value","controller","timeout","resp","json","e","params","nonce","bodyParams","bodyString","urlPath","sha256","createHash","secretBuffer","signature","createHmac","body","postData","apiSign","res","text","errors","err","buffer","secret","getServerTime","base","getSystemStatus","getAssetInfo","getTradableAssetPairs","getTickerInformation","getOhlcData","raw","last","rest","ohlc","pair","data","getOrderBook","getRecentTrades","trades","getRecentSpreads","spreads","KrakenSpotMarketDataApi","getAccountBalance","getExtendedBalance","getCreditLines","getTradeBalance","getOpenOrders","getClosedOrders","queryOrdersInfo","getOrderAmends","getTradesHistory","queryTradesInfo","getOpenPositions","getLedgersInfo","queryLedgers","getTradeVolume","requestExportReport","getExportReportStatus","retrieveExportReport","deleteExportReport","KrakenSpotAccountDataApi","addOrder","amendOrder","cancelOrder","txid","userref","cl_ord_id","provided","cancelAllOrders","cancelAllOrdersAfter","getWebSocketsToken","addOrderBatch","orders","asset_class","deadline","validate","index","o","wireOrders","wire","cancelOrderBatch","clOrdIds","countOrders","countClOrdIds","total","wireClOrdIds","id","editOrder","KrakenSpotTradingApi","getDepositMethods","getDepositAddresses","getDepositStatus","getWithdrawMethods","getWithdrawAddresses","getWithdrawInfo","withdrawFunds","asset","aclass","address","amount","max_fee","rebase_multiplier","getWithdrawStatus","method","start","end","cursor","limit","withdrawCancel","refid","walletTransfer","from","to","KrakenSpotFundingApi","createSubaccount","username","email","accountTransfer","KrakenSpotSubaccountsApi","allocateEarnFunds","strategy_id","deallocateEarnFunds","getAllocationStatus","getDeallocationStatus","listEarnStrategies","ascending","lock_type","listEarnAllocations","converted_asset","hide_zero_allocations","KrakenSpotEarnApi","getPreTradeData","symbol","getPostTradeData","from_ts","to_ts","count","KrakenSpotTransparencyApi","KrakenSpotRestClient","KrakenWebsocketBase","WebSocket","resolve","reject","WS","ws","ev","reqId","pending","parsed","handler","code","reason","payload","timeoutMs","attachAuthToken","baseParams","envelope","timeoutId","pendingRequest","msg","onStatus","ping","onHeartbeat","anyMsg","KrakenSpotWsAdminApi","subscribeTicker","unsubscribeTicker","subscribeBook","unsubscribeBook","subscribeLevel3","unsubscribeLevel3","subscribeOhlc","unsubscribeOhlc","subscribeTrade","unsubscribeTrade","subscribeInstrument","unsubscribeInstrument","KrakenSpotWsMarketDataApi","subscribeExecutions","unsubscribeExecutions","subscribeBalances","unsubscribeBalances","KrakenSpotWsUserDataApi","hasOrderId","hasClOrdId","hasOrderIds","hasClOrdIds","hasUserrefs","cancelAll","batchAdd","order","batchCancel","KrakenSpotWsUserTradingApi","KrakenSpotWebsocketV2Client","publicUrl","privateUrl","authToken","WebSocketImpl","autoReconnect","reconnectDelayMs","requestTimeoutMs","logger","baseOpts"],"mappings":"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","file":"index.cjs","sourcesContent":["export interface KrakenApiErrorDetails {\n endpoint?: string; // e.g. \"/0/public/Time\"\n httpStatus?: number; // e.g. 429, 500\n httpStatusText?: string;\n krakenErrorCodes?: string[]; // contents of result.error[]\n rawBody?: unknown; // parsed JSON if available\n}\n\n/**\n * Error thrown for any Kraken REST API issue:\n * - HTTP errors (non-2xx)\n * - Kraken-level errors (non-empty `error` array)\n * - Parse/format issues\n */\nexport class KrakenApiError extends Error {\n readonly name = 'KrakenApiError';\n\n readonly endpoint?: string;\n readonly httpStatus?: number;\n readonly httpStatusText?: string;\n readonly krakenErrorCodes?: string[];\n readonly rawBody?: unknown;\n\n constructor(message: string, details: KrakenApiErrorDetails = {}) {\n super(message);\n\n // Needed when targeting ES5\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.endpoint = details.endpoint;\n this.httpStatus = details.httpStatus;\n this.httpStatusText = details.httpStatusText;\n this.krakenErrorCodes = details.krakenErrorCodes;\n this.rawBody = details.rawBody;\n }\n}\n","import type {\n KrakenApiResponse,\n KrakenClientOptions,\n KrakenLogger,\n} from '../types/types';\nimport { KrakenApiError } from './errors';\nimport { createHash, createHmac } from 'node:crypto';\n\n/**\n * Low-level REST base for Kraken clients.\n * @internal\n */\nexport abstract class KrakenRestBase {\n protected readonly baseUrl: string;\n protected readonly timeoutMs: number;\n protected readonly userAgent?: string;\n\n protected readonly apiKey?: string;\n protected readonly apiSecret?: string;\n\n protected readonly logger?: KrakenLogger;\n\n // Nonce tracking for private endpoints\n private lastNonce?: bigint;\n private lastMs: number = 0;\n\n constructor(options: KrakenClientOptions = {}) {\n this.baseUrl = options.baseUrl ?? 'https://api.kraken.com';\n this.timeoutMs = options.timeoutMs ?? 10_000;\n this.userAgent = options.userAgent;\n\n this.apiKey = options.apiKey;\n this.apiSecret = options.apiSecret;\n\n this.logger = options.logger;\n }\n\n /**\n * Generate a strictly increasing nonce for private API calls.\n *\n * Strategy:\n * - Base value on current milliseconds * 1000 to allow many calls per ms.\n * - If current time goes backwards or stays the same, just increment\n * the last nonce.\n *\n * Safe for high throughput in a single Node process, as long as\n * createNonce() is not awaited and not called from multiple processes.\n *\n * @internal\n */\n protected createNonce(): string {\n const nowMs = Date.now();\n\n if (this.lastNonce === undefined) {\n this.lastNonce = BigInt(nowMs) * 1000n;\n this.lastMs = nowMs;\n return this.lastNonce.toString();\n }\n\n if (nowMs > this.lastMs) {\n // New millisecond, jump base up\n this.lastNonce = BigInt(nowMs) * 1000n;\n this.lastMs = nowMs;\n } else {\n // Same or earlier ms, just bump the counter\n this.lastNonce = this.lastNonce + 1n;\n // lastMs stays as-is; we care only that nonce is strictly increasing\n }\n\n return this.lastNonce.toString();\n }\n\n /**\n * Low-level helper for public GET endpoints.\n * @internal\n */\n public async publicGet<T>(\n path: string,\n query?: Record<string, string | number>,\n ): Promise<T> {\n const url = new URL(path, this.baseUrl);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n url.searchParams.set(key, String(value));\n }\n }\n\n this.logger?.debug?.('Kraken REST public GET request', {\n endpoint: path,\n url: url.toString(),\n query,\n });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const resp = await fetch(url, {\n method: 'GET',\n signal: controller.signal,\n headers: this.userAgent ? { 'User-Agent': this.userAgent } : undefined,\n });\n\n if (!resp.ok) {\n this.logger?.error?.('Kraken REST HTTP error', {\n endpoint: path,\n status: resp.status,\n statusText: resp.statusText,\n });\n\n throw new KrakenApiError(\n `HTTP error from Kraken: ${resp.status} ${resp.statusText}`,\n {\n endpoint: path,\n httpStatus: resp.status,\n httpStatusText: resp.statusText,\n },\n );\n }\n\n let json: KrakenApiResponse<T>;\n try {\n json = (await resp.json()) as KrakenApiResponse<T>;\n } catch (e) {\n this.logger?.error?.('Kraken REST JSON parse error', {\n endpoint: path,\n error: e,\n });\n\n throw new KrakenApiError('Failed to parse Kraken response JSON', {\n endpoint: path,\n httpStatus: resp.status,\n });\n }\n\n if (json.error?.length) {\n this.logger?.warn?.('Kraken REST API error', {\n endpoint: path,\n krakenErrors: json.error,\n });\n\n throw new KrakenApiError(`Kraken API error: ${json.error.join(', ')}`, {\n endpoint: path,\n httpStatus: resp.status,\n krakenErrorCodes: json.error,\n rawBody: json,\n });\n }\n\n this.logger?.debug?.('Kraken REST public GET success', {\n endpoint: path,\n });\n\n return json.result;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n /**\n * Low-level helper for private POST endpoints.\n * Handles nonce, signing, and Kraken error wrapper.\n * @internal\n */\n public async privatePost<T>(\n path: string, // e.g. \"/0/private/Balance\"\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<T> {\n if (!this.apiKey || !this.apiSecret) {\n throw new KrakenApiError(\n 'Missing apiKey or apiSecret for Kraken private API call',\n { endpoint: path },\n );\n }\n\n const url = new URL(path, this.baseUrl);\n const nonce = this.createNonce();\n\n // Build body\n const bodyParams = new URLSearchParams();\n bodyParams.set('nonce', nonce);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n bodyParams.set(key, String(value));\n }\n }\n\n const bodyString = bodyParams.toString();\n\n // Kraken signing:\n // signature = base64( HMAC-SHA512( urlPath + SHA256(nonce + POSTdata) , base64Decode(apiSecret) ) )\n const urlPath = path; // must be just the path, e.g. \"/0/private/Balance\"\n const sha256 = createHash('sha256')\n .update(nonce + bodyString)\n .digest();\n const secretBuffer = Buffer.from(this.apiSecret, 'base64');\n const hmac = createHmac('sha512', secretBuffer);\n const signature = hmac.update(urlPath + sha256).digest('base64');\n\n this.logger?.debug?.('Kraken REST private POST request', {\n endpoint: path,\n url: url.toString(),\n hasParams: !!params,\n });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const resp = await fetch(url, {\n method: 'POST',\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'API-Key': this.apiKey,\n 'API-Sign': signature,\n ...(this.userAgent ? { 'User-Agent': this.userAgent } : {}),\n },\n body: bodyString,\n });\n\n if (!resp.ok) {\n this.logger?.error?.('Kraken REST private HTTP error', {\n endpoint: path,\n status: resp.status,\n statusText: resp.statusText,\n });\n\n throw new KrakenApiError(\n `HTTP error from Kraken private API: ${resp.status} ${resp.statusText}`,\n {\n endpoint: path,\n httpStatus: resp.status,\n httpStatusText: resp.statusText,\n },\n );\n }\n\n let json: KrakenApiResponse<T>;\n try {\n json = (await resp.json()) as KrakenApiResponse<T>;\n } catch (e) {\n this.logger?.error?.('Kraken REST private JSON parse error', {\n endpoint: path,\n error: e,\n });\n\n throw new KrakenApiError(\n 'Failed to parse Kraken private API response JSON',\n {\n endpoint: path,\n httpStatus: resp.status,\n },\n );\n }\n\n if (json.error?.length) {\n this.logger?.warn?.('Kraken REST private API error', {\n endpoint: path,\n krakenErrors: json.error,\n });\n\n throw new KrakenApiError(\n `Kraken private API error: ${json.error.join(', ')}`,\n {\n endpoint: path,\n httpStatus: resp.status,\n krakenErrorCodes: json.error,\n rawBody: json,\n },\n );\n }\n\n this.logger?.debug?.('Kraken REST private POST success', {\n endpoint: path,\n });\n\n return json.result;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n /**\n * Perform a signed POST to a private Kraken endpoint and return\n * the raw binary body (ArrayBuffer).\n *\n * This is used for endpoints like /0/private/RetrieveExport which\n * return application/octet-stream (ZIP) instead of JSON.\n *\n * - Still signs the request and sends nonce like other private calls.\n * - If Kraken returns JSON with an `error` array, it throws.\n * - Otherwise it returns the raw ArrayBuffer.\n */\n protected async privatePostBinary(\n path: string,\n body?: Record<string, string>,\n ): Promise<ArrayBuffer> {\n if (!this.apiKey || !this.apiSecret) {\n throw new Error(\n 'KrakenRestBase: apiKey and apiSecret are required for private endpoints',\n );\n }\n\n const url = new URL(path, this.baseUrl);\n\n const nonce = this.createNonce();\n\n // Body is x-www-form-urlencoded; include nonce\n const params = new URLSearchParams({\n nonce,\n ...(body ?? {}),\n });\n\n const postData = params.toString();\n\n // Sign the request\n const apiSign = this.signPrivateRequest(path, nonce, postData);\n\n this.logger?.debug?.('[KrakenRestBase] privatePostBinary request', {\n url: url.toString(),\n path,\n body,\n });\n\n const res = await fetch(url.toString(), {\n method: 'POST',\n headers: {\n 'API-Key': this.apiKey,\n 'API-Sign': apiSign,\n 'User-Agent': this.userAgent ?? 'lynx-crypto-kraken-client/0.1.0',\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: postData,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n this.logger?.error?.('[KrakenRestBase] privatePostBinary HTTP error', {\n status: res.status,\n statusText: res.statusText,\n body: text,\n });\n\n throw new Error(\n `Kraken privatePostBinary failed: ${res.status} ${res.statusText} – ${text}`,\n );\n }\n\n const contentType = res.headers.get('content-type') ?? '';\n\n // Kraken will return JSON if there is an error, even for binary endpoints\n if (contentType.includes('application/json')) {\n const json = (await res.json().catch(() => null)) as {\n error?: string[];\n result?: unknown;\n } | null;\n\n if (!json) {\n throw new Error(\n 'Kraken privatePostBinary: expected JSON body for error response',\n );\n }\n\n const errors = json.error ?? [];\n if (errors.length > 0) {\n const message = `Kraken API error: ${errors.join(', ')}`;\n this.logger?.error?.(\n '[KrakenRestBase] Kraken API error (binary response)',\n { errors },\n );\n const err = new Error(message);\n (err as any).krakenErrors = errors;\n throw err;\n }\n\n // JSON but no errors on a binary endpoint = weird, treat as error\n throw new Error(\n 'Kraken privatePostBinary: expected binary data but got JSON without errors',\n );\n }\n\n // Happy path: application/octet-stream (ZIP)\n const buffer = await res.arrayBuffer();\n\n this.logger?.debug?.('[KrakenRestBase] privatePostBinary success', {\n bytes: buffer.byteLength,\n });\n\n return buffer;\n }\n\n /**\n * Sign a private Kraken request.\n *\n * API-Sign = base64( HMAC_SHA512( path + SHA256(nonce + postData), base64_decode(apiSecret) ) )\n */\n protected signPrivateRequest(\n path: string,\n nonce: string,\n postData: string,\n ): string {\n if (!this.apiSecret) {\n throw new Error(\n 'KrakenRestBase: apiSecret is required for private endpoints',\n );\n }\n\n const secret = Buffer.from(this.apiSecret, 'base64');\n\n // SHA256(nonce + POST data)\n const sha256 = createHash('sha256')\n .update(nonce + postData)\n .digest();\n\n // HMAC-SHA512(path + sha256)\n const hmac = createHmac('sha512', secret)\n .update(path + sha256)\n .digest('base64');\n\n return hmac;\n }\n}\n","// kraken/spot/rest/market-data/getServerTime.ts\nimport type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenServerTime {\n unixtime: number; // Unix timestamp\n rfc1123: string; // RFC 1123 time format\n}\n\n/**\n * GET /0/public/Time\n * Get the server's time.\n */\nexport function getServerTime(base: KrakenRestBase): Promise<KrakenServerTime> {\n // publicGet<T> will:\n // - call GET https://api.kraken.com/0/public/Time\n // - parse JSON as { error: string[]; result: T }\n // - throw KrakenApiError if error[].length > 0\n // - return result (i.e. KrakenServerTime)\n return base.publicGet<KrakenServerTime>('/0/public/Time');\n}\n","// kraken/spot/rest/market-data/getSystemStatus.ts\nimport type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenSystemStatus =\n | 'online'\n | 'maintenance'\n | 'cancel_only'\n | 'post_only';\n\nexport interface KrakenSystemStatusResult {\n status: KrakenSystemStatus;\n /**\n * Current timestamp in RFC3339 format\n * e.g. \"2025-12-10T04:18:32Z\"\n */\n timestamp: string;\n}\n\n/**\n * GET /0/public/SystemStatus\n * Get the current system status or trading mode.\n */\nexport function getSystemStatus(\n base: KrakenRestBase,\n): Promise<KrakenSystemStatusResult> {\n return base.publicGet<KrakenSystemStatusResult>('/0/public/SystemStatus');\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenAssetClass = 'currency' | 'tokenized_asset';\n\nexport type KrakenAssetStatus =\n | 'enabled'\n | 'deposit_only'\n | 'withdrawal_only'\n | 'funding_temporarily_disabled';\n\nexport interface KrakenAssetInfo {\n /**\n * Asset class (e.g. \"currency\" | \"tokenized_asset\")\n */\n aclass: string; // Kraken docs say string; we can narrow later if desired\n\n /**\n * Alternate name (e.g. \"XBT\", \"ETH\")\n */\n altname: string;\n\n /**\n * Number of decimal places for record keeping amounts of this asset\n */\n decimals: number;\n\n /**\n * Number of decimal places shown for display purposes in frontends\n */\n display_decimals: number;\n\n /**\n * Valuation as margin collateral (if applicable)\n */\n collateral_value?: number;\n\n /**\n * Status of asset.\n * - \"enabled\"\n * - \"deposit_only\"\n * - \"withdrawal_only\"\n * - \"funding_temporarily_disabled\"\n */\n status?: KrakenAssetStatus;\n}\n\n/**\n * Map of asset name -> info.\n * e.g. { \"XXBT\": { ... }, \"XETH\": { ... } }\n */\nexport type KrakenAssetInfoMap = Record<string, KrakenAssetInfo>;\n\nexport interface KrakenGetAssetInfoParams {\n /**\n * Comma-delimited list of assets to get info on (optional).\n * We accept string[] here and join internally.\n */\n asset?: string[];\n\n /**\n * Filters the asset class to retrieve (optional).\n * Default: \"currency\"\n */\n aclass?: KrakenAssetClass;\n}\n\n/**\n * GET /0/public/Assets\n * Get information about the assets that are available for deposit,\n * withdrawal, trading and earn.\n */\nexport function getAssetInfo(\n base: KrakenRestBase,\n params?: KrakenGetAssetInfoParams,\n): Promise<KrakenAssetInfoMap> {\n const query: Record<string, string> = {};\n\n if (params?.asset && params.asset.length > 0) {\n query.asset = params.asset.join(',');\n }\n\n if (params?.aclass) {\n query.aclass = params.aclass;\n }\n\n return base.publicGet<KrakenAssetInfoMap>('/0/public/Assets', query);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenAssetClass } from './getAssetInfo';\n\nexport type KrakenAssetPairStatus =\n | 'online'\n | 'cancel_only'\n | 'post_only'\n | 'limit_only'\n | 'reduce_only';\n\nexport type KrakenFeeScheduleEntry = [volume: number, percentFee: number];\n\nexport interface KrakenAssetPair {\n /** Alternate pair name (e.g. \"XBTUSD\") */\n altname: string;\n\n /** WebSocket pair name (if available) */\n wsname?: string;\n\n /** Asset class of base component */\n aclass_base: string;\n\n /** Asset ID of base component */\n base: string;\n\n /** Asset class of quote component */\n aclass_quote: string;\n\n /** Asset ID of quote component */\n quote: string;\n\n /** Volume lot size (deprecated) */\n lot: string;\n\n /** Number of decimal places for prices in this pair */\n pair_decimals: number;\n\n /** Number of decimal places for cost of trades in pair (quote asset terms) */\n cost_decimals: number;\n\n /** Number of decimal places for volume (base asset terms) */\n lot_decimals: number;\n\n /** Amount to multiply lot volume by to get currency volume */\n lot_multiplier: number;\n\n /** Array of leverage amounts available when buying */\n leverage_buy: number[];\n\n /** Array of leverage amounts available when selling */\n leverage_sell: number[];\n\n /** Fee schedule array in [<volume>, <percent fee>] tuples */\n fees: KrakenFeeScheduleEntry[];\n\n /** Maker fee schedule array (if on maker/taker) */\n fees_maker?: KrakenFeeScheduleEntry[];\n\n /** Volume discount currency */\n fee_volume_currency: string;\n\n /** Margin call level */\n margin_call: number;\n\n /** Stop-out/liquidation margin level */\n margin_stop: number;\n\n /** Minimum order size (base currency) */\n ordermin?: string;\n\n /** Minimum order cost (quote currency) */\n costmin?: string;\n\n /** Minimum increment between valid price levels */\n tick_size?: string;\n\n /** Status of asset pair */\n status?: KrakenAssetPairStatus;\n\n /** Maximum long margin position size (base currency) */\n long_position_limit?: number;\n\n /** Maximum short margin position size (base currency) */\n short_position_limit?: number;\n}\n\n/** Map of pair name -> asset pair info */\nexport type KrakenAssetPairMap = Record<string, KrakenAssetPair>;\n\nexport type KrakenAssetPairInfoType = 'info' | 'leverage' | 'fees' | 'margin';\n\nexport interface KrakenGetTradableAssetPairsParams {\n /**\n * Asset pairs to get data for (e.g. [\"BTC/USD\", \"ETH/BTC\"]).\n * If omitted, Kraken returns all pairs.\n */\n pair?: string[];\n\n /**\n * Filters the base asset class (default \"currency\").\n * - \"currency\" = spot currency pairs\n * - \"tokenized_asset\" = tokenized asset pairs (xstocks)\n */\n aclass_base?: KrakenAssetClass;\n\n /**\n * Info to retrieve (default \"info\").\n * - \"info\" = all info\n * - \"leverage\" = leverage info\n * - \"fees\" = fee schedule\n * - \"margin\" = margin info\n */\n info?: KrakenAssetPairInfoType;\n\n /**\n * Filter to only include pairs available in the provided country/region.\n * ISO 3166-1 alpha-2 code (e.g. \"CA\", \"GB\").\n */\n country_code?: string;\n}\n\n/**\n * GET /0/public/AssetPairs\n * Get tradable asset pairs.\n */\nexport function getTradableAssetPairs(\n base: KrakenRestBase,\n params?: KrakenGetTradableAssetPairsParams,\n): Promise<KrakenAssetPairMap> {\n const query: Record<string, string> = {};\n\n if (params?.pair?.length) {\n query.pair = params.pair.join(',');\n }\n\n if (params?.aclass_base) {\n query.aclass_base = params.aclass_base;\n }\n\n if (params?.info) {\n query.info = params.info;\n }\n\n if (params?.country_code) {\n query.country_code = params.country_code;\n }\n\n return base.publicGet<KrakenAssetPairMap>('/0/public/AssetPairs', query);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Asset class for ticker requests.\n * - \"forex\" = standard spot / FX pairs\n * - \"tokenized_asset\" = tokenized assets (xstocks)\n */\nexport type KrakenTickerAssetClass = 'tokenized_asset' | 'forex';\n\n/**\n * Asset Ticker Info\n *\n * Keys match Kraken's schema:\n * - a: Ask [<price>, <whole lot volume>, <lot volume>]\n * - b: Bid [<price>, <whole lot volume>, <lot volume>]\n * - c: Last trade closed [<price>, <lot volume>]\n * - v: Volume [<today>, <last 24 hours>]\n * - p: VWAP [<today>, <last 24 hours>]\n * - t: Number of trades [<today>, <last 24 hours>]\n * - l: Low [<today>, <last 24 hours>]\n * - h: High [<today>, <last 24 hours>]\n * - o: Today's opening price\n */\nexport interface KrakenAssetTickerInfo {\n a: [string, string, string];\n b: [string, string, string];\n c: [string, string];\n v: [string, string];\n p: [string, string];\n t: [number, number];\n l: [string, string];\n h: [string, string];\n o: string;\n}\n\n/**\n * Map of pair name -> ticker info\n * e.g. { \"XBTUSD\": { ... }, \"ETHUSD\": { ... } }\n */\nexport type KrakenTickerInfoMap = Record<string, KrakenAssetTickerInfo>;\n\nexport interface KrakenGetTickerInformationParams {\n /**\n * Asset pairs to get data for.\n *\n * Kraken docs say \"Asset pair\" (singular), but API supports\n * a comma-delimited list, so we accept string[] and join.\n * If omitted, all tradeable exchange pairs are returned.\n */\n pair?: string[];\n\n /**\n * Asset class for tokenized pairs / forex.\n *\n * Required when requesting tokenized pairs (xstocks).\n * If provided without `pair`, all pairs for that class are returned.\n */\n asset_class?: KrakenTickerAssetClass;\n}\n\n/**\n * GET /0/public/Ticker\n * Get ticker information for all or requested markets.\n */\nexport function getTickerInformation(\n base: KrakenRestBase,\n params?: KrakenGetTickerInformationParams,\n): Promise<KrakenTickerInfoMap> {\n const query: Record<string, string> = {};\n\n if (params?.pair?.length) {\n query.pair = params.pair.join(',');\n }\n\n if (params?.asset_class) {\n query.asset_class = params.asset_class;\n }\n\n return base.publicGet<KrakenTickerInfoMap>('/0/public/Ticker', query);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenOhlcInterval =\n | 1\n | 5\n | 15\n | 30\n | 60\n | 240\n | 1440\n | 10080\n | 21600;\n\nexport type KrakenOhlcEntry = [\n time: number,\n open: string,\n high: string,\n low: string,\n close: string,\n vwap: string,\n volume: string,\n count: number,\n];\n\nexport type KrakenOhlcMap = Record<string, KrakenOhlcEntry[]>;\n\nexport interface KrakenOhlcResponse {\n last: number;\n ohlc: KrakenOhlcMap;\n}\n\nexport interface KrakenGetOhlcDataParams {\n pair: string;\n interval?: KrakenOhlcInterval;\n since?: number;\n asset_class?: 'tokenized_asset';\n}\n\n/**\n * Raw shape from Kraken:\n *\n * {\n * last: 1688671200,\n * \"XBTUSD\": [ [time, open, high, low, close, vwap, volume, count], ... ],\n * \"ETHUSD\": [ ... ],\n * ...\n * }\n */\ninterface KrakenOhlcRawResult {\n last: number;\n [pair: string]: KrakenOhlcEntry[] | number;\n}\n\nexport async function getOhlcData(\n base: KrakenRestBase,\n params: KrakenGetOhlcDataParams,\n): Promise<KrakenOhlcResponse> {\n const query: Record<string, string> = {\n pair: params.pair,\n };\n\n if (params.interval !== undefined) {\n query.interval = String(params.interval);\n }\n\n if (params.since !== undefined) {\n query.since = String(params.since);\n }\n\n if (params.asset_class) {\n query.asset_class = params.asset_class;\n }\n\n const raw = await base.publicGet<KrakenOhlcRawResult>(\n '/0/public/OHLC',\n query,\n );\n\n const { last, ...rest } = raw;\n\n const ohlc: KrakenOhlcMap = {};\n for (const [pair, data] of Object.entries(rest)) {\n ohlc[pair] = data as KrakenOhlcEntry[];\n }\n\n return {\n last,\n ohlc,\n };\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * One level in the L2 order book:\n * [<price>, <volume>, <timestamp>]\n */\nexport type KrakenOrderBookLevel = [\n price: string,\n volume: string,\n timestamp: number,\n];\n\nexport interface KrakenOrderBook {\n asks: KrakenOrderBookLevel[];\n bids: KrakenOrderBookLevel[];\n}\n\n/** Map of pair name -> order book */\nexport type KrakenOrderBookMap = Record<string, KrakenOrderBook>;\n\nexport interface KrakenGetOrderBookParams {\n /**\n * Asset pair to get data for (required).\n * e.g. \"XBTUSD\"\n */\n pair: string;\n\n /**\n * Maximum number of asks/bids.\n * 1–500, default 100.\n */\n count?: number;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * Docs: asset_class=\"tokenized_asset\"\n */\n asset_class?: 'tokenized_asset';\n}\n\n/**\n * GET /0/public/Depth\n * Returns level 2 (L2) order book, with aggregated order quantities\n * at each price level.\n */\nexport function getOrderBook(\n base: KrakenRestBase,\n params: KrakenGetOrderBookParams,\n): Promise<KrakenOrderBookMap> {\n const query: Record<string, string> = {\n pair: params.pair,\n };\n\n if (params.count !== undefined) {\n query.count = String(params.count);\n }\n\n if (params.asset_class) {\n query.asset_class = params.asset_class;\n }\n\n return base.publicGet<KrakenOrderBookMap>('/0/public/Depth', query);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Single trade entry:\n * [<price>, <volume>, <time>, <buy/sell>, <market/limit>, <miscellaneous>, <trade_id>]\n *\n * - price -> string\n * - volume -> string\n * - time -> number (Unix timestamp)\n * - side -> string (\"buy\"/\"sell\" or shorthand)\n * - orderType -> string (\"market\"/\"limit\" or shorthand)\n * - misc -> string (flags)\n * - tradeId -> string\n */\nexport type KrakenTradeEntry = [\n price: string,\n volume: string,\n time: number,\n side: string,\n orderType: string,\n miscellaneous: string,\n tradeId: string,\n];\n\nexport type KrakenTradesMap = Record<string, KrakenTradeEntry[]>;\n\n/**\n * Normalized trades response:\n *\n * - `last` is the ID to be used as `since` when polling.\n * - `trades` is a map of pair -> trade entries.\n */\nexport interface KrakenRecentTradesResponse {\n last: string;\n trades: KrakenTradesMap;\n}\n\nexport interface KrakenGetRecentTradesParams {\n /**\n * Asset pair to get data for (required).\n * e.g. \"XBTUSD\"\n */\n pair: string;\n\n /**\n * Return trade data since given timestamp/id.\n * Kraken expects a string; we accept number or string.\n */\n since?: string | number;\n\n /**\n * Maximum number of trades to return (1–1000, default 1000).\n */\n count?: number;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * Docs: asset_class=\"tokenized_asset\"\n */\n asset_class?: 'tokenized_asset';\n}\n\n/**\n * Raw shape from Kraken:\n *\n * {\n * \"last\": \"1616663618\",\n * \"XBTUSD\": [\n * [price, volume, time, side, orderType, misc, tradeId],\n * ...\n * ]\n * }\n */\ninterface KrakenTradesRawResult {\n last: string;\n [pair: string]: KrakenTradeEntry[] | string;\n}\n\n/**\n * GET /0/public/Trades\n * Returns the last 1000 trades by default.\n */\nexport async function getRecentTrades(\n base: KrakenRestBase,\n params: KrakenGetRecentTradesParams,\n): Promise<KrakenRecentTradesResponse> {\n const query: Record<string, string> = {\n pair: params.pair,\n };\n\n if (params.since !== undefined) {\n query.since = String(params.since);\n }\n\n if (params.count !== undefined) {\n query.count = String(params.count);\n }\n\n if (params.asset_class) {\n query.asset_class = params.asset_class;\n }\n\n const raw = await base.publicGet<KrakenTradesRawResult>(\n '/0/public/Trades',\n query,\n );\n\n const { last, ...rest } = raw;\n\n const trades: KrakenTradesMap = {};\n for (const [pair, data] of Object.entries(rest)) {\n trades[pair] = data as KrakenTradeEntry[];\n }\n\n return {\n last,\n trades,\n };\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Single spread entry:\n * [int <time>, string <bid>, string <ask>]\n */\nexport type KrakenSpreadEntry = [time: number, bid: string, ask: string];\n\nexport type KrakenSpreadsMap = Record<string, KrakenSpreadEntry[]>;\n\n/**\n * Normalized spreads response:\n *\n * - `last` is the ID to be used as `since` when polling.\n * - `spreads` is a map of pair -> spread entries.\n */\nexport interface KrakenRecentSpreadsResponse {\n last: number;\n spreads: KrakenSpreadsMap;\n}\n\nexport interface KrakenGetRecentSpreadsParams {\n /**\n * Asset pair to get data for (required).\n * e.g. \"XBTUSD\"\n */\n pair: string;\n\n /**\n * Returns spread data since given timestamp.\n * Intended for incremental updates within available dataset.\n */\n since?: number;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * Docs: asset_class=\"tokenized_asset\"\n */\n asset_class?: 'tokenized_asset';\n}\n\n/**\n * Raw shape from Kraken:\n *\n * {\n * \"last\": 1678219570,\n * \"XBTUSD\": [\n * [time, bid, ask],\n * ...\n * ]\n * }\n */\ninterface KrakenSpreadsRawResult {\n last: number;\n [pair: string]: KrakenSpreadEntry[] | number;\n}\n\n/**\n * GET /0/public/Spread\n * Returns the last ~200 top-of-book spreads for a given pair.\n */\nexport async function getRecentSpreads(\n base: KrakenRestBase,\n params: KrakenGetRecentSpreadsParams,\n): Promise<KrakenRecentSpreadsResponse> {\n const query: Record<string, string> = {\n pair: params.pair,\n };\n\n if (params.since !== undefined) {\n query.since = String(params.since);\n }\n\n if (params.asset_class) {\n query.asset_class = params.asset_class;\n }\n\n const raw = await base.publicGet<KrakenSpreadsRawResult>(\n '/0/public/Spread',\n query,\n );\n\n const { last, ...rest } = raw;\n\n const spreads: KrakenSpreadsMap = {};\n for (const [pair, data] of Object.entries(rest)) {\n spreads[pair] = data as KrakenSpreadEntry[];\n }\n\n return {\n last,\n spreads,\n };\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as GetServerTime from './getServerTime';\nimport * as GetSystemStatus from './getSystemStatus';\nimport * as GetAssetInfo from './getAssetInfo';\nimport * as GetTradableAssetPairs from './getTradableAssetPairs';\nimport * as GetTickerInformation from './getTickerInformation';\nimport * as GetOhlcData from './getOhlcData';\nimport * as GetOrderBook from './getOrderBook';\nimport * as GetRecentTrades from './getRecentTrades';\nimport * as GetRecentSpreads from './getRecentSpreads';\n\nexport class KrakenSpotMarketDataApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Get the server's time.\n *\n * @example\n * const time = await kraken.marketData.getServerTime();\n * console.log(time.rfc1123);\n */\n getServerTime() {\n return GetServerTime.getServerTime(this.base);\n }\n\n /**\n * Get the current system status or trading mode.\n *\n * @example\n * const status = await kraken.marketData.getSystemStatus();\n * console.log(status.status, status.timestamp);\n */\n getSystemStatus() {\n return GetSystemStatus.getSystemStatus(this.base);\n }\n\n /**\n * Get information about assets available for deposit, withdrawal,\n * trading and earn.\n *\n * @example\n * // All spot currencies\n * const allAssets = await kraken.marketData.getAssetInfo();\n *\n * // Specific assets\n * const btcAndEth = await kraken.marketData.getAssetInfo({\n * asset: [\"XXBT\", \"XETH\"],\n * });\n */\n getAssetInfo(params?: GetAssetInfo.KrakenGetAssetInfoParams) {\n return GetAssetInfo.getAssetInfo(this.base, params);\n }\n\n /**\n * Get tradable asset pairs and their configuration.\n *\n * @example\n * // All pairs available in Canada\n * const pairs = await kraken.marketData.getTradableAssetPairs({\n * country_code: \"CA\",\n * });\n *\n * // Specific pairs\n * const subset = await kraken.marketData.getTradableAssetPairs({\n * pair: [\"XBTUSD\", \"ETHUSD\"],\n * });\n */\n getTradableAssetPairs(\n params?: GetTradableAssetPairs.KrakenGetTradableAssetPairsParams,\n ) {\n return GetTradableAssetPairs.getTradableAssetPairs(this.base, params);\n }\n\n /**\n * Get ticker information for one or more markets.\n *\n * Leaving `pair` undefined returns tickers for all tradeable pairs.\n *\n * @example\n * // Single pair\n * const tickers = await kraken.marketData.getTickerInformation({\n * pair: [\"XBTUSD\"],\n * });\n * const xbtusd = tickers[\"XBTUSD\"];\n * console.log(xbtusd.c[0]); // last traded price\n */\n getTickerInformation(\n params?: GetTickerInformation.KrakenGetTickerInformationParams,\n ) {\n return GetTickerInformation.getTickerInformation(this.base, params);\n }\n\n /**\n * Retrieve OHLC candles for a pair.\n *\n * The last entry for each pair is the current, not-yet-committed candle.\n *\n * @example\n * const { last, ohlc } = await kraken.marketData.getOhlcData({\n * pair: \"XBTUSD\",\n * interval: 1,\n * });\n *\n * const candles = ohlc[\"XBTUSD\"] ?? [];\n * console.log(\"Next since:\", last);\n */\n getOhlcData(params: GetOhlcData.KrakenGetOhlcDataParams) {\n return GetOhlcData.getOhlcData(this.base, params);\n }\n\n /**\n * Get level 2 (L2) order book for a pair.\n *\n * @example\n * const books = await kraken.marketData.getOrderBook({\n * pair: \"XBTUSD\",\n * count: 50,\n * });\n *\n * const book = books[\"XBTUSD\"];\n * const bestAsk = book?.asks[0];\n * const bestBid = book?.bids[0];\n */\n getOrderBook(params: GetOrderBook.KrakenGetOrderBookParams) {\n return GetOrderBook.getOrderBook(this.base, params);\n }\n\n /**\n * Get recent trades for a pair (up to 1000).\n *\n * Use the returned `last` value as `since` for incremental polling.\n *\n * @example\n * const first = await kraken.marketData.getRecentTrades({\n * pair: \"XBTUSD\",\n * count: 500,\n * });\n *\n * const trades = first.trades[\"XBTUSD\"] ?? [];\n * const nextSince = first.last;\n */\n getRecentTrades(params: GetRecentTrades.KrakenGetRecentTradesParams) {\n return GetRecentTrades.getRecentTrades(this.base, params);\n }\n\n /**\n * Get recent top-of-book spreads for a pair.\n *\n * Use the returned `last` value as `since` for incremental polling.\n *\n * @example\n * const first = await kraken.marketData.getRecentSpreads({\n * pair: \"XBTUSD\",\n * });\n *\n * const spreads = first.spreads[\"XBTUSD\"] ?? [];\n * const nextSince = first.last;\n */\n getRecentSpreads(params: GetRecentSpreads.KrakenGetRecentSpreadsParams) {\n return GetRecentSpreads.getRecentSpreads(this.base, params);\n }\n}\n\n// Re-export endpoint types\nexport type KrakenServerTime = GetServerTime.KrakenServerTime;\n\nexport type KrakenSystemStatus = GetSystemStatus.KrakenSystemStatus;\nexport type KrakenSystemStatusResult = GetSystemStatus.KrakenSystemStatusResult;\n\nexport type KrakenAssetClass = GetAssetInfo.KrakenAssetClass;\nexport type KrakenAssetStatus = GetAssetInfo.KrakenAssetStatus;\nexport type KrakenAssetInfo = GetAssetInfo.KrakenAssetInfo;\nexport type KrakenAssetInfoMap = GetAssetInfo.KrakenAssetInfoMap;\nexport type KrakenGetAssetInfoParams = GetAssetInfo.KrakenGetAssetInfoParams;\n\nexport type KrakenAssetPairStatus = GetTradableAssetPairs.KrakenAssetPairStatus;\nexport type KrakenFeeScheduleEntry =\n GetTradableAssetPairs.KrakenFeeScheduleEntry;\nexport type KrakenAssetPair = GetTradableAssetPairs.KrakenAssetPair;\nexport type KrakenAssetPairMap = GetTradableAssetPairs.KrakenAssetPairMap;\nexport type KrakenAssetPairInfoType =\n GetTradableAssetPairs.KrakenAssetPairInfoType;\nexport type KrakenGetTradableAssetPairsParams =\n GetTradableAssetPairs.KrakenGetTradableAssetPairsParams;\n\nexport type KrakenTickerAssetClass =\n GetTickerInformation.KrakenTickerAssetClass;\nexport type KrakenAssetTickerInfo = GetTickerInformation.KrakenAssetTickerInfo;\nexport type KrakenTickerInfoMap = GetTickerInformation.KrakenTickerInfoMap;\nexport type KrakenGetTickerInformationParams =\n GetTickerInformation.KrakenGetTickerInformationParams;\n\nexport type KrakenOhlcInterval = GetOhlcData.KrakenOhlcInterval;\nexport type KrakenOhlcEntry = GetOhlcData.KrakenOhlcEntry;\nexport type KrakenOhlcMap = GetOhlcData.KrakenOhlcMap;\nexport type KrakenOhlcResponse = GetOhlcData.KrakenOhlcResponse;\nexport type KrakenGetOhlcDataParams = GetOhlcData.KrakenGetOhlcDataParams;\n\nexport type KrakenOrderBookLevel = GetOrderBook.KrakenOrderBookLevel;\nexport type KrakenOrderBook = GetOrderBook.KrakenOrderBook;\nexport type KrakenOrderBookMap = GetOrderBook.KrakenOrderBookMap;\nexport type KrakenGetOrderBookParams = GetOrderBook.KrakenGetOrderBookParams;\n\nexport type KrakenTradeEntry = GetRecentTrades.KrakenTradeEntry;\nexport type KrakenTradesMap = GetRecentTrades.KrakenTradesMap;\nexport type KrakenRecentTradesResponse =\n GetRecentTrades.KrakenRecentTradesResponse;\nexport type KrakenGetRecentTradesParams =\n GetRecentTrades.KrakenGetRecentTradesParams;\n\nexport type KrakenSpreadEntry = GetRecentSpreads.KrakenSpreadEntry;\nexport type KrakenSpreadsMap = GetRecentSpreads.KrakenSpreadsMap;\nexport type KrakenRecentSpreadsResponse =\n GetRecentSpreads.KrakenRecentSpreadsResponse;\nexport type KrakenGetRecentSpreadsParams =\n GetRecentSpreads.KrakenGetRecentSpreadsParams;\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Rebase multiplier options for xstocks / tokenized assets.\n *\n * - \"rebased\": Display in terms of underlying equity (default).\n * - \"base\": Display in terms of SPV tokens.\n */\nexport type KrakenRebaseMultiplier = 'rebased' | 'base';\n\n/**\n * Account balance result:\n * Map of asset symbol -> balance as string.\n *\n * Example:\n * {\n * \"ZUSD\": \"123.45\",\n * \"XXBT\": \"0.0100000000\",\n * \"USDT.F\": \"50.0\"\n * }\n */\nexport type KrakenAccountBalanceMap = Record<string, string>;\n\nexport interface KrakenGetAccountBalanceParams {\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/Balance\n *\n * Retrieve all cash balances, net of pending withdrawals.\n *\n * Note: `nonce` is handled automatically by the client.\n * API key must have \"Funds – Query\" permission enabled.\n */\nexport function getAccountBalance(\n base: KrakenRestBase,\n params?: KrakenGetAccountBalanceParams,\n): Promise<KrakenAccountBalanceMap> {\n const body: Record<string, string> = {};\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenAccountBalanceMap>('/0/private/Balance', body);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\n/**\n * Extended balance fields for a single asset.\n *\n * - balance : total balance\n * - credit : total credit amount (if credit line)\n * - credit_used : used credit amount\n * - hold_trade : total held amount (e.g. open orders)\n */\nexport interface KrakenExtendedBalanceEntry {\n /** Total balance amount for an asset */\n balance: string;\n\n /** Total credit amount (only applicable if account has a credit line) */\n credit: string;\n\n /** Used credit amount (only applicable if account has a credit line) */\n credit_used: string;\n\n /** Total held amount for an asset */\n hold_trade: string;\n}\n\n/** Map of asset symbol -> extended balance info */\nexport type KrakenExtendedBalanceMap = Record<\n string,\n KrakenExtendedBalanceEntry\n>;\n\nexport interface KrakenGetExtendedBalanceParams {\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/BalanceEx\n *\n * Retrieve all extended account balances, including credits and held amounts.\n *\n * Balance available for trading is:\n * available = balance + credit - credit_used - hold_trade\n *\n * Note: `nonce` is handled automatically by the client.\n * API key must have \"Funds – Query\" permission enabled.\n */\nexport function getExtendedBalance(\n base: KrakenRestBase,\n params?: KrakenGetExtendedBalanceParams,\n): Promise<KrakenExtendedBalanceMap> {\n const body: Record<string, string> = {};\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenExtendedBalanceMap>(\n '/0/private/BalanceEx',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\n/**\n * Credit line details for a specific asset.\n */\nexport interface KrakenCreditLinesAssetEntry {\n /** Current balance for the asset */\n balance: string;\n\n /** Credit limit for the asset */\n credit_limit: string;\n\n /** Currently used credit for the asset */\n credit_used: string;\n\n /** Available credit for the asset */\n available_credit: string;\n}\n\n/** Map of asset symbol -> credit line details */\nexport type KrakenCreditLinesAssetMap = Record<\n string,\n KrakenCreditLinesAssetEntry\n>;\n\n/**\n * Aggregate credit monitor metrics.\n * All values are strings (or null) representing USD amounts/ratios.\n */\nexport interface KrakenCreditLinesLimitsMonitor {\n /** Total credit across all assets represented in USD */\n total_credit_usd?: string | null;\n\n /** Total credit used across all assets represented in USD */\n total_credit_used_usd?: string | null;\n\n /** Sum of asset balance in USD * collateral */\n total_collateral_value_usd?: string | null;\n\n /** Total collateral - total credit (in USD) */\n equity_usd?: string | null;\n\n /** Total collateral / total credit (in USD) */\n ongoing_balance?: string | null;\n\n /** Total credit used / equity (in USD) */\n debt_to_equity?: string | null;\n}\n\n/**\n * Full credit line details result.\n */\nexport interface KrakenCreditLinesResult {\n /** Balances by asset */\n asset_details: KrakenCreditLinesAssetMap;\n\n /** Aggregate credit monitor info */\n limits_monitor: KrakenCreditLinesLimitsMonitor;\n}\n\n/**\n * The API can return `null` if there are no credit lines configured.\n */\nexport type KrakenCreditLinesResponse = KrakenCreditLinesResult | null;\n\nexport interface KrakenGetCreditLinesParams {\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/CreditLines\n *\n * Retrieve all credit line details for VIPs with this functionality.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - API key must have \"Funds – Query\" permission enabled.\n * - `result` may be `null` if no credit lines exist.\n */\nexport function getCreditLines(\n base: KrakenRestBase,\n params?: KrakenGetCreditLinesParams,\n): Promise<KrakenCreditLinesResponse> {\n const body: Record<string, string> = {};\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenCreditLinesResponse>(\n '/0/private/CreditLines',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\n/**\n * Trade balance summary.\n *\n * Field meanings (all strings):\n * - eb : Equivalent balance (combined balance of all currencies)\n * - tb : Trade balance (combined balance of all equity currencies)\n * - m : Margin amount of open positions\n * - n : Unrealized net profit/loss of open positions\n * - c : Cost basis of open positions\n * - v : Current floating valuation of open positions\n * - e : Equity = trade balance + unrealized PnL\n * - mf : Free margin = equity - initial margin\n * - ml : Margin level = (equity / initial margin) * 100\n * - uv : Unexecuted value of unfilled/partially filled orders\n */\nexport interface KrakenTradeBalanceResult {\n /** Equivalent balance (combined balance of all currencies) */\n eb: string;\n\n /** Trade balance (combined balance of all equity currencies) */\n tb: string;\n\n /** Margin amount of open positions */\n m: string;\n\n /** Unrealized net profit/loss of open positions */\n n: string;\n\n /** Cost basis of open positions */\n c: string;\n\n /** Current floating valuation of open positions */\n v: string;\n\n /** Equity: trade balance + unrealized net profit/loss */\n e: string;\n\n /**\n * Free margin: Equity - initial margin\n * (maximum margin available to open new positions)\n */\n mf: string;\n\n /** Margin level: (equity / initial margin) * 100 */\n ml: string;\n\n /** Unexecuted value: value of unfilled and partially filled orders */\n uv: string;\n}\n\nexport interface KrakenGetTradeBalanceParams {\n /**\n * Base asset used to determine balance.\n * Default on Kraken is \"ZUSD\" if omitted.\n */\n asset?: string;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/TradeBalance\n *\n * Retrieve a summary of collateral balances, margin position valuations,\n * equity and margin level.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - API key must have \"Orders and trades – Query open orders & trades\".\n */\nexport function getTradeBalance(\n base: KrakenRestBase,\n params?: KrakenGetTradeBalanceParams,\n): Promise<KrakenTradeBalanceResult> {\n const body: Record<string, string> = {};\n\n if (params?.asset) {\n body.asset = params.asset;\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenTradeBalanceResult>(\n '/0/private/TradeBalance',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\nexport type KrakenOrderStatus =\n | 'pending'\n | 'open'\n | 'closed'\n | 'canceled'\n | 'expired';\n\nexport type KrakenOrderSide = 'buy' | 'sell';\n\nexport type KrakenOrderType =\n | 'market'\n | 'limit'\n | 'iceberg'\n | 'stop-loss'\n | 'take-profit'\n | 'stop-loss-limit'\n | 'take-profit-limit'\n | 'trailing-stop'\n | 'trailing-stop-limit'\n | 'settle-position';\n\nexport type KrakenOrderTrigger = 'last' | 'index';\n\nexport interface KrakenOpenOrderDescription {\n /** Asset pair (e.g. \"XBTUSD\") */\n pair: string;\n\n /** Type of order: \"buy\" or \"sell\" */\n type: KrakenOrderSide;\n\n /** Execution model of the order (market, limit, stop-loss, etc.) */\n ordertype: KrakenOrderType;\n\n /** Primary price */\n price: string;\n\n /** Secondary price (if applicable) */\n price2: string;\n\n /** Amount of leverage */\n leverage: string;\n\n /** Order description text */\n order: string;\n\n /** Conditional close order description (if any) */\n close?: string;\n}\n\n/**\n * Open order as returned by Kraken.\n *\n * Note:\n * - Some fields are optional or nullable depending on order type.\n * - `margin` is documented as boolean; we keep it boolean | string for safety.\n */\nexport interface KrakenOpenOrder {\n /** Referral order transaction ID that created this order (nullable) */\n refid?: string | null;\n\n /** Optional numeric client identifier */\n userref?: number | null;\n\n /** Optional alphanumeric client order ID */\n cl_ord_id?: string | null;\n\n /** Status of order */\n status: KrakenOrderStatus;\n\n /** Unix timestamp when order was placed */\n opentm: number;\n\n /** Unix timestamp of order start time (or 0 if not set) */\n starttm: number;\n\n /** Unix timestamp of order end time (or 0 if not set) */\n expiretm: number;\n\n /** Order description info */\n descr: KrakenOpenOrderDescription;\n\n /** Volume of order (base currency) */\n vol: string;\n\n /** Volume executed (base currency) */\n vol_exec: string;\n\n /** Total cost (quote currency) */\n cost: string;\n\n /** Total fee (quote currency) */\n fee: string;\n\n /** Average price (quote currency) */\n price: string;\n\n /** Stop price (quote currency) */\n stopprice?: string;\n\n /**\n * Triggered limit price (quote currency, when limit-based order\n * type is triggered)\n */\n limitprice?: string;\n\n /**\n * Price signal used to trigger stop/take-profit orders.\n * If not set, \"last\" is implied.\n */\n trigger?: KrakenOrderTrigger;\n\n /**\n * Indicates if the order is funded on margin.\n * (Docs show boolean; keeping union in case of API quirks.)\n */\n margin?: boolean | string;\n\n /** Comma-delimited list of miscellaneous info */\n misc: string;\n\n /**\n * Comma-delimited list of order flags (post, fcib, fciq, viqc, etc.)\n */\n oflags?: string;\n\n /**\n * List of trade IDs related to the order (if `trades=true`\n * and data is available)\n */\n trades?: string[];\n\n /**\n * For institutional accounts, identifies underlying sub-account/trader\n * for STP.\n */\n sender_sub_id?: string | null;\n}\n\n/** Map of order ID -> open order */\nexport type KrakenOpenOrdersMap = Record<string, KrakenOpenOrder>;\n\nexport interface KrakenOpenOrdersResult {\n open: KrakenOpenOrdersMap;\n}\n\nexport interface KrakenGetOpenOrdersParams {\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Restrict results to given user reference.\n */\n userref?: number;\n\n /**\n * Restrict results to given client order id.\n */\n cl_ord_id?: string;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/OpenOrders\n *\n * Retrieve information about currently open orders.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - API key must have \"Orders and trades – Query open orders & trades\".\n */\nexport function getOpenOrders(\n base: KrakenRestBase,\n params?: KrakenGetOpenOrdersParams,\n): Promise<KrakenOpenOrdersResult> {\n const body: Record<string, string> = {};\n\n if (params?.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params?.userref !== undefined) {\n body.userref = String(params.userref);\n }\n\n if (params?.cl_ord_id) {\n body.cl_ord_id = params.cl_ord_id;\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenOpenOrdersResult>(\n '/0/private/OpenOrders',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type {\n KrakenOrderStatus,\n KrakenOrderTrigger,\n KrakenOpenOrderDescription,\n} from './getOpenOrders';\n\n/**\n * Closed order as returned by Kraken.\n *\n * This extends the open-order shape with:\n * - closetm: Unix timestamp when order was closed\n * - reason : Additional info on status (if any)\n */\nexport interface KrakenClosedOrder {\n /** Referral order transaction ID that created this order (nullable) */\n refid?: string | null;\n\n /** Optional numeric client identifier */\n userref?: number | null;\n\n /** Optional alphanumeric client order ID */\n cl_ord_id?: string | null;\n\n /** Status of order (pending, open, closed, canceled, expired) */\n status: KrakenOrderStatus;\n\n /** Unix timestamp when order was placed */\n opentm: number;\n\n /** Unix timestamp of order start time (or 0 if not set) */\n starttm: number;\n\n /** Unix timestamp of order end time (or 0 if not set) */\n expiretm: number;\n\n /** Order description info */\n descr: KrakenOpenOrderDescription;\n\n /** Volume of order (base currency) */\n vol: string;\n\n /** Volume executed (base currency) */\n vol_exec: string;\n\n /** Total cost (quote currency) */\n cost: string;\n\n /** Total fee (quote currency) */\n fee: string;\n\n /** Average price (quote currency) */\n price: string;\n\n /** Stop price (quote currency) */\n stopprice?: string;\n\n /**\n * Triggered limit price (quote currency, when limit-based order\n * type triggered)\n */\n limitprice?: string;\n\n /**\n * Price signal used to trigger stop/take-profit orders.\n * If not set, \"last\" is implied.\n */\n trigger?: KrakenOrderTrigger;\n\n /**\n * Indicates if the order is funded on margin.\n * (Docs show boolean; keep union in case of API quirks.)\n */\n margin?: boolean | string;\n\n /** Comma-delimited list of miscellaneous info */\n misc: string;\n\n /**\n * Comma-delimited list of order flags:\n * - post, fcib, fciq, nompp, viqc, ...\n */\n oflags?: string;\n\n /**\n * List of trade IDs related to the order (if `trades=true`\n * and data is available)\n */\n trades?: string[];\n\n /**\n * For institutional accounts, identifies underlying sub-account/trader\n * for STP.\n */\n sender_sub_id?: string | null;\n\n /** Unix timestamp of when order was closed */\n closetm: number;\n\n /** Additional info on status (if any) */\n reason?: string;\n}\n\n/** Map of txid -> closed order */\nexport type KrakenClosedOrdersMap = Record<string, KrakenClosedOrder>;\n\nexport interface KrakenClosedOrdersResult {\n /** Closed orders keyed by transaction ID */\n closed: KrakenClosedOrdersMap;\n\n /**\n * Amount of available order info matching criteria.\n * Used with `ofs` for pagination.\n */\n count: number;\n}\n\nexport type KrakenClosedOrdersCloseTime = 'open' | 'close' | 'both';\n\nexport interface KrakenGetClosedOrdersParams {\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Restrict results to given user reference.\n */\n userref?: number;\n\n /**\n * Restrict results to given client order id.\n */\n cl_ord_id?: string;\n\n /**\n * Starting unix timestamp or order tx ID of results (exclusive).\n */\n start?: number | string;\n\n /**\n * Ending unix timestamp or order tx ID of results (inclusive).\n */\n end?: number | string;\n\n /**\n * Result offset for pagination.\n * 50 results are returned per page by default.\n */\n ofs?: number;\n\n /**\n * Which time to use to search:\n * - \"open\" : opentm\n * - \"close\" : closetm\n * - \"both\" : both\n *\n * Default on Kraken is \"both\".\n */\n closetime?: KrakenClosedOrdersCloseTime;\n\n /**\n * Whether or not to consolidate trades by individual taker trades.\n * Default on Kraken is true.\n */\n consolidate_taker?: boolean;\n\n /**\n * Whether or not to include page count in result.\n * `true` is faster for users with many closed orders.\n * (If true, `count` may be omitted by Kraken.)\n */\n without_count?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/ClosedOrders\n *\n * Retrieve information about orders that have been closed\n * (filled or cancelled). 50 results are returned at a time,\n * most recent by default.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - API key must have \"Orders and trades – Query closed orders & trades\".\n */\nexport function getClosedOrders(\n base: KrakenRestBase,\n params?: KrakenGetClosedOrdersParams,\n): Promise<KrakenClosedOrdersResult> {\n const body: Record<string, string> = {};\n\n if (params?.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params?.userref !== undefined) {\n body.userref = String(params.userref);\n }\n\n if (params?.cl_ord_id) {\n body.cl_ord_id = params.cl_ord_id;\n }\n\n if (params?.start !== undefined) {\n body.start = String(params.start);\n }\n\n if (params?.end !== undefined) {\n body.end = String(params.end);\n }\n\n if (params?.ofs !== undefined) {\n body.ofs = String(params.ofs);\n }\n\n if (params?.closetime) {\n body.closetime = params.closetime;\n }\n\n if (params?.consolidate_taker !== undefined) {\n body.consolidate_taker = params.consolidate_taker ? 'true' : 'false';\n }\n\n if (params?.without_count !== undefined) {\n body.without_count = params.without_count ? 'true' : 'false';\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenClosedOrdersResult>(\n '/0/private/ClosedOrders',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type {\n KrakenOrderStatus,\n KrakenOrderTrigger,\n KrakenOpenOrderDescription,\n} from './getOpenOrders';\n\n/**\n * Order as returned by QueryOrders.\n *\n * It’s basically the same shape as a closed order, but may represent\n * open or closed orders depending on txid/status, so `closetm`/`reason`\n * are optional.\n */\nexport interface KrakenQueriedOrder {\n /** Referral order transaction ID that created this order (nullable) */\n refid?: string | null;\n\n /** Optional numeric, client identifier associated with one or more orders */\n userref?: number | null;\n\n /** Optional alphanumeric, client identifier associated with the order */\n cl_ord_id?: string | null;\n\n /** Status of order (pending, open, closed, canceled, expired) */\n status: KrakenOrderStatus;\n\n /** Unix timestamp of when order was placed */\n opentm: number;\n\n /** Unix timestamp of order start time (or 0 if not set) */\n starttm: number;\n\n /** Unix timestamp of order end time (or 0 if not set) */\n expiretm: number;\n\n /** Order description info */\n descr: KrakenOpenOrderDescription;\n\n /** Volume of order (base currency) */\n vol: string;\n\n /** Volume executed (base currency) */\n vol_exec: string;\n\n /** Total cost (quote currency) */\n cost: string;\n\n /** Total fee (quote currency) */\n fee: string;\n\n /** Average price (quote currency) */\n price: string;\n\n /** Stop price (quote currency) */\n stopprice?: string;\n\n /**\n * Triggered limit price (quote currency, when limit-based\n * order type triggered)\n */\n limitprice?: string;\n\n /**\n * Price signal used to trigger stop/take-profit orders.\n * If not set, \"last\" is implied.\n */\n trigger?: KrakenOrderTrigger;\n\n /**\n * Indicates if the order is funded on margin.\n * (Docs show boolean; union kept for API quirks.)\n */\n margin?: boolean | string;\n\n /** Comma-delimited list of miscellaneous info */\n misc: string;\n\n /**\n * Comma-delimited list of order flags:\n * - post, fcib, fciq, nompp, viqc, ...\n */\n oflags?: string;\n\n /**\n * List of trade IDs related to order (if trades info requested\n * and data available)\n */\n trades?: string[];\n\n /**\n * For institutional accounts, identifies underlying sub-account/trader\n * for STP.\n */\n sender_sub_id?: string | null;\n\n /** Unix timestamp of when order was closed (for closed orders) */\n closetm?: number;\n\n /** Additional info on status (if any) */\n reason?: string;\n}\n\n/** Map of txid -> queried order */\nexport type KrakenQueriedOrdersMap = Record<string, KrakenQueriedOrder>;\n\nexport interface KrakenGetOrdersInfoParams {\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Restrict results to given user reference id.\n */\n userref?: number;\n\n /**\n * The Kraken order identifier(s).\n * Up to 50 ids. Will be sent as a comma-delimited list.\n */\n txid: string | string[];\n\n /**\n * Whether or not to consolidate trades by individual taker trades.\n * Default on Kraken is true.\n */\n consolidate_taker?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/QueryOrders\n *\n * Retrieve information about specific orders.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Query open orders & trades\" or \"Query closed orders & trades\"\n * depending on the status of the orders queried.\n */\nexport function queryOrdersInfo(\n base: KrakenRestBase,\n params: KrakenGetOrdersInfoParams,\n): Promise<KrakenQueriedOrdersMap> {\n const body: Record<string, string> = {};\n\n if (params.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params.userref !== undefined) {\n body.userref = String(params.userref);\n }\n\n // txid is required; support string or string[]\n if (Array.isArray(params.txid)) {\n body.txid = params.txid.join(',');\n } else {\n body.txid = params.txid;\n }\n\n if (params.consolidate_taker !== undefined) {\n body.consolidate_taker = params.consolidate_taker ? 'true' : 'false';\n }\n\n if (params.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenQueriedOrdersMap>(\n '/0/private/QueryOrders',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\nexport type KrakenOrderAmendType = 'original' | 'user' | 'restated';\n\n/**\n * Single amend entry in the audit trail.\n *\n * The first entry contains the original order parameters\n * and has amend_type of \"original\".\n */\nexport interface KrakenOrderAmendEntry {\n /** Kraken amend identifier */\n amend_id: string;\n\n /**\n * The type of amend transaction:\n * - \"original\": original order values on order entry\n * - \"user\": user requested amendment\n * - \"restated\": engine order maintenance amendment\n */\n amend_type: KrakenOrderAmendType;\n\n /** Order quantity in terms of the base asset */\n order_qty: string;\n\n /** Quantity shown in the book for iceberg orders */\n display_qty: string;\n\n /** Remaining un-traded quantity on the order */\n remaining_qty: string;\n\n /** Limit price restriction on the order */\n limit_price: string;\n\n /** Trigger price on trigger order types */\n trigger_price: string;\n\n /** Description of the reason for this amend */\n reason: string;\n\n /** Indicates if the transaction was restricted from taking liquidity */\n post_only: boolean;\n\n /** UNIX timestamp for the amend transaction */\n timestamp: number;\n}\n\n/**\n * Full amend history result for an order.\n */\nexport interface KrakenOrderAmendsResult {\n /**\n * Total count of new and amend transactions\n * (includes the original order entry).\n */\n count: number;\n\n /**\n * List of amend transactions ordered by ascending amend timestamp.\n */\n amends: KrakenOrderAmendEntry[];\n}\n\nexport interface KrakenGetOrderAmendsParams {\n /**\n * The Kraken order identifier for the amended order.\n */\n order_id: string;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/OrderAmends\n *\n * Retrieves an audit trail of amend transactions on the specified order.\n * The list is ordered by ascending amend timestamp.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires the appropriate \"Orders and trades\" query permission,\n * depending on the status of the order.\n */\nexport function getOrderAmends(\n base: KrakenRestBase,\n params: KrakenGetOrderAmendsParams,\n): Promise<KrakenOrderAmendsResult> {\n const body: Record<string, string> = {\n order_id: params.order_id,\n };\n\n if (params.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenOrderAmendsResult>(\n '/0/private/OrderAmends',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type { KrakenOrderSide, KrakenOrderType } from './getOpenOrders';\n\n/**\n * Trade type filter for TradesHistory.\n *\n * - \"all\" : all trades\n * - \"any position\" : any position\n * - \"closed position\" : closed positions\n * - \"closing position\" : closing trades\n * - \"no position\" : trades not opening/closing positions\n */\nexport type KrakenTradeHistoryTypeFilter =\n | 'all'\n | 'any position'\n | 'closed position'\n | 'closing position'\n | 'no position';\n\n/**\n * Trade info as returned by TradesHistory.\n */\nexport interface KrakenTradeHistoryEntry {\n /** Order responsible for execution of trade */\n ordertxid: string;\n\n /** Position responsible for execution of trade */\n postxid: string;\n\n /** Asset pair */\n pair: string;\n\n /** Unix timestamp of trade */\n time: number;\n\n /** Type of order (buy/sell) */\n type: KrakenOrderSide;\n\n /** Order type (market, limit, etc.) */\n ordertype: KrakenOrderType;\n\n /** Average price order was executed at (quote currency) */\n price: string;\n\n /** Total cost of order (quote currency) */\n cost: string;\n\n /** Total fee (quote currency) */\n fee: string;\n\n /** Volume (base currency) */\n vol: string;\n\n /** Initial margin (quote currency) */\n margin: string;\n\n /** Amount of leverage used in trade */\n leverage: string;\n\n /**\n * Comma-delimited list of miscellaneous info.\n * e.g. \"closing\" if trade closes all or part of a position.\n */\n misc: string;\n\n /**\n * List of ledger ids for entries associated with trade.\n * Only present if `ledgers=true`.\n */\n ledgers?: string[];\n\n /** Unique identifier of trade executed */\n trade_id: number;\n\n /** true if trade was executed with user as maker, false if taker */\n maker: boolean;\n\n /**\n * Position status (open/closed).\n * Only present if trade opened a position.\n */\n posstatus?: string;\n\n /**\n * Average price of closed portion of position (quote currency).\n * Only present if trade opened a position.\n */\n cprice?: number;\n\n /**\n * Total cost of closed portion of position (quote currency).\n * Only present if trade opened a position.\n */\n ccost?: number;\n\n /**\n * Total fee of closed portion of position (quote currency).\n * Only present if trade opened a position.\n */\n cfee?: number;\n\n /**\n * Total volume of closed portion of position (base currency).\n * (Docs text is a bit inconsistent, but this is the closed volume.)\n * Only present if trade opened a position.\n */\n cvol?: number;\n\n /**\n * Total margin freed in closed portion of position (quote currency).\n * Only present if trade opened a position.\n */\n cmargin?: number;\n\n /**\n * Net profit/loss of closed portion of position\n * (quote currency, quote currency scale).\n * Only present if trade opened a position.\n */\n net?: number;\n\n /**\n * List of closing trades for position (if available).\n * Only present if trade opened a position.\n */\n trades?: string[];\n}\n\n/** Map of trade ID (string key) -> trade entry */\nexport type KrakenTradeHistoryMap = Record<string, KrakenTradeHistoryEntry>;\n\nexport interface KrakenTradesHistoryResult {\n /**\n * Amount of available trades matching criteria.\n * Used with `ofs` for pagination.\n */\n count: number;\n\n /** Trades keyed by internal trade ID */\n trades: KrakenTradeHistoryMap;\n}\n\nexport interface KrakenGetTradesHistoryParams {\n /**\n * Type of trade filter.\n * Default on Kraken is \"all\".\n */\n type?: KrakenTradeHistoryTypeFilter;\n\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Starting unix timestamp or trade tx ID of results (exclusive).\n */\n start?: number | string;\n\n /**\n * Ending unix timestamp or trade tx ID of results (inclusive).\n */\n end?: number | string;\n\n /**\n * Result offset for pagination.\n * 50 results are returned per page by default.\n */\n ofs?: number;\n\n /**\n * Whether or not to consolidate trades by individual taker trades.\n * Default on Kraken is true.\n */\n consolidate_taker?: boolean;\n\n /**\n * Whether or not to include related ledger ids for given trade.\n * Note that setting this to true will slow request performance.\n * Default on Kraken is false.\n */\n ledgers?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/TradesHistory\n *\n * Retrieve information about trades/fills.\n * 50 results are returned at a time, most recent by default.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Orders and trades – Query closed orders & trades\".\n */\nexport function getTradesHistory(\n base: KrakenRestBase,\n params?: KrakenGetTradesHistoryParams,\n): Promise<KrakenTradesHistoryResult> {\n const body: Record<string, string> = {};\n\n if (params?.type) {\n body.type = params.type;\n }\n\n if (params?.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params?.start !== undefined) {\n body.start = String(params.start);\n }\n\n if (params?.end !== undefined) {\n body.end = String(params.end);\n }\n\n if (params?.ofs !== undefined) {\n body.ofs = String(params.ofs);\n }\n\n if (params?.consolidate_taker !== undefined) {\n body.consolidate_taker = params.consolidate_taker ? 'true' : 'false';\n }\n\n if (params?.ledgers !== undefined) {\n body.ledgers = params.ledgers ? 'true' : 'false';\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenTradesHistoryResult>(\n '/0/private/TradesHistory',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type { KrakenTradeHistoryEntry } from './getTradesHistory';\n\n/** Map of txid -> trade entry (same shape as TradesHistory) */\nexport type KrakenQueriedTradesMap = Record<string, KrakenTradeHistoryEntry>;\n\nexport interface KrakenGetTradesInfoParams {\n /**\n * Comma-delimited list of transaction IDs to query info about,\n * or an array of IDs (will be joined).\n * Maximum 20 IDs.\n */\n txid: string | string[];\n\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/QueryTrades\n *\n * Retrieve information about specific trades/fills.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Orders and trades – Query closed orders & trades\".\n */\nexport function queryTradesInfo(\n base: KrakenRestBase,\n params: KrakenGetTradesInfoParams,\n): Promise<KrakenQueriedTradesMap> {\n const body: Record<string, string> = {};\n\n // txid required, support string or string[]\n if (Array.isArray(params.txid)) {\n body.txid = params.txid.join(',');\n } else {\n body.txid = params.txid;\n }\n\n if (params.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenQueriedTradesMap>(\n '/0/private/QueryTrades',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type { KrakenOrderSide, KrakenOrderType } from './getOpenOrders';\n\n/**\n * Currently the only documented posstatus is \"open\",\n * but keeping it as a string union in case Kraken extends it.\n */\nexport type KrakenPositionStatus = 'open';\n\n/**\n * Single open margin position.\n *\n * If `docalcs=true`, `value` and `net` will be populated.\n */\nexport interface KrakenOpenPosition {\n /** Order ID responsible for the position */\n ordertxid: string;\n\n /** Position status (currently only \"open\") */\n posstatus: KrakenPositionStatus;\n\n /** Asset pair */\n pair: string;\n\n /** Unix timestamp of trade that opened the position */\n time: number;\n\n /** Direction (buy/sell) of position */\n type: KrakenOrderSide;\n\n /** Order type used to open position */\n ordertype: KrakenOrderType;\n\n /** Opening cost of position (quote currency) */\n cost: string;\n\n /** Opening fee of position (quote currency) */\n fee: string;\n\n /** Position opening size (base currency) */\n vol: string;\n\n /** Quantity closed (base currency) */\n vol_closed: string;\n\n /** Initial margin consumed (quote currency) */\n margin: string;\n\n /**\n * Current value of remaining position (if `docalcs` requested).\n * Quote currency.\n */\n value?: string;\n\n /**\n * Unrealised P&L of remaining position (if `docalcs` requested).\n * Quote currency.\n */\n net?: string;\n\n /** Funding cost and term of position */\n terms: string;\n\n /** Timestamp of next margin rollover fee (string as per docs) */\n rollovertm: string;\n\n /** Comma-delimited list of additional info */\n misc: string;\n\n /** Comma-delimited list of opening order flags */\n oflags: string;\n}\n\n/** Map of position txid -> open position details */\nexport type KrakenOpenPositionsMap = Record<string, KrakenOpenPosition>;\n\n/**\n * Consolidation mode.\n * Currently only \"market\" is documented.\n */\nexport type KrakenOpenPositionsConsolidationMode = 'market';\n\nexport interface KrakenGetOpenPositionsParams {\n /**\n * Comma-delimited list of txids to limit output to,\n * or an array of txids. Optional: if omitted, returns all.\n */\n txid?: string | string[];\n\n /**\n * Whether to include P&L calculations (`value` and `net`).\n * Default on Kraken is false.\n */\n docalcs?: boolean;\n\n /**\n * Consolidate positions by market/pair.\n * Currently only \"market\" is supported.\n */\n consolidation?: KrakenOpenPositionsConsolidationMode;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/OpenPositions\n *\n * Get information about open margin positions.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Orders and trades – Query open orders & trades\".\n */\nexport function getOpenPositions(\n base: KrakenRestBase,\n params?: KrakenGetOpenPositionsParams,\n): Promise<KrakenOpenPositionsMap> {\n const body: Record<string, string> = {};\n\n if (params?.txid !== undefined) {\n body.txid = Array.isArray(params.txid)\n ? params.txid.join(',')\n : params.txid;\n }\n\n if (params?.docalcs !== undefined) {\n body.docalcs = params.docalcs ? 'true' : 'false';\n }\n\n if (params?.consolidation) {\n body.consolidation = params.consolidation;\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenOpenPositionsMap>(\n '/0/private/OpenPositions',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\n/**\n * Ledger type filter for LedgersInfo.\n */\nexport type KrakenLedgerTypeFilter =\n | 'all'\n | 'trade'\n | 'deposit'\n | 'withdrawal'\n | 'transfer'\n | 'margin'\n | 'adjustment'\n | 'rollover'\n | 'credit'\n | 'settled'\n | 'staking'\n | 'dividend'\n | 'sale'\n | 'nft_rebate';\n\n/**\n * Actual ledger entry type as returned by the API.\n * (This can be larger than the filter set.)\n */\nexport type KrakenLedgerEntryType =\n | 'none'\n | 'trade'\n | 'deposit'\n | 'withdrawal'\n | 'transfer'\n | 'margin'\n | 'adjustment'\n | 'rollover'\n | 'spend'\n | 'receive'\n | 'settled'\n | 'credit'\n | 'staking'\n | 'reward'\n | 'dividend'\n | 'sale'\n | 'conversion'\n | 'nfttrade'\n | 'nftcreatorfee'\n | 'nftrebate'\n | 'custodytransfer';\n\n/**\n * Single ledger entry.\n */\nexport interface KrakenLedgerEntry {\n /** Reference ID of the parent transaction (trade, deposit, withdrawal, etc.) */\n refid: string;\n\n /** Unix timestamp of ledger entry */\n time: number;\n\n /** Type of ledger entry */\n type: KrakenLedgerEntryType;\n\n /** Additional info relating to the ledger entry type, where applicable */\n subtype: string;\n\n /** Asset class */\n aclass: string;\n\n /** Asset code (e.g. \"ZUSD\", \"XXBT\", \"USDT.F\") */\n asset: string;\n\n /** Transaction amount */\n amount: string;\n\n /** Transaction fee */\n fee: string;\n\n /** Resulting balance */\n balance: string;\n}\n\n/** Map of ledger ID -> ledger entry */\nexport type KrakenLedgerMap = Record<string, KrakenLedgerEntry>;\n\nexport interface KrakenLedgersInfoResult {\n /** Ledger entries keyed by ledger ID */\n ledger: KrakenLedgerMap;\n\n /**\n * Amount of available ledger info matching criteria.\n * May be omitted if `without_count=true`.\n */\n count?: number;\n}\n\nexport interface KrakenGetLedgersInfoParams {\n /**\n * Filter output by asset or list of assets.\n * e.g. \"ZUSD\" or [\"ZUSD\", \"XXBT\", \"USDT.F\"].\n * Default on Kraken is \"all\".\n */\n asset?: string | string[];\n\n /**\n * Filter output by asset class.\n * Default on Kraken is \"currency\".\n */\n aclass?: string;\n\n /**\n * Type of ledger entries to retrieve.\n * Default on Kraken is \"all\".\n */\n type?: KrakenLedgerTypeFilter;\n\n /**\n * Starting unix timestamp or ledger ID of results (exclusive).\n */\n start?: number | string;\n\n /**\n * Ending unix timestamp or ledger ID of results (inclusive).\n */\n end?: number | string;\n\n /**\n * Result offset for pagination.\n * 50 results are returned per page by default.\n */\n ofs?: number;\n\n /**\n * If true, does not retrieve count of ledger entries.\n * Can be noticeably faster for users with many entries.\n */\n without_count?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/Ledgers\n *\n * Retrieve information about ledger entries.\n * 50 results are returned at a time, most recent by default.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Query ledger entries\" permission.\n */\nexport function getLedgersInfo(\n base: KrakenRestBase,\n params?: KrakenGetLedgersInfoParams,\n): Promise<KrakenLedgersInfoResult> {\n const body: Record<string, string> = {};\n\n if (params?.asset !== undefined) {\n body.asset = Array.isArray(params.asset)\n ? params.asset.join(',')\n : params.asset;\n }\n\n if (params?.aclass) {\n body.aclass = params.aclass;\n }\n\n if (params?.type) {\n body.type = params.type;\n }\n\n if (params?.start !== undefined) {\n body.start = String(params.start);\n }\n\n if (params?.end !== undefined) {\n body.end = String(params.end);\n }\n\n if (params?.ofs !== undefined) {\n body.ofs = String(params.ofs);\n }\n\n if (params?.without_count !== undefined) {\n body.without_count = params.without_count ? 'true' : 'false';\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenLedgersInfoResult>('/0/private/Ledgers', body);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\nimport type { KrakenLedgerMap } from './getLedgersInfo';\n\n/** Map of ledger ID -> ledger entry (same shape as LedgersInfo) */\nexport type KrakenQueriedLedgersMap = KrakenLedgerMap;\n\nexport interface KrakenGetLedgersQueryParams {\n /**\n * Comma-delimited list of ledger IDs to query info about (20 maximum),\n * or an array of IDs (will be joined).\n */\n id: string | string[];\n\n /**\n * Whether or not to include trades related to position in output.\n * Default on Kraken is false.\n */\n trades?: boolean;\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/QueryLedgers\n *\n * Retrieve information about specific ledger entries.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Query ledger entries\" permission.\n */\nexport function queryLedgers(\n base: KrakenRestBase,\n params: KrakenGetLedgersQueryParams,\n): Promise<KrakenQueriedLedgersMap> {\n const body: Record<string, string> = {};\n\n // id is required; support string or string[]\n if (Array.isArray(params.id)) {\n body.id = params.id.join(',');\n } else {\n body.id = params.id;\n }\n\n if (params.trades !== undefined) {\n body.trades = params.trades ? 'true' : 'false';\n }\n\n if (params.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenQueriedLedgersMap>(\n '/0/private/QueryLedgers',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getAccountBalance';\n\n/**\n * Fee tier info for a single pair (taker or maker side).\n */\nexport interface KrakenFeeTierInfo {\n /** Current fee (in percent) */\n fee: string;\n\n /** Minimum fee for pair (if not fixed fee) */\n min_fee: string;\n\n /** Maximum fee for pair (if not fixed fee) */\n max_fee: string;\n\n /**\n * Next tier's fee for pair (if not fixed fee,\n * null if at lowest fee tier)\n */\n next_fee: string | null;\n\n /**\n * Volume level of current tier (if not fixed fee,\n * null if at lowest fee tier)\n */\n tier_volume: string | null;\n\n /**\n * Volume level of next tier (if not fixed fee,\n * null if at lowest fee tier)\n */\n next_volume: string | null;\n}\n\n/** Map of asset pair -> fee tier info */\nexport type KrakenTradeVolumeFeesMap = Record<string, KrakenFeeTierInfo>;\n\n/**\n * Trade volume + fee schedule result.\n */\nexport interface KrakenTradeVolumeResult {\n /**\n * Fee volume currency (will always be USD according to docs).\n */\n currency: string;\n\n /**\n * Current fee discount volume (in USD, breakdown by subaccount\n * if applicable and logged in to master account).\n */\n volume: string;\n\n /**\n * Taker fees applied for each pair included in the request.\n * Default is missing / empty if no pairs were requested.\n */\n fees?: KrakenTradeVolumeFeesMap;\n\n /**\n * Maker fees applied for each pair included in the request\n * (only for maker/taker pairs).\n * Default is missing / empty if no pairs were requested.\n */\n fees_maker?: KrakenTradeVolumeFeesMap;\n}\n\nexport interface KrakenGetTradeVolumeParams {\n /**\n * Comma-delimited list of asset pairs to get fee info on,\n * or an array of pairs.\n *\n * Optional, but required if any fee info is desired.\n */\n pair?: string | string[];\n\n /**\n * Optional parameter for viewing xstocks data.\n *\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Default on Kraken is \"rebased\" if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\n/**\n * POST /0/private/TradeVolume\n *\n * Returns 30 day USD trading volume and resulting fee schedule\n * for any asset pairs provided.\n *\n * Notes:\n * - Fees will not be included if `pair` is not specified.\n * - If a pair is on a maker/taker fee schedule, taker side is in `fees`\n * and maker side in `fees_maker`.\n * - `nonce` is handled automatically by the client.\n * - Requires \"Funds – Query\" permission.\n */\nexport function getTradeVolume(\n base: KrakenRestBase,\n params?: KrakenGetTradeVolumeParams,\n): Promise<KrakenTradeVolumeResult> {\n const body: Record<string, string> = {};\n\n if (params?.pair !== undefined) {\n body.pair = Array.isArray(params.pair)\n ? params.pair.join(',')\n : params.pair;\n }\n\n if (params?.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenTradeVolumeResult>(\n '/0/private/TradeVolume',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenExportReportType = 'trades' | 'ledgers';\nexport type KrakenExportReportFormat = 'CSV' | 'TSV';\n\nexport interface KrakenRequestExportReportParams {\n /**\n * Type of data to export.\n * - \"trades\"\n * - \"ledgers\"\n */\n report: KrakenExportReportType;\n\n /**\n * File format to export.\n * Default on Kraken is \"CSV\" if omitted.\n */\n format?: KrakenExportReportFormat;\n\n /**\n * Description for the export (required by API).\n */\n description: string;\n\n /**\n * Comma-delimited list of fields to include.\n *\n * Default on Kraken is \"all\" if omitted.\n *\n * For trades:\n * ordertxid, time, ordertype, price, cost, fee, vol,\n * margin, misc, ledgers\n *\n * For ledgers:\n * refid, time, type, subtype, aclass, asset,\n * amount, fee, balance, wallet\n */\n fields?: string;\n\n /**\n * UNIX timestamp for report start time.\n * Default on Kraken is the 1st of the current month if omitted.\n */\n starttm?: number;\n\n /**\n * UNIX timestamp for report end time.\n * Default on Kraken is \"now\" if omitted.\n */\n endtm?: number;\n}\n\n/**\n * Response payload when requesting an export.\n */\nexport interface KrakenRequestExportReportResult {\n /** Report ID assigned by Kraken */\n id: string;\n}\n\n/**\n * POST /0/private/AddExport\n *\n * Request export of trades or ledgers.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Export data\" permission.\n */\nexport function requestExportReport(\n base: KrakenRestBase,\n params: KrakenRequestExportReportParams,\n): Promise<KrakenRequestExportReportResult> {\n const body: Record<string, string> = {\n report: params.report,\n description: params.description,\n };\n\n if (params.format) {\n body.format = params.format;\n }\n\n if (params.fields) {\n body.fields = params.fields;\n }\n\n if (params.starttm !== undefined) {\n body.starttm = String(params.starttm);\n }\n\n if (params.endtm !== undefined) {\n body.endtm = String(params.endtm);\n }\n\n return base.privatePost<KrakenRequestExportReportResult>(\n '/0/private/AddExport',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenExportReportType } from './requestExportReport';\n\n/**\n * Status of a single export report.\n */\nexport type KrakenExportReportStatusState =\n | 'Queued'\n | 'Processing'\n | 'Processed';\n\nexport interface KrakenExportReportStatus {\n /** Report ID */\n id: string;\n\n /** Description provided when the export was requested */\n descr: string;\n\n /** File format (CSV or TSV) */\n format: string;\n\n /** Report type (\"trades\" or \"ledgers\") */\n report: KrakenExportReportType;\n\n /** Subtype (not well-documented; keep as string) */\n subtype: string;\n\n /** Status of the report */\n status: KrakenExportReportStatusState;\n\n /** Deprecated flags field */\n flags?: string;\n\n /** Comma-delimited list of fields included in the report */\n fields: string;\n\n /** UNIX timestamp of report request (string per docs) */\n createdtm: string;\n\n /** Deprecated expire time */\n expiretm?: string;\n\n /** UNIX timestamp report processing began (string per docs) */\n starttm: string;\n\n /** UNIX timestamp report processing finished (string per docs) */\n completedtm: string;\n\n /** UNIX timestamp of report data start time (string per docs) */\n datastarttm: string;\n\n /** UNIX timestamp of report data end time (string per docs) */\n dataendtm: string;\n\n /** Deprecated asset class */\n aclass?: string;\n\n /** Asset (if applicable) */\n asset: string;\n}\n\n/**\n * Request parameters for ExportStatus.\n */\nexport interface KrakenGetExportReportStatusParams {\n /**\n * Type of reports to inquire about.\n * - \"trades\"\n * - \"ledgers\"\n */\n report: KrakenExportReportType;\n}\n\n/**\n * POST /0/private/ExportStatus\n *\n * Get status of requested data exports.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Export data\" permission.\n */\nexport function getExportReportStatus(\n base: KrakenRestBase,\n params: KrakenGetExportReportStatusParams,\n): Promise<KrakenExportReportStatus[]> {\n const body: Record<string, string> = {\n report: params.report,\n };\n\n return base.privatePost<KrakenExportReportStatus[]>(\n '/0/private/ExportStatus',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Params for RetrieveExport.\n */\nexport interface KrakenRetrieveExportParams {\n /**\n * Report ID to retrieve (from AddExport / ExportStatus).\n */\n id: string;\n}\n\n/**\n * Result of RetrieveExport.\n *\n * We return raw binary (ZIP archive). You can wrap/convert this to\n * Buffer, write to disk, etc., in your calling code.\n */\nexport type KrakenRetrieveExportResult = ArrayBuffer;\n\n/**\n * POST /0/private/RetrieveExport\n *\n * Retrieve a processed data export.\n *\n * Note:\n * - Response is `application/octet-stream` (binary ZIP), not JSON.\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Export data\" permission.\n *\n * IMPORTANT:\n * - Your KrakenRestBase should expose a `privatePostBinary` (or similar)\n * that returns an ArrayBuffer instead of JSON.\n */\nexport function retrieveExportReport(\n base: KrakenRestBase & {\n // You’ll need to add this to your concrete RestBase implementation.\n privatePostBinary(\n path: string,\n body?: Record<string, string>,\n ): Promise<ArrayBuffer>;\n },\n params: KrakenRetrieveExportParams,\n): Promise<KrakenRetrieveExportResult> {\n const body: Record<string, string> = {\n id: params.id,\n };\n\n return base.privatePostBinary('/0/private/RetrieveExport', body);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Operation to perform on the export report:\n * - \"cancel\": for queued or processing reports\n * - \"delete\": for already processed reports\n */\nexport type KrakenDeleteExportReportType = 'cancel' | 'delete';\n\nexport interface KrakenDeleteExportReportParams {\n /**\n * ID of report to delete or cancel.\n */\n id: string;\n\n /**\n * Operation to perform:\n * - \"cancel\" for queued/processing reports\n * - \"delete\" for processed reports\n */\n type: KrakenDeleteExportReportType;\n}\n\nexport interface KrakenDeleteExportReportResult {\n /**\n * Whether deletion was successful.\n * Only meaningful when `type = \"delete\"`.\n */\n delete: boolean;\n\n /**\n * Whether cancellation was successful.\n * Only meaningful when `type = \"cancel\"`.\n */\n cancel: boolean;\n}\n\n/**\n * POST /0/private/RemoveExport\n *\n * Delete or cancel an exported trades/ledgers report.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Data – Export data\" permission.\n */\nexport function deleteExportReport(\n base: KrakenRestBase,\n params: KrakenDeleteExportReportParams,\n): Promise<KrakenDeleteExportReportResult> {\n const body: Record<string, string> = {\n id: params.id,\n type: params.type,\n };\n\n return base.privatePost<KrakenDeleteExportReportResult>(\n '/0/private/RemoveExport',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as GetAccountBalance from './getAccountBalance';\nimport * as GetExtendedBalance from './getExtendedBalance';\nimport * as GetCreditLines from './getCreditLines';\nimport * as GetTradeBalance from './getTradeBalance';\nimport * as GetOpenOrders from './getOpenOrders';\nimport * as GetClosedOrders from './getClosedOrders';\nimport * as QueryOrdersInfo from './queryOrdersInfo';\nimport * as GetOrderAmends from './getOrderAmends';\nimport * as GetTradesHistory from './getTradesHistory';\nimport * as QueryTradesInfo from './queryTradesInfo';\nimport * as GetOpenPositions from './getOpenPositions';\nimport * as GetLedgersInfo from './getLedgersInfo';\nimport * as QueryLedgers from './queryLedgers';\nimport * as GetTradeVolume from './getTradeVolume';\nimport * as RequestExportReport from './requestExportReport';\nimport * as GetExportReportStatus from './getExportReportStatus';\nimport * as RetrieveExportReport from './retrieveExportReport';\nimport * as DeleteExportReport from './deleteExportReport';\n\ntype KrakenRestBaseWithBinary = KrakenRestBase & {\n privatePostBinary(\n path: string,\n body?: Record<string, string>,\n ): Promise<ArrayBuffer>;\n};\n\nexport class KrakenSpotAccountDataApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Retrieve all cash balances, net of pending withdrawals.\n *\n * @example\n * const balances = await kraken.accountData.getAccountBalance();\n *\n * console.log(\"USD balance:\", balances[\"ZUSD\"]);\n * console.log(\"BTC balance:\", balances[\"XXBT\"]);\n */\n getAccountBalance(params?: GetAccountBalance.KrakenGetAccountBalanceParams) {\n return GetAccountBalance.getAccountBalance(this.base, params);\n }\n\n /**\n * Retrieve extended balances for all assets, including credit and held amounts.\n *\n * Balance available for trading is calculated as:\n * available = balance + credit - credit_used - hold_trade\n *\n * @example\n * const extended = await kraken.accountData.getExtendedBalance();\n *\n * const usd = extended[\"ZUSD\"];\n * const availableUsd =\n * Number(usd.balance) +\n * Number(usd.credit) -\n * Number(usd.credit_used) -\n * Number(usd.hold_trade);\n */\n getExtendedBalance(\n params?: GetExtendedBalance.KrakenGetExtendedBalanceParams,\n ) {\n return GetExtendedBalance.getExtendedBalance(this.base, params);\n }\n\n /**\n * Retrieve all credit line details for the account (if any).\n *\n * Returns `null` if there are no credit lines configured.\n *\n * @example\n * const credit = await kraken.accountData.getCreditLines();\n *\n * if (!credit) {\n * console.log(\"No credit lines configured\");\n * } else {\n * const usdLine = credit.asset_details[\"ZUSD\"];\n * console.log(\"USD credit limit:\", usdLine.credit_limit);\n * console.log(\"USD available credit:\", usdLine.available_credit);\n *\n * const monitor = credit.limits_monitor;\n * console.log(\"Total credit (USD):\", monitor.total_credit_usd);\n * }\n */\n getCreditLines(params?: GetCreditLines.KrakenGetCreditLinesParams) {\n return GetCreditLines.getCreditLines(this.base, params);\n }\n\n /**\n * Retrieve a summary of collateral balances, margin position valuations,\n * equity and margin level.\n *\n * @example\n * const tb = await kraken.accountData.getTradeBalance();\n *\n * console.log(\"Equity (e):\", tb.e);\n * console.log(\"Free margin (mf):\", tb.mf);\n * console.log(\"Margin level (ml):\", tb.ml);\n */\n getTradeBalance(params?: GetTradeBalance.KrakenGetTradeBalanceParams) {\n return GetTradeBalance.getTradeBalance(this.base, params);\n }\n\n /**\n * Retrieve information about currently open orders.\n *\n * @example\n * const { open } = await kraken.accountData.getOpenOrders({\n * trades: true,\n * });\n *\n * for (const [orderId, order] of Object.entries(open)) {\n * console.log(orderId, order.status, order.descr.order, order.vol, order.vol_exec);\n * }\n */\n getOpenOrders(params?: GetOpenOrders.KrakenGetOpenOrdersParams) {\n return GetOpenOrders.getOpenOrders(this.base, params);\n }\n\n /**\n * Retrieve information about orders that have been closed\n * (filled or cancelled). 50 results are returned at a time,\n * most recent by default.\n *\n * @example\n * const { closed, count } = await kraken.accountData.getClosedOrders({\n * trades: true,\n * closetime: \"close\",\n * ofs: 0,\n * });\n *\n * for (const [txid, order] of Object.entries(closed)) {\n * console.log(\n * txid,\n * order.status,\n * order.descr.order,\n * order.vol_exec,\n * order.price,\n * );\n * }\n */\n getClosedOrders(params?: GetClosedOrders.KrakenGetClosedOrdersParams) {\n return GetClosedOrders.getClosedOrders(this.base, params);\n }\n\n /**\n * Retrieve information about specific orders by txid.\n *\n * @example\n * const orders = await kraken.accountData.queryOrdersInfo({\n * txid: [\"OABCDEFGHIJKLMN\", \"O1234567890ABCDE\"],\n * trades: true,\n * });\n *\n * for (const [txid, order] of Object.entries(orders)) {\n * console.log(\n * txid,\n * order.status,\n * order.descr.order,\n * order.vol_exec,\n * order.price,\n * );\n * }\n */\n queryOrdersInfo(params: QueryOrdersInfo.KrakenGetOrdersInfoParams) {\n return QueryOrdersInfo.queryOrdersInfo(this.base, params);\n }\n\n /**\n * Retrieve the amend history (audit trail) for a specific order.\n *\n * The first entry contains the original order parameters and has\n * amend_type of \"original\".\n *\n * @example\n * const history = await kraken.accountData.getOrderAmends({\n * order_id: \"OABCDEFGHIJKLMN\",\n * });\n *\n * for (const amend of history.amends) {\n * console.log(\n * amend.timestamp,\n * amend.amend_type,\n * amend.order_qty,\n * amend.limit_price,\n * amend.reason,\n * );\n * }\n */\n getOrderAmends(params: GetOrderAmends.KrakenGetOrderAmendsParams) {\n return GetOrderAmends.getOrderAmends(this.base, params);\n }\n\n /**\n * Retrieve information about trades / fills.\n * 50 results are returned at a time, most recent by default.\n *\n * @example\n * const history = await kraken.accountData.getTradesHistory({\n * type: \"all\",\n * ofs: 0,\n * ledgers: false,\n * });\n *\n * console.log(\"Total trades:\", history.count);\n * for (const [id, trade] of Object.entries(history.trades)) {\n * console.log(\n * id,\n * trade.time,\n * trade.pair,\n * trade.type,\n * trade.vol,\n * trade.price,\n * );\n * }\n */\n getTradesHistory(params?: GetTradesHistory.KrakenGetTradesHistoryParams) {\n return GetTradesHistory.getTradesHistory(this.base, params);\n }\n\n /**\n * Retrieve information about specific trades/fills by txid.\n *\n * @example\n * const trades = await kraken.accountData.queryTradesInfo({\n * txid: [\"TABCDEFG1234567\", \"T7654321GFEDCBA\"],\n * trades: false,\n * });\n *\n * for (const [id, t] of Object.entries(trades)) {\n * console.log(\n * id,\n * t.time,\n * t.pair,\n * t.type,\n * t.vol,\n * t.price,\n * );\n * }\n */\n queryTradesInfo(params: QueryTradesInfo.KrakenGetTradesInfoParams) {\n return QueryTradesInfo.queryTradesInfo(this.base, params);\n }\n\n /**\n * Get information about open margin positions.\n *\n * @example\n * const positions = await kraken.accountData.getOpenPositions({\n * docalcs: true,\n * });\n *\n * for (const [txid, pos] of Object.entries(positions)) {\n * console.log(\n * txid,\n * pos.pair,\n * pos.type,\n * pos.vol,\n * pos.cost,\n * pos.value,\n * pos.net,\n * );\n * }\n */\n getOpenPositions(params?: GetOpenPositions.KrakenGetOpenPositionsParams) {\n return GetOpenPositions.getOpenPositions(this.base, params);\n }\n\n /**\n * Retrieve information about ledger entries.\n * 50 results are returned at a time, most recent by default.\n *\n * @example\n * const result = await kraken.accountData.getLedgersInfo({\n * asset: [\"ZUSD\", \"XXBT\"],\n * type: \"all\",\n * ofs: 0,\n * });\n *\n * console.log(\"Total ledger entries (if provided):\", result.count);\n * for (const [id, entry] of Object.entries(result.ledger)) {\n * console.log(\n * id,\n * entry.time,\n * entry.type,\n * entry.asset,\n * entry.amount,\n * entry.balance,\n * );\n * }\n */\n getLedgersInfo(params?: GetLedgersInfo.KrakenGetLedgersInfoParams) {\n return GetLedgersInfo.getLedgersInfo(this.base, params);\n }\n\n /**\n * Retrieve information about specific ledger entries by ID.\n *\n * @example\n * const ledgers = await kraken.accountData.queryLedgers({\n * id: [\"L12345ABCDE\", \"L67890FGHIJ\"],\n * });\n *\n * for (const [id, entry] of Object.entries(ledgers)) {\n * console.log(\n * id,\n * entry.time,\n * entry.type,\n * entry.asset,\n * entry.amount,\n * entry.balance,\n * );\n * }\n */\n queryLedgers(params: QueryLedgers.KrakenGetLedgersQueryParams) {\n return QueryLedgers.queryLedgers(this.base, params);\n }\n\n /**\n * Get 30-day USD trading volume and resulting fee schedule.\n *\n * Fees will not be included if `pair` is not specified.\n *\n * @example\n * const tv = await kraken.accountData.getTradeVolume({\n * pair: [\"XBTUSD\", \"ETHUSD\"],\n * });\n *\n * console.log(\"Volume currency:\", tv.currency); // \"USD\"\n * console.log(\"30d volume (USD):\", tv.volume);\n *\n * const xbtFees = tv.fees?.[\"XBTUSD\"];\n * if (xbtFees) {\n * console.log(\"XBTUSD taker fee:\", xbtFees.fee);\n * }\n */\n getTradeVolume(params?: GetTradeVolume.KrakenGetTradeVolumeParams) {\n return GetTradeVolume.getTradeVolume(this.base, params);\n }\n\n /**\n * Request an export report for trades or ledgers.\n *\n * Use the returned report ID with the export status/download\n * endpoints (not yet implemented here) to track and retrieve\n * the generated file.\n *\n * @example\n * const { id } = await kraken.accountData.requestExportReport({\n * report: \"trades\",\n * format: \"CSV\",\n * description: \"My trades export\",\n * // optional filters:\n * // starttm: Math.floor(Date.now() / 1000) - 30 * 86400,\n * // endtm: Math.floor(Date.now() / 1000),\n * });\n *\n * console.log(\"Export report ID:\", id);\n */\n requestExportReport(\n params: RequestExportReport.KrakenRequestExportReportParams,\n ) {\n return RequestExportReport.requestExportReport(this.base, params);\n }\n\n /**\n * Get status of requested export reports (trades or ledgers).\n *\n * @example\n * const statuses = await kraken.accountData.getExportReportStatus({\n * report: \"trades\",\n * });\n *\n * for (const s of statuses) {\n * console.log(\n * s.id,\n * s.status,\n * s.descr,\n * s.createdtm,\n * s.completedtm,\n * );\n * }\n */\n getExportReportStatus(\n params: GetExportReportStatus.KrakenGetExportReportStatusParams,\n ) {\n return GetExportReportStatus.getExportReportStatus(this.base, params);\n }\n\n /**\n * Retrieve a processed data export as a ZIP archive (binary).\n *\n * @example\n * const zipBytes = await kraken.accountData.RetrieveExportReport({\n * id: \"EXPORT_REPORT_ID\",\n * });\n *\n * // In Node, for example:\n * // await fs.promises.writeFile(\"export.zip\", Buffer.from(zipBytes));\n */\n retrieveExportReport(\n params: RetrieveExportReport.KrakenRetrieveExportParams,\n ) {\n // Cast here to satisfy the extended interface with privatePostBinary\n return RetrieveExportReport.retrieveExportReport(\n this.base as KrakenRestBaseWithBinary,\n params,\n );\n }\n\n /**\n * Delete or cancel an export report.\n *\n * - Use `type: \"cancel\"` for queued/processing reports.\n * - Use `type: \"delete\"` for processed reports.\n *\n * @example\n * const result = await kraken.accountData.deleteExportReport({\n * id: \"EXPORT_REPORT_ID\",\n * type: \"cancel\",\n * });\n *\n * console.log(\"cancel success:\", result.cancel);\n */\n deleteExportReport(\n params: DeleteExportReport.KrakenDeleteExportReportParams,\n ) {\n return DeleteExportReport.deleteExportReport(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenRebaseMultiplier = GetAccountBalance.KrakenRebaseMultiplier;\nexport type KrakenAccountBalanceMap = GetAccountBalance.KrakenAccountBalanceMap;\nexport type KrakenGetAccountBalanceParams =\n GetAccountBalance.KrakenGetAccountBalanceParams;\n\nexport type KrakenExtendedBalanceEntry =\n GetExtendedBalance.KrakenExtendedBalanceEntry;\nexport type KrakenExtendedBalanceMap =\n GetExtendedBalance.KrakenExtendedBalanceMap;\nexport type KrakenGetExtendedBalanceParams =\n GetExtendedBalance.KrakenGetExtendedBalanceParams;\n\nexport type KrakenCreditLinesAssetEntry =\n GetCreditLines.KrakenCreditLinesAssetEntry;\nexport type KrakenCreditLinesAssetMap =\n GetCreditLines.KrakenCreditLinesAssetMap;\nexport type KrakenCreditLinesLimitsMonitor =\n GetCreditLines.KrakenCreditLinesLimitsMonitor;\nexport type KrakenCreditLinesResult = GetCreditLines.KrakenCreditLinesResult;\nexport type KrakenCreditLinesResponse =\n GetCreditLines.KrakenCreditLinesResponse;\nexport type KrakenGetCreditLinesParams =\n GetCreditLines.KrakenGetCreditLinesParams;\n\nexport type KrakenTradeBalanceResult = GetTradeBalance.KrakenTradeBalanceResult;\nexport type KrakenGetTradeBalanceParams =\n GetTradeBalance.KrakenGetTradeBalanceParams;\n\nexport type KrakenOrderStatus = GetOpenOrders.KrakenOrderStatus;\nexport type KrakenOrderSide = GetOpenOrders.KrakenOrderSide;\nexport type KrakenOrderType = GetOpenOrders.KrakenOrderType;\nexport type KrakenOrderTrigger = GetOpenOrders.KrakenOrderTrigger;\nexport type KrakenOpenOrderDescription =\n GetOpenOrders.KrakenOpenOrderDescription;\nexport type KrakenOpenOrder = GetOpenOrders.KrakenOpenOrder;\nexport type KrakenOpenOrdersMap = GetOpenOrders.KrakenOpenOrdersMap;\nexport type KrakenOpenOrdersResult = GetOpenOrders.KrakenOpenOrdersResult;\nexport type KrakenGetOpenOrdersParams = GetOpenOrders.KrakenGetOpenOrdersParams;\n\nexport type KrakenClosedOrder = GetClosedOrders.KrakenClosedOrder;\nexport type KrakenClosedOrdersMap = GetClosedOrders.KrakenClosedOrdersMap;\nexport type KrakenClosedOrdersResult = GetClosedOrders.KrakenClosedOrdersResult;\nexport type KrakenClosedOrdersCloseTime =\n GetClosedOrders.KrakenClosedOrdersCloseTime;\nexport type KrakenGetClosedOrdersParams =\n GetClosedOrders.KrakenGetClosedOrdersParams;\n\nexport type KrakenQueriedOrder = QueryOrdersInfo.KrakenQueriedOrder;\nexport type KrakenQueriedOrdersMap = QueryOrdersInfo.KrakenQueriedOrdersMap;\nexport type KrakenGetOrdersInfoParams =\n QueryOrdersInfo.KrakenGetOrdersInfoParams;\n\nexport type KrakenOrderAmendType = GetOrderAmends.KrakenOrderAmendType;\nexport type KrakenOrderAmendEntry = GetOrderAmends.KrakenOrderAmendEntry;\nexport type KrakenOrderAmendsResult = GetOrderAmends.KrakenOrderAmendsResult;\nexport type KrakenGetOrderAmendsParams =\n GetOrderAmends.KrakenGetOrderAmendsParams;\n\nexport type KrakenTradeHistoryTypeFilter =\n GetTradesHistory.KrakenTradeHistoryTypeFilter;\nexport type KrakenTradeHistoryEntry = GetTradesHistory.KrakenTradeHistoryEntry;\nexport type KrakenTradeHistoryMap = GetTradesHistory.KrakenTradeHistoryMap;\nexport type KrakenTradesHistoryResult =\n GetTradesHistory.KrakenTradesHistoryResult;\nexport type KrakenGetTradesHistoryParams =\n GetTradesHistory.KrakenGetTradesHistoryParams;\n\nexport type KrakenQueriedTradesMap = QueryTradesInfo.KrakenQueriedTradesMap;\nexport type KrakenGetTradesInfoParams =\n QueryTradesInfo.KrakenGetTradesInfoParams;\n\nexport type KrakenPositionStatus = GetOpenPositions.KrakenPositionStatus;\nexport type KrakenOpenPosition = GetOpenPositions.KrakenOpenPosition;\nexport type KrakenOpenPositionsMap = GetOpenPositions.KrakenOpenPositionsMap;\nexport type KrakenOpenPositionsConsolidationMode =\n GetOpenPositions.KrakenOpenPositionsConsolidationMode;\nexport type KrakenGetOpenPositionsParams =\n GetOpenPositions.KrakenGetOpenPositionsParams;\n\nexport type KrakenLedgerTypeFilter = GetLedgersInfo.KrakenLedgerTypeFilter;\nexport type KrakenLedgerEntryType = GetLedgersInfo.KrakenLedgerEntryType;\nexport type KrakenLedgerEntry = GetLedgersInfo.KrakenLedgerEntry;\nexport type KrakenLedgerMap = GetLedgersInfo.KrakenLedgerMap;\nexport type KrakenLedgersInfoResult = GetLedgersInfo.KrakenLedgersInfoResult;\nexport type KrakenGetLedgersInfoParams =\n GetLedgersInfo.KrakenGetLedgersInfoParams;\n\nexport type KrakenQueriedLedgersMap = QueryLedgers.KrakenQueriedLedgersMap;\nexport type KrakenGetLedgersQueryParams =\n QueryLedgers.KrakenGetLedgersQueryParams;\n\nexport type KrakenFeeTierInfo = GetTradeVolume.KrakenFeeTierInfo;\nexport type KrakenTradeVolumeFeesMap = GetTradeVolume.KrakenTradeVolumeFeesMap;\nexport type KrakenTradeVolumeResult = GetTradeVolume.KrakenTradeVolumeResult;\nexport type KrakenGetTradeVolumeParams =\n GetTradeVolume.KrakenGetTradeVolumeParams;\n\nexport type KrakenExportReportType = RequestExportReport.KrakenExportReportType;\nexport type KrakenExportReportFormat =\n RequestExportReport.KrakenExportReportFormat;\nexport type KrakenRequestExportReportParams =\n RequestExportReport.KrakenRequestExportReportParams;\nexport type KrakenRequestExportReportResult =\n RequestExportReport.KrakenRequestExportReportResult;\n\nexport type KrakenExportReportStatusState =\n GetExportReportStatus.KrakenExportReportStatusState;\nexport type KrakenExportReportStatus =\n GetExportReportStatus.KrakenExportReportStatus;\nexport type KrakenGetExportReportStatusParams =\n GetExportReportStatus.KrakenGetExportReportStatusParams;\n\nexport type KrakenRetrieveExportParams =\n RetrieveExportReport.KrakenRetrieveExportParams;\nexport type KrakenRetrieveExportResult =\n RetrieveExportReport.KrakenRetrieveExportResult;\n\nexport type KrakenDeleteExportReportType =\n DeleteExportReport.KrakenDeleteExportReportType;\nexport type KrakenDeleteExportReportParams =\n DeleteExportReport.KrakenDeleteExportReportParams;\nexport type KrakenDeleteExportReportResult =\n DeleteExportReport.KrakenDeleteExportReportResult;\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type {\n KrakenOrderSide,\n KrakenOrderType,\n KrakenOrderTrigger,\n} from '../account-data/getOpenOrders';\n\nexport type KrakenAddOrderTimeInForce = 'GTC' | 'IOC' | 'GTD';\n\nexport type KrakenAddOrderStpType =\n | 'cancel-newest'\n | 'cancel-oldest'\n | 'cancel-both';\n\n/**\n * Conditional close order parameters.\n *\n * These are mapped to:\n * - close[ordertype]\n * - close[price]\n * - close[price2]\n */\nexport interface KrakenAddOrderCloseParams {\n /**\n * Conditional close order type.\n * Docs list a subset, but we reuse KrakenOrderType for now.\n */\n ordertype: KrakenOrderType;\n\n /** Conditional close order price */\n price?: string;\n\n /** Conditional close order secondary price */\n price2?: string;\n}\n\nexport interface KrakenAddOrderParams {\n /**\n * Optional non-unique numeric identifier for grouping orders.\n * Mutually exclusive with `cl_ord_id`.\n */\n userref?: number;\n\n /**\n * Client order ID, unique per client.\n * Mutually exclusive with `userref`.\n *\n * Long / short UUID or free-text up to 18 chars.\n */\n cl_ord_id?: string;\n\n /**\n * Execution model of the order.\n * e.g. \"market\", \"limit\", \"stop-loss\", etc.\n */\n ordertype: KrakenOrderType;\n\n /** Order direction (\"buy\" / \"sell\") */\n type: KrakenOrderSide;\n\n /**\n * Order quantity in terms of the base asset.\n *\n * Note: Volume can be specified as \"0\" for closing margin orders\n * to automatically fill the requisite quantity.\n */\n volume: string;\n\n /**\n * For iceberg orders: quantity to show in the book while the rest\n * of the order remains hidden. Minimum = 1/15 of `volume`.\n */\n displayvol?: string;\n\n /** Asset pair id or altname (e.g. \"XBTUSD\") */\n pair: string;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * e.g. \"tokenized_asset\"\n */\n asset_class?: 'tokenized_asset';\n\n /**\n * Price:\n * - Limit price for limit/iceberg\n * - Trigger price for stop/TP/trailing orders\n *\n * Relative formats (+,-,#, %) are supported by Kraken.\n */\n price?: string;\n\n /**\n * Secondary price:\n * - Limit price for *-limit order types (e.g. stop-loss-limit)\n * - For trailing-stop-limit, relative price offset from trigger.\n */\n price2?: string;\n\n /**\n * Price signal used to trigger stop/TP/trailing orders.\n *\n * Default on Kraken is \"last\".\n */\n trigger?: KrakenOrderTrigger;\n\n /**\n * Amount of leverage desired (quote string, e.g. \"5\").\n * Default is no leverage if omitted.\n */\n leverage?: string;\n\n /**\n * If true, order will only reduce a currently open position,\n * not increase it or open a new one.\n */\n reduce_only?: boolean;\n\n /**\n * Self Trade Prevention mode:\n * - \"cancel-newest\" (default)\n * - \"cancel-oldest\"\n * - \"cancel-both\"\n */\n stptype?: KrakenAddOrderStpType;\n\n /**\n * Comma-delimited list of order flags:\n * - post, fcib, fciq, nompp, viqc\n */\n oflags?: string;\n\n /**\n * Time-in-force:\n * - GTC (default)\n * - IOC\n * - GTD (must coincide with expiretm)\n */\n timeinforce?: KrakenAddOrderTimeInForce;\n\n /**\n * Scheduled start time:\n * - \"0\" now (default)\n * - \"<n>\" unix timestamp\n * - \"+<n>\" seconds from now (must be URL-encoded as %2b)\n */\n starttm?: string;\n\n /**\n * Expiry time (for GTD or other good-until orders):\n * - \"0\" no expiration (default)\n * - \"<n>\" unix timestamp\n * - \"+<n>\" expire <n> seconds from now (min 5s)\n */\n expiretm?: string;\n\n /**\n * Optional conditional close order that will be placed\n * once the primary order executes.\n */\n close?: KrakenAddOrderCloseParams;\n\n /**\n * RFC3339 deadline timestamp.\n * e.g. \"2021-04-01T00:18:45Z\"\n * min now()+2s, max now()+60s.\n */\n deadline?: string;\n\n /**\n * If true, the order will be validated only and will not\n * actually be sent to the matching engine.\n */\n validate?: boolean;\n}\n\nexport interface KrakenAddOrderDescription {\n /** Order description text */\n order: string;\n\n /** Conditional close order description (if applicable) */\n close?: string;\n}\n\nexport interface KrakenAddOrderResult {\n /** Order description info */\n descr: KrakenAddOrderDescription;\n\n /**\n * Transaction IDs for the order (if it was added successfully).\n *\n * Note: If `validate=true`, Kraken may omit txid since\n * the order isn’t actually created.\n */\n txid?: string[];\n}\n\n/**\n * POST /0/private/AddOrder\n *\n * Place a new order.\n *\n * Note:\n * - `nonce` is handled automatically by the client.\n * - Requires \"Orders and trades – Create & modify orders\".\n */\nexport function addOrder(\n base: KrakenRestBase,\n params: KrakenAddOrderParams,\n): Promise<KrakenAddOrderResult> {\n // Enforce documented mutual exclusion client-side\n if (params.userref !== undefined && params.cl_ord_id) {\n throw new Error(\n 'KrakenAddOrderParams: userref and cl_ord_id are mutually exclusive',\n );\n }\n\n const body: Record<string, string> = {\n ordertype: params.ordertype,\n type: params.type,\n volume: params.volume,\n pair: params.pair,\n };\n\n if (params.userref !== undefined) {\n body.userref = String(params.userref);\n }\n\n if (params.cl_ord_id) {\n body.cl_ord_id = params.cl_ord_id;\n }\n\n if (params.displayvol) {\n body.displayvol = params.displayvol;\n }\n\n if (params.asset_class) {\n body.asset_class = params.asset_class;\n }\n\n if (params.price !== undefined) {\n body.price = params.price;\n }\n\n if (params.price2 !== undefined) {\n body.price2 = params.price2;\n }\n\n if (params.trigger) {\n body.trigger = params.trigger;\n }\n\n if (params.leverage !== undefined) {\n body.leverage = params.leverage;\n }\n\n if (params.reduce_only !== undefined) {\n body.reduce_only = params.reduce_only ? 'true' : 'false';\n }\n\n if (params.stptype) {\n body.stptype = params.stptype;\n }\n\n if (params.oflags) {\n body.oflags = params.oflags;\n }\n\n if (params.timeinforce) {\n body.timeinforce = params.timeinforce;\n }\n\n if (params.starttm !== undefined) {\n body.starttm = params.starttm;\n }\n\n if (params.expiretm !== undefined) {\n body.expiretm = params.expiretm;\n }\n\n if (params.deadline !== undefined) {\n body.deadline = params.deadline;\n }\n\n if (params.validate !== undefined) {\n body.validate = params.validate ? 'true' : 'false';\n }\n\n if (params.close) {\n body['close[ordertype]'] = params.close.ordertype;\n\n if (params.close.price !== undefined) {\n body['close[price]'] = params.close.price;\n }\n\n if (params.close.price2 !== undefined) {\n body['close[price2]'] = params.close.price2;\n }\n }\n\n return base.privatePost<KrakenAddOrderResult>('/0/private/AddOrder', body);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Parameters to amend an existing order.\n *\n * Either `txid` or `cl_ord_id` is required.\n */\nexport interface KrakenAmendOrderParams {\n /**\n * The Kraken identifier for the order to be amended.\n * Either `txid` or `cl_ord_id` is required.\n */\n txid?: string;\n\n /**\n * The client identifier for the order to be amended.\n * Either `txid` or `cl_ord_id` is required.\n */\n cl_ord_id?: string;\n\n /**\n * New order quantity in terms of the base asset.\n *\n * If provided and reduced below already-filled quantity,\n * the remaining quantity will be cancelled.\n */\n order_qty?: string;\n\n /**\n * For iceberg orders only, defines the new quantity to show\n * in the book while the rest remains hidden.\n * Minimum value = 1/15 of remaining order quantity.\n */\n display_qty?: string;\n\n /**\n * New limit price restriction on the order (for order types\n * that support limit price only).\n *\n * Relative pricing supported via + / - prefixes and % suffix.\n */\n limit_price?: string;\n\n /**\n * New trigger price to activate the order (for triggered\n * order types only).\n *\n * Relative pricing supported via + / - prefixes and % suffix.\n */\n trigger_price?: string;\n\n /**\n * Required on amends for non-crypto pairs (xstocks).\n * Provide the pair symbol.\n */\n pair?: string;\n\n /**\n * Optional flag for limit_price amends. If true, the limit\n * price change will be rejected if the order cannot be\n * posted passively in the book.\n */\n post_only?: boolean;\n\n /**\n * RFC3339 timestamp after which the matching engine should\n * reject the amend request in presence of latency/queuing.\n * Example: \"2021-04-01T00:18:45Z\"\n *\n * min = now() + 2s, max = now() + 60s.\n */\n deadline?: string;\n}\n\n/**\n * Result payload for a successful amend.\n */\nexport interface KrakenAmendOrderResult {\n /**\n * The unique Kraken identifier generated for this amend\n * transaction.\n */\n amend_id: string;\n}\n\n/**\n * POST /0/private/AmendOrder\n *\n * Modify order parameters in-place without cancel+new.\n *\n * Notes:\n * - Either `txid` or `cl_ord_id` is required.\n * - Nonce, signing, etc. are handled by KrakenRestBase.\n * - Requires \"Create & modify orders\" or \"Cancel & close orders\".\n */\nexport function amendOrder(\n base: KrakenRestBase,\n params: KrakenAmendOrderParams,\n): Promise<KrakenAmendOrderResult> {\n if (!params.txid && !params.cl_ord_id) {\n throw new Error(\n 'KrakenAmendOrderParams: either txid or cl_ord_id must be provided',\n );\n }\n\n const body: Record<string, string> = {};\n\n if (params.txid) {\n body.txid = params.txid;\n }\n if (params.cl_ord_id) {\n body.cl_ord_id = params.cl_ord_id;\n }\n\n if (params.order_qty !== undefined) {\n body.order_qty = params.order_qty;\n }\n\n if (params.display_qty !== undefined) {\n body.display_qty = params.display_qty;\n }\n\n if (params.limit_price !== undefined) {\n body.limit_price = params.limit_price;\n }\n\n if (params.trigger_price !== undefined) {\n body.trigger_price = params.trigger_price;\n }\n\n if (params.pair !== undefined) {\n body.pair = params.pair;\n }\n\n if (params.post_only !== undefined) {\n body.post_only = params.post_only ? 'true' : 'false';\n }\n\n if (params.deadline !== undefined) {\n body.deadline = params.deadline;\n }\n\n return base.privatePost<KrakenAmendOrderResult>(\n '/0/private/AmendOrder',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Cancel a particular open order (or set of open orders) by:\n * - Kraken order identifier(s) (txid),\n * - user reference (userref), or\n * - client order identifier(s) (cl_ord_id).\n *\n * Exactly one of these fields must be provided.\n */\nexport interface KrakenCancelOrderParams {\n /**\n * Kraken order identifier(s).\n * Can be a single txid or an array which will be joined with commas.\n */\n txid?: string | string[];\n\n /**\n * User reference to cancel against.\n * When provided, Kraken expects it in the `txid` field as an integer.\n */\n userref?: number;\n\n /**\n * Client order identifier(s).\n * Can be a single ID or an array, joined with commas.\n */\n cl_ord_id?: string | string[];\n}\n\n/**\n * Result payload for CancelOrder and CancelAll.\n */\nexport interface KrakenCancelOrderResult {\n /** Number of orders cancelled */\n count: number;\n\n /** If true, orders are pending cancellation */\n pending?: boolean;\n}\n\n/**\n * POST /0/private/CancelOrder\n *\n * Cancel one or more open orders by txid, userref, or cl_ord_id.\n *\n * Notes:\n * - `nonce` is handled automatically by KrakenRestBase.\n * - Requires \"Create & modify orders\" or \"Cancel & close orders\".\n */\nexport function cancelOrder(\n base: KrakenRestBase,\n params: KrakenCancelOrderParams,\n): Promise<KrakenCancelOrderResult> {\n const { txid, userref, cl_ord_id } = params;\n\n const provided =\n (txid !== undefined ? 1 : 0) +\n (userref !== undefined ? 1 : 0) +\n (cl_ord_id !== undefined ? 1 : 0);\n\n if (provided === 0) {\n throw new Error(\n 'KrakenCancelOrderParams: one of txid, userref, or cl_ord_id must be provided',\n );\n }\n\n if (provided > 1) {\n throw new Error(\n 'KrakenCancelOrderParams: txid, userref, and cl_ord_id are mutually exclusive; provide exactly one',\n );\n }\n\n const body: Record<string, string> = {};\n\n if (userref !== undefined) {\n // Cancel by userref: Kraken expects it in `txid` field as an integer\n body.txid = String(userref);\n } else if (cl_ord_id !== undefined) {\n // Cancel by client order id(s)\n body.cl_ord_id = Array.isArray(cl_ord_id) ? cl_ord_id.join(',') : cl_ord_id;\n } else if (txid !== undefined) {\n // Cancel by txid(s)\n body.txid = Array.isArray(txid) ? txid.join(',') : txid;\n }\n\n return base.privatePost<KrakenCancelOrderResult>(\n '/0/private/CancelOrder',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenCancelOrderResult } from './cancelOrder';\n\n/**\n * Result of CancelAll. Shape is identical to CancelOrder.\n */\nexport type KrakenCancelAllOrdersResult = KrakenCancelOrderResult;\n\n/**\n * POST /0/private/CancelAll\n *\n * Cancel all open orders.\n *\n * Notes:\n * - `nonce` is handled automatically by KrakenRestBase.\n * - Requires \"Create & modify orders\" or \"Cancel & close orders\".\n */\nexport function cancelAllOrders(\n base: KrakenRestBase,\n): Promise<KrakenCancelAllOrdersResult> {\n // Body is just nonce, which RestBase adds automatically.\n return base.privatePost<KrakenCancelAllOrdersResult>(\n '/0/private/CancelAll',\n {},\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Params for CancelAllOrdersAfter.\n */\nexport interface KrakenCancelAllOrdersAfterParams {\n /**\n * Duration (in seconds) to set/extend the timer.\n * Must be < 86400.\n *\n * Use 0 to disable the timer.\n */\n timeout: number;\n}\n\n/**\n * Result payload for CancelAllOrdersAfter.\n */\nexport interface KrakenCancelAllOrdersAfterResult {\n /**\n * Timestamp (RFC3339) at which the request was received.\n */\n currentTime: string;\n\n /**\n * Timestamp (RFC3339) after which all orders will be cancelled,\n * unless the timer is extended or disabled.\n *\n * If the timer is disabled (timeout = 0), Kraken returns\n * `triggerTime` equal to `currentTime` or a past time.\n */\n triggerTime: string;\n}\n\n/**\n * POST /0/private/CancelAllOrdersAfter\n *\n * \"Dead Man's Switch\" for cancelling all orders after a timeout.\n *\n * Notes:\n * - `timeout` is in seconds, must be < 86400.\n * - `timeout = 0` disables the mechanism.\n * - `nonce` & signing handled by KrakenRestBase.\n * - Requires \"Create & modify orders\" or \"Cancel & close orders\".\n */\nexport function cancelAllOrdersAfter(\n base: KrakenRestBase,\n params: KrakenCancelAllOrdersAfterParams,\n): Promise<KrakenCancelAllOrdersAfterResult> {\n const body: Record<string, string> = {\n timeout: String(params.timeout),\n };\n\n return base.privatePost<KrakenCancelAllOrdersAfterResult>(\n '/0/private/CancelAllOrdersAfter',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Result of GetWebSocketsToken.\n */\nexport interface KrakenGetWebSocketsTokenResult {\n /**\n * WebSockets token to authenticate private WS subscriptions.\n *\n * Must be used within ~15 minutes of creation, but does not\n * expire as long as a WS connection using it is established\n * and maintained.\n */\n token: string;\n\n /**\n * Time (in seconds) after which the token expires\n * (if not used to establish a WS connection).\n */\n expires: number;\n}\n\n/**\n * POST /0/private/GetWebSocketsToken\n *\n * Request an authentication token for Kraken's WebSockets API.\n *\n * Notes:\n * - `nonce` and signing are handled by KrakenRestBase.\n * - Requires API key permission: \"WebSocket interface - On\".\n */\nexport function getWebSocketsToken(\n base: KrakenRestBase,\n): Promise<KrakenGetWebSocketsTokenResult> {\n // Body is just nonce; RestBase will inject it.\n return base.privatePost<KrakenGetWebSocketsTokenResult>(\n '/0/private/GetWebSocketsToken',\n {},\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type {\n KrakenOrderSide,\n KrakenOrderType,\n KrakenOrderTrigger,\n} from '../account-data/getOpenOrders';\nimport type {\n KrakenAddOrderTimeInForce,\n KrakenAddOrderStpType,\n} from './addOrder';\n\n/**\n * Parameters for a single order inside AddOrderBatch.\n *\n * NOTE:\n * - Pair / asset_class are top-level on the batch, not per order.\n * - userref and cl_ord_id are mutually exclusive per order.\n */\nexport interface KrakenAddOrderBatchOrderParams {\n /**\n * Optional non-unique numeric identifier for grouping orders.\n * Mutually exclusive with `cl_ord_id`.\n */\n userref?: number;\n\n /**\n * Client order ID, unique per client.\n * Mutually exclusive with `userref`.\n */\n cl_ord_id?: string;\n\n /** Execution model of the order. */\n ordertype: KrakenOrderType;\n\n /** Order direction (\"buy\" / \"sell\"). */\n type: KrakenOrderSide;\n\n /**\n * Order quantity in base asset terms.\n * Volume can be \"0\" for closing margin orders.\n */\n volume: string;\n\n /**\n * Iceberg quantity to display in the book (optional).\n * Minimum = 1/15 of volume.\n */\n displayvol?: string;\n\n /**\n * Price:\n * - Limit price for limit / iceberg\n * - Trigger price for stop / take-profit order types\n * Relative formats (+, -, #, %) supported by Kraken.\n */\n price?: string;\n\n /**\n * Secondary price:\n * - Limit price for *-limit variants (stop-loss-limit, take-profit-limit)\n */\n price2?: string;\n\n /**\n * Trigger reference price for triggered orders.\n * Default is \"last\" if omitted.\n */\n trigger?: KrakenOrderTrigger;\n\n /**\n * Leverage amount as a string (e.g. \"5\").\n * Default = none if omitted.\n */\n leverage?: string;\n\n /**\n * If true, order will only reduce existing position.\n */\n reduce_only?: boolean;\n\n /**\n * Self Trade Prevention mode.\n * Default: \"cancel-newest\".\n */\n stptype?: KrakenAddOrderStpType;\n\n /**\n * Comma-delimited order flags:\n * - post, fcib, fciq, nompp, viqc\n */\n oflags?: string;\n\n /**\n * Time-in-force:\n * - GTC (default)\n * - IOC\n * - GTD\n */\n timeinforce?: KrakenAddOrderTimeInForce;\n\n /**\n * Scheduled start time:\n * - \"0\" now (default)\n * - \"<n>\" unix timestamp\n * - \"+<n>\" seconds from now\n */\n starttm?: string;\n\n /**\n * Expiry time:\n * - \"0\" no expiration (default)\n * - \"<n>\" unix timestamp\n * - \"+<n>\" expire <n> seconds from now (min 5s)\n */\n expiretm?: string;\n}\n\n/**\n * Top-level params for AddOrderBatch.\n *\n * All orders must be for the same pair.\n */\nexport interface KrakenAddOrderBatchParams {\n /**\n * List of orders to place.\n * Must contain between 2 and 15 orders.\n */\n orders: KrakenAddOrderBatchOrderParams[];\n\n /**\n * Asset pair id or altname (e.g. \"XBTUSD\").\n * All orders in the batch will use this pair.\n */\n pair: string;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * e.g. \"tokenized_asset\".\n */\n asset_class?: 'tokenized_asset';\n\n /**\n * RFC3339 timestamp after which the matching engine\n * should reject the batch (latency / queuing protection).\n *\n * min now()+2s, max now()+60s.\n */\n deadline?: string;\n\n /**\n * If true, validate inputs only and do not actually\n * submit the orders.\n */\n validate?: boolean;\n}\n\n/**\n * Description of an individual order in the batch result.\n */\nexport interface KrakenAddOrderBatchOrderDescription {\n /** Order description text. */\n order: string;\n}\n\n/**\n * Result for a single order inside the batch.\n *\n * Notes:\n * - `error` is set if that individual order failed (while others may succeed).\n * - `txid` is set if that individual order was accepted.\n */\nexport interface KrakenAddOrderBatchOrderResult {\n descr: KrakenAddOrderBatchOrderDescription;\n error?: string;\n txid?: string;\n}\n\n/**\n * Full result payload for AddOrderBatch.\n *\n * The order of elements in `orders` matches the order\n * of the `orders` array sent in the request.\n */\nexport interface KrakenAddOrderBatchResult {\n orders: KrakenAddOrderBatchOrderResult[];\n}\n\n/**\n * POST /0/private/AddOrderBatch\n *\n * Send a batch of orders (2–15) for a single pair.\n *\n * Notes:\n * - Validation is performed on the whole batch before engine submission.\n * - On engine submission, failing orders are rejected individually.\n * - All orders must be for the same `pair`.\n * - `nonce` & signing handled by KrakenRestBase.\n */\nexport function addOrderBatch(\n base: KrakenRestBase,\n params: KrakenAddOrderBatchParams,\n): Promise<KrakenAddOrderBatchResult> {\n const { orders, pair, asset_class, deadline, validate } = params;\n\n if (!Array.isArray(orders) || orders.length < 2 || orders.length > 15) {\n throw new Error(\n `KrakenAddOrderBatchParams: orders must contain between 2 and 15 items (got ${orders.length})`,\n );\n }\n\n // Enforce userref vs cl_ord_id exclusivity per order (runtime)\n for (const [index, o] of orders.entries()) {\n if (o.userref !== undefined && o.cl_ord_id !== undefined) {\n throw new Error(\n `KrakenAddOrderBatchParams: order[${index}] cannot have both userref and cl_ord_id`,\n );\n }\n }\n\n const body: Record<string, string> = {\n pair,\n };\n\n if (asset_class) {\n body.asset_class = asset_class;\n }\n\n if (deadline !== undefined) {\n body.deadline = deadline;\n }\n\n if (validate !== undefined) {\n body.validate = validate ? 'true' : 'false';\n }\n\n // Kraken expects \"orders\" as a JSON-encoded array in the POST body.\n const wireOrders = orders.map((o) => {\n const wire: Record<string, string> = {\n ordertype: o.ordertype,\n type: o.type,\n volume: o.volume,\n };\n\n if (o.userref !== undefined) {\n wire.userref = String(o.userref);\n }\n if (o.cl_ord_id !== undefined) {\n wire.cl_ord_id = o.cl_ord_id;\n }\n if (o.displayvol !== undefined) {\n wire.displayvol = o.displayvol;\n }\n if (o.price !== undefined) {\n wire.price = o.price;\n }\n if (o.price2 !== undefined) {\n wire.price2 = o.price2;\n }\n if (o.trigger !== undefined) {\n wire.trigger = o.trigger;\n }\n if (o.leverage !== undefined) {\n wire.leverage = o.leverage;\n }\n if (o.reduce_only !== undefined) {\n wire.reduce_only = o.reduce_only ? 'true' : 'false';\n }\n if (o.stptype !== undefined) {\n wire.stptype = o.stptype;\n }\n if (o.oflags !== undefined) {\n wire.oflags = o.oflags;\n }\n if (o.timeinforce !== undefined) {\n wire.timeinforce = o.timeinforce;\n }\n if (o.starttm !== undefined) {\n wire.starttm = o.starttm;\n }\n if (o.expiretm !== undefined) {\n wire.expiretm = o.expiretm;\n }\n\n return wire;\n });\n\n body.orders = JSON.stringify(wireOrders);\n\n return base.privatePost<KrakenAddOrderBatchResult>(\n '/0/private/AddOrderBatch',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenCancelOrderResult } from './cancelOrder';\n\n/**\n * Single cancel entry by txid or userref.\n *\n * The API uses the same `txid` field for both Kraken order ids\n * and user references (integers).\n */\nexport interface KrakenCancelOrderBatchOrderRef {\n /**\n * Kraken order transaction ID (txid) OR user reference (userref).\n *\n * We accept number (for userref) or string and stringify before\n * sending to Kraken.\n */\n txid: string | number;\n}\n\n/**\n * Parameters for CancelOrderBatch.\n *\n * - `orders` is an array of objects containing txid/userref.\n * - `clOrdIds` is a flat array of client order IDs.\n *\n * Total unique IDs across both must be <= 50.\n */\nexport interface KrakenCancelOrderBatchParams {\n /**\n * Open order transaction IDs (txid) or user references (userref),\n * up to a maximum of 50 total unique IDs/references.\n */\n orders?: KrakenCancelOrderBatchOrderRef[];\n\n /**\n * Client order identifiers, up to a maximum of 50 total\n * unique IDs/references.\n */\n clOrdIds?: string[];\n}\n\n/**\n * Result payload for CancelOrderBatch.\n *\n * Kraken docs describe the same semantics as CancelOrder:\n * - `count`: number of orders cancelled\n * - `pending`: if true, cancels are still pending\n */\nexport type KrakenCancelOrderBatchResult = KrakenCancelOrderResult;\n\n/**\n * POST /0/private/CancelOrderBatch\n *\n * Cancel multiple open orders by txid/userref or cl_ord_id.\n *\n * Notes:\n * - Max 50 total unique IDs/references across both arrays.\n * - `nonce` & signing handled by KrakenRestBase.\n */\nexport function cancelOrderBatch(\n base: KrakenRestBase,\n params: KrakenCancelOrderBatchParams,\n): Promise<KrakenCancelOrderBatchResult> {\n const { orders, clOrdIds } = params;\n\n const countOrders = orders?.length ?? 0;\n const countClOrdIds = clOrdIds?.length ?? 0;\n const total = countOrders + countClOrdIds;\n\n if (total === 0) {\n throw new Error(\n 'KrakenCancelOrderBatchParams: at least one txid/userref or cl_ord_id is required',\n );\n }\n\n if (total > 50) {\n throw new Error(\n `KrakenCancelOrderBatchParams: maximum 50 total ids/references allowed, got ${total}`,\n );\n }\n\n const body: Record<string, string> = {};\n\n if (orders && orders.length > 0) {\n // API expects: orders=[{txid:<string>}, ...] JSON-encoded\n const wireOrders = orders.map((o) => ({\n txid: String(o.txid),\n }));\n\n body.orders = JSON.stringify(wireOrders);\n }\n\n if (clOrdIds && clOrdIds.length > 0) {\n // API expects: cl_ord_ids=[{cl_ord_id:<string>}, ...] JSON-encoded\n const wireClOrdIds = clOrdIds.map((id) => ({\n cl_ord_id: id,\n }));\n\n body.cl_ord_ids = JSON.stringify(wireClOrdIds);\n }\n\n return base.privatePost<KrakenCancelOrderBatchResult>(\n '/0/private/CancelOrderBatch',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Parameters to edit an existing live order.\n *\n * Notes / caveats (per Kraken docs):\n * - triggered stop-loss / take-profit orders are NOT supported\n * - orders with conditional close terms are NOT supported\n * - orders where executed volume > new volume will be rejected\n * - cl_ord_id is NOT supported\n * - queue position is NOT maintained\n * - executions remain associated with original order\n */\nexport interface KrakenEditOrderParams {\n /**\n * Original Order ID (txid) or userref of the original order.\n *\n * If userref is not unique and was used with multiple orders,\n * the edit request will be rejected.\n */\n txid: string | number;\n\n /**\n * Optional user reference for this *edit request*.\n *\n * Note: userref from parent order is NOT retained on the\n * new order after edit. This is only for the edit itself.\n */\n userref?: number;\n\n /**\n * New order quantity in terms of the base asset.\n * Optional – omit to keep original volume.\n */\n volume?: string;\n\n /**\n * For iceberg orders only, defines the quantity to show in\n * the book. Minimum = 1/15 of volume.\n */\n displayvol?: string;\n\n /**\n * Asset pair id or altname (e.g. \"XBTUSD\").\n */\n pair: string;\n\n /**\n * Required for non-crypto pairs (xstocks).\n * e.g. \"tokenized_asset\".\n */\n asset_class?: 'tokenized_asset';\n\n /**\n * New price:\n * - Limit price for limit/iceberg\n * - Trigger price for stop/TP/trailing types\n *\n * Relative formats (+, -, #, %) supported by Kraken.\n */\n price?: string;\n\n /**\n * New secondary price for *-limit order types:\n * - Limit price for stop-loss-limit, take-profit-limit,\n * trailing-stop-limit.\n */\n price2?: string;\n\n /**\n * Comma-delimited list of order flags.\n *\n * Only these can actually be changed by EditOrder:\n * - post (post-only)\n *\n * All other flags from the parent order are retained.\n * If you want the edited order to remain post-only,\n * you must explicitly include \"post\".\n */\n oflags?: string;\n\n /**\n * RFC3339 timestamp after which the matching engine should\n * reject the edit request in presence of latency/queuing.\n *\n * Example: \"2021-04-01T00:18:45Z\"\n * min now()+2s, max now()+60s.\n */\n deadline?: string;\n\n /**\n * If true, the API may return a \"pending replace\" response\n * before the order is fully replaced.\n */\n cancel_response?: boolean;\n\n /**\n * If true, validate inputs only and do not actually submit\n * the edited order.\n */\n validate?: boolean;\n}\n\n/**\n * Description of the edited order.\n */\nexport interface KrakenEditOrderDescription {\n /** Order description text */\n order: string;\n}\n\n/**\n * Result payload for EditOrder.\n */\nexport interface KrakenEditOrderResult {\n /** Description info of the new order */\n descr: KrakenEditOrderDescription;\n\n /** New transaction ID (if edit succeeded and order created) */\n txid?: string;\n\n /** New userref if specified on the edit request */\n newuserref?: string;\n\n /** Original userref (from parent order) if present */\n olduserref?: string;\n\n /** Number of orders cancelled (0 or 1) */\n orders_cancelled: number;\n\n /** Original transaction ID */\n originaltxid: string;\n\n /** Status of the edit, e.g. \"Ok\" or \"Err\" */\n status: string;\n\n /** Updated volume (if provided) */\n volume?: string;\n\n /** Updated price (if provided) */\n price?: string;\n\n /** Updated secondary price (if provided) */\n price2?: string;\n\n /** Error message if unsuccessful */\n error_message?: string;\n}\n\n/**\n * POST /0/private/EditOrder\n *\n * Edit an existing live order by cancelling the original and\n * creating a new order with adjusted parameters.\n *\n * Notes:\n * - Prefer /0/private/AmendOrder for new integrations when possible.\n * - `nonce` & signing handled by KrakenRestBase.\n * - Requires both:\n * - \"Create & modify orders\"\n * - \"Cancel & close orders\"\n */\nexport function editOrder(\n base: KrakenRestBase,\n params: KrakenEditOrderParams,\n): Promise<KrakenEditOrderResult> {\n const body: Record<string, string> = {\n txid: String(params.txid),\n pair: params.pair,\n };\n\n if (params.userref !== undefined) {\n body.userref = String(params.userref);\n }\n\n if (params.volume !== undefined) {\n body.volume = params.volume;\n }\n\n if (params.displayvol !== undefined) {\n body.displayvol = params.displayvol;\n }\n\n if (params.asset_class !== undefined) {\n body.asset_class = params.asset_class;\n }\n\n if (params.price !== undefined) {\n body.price = params.price;\n }\n\n if (params.price2 !== undefined) {\n body.price2 = params.price2;\n }\n\n if (params.oflags !== undefined) {\n body.oflags = params.oflags;\n }\n\n if (params.deadline !== undefined) {\n body.deadline = params.deadline;\n }\n\n if (params.cancel_response !== undefined) {\n body.cancel_response = params.cancel_response ? 'true' : 'false';\n }\n\n if (params.validate !== undefined) {\n body.validate = params.validate ? 'true' : 'false';\n }\n\n return base.privatePost<KrakenEditOrderResult>('/0/private/EditOrder', body);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as AddOrder from './addOrder';\nimport * as AmendOrder from './amendOrder';\nimport * as CancelOrder from './cancelOrder';\nimport * as CancelAllOrders from './cancelAllOrders';\nimport * as CancelAllOrdersAfter from './cancelAllOrdersAfter';\nimport * as GetWebSocketsToken from './getWebSocketsToken';\nimport * as AddOrderBatch from './addOrderBatch';\nimport * as CancelOrderBatch from './cancelOrderBatch';\nimport * as EditOrder from './editOrder';\n\nexport class KrakenSpotTradingApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Place a new order.\n *\n * @example\n * const result = await kraken.trading.addOrder({\n * pair: \"XBTUSD\",\n * type: \"buy\",\n * ordertype: \"limit\",\n * volume: \"0.01\",\n * price: \"40000\",\n * timeinforce: \"GTC\",\n * });\n *\n * console.log(result.descr.order, result.txid);\n */\n addOrder(params: AddOrder.KrakenAddOrderParams) {\n return AddOrder.addOrder(this.base, params);\n }\n\n /**\n * Amend an existing order in-place.\n *\n * @example\n * // Reduce quantity + move limit price:\n * const result = await kraken.trading.amendOrder({\n * txid: \"OABCDEFGHIJKL\",\n * order_qty: \"0.005\",\n * limit_price: \"39500\",\n * });\n *\n * console.log(\"Amend ID:\", result.amend_id);\n */\n amendOrder(params: AmendOrder.KrakenAmendOrderParams) {\n return AmendOrder.amendOrder(this.base, params);\n }\n\n /**\n * Cancel open orders by txid, userref, or cl_ord_id.\n *\n * @example\n * // By single txid\n * const res1 = await kraken.trading.cancelOrder({\n * txid: \"OABCDEFGHIJKL\",\n * });\n *\n * // By multiple txids\n * const res2 = await kraken.trading.cancelOrder({\n * txid: [\"OAAAA...\", \"OBBBB...\"],\n * });\n *\n * // By userref\n * const res3 = await kraken.trading.cancelOrder({\n * userref: 123456,\n * });\n *\n * // By client order id\n * const res4 = await kraken.trading.cancelOrder({\n * cl_ord_id: \"arb-20240509-00010\",\n * });\n */\n cancelOrder(params: CancelOrder.KrakenCancelOrderParams) {\n return CancelOrder.cancelOrder(this.base, params);\n }\n\n /**\n * Cancel all open orders for this account.\n *\n * @example\n * const res = await kraken.trading.cancelAllOrders();\n * console.log(\"Cancelled count:\", res.count, \"pending:\", res.pending);\n */\n cancelAllOrders() {\n return CancelAllOrders.cancelAllOrders(this.base);\n }\n\n /**\n * Set or extend the \"Dead Man's Switch\" timer that will\n * cancel all open orders after `timeout` seconds.\n *\n * Pass `timeout = 0` to disable the timer.\n *\n * @example\n * // Typical pattern: call every 15–30s with timeout=60\n * const result = await kraken.trading.cancelAllOrdersAfter({\n * timeout: 60,\n * });\n *\n * console.log(\"Current:\", result.currentTime);\n * console.log(\"Trigger:\", result.triggerTime);\n */\n cancelAllOrdersAfter(\n params: CancelAllOrdersAfter.KrakenCancelAllOrdersAfterParams,\n ) {\n return CancelAllOrdersAfter.cancelAllOrdersAfter(this.base, params);\n }\n\n /**\n * Get a WebSockets authentication token for private WS API.\n *\n * Typical flow:\n * 1. Call this REST endpoint to get { token, expires }.\n * 2. Use `token` when authenticating your WebSocket connection.\n * 3. Ensure \"WebSocket interface\" is enabled on your API key.\n *\n * @example\n * const { token, expires } = await kraken.accountData.getWebSocketsToken();\n * console.log(\"WS token:\", token, \"expires in:\", expires, \"seconds\");\n */\n getWebSocketsToken() {\n return GetWebSocketsToken.getWebSocketsToken(this.base);\n }\n\n /**\n * Place a batch of orders (2–15) for a single pair.\n *\n * @example\n * const result = await kraken.trading.addOrderBatch({\n * pair: \"XBTUSD\",\n * orders: [\n * {\n * type: \"buy\",\n * ordertype: \"limit\",\n * volume: \"0.01\",\n * price: \"40000\",\n * },\n * {\n * type: \"sell\",\n * ordertype: \"limit\",\n * volume: \"0.01\",\n * price: \"45000\",\n * },\n * ],\n * });\n *\n * for (const o of result.orders) {\n * console.log(o.descr.order, o.txid, o.error);\n * }\n */\n addOrderBatch(params: AddOrderBatch.KrakenAddOrderBatchParams) {\n return AddOrderBatch.addOrderBatch(this.base, params);\n }\n\n /**\n * Cancel multiple open orders by txid/userref or cl_ord_id.\n *\n * @example\n * const res = await kraken.trading.cancelOrderBatch({\n * orders: [\n * { txid: \"OABCDEF...\" }, // by Kraken order id\n * { txid: 12345 }, // by userref\n * ],\n * clOrdIds: [\"arb-20240509-00010\"],\n * });\n *\n * console.log(\"Cancelled:\", res.count, \"pending:\", res.pending);\n */\n cancelOrderBatch(params: CancelOrderBatch.KrakenCancelOrderBatchParams) {\n return CancelOrderBatch.cancelOrderBatch(this.base, params);\n }\n\n /**\n * Edit an existing live order.\n *\n * Under the hood this:\n * - cancels the original order\n * - creates a new order with adjusted parameters\n * - returns the new txid and original txid\n *\n * Caveats (per Kraken):\n * - does NOT preserve queue position\n * - does NOT support orders with conditional closes\n * - does NOT support triggered stop-loss / take-profit orders\n *\n * Prefer {@link amendOrder} where possible.\n *\n * @example\n * const res = await kraken.trading.editOrder({\n * txid: \"OABCDEFGHIJKL\",\n * pair: \"XBTUSD\",\n * price: \"40100\",\n * volume: \"0.01\",\n * });\n *\n * console.log(\"New txid:\", res.txid, \"original:\", res.originaltxid);\n */\n editOrder(params: EditOrder.KrakenEditOrderParams) {\n return EditOrder.editOrder(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenAddOrderParams = AddOrder.KrakenAddOrderParams;\nexport type KrakenAddOrderResult = AddOrder.KrakenAddOrderResult;\nexport type KrakenAddOrderDescription = AddOrder.KrakenAddOrderDescription;\nexport type KrakenAddOrderTimeInForce = AddOrder.KrakenAddOrderTimeInForce;\nexport type KrakenAddOrderStpType = AddOrder.KrakenAddOrderStpType;\n\nexport type KrakenAmendOrderParams = AmendOrder.KrakenAmendOrderParams;\nexport type KrakenAmendOrderResult = AmendOrder.KrakenAmendOrderResult;\n\nexport type KrakenCancelOrderParams = CancelOrder.KrakenCancelOrderParams;\nexport type KrakenCancelOrderResult = CancelOrder.KrakenCancelOrderResult;\n\nexport type KrakenCancelAllOrdersResult =\n CancelAllOrders.KrakenCancelAllOrdersResult;\n\nexport type KrakenCancelAllOrdersAfterParams =\n CancelAllOrdersAfter.KrakenCancelAllOrdersAfterParams;\nexport type KrakenCancelAllOrdersAfterResult =\n CancelAllOrdersAfter.KrakenCancelAllOrdersAfterResult;\n\nexport type KrakenGetWebSocketsTokenResult =\n GetWebSocketsToken.KrakenGetWebSocketsTokenResult;\n\nexport type KrakenAddOrderBatchOrderParams =\n AddOrderBatch.KrakenAddOrderBatchOrderParams;\nexport type KrakenAddOrderBatchParams = AddOrderBatch.KrakenAddOrderBatchParams;\nexport type KrakenAddOrderBatchOrderDescription =\n AddOrderBatch.KrakenAddOrderBatchOrderDescription;\nexport type KrakenAddOrderBatchOrderResult =\n AddOrderBatch.KrakenAddOrderBatchOrderResult;\nexport type KrakenAddOrderBatchResult = AddOrderBatch.KrakenAddOrderBatchResult;\n\nexport type KrakenCancelOrderBatchOrderRef =\n CancelOrderBatch.KrakenCancelOrderBatchOrderRef;\nexport type KrakenCancelOrderBatchParams =\n CancelOrderBatch.KrakenCancelOrderBatchParams;\nexport type KrakenCancelOrderBatchResult =\n CancelOrderBatch.KrakenCancelOrderBatchResult;\n\nexport type KrakenEditOrderParams = EditOrder.KrakenEditOrderParams;\nexport type KrakenEditOrderResult = EditOrder.KrakenEditOrderResult;\nexport type KrakenEditOrderDescription = EditOrder.KrakenEditOrderDescription;\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Parameters for GetDepositMethods.\n */\nexport interface KrakenGetDepositMethodsParams {\n asset: string;\n aclass?: 'currency' | 'tokenized_asset';\n rebase_multiplier?: 'rebased' | 'base';\n}\n\n/**\n * Single deposit method entry.\n *\n * Note: some keys use hyphens as in Kraken's API response\n * and must be accessed with bracket notation.\n */\nexport interface KrakenDepositMethod {\n method: string;\n limit: string | boolean;\n fee: string;\n 'address-setup-fee': string;\n 'gen-address': boolean;\n minimum: string;\n}\n\n/**\n * KrakenRestBase.privatePost unwraps { error, result } and returns `result`,\n * so this endpoint returns the array directly.\n */\nexport type KrakenGetDepositMethodsResult = KrakenDepositMethod[];\n\n/**\n * POST /0/private/DepositMethods\n */\nexport function getDepositMethods(\n base: KrakenRestBase,\n params: KrakenGetDepositMethodsParams,\n): Promise<KrakenGetDepositMethodsResult> {\n const body: Record<string, string> = {\n asset: params.asset,\n };\n\n if (params.aclass !== undefined) {\n body.aclass = params.aclass;\n }\n\n if (params.rebase_multiplier !== undefined) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenGetDepositMethodsResult>(\n '/0/private/DepositMethods',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\n/**\n * Parameters for GetDepositAddresses.\n */\nexport interface KrakenGetDepositAddressesParams {\n asset: string;\n aclass?: 'currency' | 'tokenized_asset';\n method: string;\n new?: boolean;\n amount?: string | number;\n}\n\n/**\n * Single deposit address entry.\n */\nexport interface KrakenDepositAddress {\n address: string;\n expiretm: string;\n new: boolean;\n tag?: string;\n}\n\n/**\n * Result payload for GetDepositAddresses.\n *\n * KrakenRestBase.privatePost unwraps { error, result } and returns `result`,\n * so this endpoint returns the array directly.\n */\nexport type KrakenGetDepositAddressesResult = KrakenDepositAddress[];\n\n/**\n * POST /0/private/DepositAddresses\n *\n * Retrieve (or generate) deposit addresses for a given asset\n * and deposit method.\n */\nexport function getDepositAddresses(\n base: KrakenRestBase,\n params: KrakenGetDepositAddressesParams,\n): Promise<KrakenGetDepositAddressesResult> {\n const body: Record<string, string> = {\n asset: params.asset,\n method: params.method,\n };\n\n if (params.aclass !== undefined) {\n body.aclass = params.aclass;\n }\n\n if (params.new !== undefined) {\n body.new = params.new ? 'true' : 'false';\n }\n\n if (params.amount !== undefined) {\n body.amount = String(params.amount);\n }\n\n return base.privatePost<KrakenGetDepositAddressesResult>(\n '/0/private/DepositAddresses',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenRebaseMultiplier = 'rebased' | 'base';\n\nexport interface KrakenGetDepositStatusParams {\n asset?: string;\n aclass?: 'currency' | 'tokenized_asset';\n method?: string;\n start?: number | string;\n end?: number | string;\n\n /**\n * Cursor token returned from a previous response.\n * (Kraken uses this for pagination.)\n */\n cursor?: string;\n\n limit?: number;\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\nexport interface KrakenDepositStatusEntry {\n method: string;\n aclass: string;\n asset: string;\n refid: string;\n txid: string;\n info: string;\n amount: string;\n fee: string;\n time: number;\n status: string;\n 'status-prop'?: 'return' | 'onhold';\n originators?: string[];\n}\n\n/**\n * POST /0/private/DepositStatus\n *\n * Retrieve information about recent deposits.\n */\nexport function getDepositStatus(\n base: KrakenRestBase,\n params: KrakenGetDepositStatusParams = {},\n): Promise<KrakenDepositStatusEntry[]> {\n const body: Record<string, string> = {};\n\n if (params.asset) body.asset = params.asset;\n if (params.aclass) body.aclass = params.aclass;\n if (params.method) body.method = params.method;\n\n if (params.start !== undefined) body.start = String(params.start);\n if (params.end !== undefined) body.end = String(params.end);\n\n if (params.cursor) body.cursor = params.cursor;\n\n if (params.limit !== undefined) body.limit = String(params.limit);\n\n if (params.rebase_multiplier) {\n body.rebase_multiplier = params.rebase_multiplier;\n }\n\n return base.privatePost<KrakenDepositStatusEntry[]>(\n '/0/private/DepositStatus',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getDepositStatus';\n\nexport interface KrakenGetWithdrawMethodsParams {\n asset: string;\n aclass?: 'currency' | 'tokenized_asset';\n network?: string;\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\nexport interface KrakenWithdrawMethod {\n asset: string;\n method: string;\n network: string;\n minimum: string;\n}\n\nexport type KrakenGetWithdrawMethodsResult = KrakenWithdrawMethod[];\n\n/**\n * POST /0/private/WithdrawMethods\n */\nexport function getWithdrawMethods(\n base: KrakenRestBase,\n params: KrakenGetWithdrawMethodsParams,\n): Promise<KrakenGetWithdrawMethodsResult> {\n const body: Record<string, string> = {\n asset: params.asset,\n };\n\n if (params.aclass) body.aclass = params.aclass;\n if (params.network) body.network = params.network;\n if (params.rebase_multiplier)\n body.rebase_multiplier = params.rebase_multiplier;\n\n return base.privatePost<KrakenGetWithdrawMethodsResult>(\n '/0/private/WithdrawMethods',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenGetWithdrawAddressesParams {\n asset: string;\n aclass?: 'currency' | 'tokenized_asset';\n method?: string;\n key?: string;\n verified?: boolean;\n}\n\nexport interface KrakenWithdrawAddress {\n address: string;\n asset: string;\n method: string;\n key: string;\n tag?: string;\n verified: boolean;\n}\n\nexport type KrakenGetWithdrawAddressesResult = KrakenWithdrawAddress[];\n\n/**\n * POST /0/private/WithdrawAddresses\n */\nexport function getWithdrawAddresses(\n base: KrakenRestBase,\n params: KrakenGetWithdrawAddressesParams,\n): Promise<KrakenGetWithdrawAddressesResult> {\n const body: Record<string, string> = {\n asset: params.asset,\n };\n\n if (params.aclass) body.aclass = params.aclass;\n if (params.method) body.method = params.method;\n if (params.key) body.key = params.key;\n if (params.verified !== undefined) {\n body.verified = params.verified ? 'true' : 'false';\n }\n\n return base.privatePost<KrakenGetWithdrawAddressesResult>(\n '/0/private/WithdrawAddresses',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenGetWithdrawInfoParams {\n asset: string;\n key: string;\n amount: string | number;\n}\n\nexport interface KrakenWithdrawInfo {\n method: string;\n limit: string;\n amount: string;\n fee: string;\n}\n\nexport type KrakenGetWithdrawInfoResult = KrakenWithdrawInfo;\n\n/**\n * POST /0/private/WithdrawInfo\n */\nexport function getWithdrawInfo(\n base: KrakenRestBase,\n params: KrakenGetWithdrawInfoParams,\n): Promise<KrakenGetWithdrawInfoResult> {\n const body: Record<string, string> = {\n asset: params.asset,\n key: params.key,\n amount: String(params.amount),\n };\n\n return base.privatePost<KrakenGetWithdrawInfoResult>(\n '/0/private/WithdrawInfo',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getDepositStatus';\n\nexport interface KrakenWithdrawFundsParams {\n asset: string;\n aclass?: 'currency' | 'tokenized_asset';\n key: string;\n address?: string;\n amount: string | number;\n max_fee?: string | number;\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\nexport interface KrakenWithdrawFundsResult {\n refid: string;\n}\n\nexport type KrakenWithdrawFundsResponse = KrakenWithdrawFundsResult;\n\n/**\n * POST /0/private/Withdraw\n */\nexport function withdrawFunds(\n base: KrakenRestBase,\n params: KrakenWithdrawFundsParams,\n): Promise<KrakenWithdrawFundsResponse> {\n const { asset, aclass, key, address, amount, max_fee, rebase_multiplier } =\n params;\n\n const body: Record<string, string> = {\n asset,\n key,\n amount: String(amount),\n };\n\n if (aclass) body.aclass = aclass;\n if (address) body.address = address;\n if (max_fee !== undefined) body.max_fee = String(max_fee);\n if (rebase_multiplier) body.rebase_multiplier = rebase_multiplier;\n\n return base.privatePost<KrakenWithdrawFundsResponse>(\n '/0/private/Withdraw',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport type { KrakenRebaseMultiplier } from './getDepositStatus';\n\nexport interface KrakenGetWithdrawStatusParams {\n /**\n * Filter for specific asset being withdrawn (e.g. \"USDT\", \"XBT\").\n */\n asset?: string;\n\n /**\n * Filter for specific asset class being withdrawn.\n * Defaults to \"currency\" on Kraken if omitted.\n */\n aclass?: 'currency' | 'tokenized_asset';\n\n /**\n * Filter for specific name of withdrawal method.\n */\n method?: string;\n\n /**\n * Start timestamp. Withdrawals created strictly before this\n * will NOT be included in the response.\n *\n * Unix timestamp (seconds) or a string accepted by Kraken.\n */\n start?: number | string;\n\n /**\n * End timestamp. Withdrawals created strictly after this\n * will NOT be included in the response.\n *\n * Unix timestamp (seconds) or a string accepted by Kraken.\n */\n end?: number | string;\n\n /**\n * Pagination control:\n * - boolean: true/false to enable/disable paginated response\n * - string: cursor for next page of results\n *\n * Default on Kraken is false (no pagination) if omitted.\n */\n cursor?: boolean | string;\n\n /**\n * Number of results to include per page.\n * Default on Kraken is 500 if omitted.\n */\n limit?: number;\n\n /**\n * Optional parameter for viewing xstocks data.\n * - \"rebased\": Display in terms of underlying equity.\n * - \"base\": Display in terms of SPV tokens.\n *\n * Defaults to \"rebased\" on Kraken if omitted.\n */\n rebase_multiplier?: KrakenRebaseMultiplier;\n}\n\nexport interface KrakenWithdrawStatusEntry {\n /**\n * Name of withdrawal method.\n */\n method: string;\n\n /**\n * Network name based on the funding method used.\n */\n network: string;\n\n /**\n * Asset class.\n */\n aclass: string;\n\n /**\n * Asset.\n */\n asset: string;\n\n /**\n * Reference ID.\n */\n refid: string;\n\n /**\n * Method transaction ID.\n */\n txid: string;\n\n /**\n * Method transaction information.\n */\n info: string;\n\n /**\n * Amount withdrawn.\n */\n amount: string;\n\n /**\n * Fees paid.\n */\n fee: string;\n\n /**\n * Unix timestamp when request was made.\n */\n time: number;\n\n /**\n * Status of withdrawal (see IFEX financial transaction states).\n *\n * Known values: \"Initial\", \"Pending\", \"Settled\", \"Success\", \"Failure\".\n */\n status: string;\n\n /**\n * Additional status properties (if available):\n * - \"cancel-pending\": cancellation requested\n * - \"canceled\": canceled\n * - \"cancel-denied\": cancellation requested but was denied\n * - \"return\": a return transaction initiated by Kraken; cannot be canceled\n * - \"onhold\": withdrawal is on hold pending review\n */\n 'status-prop'?:\n | 'cancel-pending'\n | 'canceled'\n | 'cancel-denied'\n | 'return'\n | 'onhold';\n\n /**\n * Withdrawal key name, as set up on your account.\n */\n key: string;\n}\n\n/**\n * Kraken returns an array of withdrawal-status objects as `result`.\n */\nexport type KrakenGetWithdrawStatusResult = KrakenWithdrawStatusEntry[];\n\n/**\n * Retrieve information about recent withdrawals.\n *\n * Results are sorted by recency. Use `cursor`, `start`, `end` and `limit`\n * to iterate through the history.\n *\n * Kraken docs: POST /0/private/WithdrawStatus\n */\nexport async function getWithdrawStatus(\n base: KrakenRestBase,\n params: KrakenGetWithdrawStatusParams = {},\n): Promise<KrakenGetWithdrawStatusResult> {\n const {\n asset,\n aclass,\n method,\n start,\n end,\n cursor,\n limit,\n rebase_multiplier,\n } = params;\n\n const body: Record<string, string | number | boolean> = {};\n\n if (asset) body.asset = asset;\n if (aclass) body.aclass = aclass;\n if (method) body.method = method;\n if (start !== undefined) body.start = start;\n if (end !== undefined) body.end = end;\n if (cursor !== undefined) {\n body.cursor = cursor;\n }\n if (limit !== undefined) body.limit = limit;\n if (rebase_multiplier) body.rebase_multiplier = rebase_multiplier;\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenGetWithdrawStatusResult>(\n '/0/private/WithdrawStatus',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenWithdrawCancelParams {\n asset: string;\n refid: string;\n}\n\nexport type KrakenWithdrawCancelResult = boolean;\n\n/**\n * POST /0/private/WithdrawCancel\n */\nexport function withdrawCancel(\n base: KrakenRestBase,\n params: KrakenWithdrawCancelParams,\n): Promise<KrakenWithdrawCancelResult> {\n const { asset, refid } = params;\n\n const body: Record<string, string> = {\n asset,\n refid,\n };\n\n return base.privatePost<KrakenWithdrawCancelResult>(\n '/0/private/WithdrawCancel',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenWalletTransferSource = 'Spot Wallet';\nexport type KrakenWalletTransferDestination = 'Futures Wallet';\n\nexport interface KrakenWalletTransferParams {\n asset: string;\n from: KrakenWalletTransferSource;\n to: KrakenWalletTransferDestination;\n amount: string | number;\n}\n\nexport interface KrakenWalletTransferResult {\n refid: string;\n}\n\n/**\n * POST /0/private/WalletTransfer\n */\nexport function walletTransfer(\n base: KrakenRestBase,\n params: KrakenWalletTransferParams,\n): Promise<KrakenWalletTransferResult> {\n const { asset, from, to, amount } = params;\n\n const body: Record<string, string> = {\n asset,\n from,\n to,\n amount: String(amount),\n };\n\n return base.privatePost<KrakenWalletTransferResult>(\n '/0/private/WalletTransfer',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as GetDepositMethods from './getDepositMethods';\nimport * as GetDepositAddresses from './getDepositAddresses';\nimport * as GetDepositStatus from './getDepositStatus';\nimport * as GetWithdrawMethods from './getWithdrawMethods';\nimport * as GetWithdrawAddresses from './getWithdrawAddresses';\nimport * as GetWithdrawInfo from './getWithdrawInfo';\nimport * as WithdrawFunds from './withdrawFunds';\nimport * as GetWithdrawStatus from './getWithdrawStatus';\nimport * as WithdrawCancel from './withdrawCancel';\nimport * as WalletTransfer from './walletTransfer';\n\n/**\n * Kraken Spot Funding API.\n *\n * Covers deposit / withdrawal–related endpoints (methods,\n * addresses, status, etc.).\n */\nexport class KrakenSpotFundingApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Retrieve deposit methods available for a particular asset.\n *\n * @example\n * ```ts\n * const methods = await kraken.funding.getDepositMethods({\n * asset: \"USDT\",\n * });\n *\n * for (const m of methods.result) {\n * console.log(\n * m.method,\n * \"min:\", m.minimum,\n * \"limit:\", m.limit,\n * \"fee:\", m.fee,\n * );\n * }\n * ```\n */\n getDepositMethods(params: GetDepositMethods.KrakenGetDepositMethodsParams) {\n return GetDepositMethods.getDepositMethods(this.base, params);\n }\n\n /**\n * Retrieve (or generate) deposit addresses for a particular\n * asset and deposit method.\n *\n * @example\n * ```ts\n * const res = await kraken.funding.getDepositAddresses({\n * asset: \"USDT\",\n * method: \"USDT (Tether ERC20)\",\n * new: false,\n * });\n *\n * for (const addr of res.result) {\n * console.log(addr.address, \"expires:\", addr.expiretm, \"new:\", addr.new);\n * }\n * ```\n */\n getDepositAddresses(\n params: GetDepositAddresses.KrakenGetDepositAddressesParams,\n ) {\n return GetDepositAddresses.getDepositAddresses(this.base, params);\n }\n\n /**\n * Retrieve information about recent deposits.\n * Results are sorted by recency. Use `cursor`, `start`, `end` and `limit`\n * to iterate through the history.\n * @example\n * ```ts\n * const deposits = await kraken.funding.getDepositStatus({\n * asset: \"USDT\",\n * limit: 25,\n * });\n *\n * for (const d of deposits) {\n * console.log(d.asset, d.amount, d.status);\n * }\n * ```\n */\n getDepositStatus(params: GetDepositStatus.KrakenGetDepositStatusParams = {}) {\n return GetDepositStatus.getDepositStatus(this.base, params);\n }\n\n /**\n * Retrieve withdrawal methods available for a particular asset\n * (and optionally network).\n *\n * @example\n * ```ts\n * const methods = await kraken.funding.getWithdrawMethods({\n * asset: \"USDT\",\n * network: \"ERC20\",\n * });\n *\n * for (const m of methods) {\n * console.log(m.asset, m.method, m.network, \"min:\", m.minimum);\n * }\n * ```\n */\n getWithdrawMethods(\n params: GetWithdrawMethods.KrakenGetWithdrawMethodsParams,\n ) {\n return GetWithdrawMethods.getWithdrawMethods(this.base, params);\n }\n\n /**\n * Retrieve withdrawal addresses available for the user.\n *\n * @example\n * ```ts\n * const addresses = await kraken.funding.getWithdrawAddresses({\n * asset: \"USDT\",\n * method: \"USDT (Tether ERC20)\",\n * });\n *\n * for (const a of addresses) {\n * console.log(a.address, a.asset, a.method, a.key, a.verified);\n * }\n * ```\n */\n getWithdrawAddresses(\n params: GetWithdrawAddresses.KrakenGetWithdrawAddressesParams,\n ) {\n return GetWithdrawAddresses.getWithdrawAddresses(this.base, params);\n }\n\n /**\n * Retrieve fee information about a potential withdrawal for a given\n * asset, withdrawal key, and amount.\n *\n * @example\n * ```ts\n * const info = await kraken.funding.getWithdrawInfo({\n * asset: \"USDT\",\n * key: \"my-usdt-key\",\n * amount: \"100\",\n * });\n *\n * console.log(\n * \"method:\", info.method,\n * \"limit:\", info.limit,\n * \"net amount:\", info.amount,\n * \"fee:\", info.fee,\n * );\n * ```\n */\n getWithdrawInfo(params: GetWithdrawInfo.KrakenGetWithdrawInfoParams) {\n return GetWithdrawInfo.getWithdrawInfo(this.base, params);\n }\n\n /**\n * Make a withdrawal request.\n *\n * @example\n * ```ts\n * const res = await kraken.funding.withdrawFunds({\n * asset: \"USDT\",\n * key: \"my-usdt-key\",\n * amount: \"100\",\n * });\n *\n * console.log(\"withdrawal refid:\", res.refid);\n * ```\n */\n withdrawFunds(params: WithdrawFunds.KrakenWithdrawFundsParams) {\n return WithdrawFunds.withdrawFunds(this.base, params);\n }\n\n /**\n * Retrieve information about recent withdrawals.\n * Results are sorted by recency. Use `cursor`, `start`, `end` and `limit`\n * to iterate through the history.\n *\n * @example\n * ```ts\n * const withdrawals = await kraken.funding.getWithdrawStatus({\n * asset: \"USDT\",\n * limit: 100,\n * });\n *\n * for (const w of withdrawals) {\n * console.log(w.asset, w.amount, w.status, w.key);\n * }\n * ```\n */\n getWithdrawStatus(\n params: GetWithdrawStatus.KrakenGetWithdrawStatusParams = {},\n ) {\n return GetWithdrawStatus.getWithdrawStatus(this.base, params);\n }\n\n /**\n * Request cancellation of a recently requested withdrawal, if it has\n * not already been successfully processed.\n *\n * @example\n * ```ts\n * const ok = await kraken.funding.withdrawCancel({\n * asset: \"USDT\",\n * refid: \"ABC123-REFID\",\n * });\n *\n * console.log(\"cancellation success:\", ok);\n * ```\n */\n withdrawCancel(params: WithdrawCancel.KrakenWithdrawCancelParams) {\n return WithdrawCancel.withdrawCancel(this.base, params);\n }\n\n /**\n * Request a transfer from a Kraken spot wallet to a Kraken Futures wallet.\n *\n * @example\n * ```ts\n * const res = await kraken.funding.walletTransfer({\n * asset: \"USDT\",\n * from: \"Spot Wallet\",\n * to: \"Futures Wallet\",\n * amount: \"50\",\n * });\n *\n * console.log(\"wallet transfer refid:\", res.refid);\n * ```\n */\n walletTransfer(params: WalletTransfer.KrakenWalletTransferParams) {\n return WalletTransfer.walletTransfer(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenGetDepositMethodsParams =\n GetDepositMethods.KrakenGetDepositMethodsParams;\nexport type KrakenGetDepositMethodsResult =\n GetDepositMethods.KrakenGetDepositMethodsResult;\nexport type KrakenDepositMethod = GetDepositMethods.KrakenDepositMethod;\n\nexport type KrakenGetDepositAddressesParams =\n GetDepositAddresses.KrakenGetDepositAddressesParams;\nexport type KrakenGetDepositAddressesResult =\n GetDepositAddresses.KrakenGetDepositAddressesResult;\nexport type KrakenDepositAddress = GetDepositAddresses.KrakenDepositAddress;\n\nexport type KrakenGetDepositStatusParams =\n GetDepositStatus.KrakenGetDepositStatusParams;\nexport type KrakenDepositStatusEntry =\n GetDepositStatus.KrakenDepositStatusEntry;\n\nexport type KrakenGetWithdrawMethodsParams =\n GetWithdrawMethods.KrakenGetWithdrawMethodsParams;\nexport type KrakenGetWithdrawMethodsResult =\n GetWithdrawMethods.KrakenGetWithdrawMethodsResult;\nexport type KrakenWithdrawMethod = GetWithdrawMethods.KrakenWithdrawMethod;\n\nexport type KrakenGetWithdrawAddressesParams =\n GetWithdrawAddresses.KrakenGetWithdrawAddressesParams;\nexport type KrakenGetWithdrawAddressesResult =\n GetWithdrawAddresses.KrakenGetWithdrawAddressesResult;\nexport type KrakenWithdrawAddress = GetWithdrawAddresses.KrakenWithdrawAddress;\n\nexport type KrakenGetWithdrawInfoParams =\n GetWithdrawInfo.KrakenGetWithdrawInfoParams;\nexport type KrakenGetWithdrawInfoResult =\n GetWithdrawInfo.KrakenGetWithdrawInfoResult;\nexport type KrakenWithdrawInfo = GetWithdrawInfo.KrakenWithdrawInfo;\n\nexport type KrakenWithdrawFundsParams = WithdrawFunds.KrakenWithdrawFundsParams;\nexport type KrakenWithdrawFundsResult =\n WithdrawFunds.KrakenWithdrawFundsResponse;\n\nexport type KrakenGetWithdrawStatusParams =\n GetWithdrawStatus.KrakenGetWithdrawStatusParams;\nexport type KrakenGetWithdrawStatusResult =\n GetWithdrawStatus.KrakenGetWithdrawStatusResult;\nexport type KrakenWithdrawStatusEntry =\n GetWithdrawStatus.KrakenWithdrawStatusEntry;\n\nexport type KrakenWithdrawCancelParams =\n WithdrawCancel.KrakenWithdrawCancelParams;\nexport type KrakenWithdrawCancelResult =\n WithdrawCancel.KrakenWithdrawCancelResult;\n\nexport type KrakenWalletTransferParams =\n WalletTransfer.KrakenWalletTransferParams;\nexport type KrakenWalletTransferResult =\n WalletTransfer.KrakenWalletTransferResult;\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenCreateSubaccountParams {\n /**\n * Username for the subaccount.\n */\n username: string;\n\n /**\n * Email address for the subaccount.\n */\n email: string;\n}\n\n/**\n * Whether subaccount creation was successful or not.\n */\nexport type KrakenCreateSubaccountResult = boolean;\n\n/**\n * Create a trading subaccount.\n *\n * Note: CreateSubaccount must be called using an API key from the\n * master account.\n *\n * Kraken docs: POST /0/private/CreateSubaccount\n */\nexport async function createSubaccount(\n base: KrakenRestBase,\n params: KrakenCreateSubaccountParams,\n): Promise<KrakenCreateSubaccountResult> {\n const { username, email } = params;\n\n const body: Record<string, string> = {\n username,\n email,\n };\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenCreateSubaccountResult>(\n '/0/private/CreateSubaccount',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenAccountTransferAssetClass = 'currency' | 'tokenized_asset';\n\nexport interface KrakenAccountTransferParams {\n /**\n * Asset being transferred (e.g. \"USDT\", \"XBT\").\n */\n asset: string;\n\n /**\n * Specify the asset class of the asset being transferred.\n * Defaults to \"currency\" on Kraken if omitted.\n */\n asset_class?: KrakenAccountTransferAssetClass;\n\n /**\n * Amount of asset to transfer.\n * Will be sent to Kraken as a string.\n */\n amount: string | number;\n\n /**\n * IIBAN of the source account.\n */\n from: string;\n\n /**\n * IIBAN of the destination account.\n */\n to: string;\n}\n\nexport interface KrakenAccountTransferResult {\n /**\n * Transfer ID.\n */\n transfer_id: string;\n\n /**\n * Transfer status: \"pending\" or \"complete\".\n */\n status: 'pending' | 'complete';\n}\n\n/**\n * Transfer funds to and from master and subaccounts.\n *\n * Note: AccountTransfer must be called using an API key from\n * the master account.\n *\n * Kraken docs: POST /0/private/AccountTransfer\n */\nexport async function accountTransfer(\n base: KrakenRestBase,\n params: KrakenAccountTransferParams,\n): Promise<KrakenAccountTransferResult> {\n const { asset, asset_class, amount, from, to } = params;\n\n const body: Record<string, string | number | boolean> = {\n asset,\n amount: String(amount),\n from,\n to,\n };\n\n if (asset_class) {\n body.asset_class = asset_class;\n }\n\n return base.privatePost<KrakenAccountTransferResult>(\n '/0/private/AccountTransfer',\n body as any, // remove this if privatePost already accepts the union type\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as CreateSubaccount from './createSubaccount';\nimport * as AccountTransfer from './accountTransfer';\n\n/**\n * Kraken Spot Subaccounts API.\n *\n * Covers creation and management of trading subaccounts.\n */\nexport class KrakenSpotSubaccountsApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Create a trading subaccount.\n *\n * Note: must be called using an API key from the master account.\n *\n * @example\n * ```ts\n * const sub = await kraken.subaccounts.createSubaccount({\n * username: \"my-sub-user\",\n * email: \"subuser@example.com\",\n * });\n *\n * console.log(\"subaccount created:\", sub);\n * ```\n */\n createSubaccount(params: CreateSubaccount.KrakenCreateSubaccountParams) {\n return CreateSubaccount.createSubaccount(this.base, params);\n }\n\n /**\n * Transfer funds between master and subaccounts.\n *\n * Note: must be called using an API key from the master account.\n *\n * @example\n * ```ts\n * const res = await kraken.subaccounts.accountTransfer({\n * asset: \"USDT\",\n * amount: \"50\",\n * from: \"IIBAN-MASTER\",\n * to: \"IIBAN-SUB-1\",\n * });\n *\n * console.log(res.transfer_id, res.status);\n * ```\n */\n accountTransfer(params: AccountTransfer.KrakenAccountTransferParams) {\n return AccountTransfer.accountTransfer(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenCreateSubaccountParams =\n CreateSubaccount.KrakenCreateSubaccountParams;\nexport type KrakenCreateSubaccountResult =\n CreateSubaccount.KrakenCreateSubaccountResult;\n\nexport type KrakenAccountTransferParams =\n AccountTransfer.KrakenAccountTransferParams;\nexport type KrakenAccountTransferResult =\n AccountTransfer.KrakenAccountTransferResult;\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenEarnAllocateFundsParams {\n /**\n * The amount to allocate.\n * Will be sent to Kraken as a string.\n */\n amount: string | number;\n\n /**\n * A unique identifier of the chosen earn strategy,\n * as returned from /0/private/Earn/Strategies.\n */\n strategy_id: string;\n}\n\n/**\n * Will return `true` when the operation is successful,\n * `null` when an error occurred.\n *\n * NOTE: This endpoint is asynchronous. You must poll\n * /0/private/Earn/AllocateStatus for the final status.\n */\nexport type KrakenEarnAllocateFundsResult = boolean | null;\n\n/**\n * Allocate funds to an Earn strategy.\n *\n * Requires the Earn Funds API key permission.\n *\n * This method is asynchronous — only preflight checks are done\n * synchronously. For the full result, poll /0/private/Earn/AllocateStatus.\n *\n * Kraken docs: POST /0/private/Earn/Allocate\n */\nexport async function allocateEarnFunds(\n base: KrakenRestBase,\n params: KrakenEarnAllocateFundsParams,\n): Promise<KrakenEarnAllocateFundsResult> {\n const { amount, strategy_id } = params;\n\n const body: Record<string, string> = {\n amount: String(amount),\n strategy_id,\n };\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenEarnAllocateFundsResult>(\n '/0/private/Earn/Allocate',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenEarnDeallocateFundsParams {\n /**\n * The amount to deallocate.\n * Will be sent to Kraken as a string.\n */\n amount: string | number;\n\n /**\n * A unique identifier of the chosen earn strategy.\n */\n strategy_id: string;\n}\n\n/**\n * Will return `true` when the operation is successful,\n * `null` when an error occurred.\n *\n * NOTE: This endpoint is asynchronous. You must poll\n * /0/private/Earn/DeallocateStatus (and/or use Allocations)\n * for the final status.\n */\nexport type KrakenEarnDeallocateFundsResult = boolean | null;\n\n/**\n * Deallocate funds from an Earn strategy.\n *\n * Requires the Earn Funds API key permission.\n *\n * This method is asynchronous — only preflight checks are done\n * synchronously. For the full result, poll /0/private/Earn/DeallocateStatus.\n *\n * Kraken docs: POST /0/private/Earn/Deallocate\n */\nexport async function deallocateEarnFunds(\n base: KrakenRestBase,\n params: KrakenEarnDeallocateFundsParams,\n): Promise<KrakenEarnDeallocateFundsResult> {\n const { amount, strategy_id } = params;\n\n const body: Record<string, string> = {\n amount: String(amount),\n strategy_id,\n };\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenEarnDeallocateFundsResult>(\n '/0/private/Earn/Deallocate',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenEarnGetAllocationStatusParams {\n /**\n * ID of the earn strategy.\n * Call /0/private/Earn/Strategies to list available strategies.\n */\n strategy_id: string;\n}\n\n/**\n * Status of async earn (de)allocation operation.\n */\nexport interface KrakenEarnAllocationStatus {\n /**\n * true if an operation is still in progress on the same strategy,\n * false if it has successfully completed.\n */\n pending: boolean;\n}\n\n/**\n * Will be:\n * - an object with `pending` when the endpoint returns normally\n * - `null` if Kraken ever extends the schema that way (docs say \"object|null\")\n */\nexport type KrakenEarnGetAllocationStatusResult =\n KrakenEarnAllocationStatus | null;\n\n/**\n * Get the status of the last allocation/deallocation request for a strategy.\n *\n * Requires either the Earn Funds or Query Funds API key permission.\n *\n * Kraken docs: POST /0/private/Earn/AllocateStatus\n */\nexport async function getAllocationStatus(\n base: KrakenRestBase,\n params: KrakenEarnGetAllocationStatusParams,\n): Promise<KrakenEarnGetAllocationStatusResult> {\n const { strategy_id } = params;\n\n const body: Record<string, string> = {\n strategy_id,\n };\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenEarnGetAllocationStatusResult>(\n '/0/private/Earn/AllocateStatus',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenEarnGetDeallocationStatusParams {\n /**\n * ID of the earn strategy.\n * Call /0/private/Earn/Strategies to list available strategies.\n */\n strategy_id: string;\n}\n\n/**\n * Status of async earn (de)allocation operation.\n *\n * Same shape as AllocateStatus.\n */\nexport interface KrakenEarnDeallocationStatus {\n /**\n * true if an operation is still in progress on the same strategy,\n * false if it has successfully completed.\n */\n pending: boolean;\n}\n\nexport type KrakenEarnGetDeallocationStatusResult =\n KrakenEarnDeallocationStatus | null;\n\n/**\n * Get the status of the last deallocation request for a strategy.\n *\n * Requires either the Earn Funds or Query Funds API key permission.\n *\n * Kraken docs: POST /0/private/Earn/DeallocateStatus\n */\nexport async function getDeallocationStatus(\n base: KrakenRestBase,\n params: KrakenEarnGetDeallocationStatusParams,\n): Promise<KrakenEarnGetDeallocationStatusResult> {\n const { strategy_id } = params;\n\n const body: Record<string, string> = {\n strategy_id,\n };\n\n // KrakenRestBase.privatePost unwraps { error, result } and returns just result.\n return base.privatePost<KrakenEarnGetDeallocationStatusResult>(\n '/0/private/Earn/DeallocateStatus',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport type KrakenEarnLockType = 'flex' | 'bonded' | 'timed' | 'instant';\n\nexport interface KrakenEarnListStrategiesParams {\n ascending?: boolean | null;\n asset?: string | null;\n cursor?: string | null;\n limit?: number | null;\n lock_type?: ReadonlyArray<KrakenEarnLockType> | null;\n}\n\nexport interface KrakenEarnAprEstimate {\n low: string;\n high: string;\n}\n\nexport interface KrakenEarnFeeInfo {\n fee: string;\n}\n\nexport interface KrakenEarnAutoCompoundInfo {\n type: string;\n}\n\nexport interface KrakenEarnLockTypeInfo {\n type: KrakenEarnLockType | string;\n}\n\nexport interface KrakenEarnYieldSourceInfo {\n type: string;\n}\n\nexport interface KrakenEarnStrategy {\n allocation_fee: KrakenEarnFeeInfo | string | number;\n allocation_restriction_info?: string[];\n apr_estimate?: KrakenEarnAprEstimate | null;\n asset: string;\n auto_compound: KrakenEarnAutoCompoundInfo;\n can_allocate: boolean;\n can_deallocate: boolean;\n deallocation_fee: KrakenEarnFeeInfo | string | number;\n id: string;\n lock_type: KrakenEarnLockTypeInfo;\n user_cap?: string | null;\n user_min_allocation?: string | null;\n yield_source: KrakenEarnYieldSourceInfo;\n}\n\nexport interface KrakenEarnListStrategiesResultObject {\n items: KrakenEarnStrategy[];\n next_cursor: string | null;\n}\n\nexport type KrakenEarnListStrategiesResult =\n KrakenEarnListStrategiesResultObject | null;\n\n/**\n * List earn strategies available to the user along with their parameters.\n *\n * Requires a valid API key but no specific permission.\n * Only strategies available to the user (e.g. based on geographic region)\n * are returned.\n *\n * Kraken docs: POST /0/private/Earn/Strategies\n */\nexport async function listEarnStrategies(\n base: KrakenRestBase,\n params: KrakenEarnListStrategiesParams = {},\n): Promise<KrakenEarnListStrategiesResult> {\n const { ascending, asset, cursor, limit, lock_type } = params;\n\n // IMPORTANT: keep this in sync with KrakenRestBase.privatePost signature:\n // Record<string, string | number | boolean>\n const body: Record<string, string | number | boolean> = {};\n\n if (ascending !== undefined && ascending !== null) {\n body.ascending = ascending;\n }\n if (asset !== undefined && asset !== null) {\n body.asset = asset;\n }\n if (cursor !== undefined && cursor !== null) {\n body.cursor = cursor;\n }\n if (limit !== undefined && limit !== null) {\n body.limit = limit;\n }\n if (lock_type && lock_type.length > 0) {\n // Encode array as JSON string, same pattern as batch endpoints.\n body.lock_type = JSON.stringify(lock_type);\n }\n\n return base.privatePost<KrakenEarnListStrategiesResult>(\n '/0/private/Earn/Strategies',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenEarnListAllocationsParams {\n /**\n * true to sort ascending, false (the default) for descending.\n */\n ascending?: boolean | null;\n\n /**\n * A secondary currency to express the value of your allocations\n * (the default is USD).\n */\n converted_asset?: string | null;\n\n /**\n * Omit entries for strategies that were used in the past but now\n * hold no allocation (default is false).\n */\n hide_zero_allocations?: boolean | null;\n}\n\n/**\n * Simple converted/native pair used in many Earn allocation fields.\n */\nexport interface KrakenEarnAmountBreakdown {\n /**\n * Amount converted into the requested asset.\n */\n converted: string;\n\n /**\n * Amount in the native asset.\n */\n native: string;\n}\n\n/**\n * Per-allocation detail for a bonding/exit_queue/unbonding state.\n */\nexport interface KrakenEarnStateAllocationDetail {\n /**\n * Amount converted into the requested asset.\n */\n converted: string;\n\n /**\n * Amount in the native asset.\n */\n native: string;\n\n /**\n * Date/time when the (de)allocation request was received/processed.\n */\n created_at: string;\n\n /**\n * Date/time when the funds will move to the next state.\n */\n expires: string;\n}\n\n/**\n * Aggregated block for bonding/exit_queue/unbonding.\n */\nexport interface KrakenEarnStateAllocationBlock {\n /**\n * The total number of allocations in this state for this asset.\n */\n allocation_count: number;\n\n /**\n * Details about when each allocation will expire and move\n * to the next state.\n */\n allocations: KrakenEarnStateAllocationDetail[];\n\n /**\n * Amount converted into the requested asset.\n */\n converted: string;\n\n /**\n * Amount in the native asset.\n */\n native: string;\n}\n\n/**\n * Amounts allocated to this Earn strategy, broken down by state.\n */\nexport interface KrakenEarnAmountAllocated {\n /**\n * Amount allocated in bonding status.\n * Only present when there are bonding allocations.\n */\n bonding?: KrakenEarnStateAllocationBlock | null;\n\n /**\n * Amount allocated in the exit-queue status (ETH only).\n * Only present when there are exit_queue allocations.\n */\n exit_queue?: KrakenEarnStateAllocationBlock | null;\n\n /**\n * Pending allocation amount – can be negative if the pending\n * operation is a deallocation. Only present when there are\n * pending allocations.\n */\n pending?: KrakenEarnAmountBreakdown | null;\n\n /**\n * Total amount allocated to this Earn strategy.\n */\n total: KrakenEarnAmountBreakdown;\n\n /**\n * Amount allocated in unbonding status.\n * Only present when there are unbonding allocations.\n */\n unbonding?: KrakenEarnStateAllocationBlock | null;\n\n /**\n * Total amount converted into the requested asset for this strategy.\n */\n converted: string;\n\n /**\n * Total amount in the native asset for this strategy.\n */\n native: string;\n}\n\n/**\n * Information about the current payout period.\n */\nexport interface KrakenEarnPayoutInfo {\n /**\n * Reward accumulated in the payout period until now.\n */\n accumulated_reward: KrakenEarnAmountBreakdown;\n\n /**\n * Estimated reward from now until the payout.\n */\n estimated_reward: KrakenEarnAmountBreakdown;\n\n /**\n * Tentative date of the next reward payout.\n */\n period_end: string;\n\n /**\n * When the current payout period started.\n * Either the date of the last payout or when it was enabled.\n */\n period_start: string;\n}\n\n/**\n * Single allocation entry per strategy.\n */\nexport interface KrakenEarnAllocationItem {\n /**\n * Amounts allocated to this Earn strategy, broken down by state.\n */\n amount_allocated: KrakenEarnAmountAllocated;\n\n /**\n * The asset of the native currency of this allocation.\n */\n native_asset: string;\n\n /**\n * Information about the current payout period, absent when\n * there is no current payout period.\n */\n payout?: KrakenEarnPayoutInfo | null;\n\n /**\n * Unique ID for Earn Strategy.\n */\n strategy_id: string;\n\n /**\n * Amount earned using the strategy during the whole lifetime\n * of user account.\n */\n total_rewarded: KrakenEarnAmountBreakdown;\n}\n\n/**\n * Page response for /0/private/Earn/Allocations.\n */\nexport interface KrakenEarnListAllocationsResultObject {\n /**\n * A secondary asset to show the value of allocations\n * (e.g. \"USD\").\n */\n converted_asset: string;\n\n /**\n * Per-strategy allocation items.\n */\n items: KrakenEarnAllocationItem[];\n\n /**\n * The total amount allocated across all strategies,\n * denominated in the converted_asset currency.\n */\n total_allocated: string;\n\n /**\n * Amount earned across all strategies during the whole lifetime\n * of user account, denominated in converted_asset currency.\n */\n total_rewarded: string;\n}\n\n/**\n * `result` is documented as `object|null`.\n */\nexport type KrakenEarnListAllocationsResult =\n KrakenEarnListAllocationsResultObject | null;\n\n/**\n * List all allocations for the user.\n *\n * Requires the Query Funds API key permission.\n *\n * By default, all allocations are returned, even for strategies that\n * currently have zero balance. Use `hide_zero_allocations` to omit\n * those entries.\n *\n * Kraken docs: POST /0/private/Earn/Allocations\n */\nexport async function listEarnAllocations(\n base: KrakenRestBase,\n params: KrakenEarnListAllocationsParams = {},\n): Promise<KrakenEarnListAllocationsResult> {\n const { ascending, converted_asset, hide_zero_allocations } = params;\n\n // Must match KrakenRestBase.privatePost signature:\n // Record<string, string | number | boolean>\n const body: Record<string, string | number | boolean> = {};\n\n if (ascending !== undefined && ascending !== null) {\n body.ascending = ascending;\n }\n if (converted_asset !== undefined && converted_asset !== null) {\n body.converted_asset = converted_asset;\n }\n if (hide_zero_allocations !== undefined && hide_zero_allocations !== null) {\n body.hide_zero_allocations = hide_zero_allocations;\n }\n\n return base.privatePost<KrakenEarnListAllocationsResult>(\n '/0/private/Earn/Allocations',\n body,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as AllocateEarnFunds from './allocateEarnFunds';\nimport * as DeallocateEarnFunds from './deallocateEarnFunds';\nimport * as GetAllocationStatus from './getAllocationStatus';\nimport * as GetDeallocationStatus from './getDeallocationStatus';\nimport * as ListStrategies from './listStrategies';\nimport * as ListAllocations from './listAllocations';\n\n/**\n * Kraken Spot Earn API.\n *\n * Covers allocation and deallocation of funds to Earn strategies,\n * plus related status / strategy discovery endpoints.\n */\nexport class KrakenSpotEarnApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Allocate funds to an Earn strategy.\n *\n * Note:\n * - Requires the Earn Funds API key permission.\n * - Operation is asynchronous; poll AllocateStatus for completion.\n *\n * @example\n * ```ts\n * const res = await kraken.earn.allocateFunds({\n * amount: \"100\",\n * strategy_id: \"STRAT-123\",\n * });\n *\n * if (res === true) {\n * console.log(\"preflight checks passed, allocation dispatched\");\n * } else {\n * console.log(\"preflight failed or returned null\");\n * }\n * ```\n */\n allocateFunds(params: AllocateEarnFunds.KrakenEarnAllocateFundsParams) {\n return AllocateEarnFunds.allocateEarnFunds(this.base, params);\n }\n\n /**\n * Deallocate funds from an Earn strategy.\n *\n * Note:\n * - Requires the Earn Funds API key permission.\n * - Operation is asynchronous; poll DeallocateStatus for completion.\n *\n * @example\n * ```ts\n * const res = await kraken.earn.deallocateFunds({\n * amount: \"50\",\n * strategy_id: \"STRAT-123\",\n * });\n *\n * if (res === true) {\n * console.log(\"preflight checks passed, deallocation dispatched\");\n * } else {\n * console.log(\"preflight failed or returned null\");\n * }\n * ```\n */\n deallocateFunds(params: DeallocateEarnFunds.KrakenEarnDeallocateFundsParams) {\n return DeallocateEarnFunds.deallocateEarnFunds(this.base, params);\n }\n\n /**\n * Get the status of the last allocation/deallocation request for\n * a given strategy (allocate-side status).\n *\n * Requires either Earn Funds or Query Funds API key permission.\n *\n * @example\n * ```ts\n * const status = await kraken.earn.getAllocationStatus({\n * strategy_id: \"STRAT-123\",\n * });\n *\n * if (!status) {\n * console.log(\"no allocation status available\");\n * } else if (status.pending) {\n * console.log(\"allocation still in progress\");\n * } else {\n * console.log(\"allocation completed\");\n * }\n * ```\n */\n getAllocationStatus(\n params: GetAllocationStatus.KrakenEarnGetAllocationStatusParams,\n ) {\n return GetAllocationStatus.getAllocationStatus(this.base, params);\n }\n\n /**\n * Get the status of the last deallocation request for\n * a given strategy (deallocate-side status).\n *\n * Requires either Earn Funds or Query Funds API key permission.\n *\n * @example\n * ```ts\n * const status = await kraken.earn.getDeallocationStatus({\n * strategy_id: \"STRAT-123\",\n * });\n *\n * if (!status) {\n * console.log(\"no deallocation status available\");\n * } else if (status.pending) {\n * console.log(\"deallocation still in progress\");\n * } else {\n * console.log(\"deallocation completed\");\n * }\n * ```\n */\n getDeallocationStatus(\n params: GetDeallocationStatus.KrakenEarnGetDeallocationStatusParams,\n ) {\n return GetDeallocationStatus.getDeallocationStatus(this.base, params);\n }\n\n /**\n * List earn strategies available to the user along with their parameters.\n *\n * Requires a valid API key but no specific permission.\n * Only strategies available to the user (e.g. based on geographic region)\n * are returned.\n *\n * @example\n * ```ts\n * const res = await kraken.earn.listStrategies({\n * asset: \"USDT\",\n * lock_type: [\"flex\", \"bonded\"],\n * });\n *\n * if (!res) {\n * console.log(\"no strategies available\");\n * } else {\n * for (const s of res.items) {\n * console.log(\n * s.id,\n * s.asset,\n * s.lock_type.type,\n * \"can_allocate:\", s.can_allocate,\n * \"APR:\", s.apr_estimate?.low, \"-\", s.apr_estimate?.high,\n * );\n * }\n * }\n * ```\n */\n listStrategies(params: ListStrategies.KrakenEarnListStrategiesParams = {}) {\n return ListStrategies.listEarnStrategies(this.base, params);\n }\n\n /**\n * List all Earn allocations for the user.\n *\n * Requires the Query Funds API key permission.\n *\n * By default, all allocations are returned, even for strategies\n * that currently have zero balance. Use `hide_zero_allocations`\n * to omit those entries.\n *\n * @example\n * ```ts\n * const res = await kraken.earn.listAllocations({\n * converted_asset: \"USD\",\n * hide_zero_allocations: true,\n * });\n *\n * if (!res) {\n * console.log(\"no allocations found\");\n * } else {\n * console.log(\"total allocated (USD):\", res.total_allocated);\n * console.log(\"total rewarded (USD):\", res.total_rewarded);\n *\n * for (const a of res.items) {\n * console.log(\n * \"strategy:\", a.strategy_id,\n * \"native asset:\", a.native_asset,\n * \"allocated (native):\", a.amount_allocated.native,\n * \"allocated (converted):\", a.amount_allocated.converted,\n * );\n * }\n * }\n * ```\n */\n listAllocations(\n params: ListAllocations.KrakenEarnListAllocationsParams = {},\n ) {\n return ListAllocations.listEarnAllocations(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenEarnAllocateFundsParams =\n AllocateEarnFunds.KrakenEarnAllocateFundsParams;\nexport type KrakenEarnAllocateFundsResult =\n AllocateEarnFunds.KrakenEarnAllocateFundsResult;\n\nexport type KrakenEarnDeallocateFundsParams =\n DeallocateEarnFunds.KrakenEarnDeallocateFundsParams;\nexport type KrakenEarnDeallocateFundsResult =\n DeallocateEarnFunds.KrakenEarnDeallocateFundsResult;\n\nexport type KrakenEarnGetAllocationStatusParams =\n GetAllocationStatus.KrakenEarnGetAllocationStatusParams;\nexport type KrakenEarnGetAllocationStatusResult =\n GetAllocationStatus.KrakenEarnGetAllocationStatusResult;\nexport type KrakenEarnAllocationStatus =\n GetAllocationStatus.KrakenEarnAllocationStatus;\n\nexport type KrakenEarnGetDeallocationStatusParams =\n GetDeallocationStatus.KrakenEarnGetDeallocationStatusParams;\nexport type KrakenEarnGetDeallocationStatusResult =\n GetDeallocationStatus.KrakenEarnGetDeallocationStatusResult;\nexport type KrakenEarnDeallocationStatus =\n GetDeallocationStatus.KrakenEarnDeallocationStatus;\n\nexport type KrakenEarnListStrategiesParams =\n ListStrategies.KrakenEarnListStrategiesParams;\nexport type KrakenEarnListStrategiesResult =\n ListStrategies.KrakenEarnListStrategiesResult;\nexport type KrakenEarnStrategy = ListStrategies.KrakenEarnStrategy;\nexport type KrakenEarnLockType = ListStrategies.KrakenEarnLockType;\nexport type KrakenEarnListStrategiesResultObject =\n ListStrategies.KrakenEarnListStrategiesResultObject;\n\nexport type KrakenEarnListAllocationsParams =\n ListAllocations.KrakenEarnListAllocationsParams;\nexport type KrakenEarnListAllocationsResult =\n ListAllocations.KrakenEarnListAllocationsResult;\nexport type KrakenEarnAllocationItem = ListAllocations.KrakenEarnAllocationItem;\nexport type KrakenEarnAmountBreakdown =\n ListAllocations.KrakenEarnAmountBreakdown;\nexport type KrakenEarnListAllocationsResultObject =\n ListAllocations.KrakenEarnListAllocationsResultObject;\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenGetPreTradeDataParams {\n /**\n * A list of symbols for the currency pairs.\n *\n * Kraken docs:\n * - \"symbol\" is a string, 3–32 chars.\n * - Can represent a list of symbols; we support both string and string[].\n *\n * Example: \"BTC/USD\" or [\"BTC/USD\", \"ETH/USD\"]\n */\n symbol: string | ReadonlyArray<string>;\n}\n\n/**\n * Raw result from /0/public/PreTrade.\n *\n * As of the current Kraken docs, the schema is only documented as \"object\",\n * without field-level detail. We keep this generic to avoid incorrect typing.\n */\nexport type KrakenPreTradeDataResult = Record<string, unknown>;\n\n/**\n * Returns the price levels in the order book with aggregated order\n * quantities at each price level. The top 10 levels are returned for\n * each trading pair.\n *\n * Kraken docs: GET /0/public/PreTrade\n */\nexport async function getPreTradeData(\n base: KrakenRestBase,\n params: KrakenGetPreTradeDataParams,\n): Promise<KrakenPreTradeDataResult> {\n const { symbol } = params;\n\n const symbolParam = typeof symbol === 'string' ? symbol : symbol.join(',');\n\n const query: Record<string, string> = {\n symbol: symbolParam,\n };\n\n return base.publicGet<KrakenPreTradeDataResult>('/0/public/PreTrade', query);\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\n\nexport interface KrakenGetPostTradeDataParams {\n /**\n * Filter the results to the currency pair.\n * Example: \"BTC/USD\"\n */\n symbol?: string;\n\n /**\n * Filter the results to include trades AFTER this timestamp (exclusive).\n * ISO 8601, e.g. \"2024-05-30T12:34:56.123456789Z\".\n */\n from_ts?: string;\n\n /**\n * Filter the results to include trades BEFORE or AT this timestamp.\n * ISO 8601, e.g. \"2024-05-30T12:34:56.123456789Z\".\n */\n to_ts?: string;\n\n /**\n * The maximum number of trades to return.\n * Default on Kraken is 1000, range [1, 1000].\n */\n count?: number;\n}\n\nexport interface KrakenPostTradeEntry {\n trade_id: string;\n price: string;\n quantity: string;\n symbol: string;\n description: string;\n base_asset: string;\n base_notation: string;\n quote_asset: string;\n quote_notation: string;\n trade_venue: string;\n trade_ts: string;\n publication_venue: string;\n publication_ts: string;\n}\n\nexport interface KrakenGetPostTradeDataResult {\n last_ts: string;\n count: number;\n trades: KrakenPostTradeEntry[];\n}\n\n/**\n * Returns a list of trades on the spot exchange.\n *\n * If no filter parameters are specified, the last 1000 trades\n * for all pairs are returned.\n *\n * Kraken docs: GET /0/public/PostTrade\n */\nexport async function getPostTradeData(\n base: KrakenRestBase,\n params: KrakenGetPostTradeDataParams = {},\n): Promise<KrakenGetPostTradeDataResult> {\n const { symbol, from_ts, to_ts, count } = params;\n\n // Match KrakenRestBase.publicGet signature: Record<string, string | number>\n const query: Record<string, string | number> = {};\n\n if (symbol) {\n query.symbol = symbol;\n }\n if (from_ts) {\n query.from_ts = from_ts;\n }\n if (to_ts) {\n query.to_ts = to_ts;\n }\n if (count !== undefined) {\n query.count = count;\n }\n\n return base.publicGet<KrakenGetPostTradeDataResult>(\n '/0/public/PostTrade',\n query,\n );\n}\n","import type { KrakenRestBase } from '../../../base/restBase';\nimport * as GetPreTradeData from './getPreTradeData';\nimport * as GetPostTradeData from './getPostTradeData';\n\n/**\n * Kraken Spot Transparency API.\n *\n * Covers transparency-related public data such as pre-/post-trade data.\n */\nexport class KrakenSpotTransparencyApi {\n constructor(private readonly base: KrakenRestBase) {}\n\n /**\n * Get pre-trade aggregated order book data.\n *\n * Returns the price levels in the order book with aggregated order\n * quantities at each price level. The top 10 levels are returned\n * for each trading pair.\n *\n * @example\n * ```ts\n * const preTrade = await kraken.transparency.getPreTradeData({\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * });\n *\n * // Result schema is not fully documented by Kraken yet,\n * // so treat it as an opaque object and inspect the shape:\n * console.log(JSON.stringify(preTrade, null, 2));\n * ```\n */\n getPreTradeData(params: GetPreTradeData.KrakenGetPreTradeDataParams) {\n return GetPreTradeData.getPreTradeData(this.base, params);\n }\n\n /**\n * Get post-trade data (executed trades) on the spot exchange.\n *\n * Returns a list of trades in ascending timestamp order.\n * If no filter parameters are specified, the last 1000 trades\n * for all pairs are returned.\n *\n * @example\n * ```ts\n * const res = await kraken.transparency.getPostTradeData({\n * symbol: \"BTC/USD\",\n * count: 100,\n * });\n *\n * console.log(\"last_ts:\", res.last_ts, \"count:\", res.count);\n *\n * for (const t of res.trades) {\n * console.log(\n * t.trade_id,\n * t.symbol,\n * \"price:\", t.price,\n * \"qty:\", t.quantity,\n * \"trade_ts:\", t.trade_ts,\n * );\n * }\n * ```\n */\n getPostTradeData(params: GetPostTradeData.KrakenGetPostTradeDataParams = {}) {\n return GetPostTradeData.getPostTradeData(this.base, params);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenGetPreTradeDataParams =\n GetPreTradeData.KrakenGetPreTradeDataParams;\nexport type KrakenPreTradeDataResult = GetPreTradeData.KrakenPreTradeDataResult;\n\nexport type KrakenGetPostTradeDataParams =\n GetPostTradeData.KrakenGetPostTradeDataParams;\nexport type KrakenGetPostTradeDataResult =\n GetPostTradeData.KrakenGetPostTradeDataResult;\nexport type KrakenPostTradeEntry = GetPostTradeData.KrakenPostTradeEntry;\n","import { KrakenRestBase } from '../../base/restBase';\nimport type { KrakenClientOptions } from '../../types/types';\nimport { KrakenSpotMarketDataApi } from './market-data';\nimport { KrakenSpotAccountDataApi } from './account-data';\nimport { KrakenSpotTradingApi } from './trading';\nimport { KrakenSpotFundingApi } from './funding';\nimport { KrakenSpotSubaccountsApi } from './subaccounts';\nimport { KrakenSpotEarnApi } from './earn';\nimport { KrakenSpotTransparencyApi } from './transparency';\n\n/**\n * Kraken Spot REST client.\n *\n * This is the main entry point for accessing Kraken's spot REST API.\n * It exposes sub-APIs such as:\n * - `marketData` for public market endpoints\n * - `accountData` for private account endpoints (requires API key)\n *\n * @example\n * ```ts\n * import { KrakenSpotRestClient } from \"@lynx/kraken-spot-rest\";\n *\n * const kraken = new KrakenSpotRestClient({\n * userAgent: \"my-app/1.0.0\",\n * });\n *\n * const time = await kraken.marketData.getServerTime();\n * console.log(\"Kraken time:\", time.rfc1123);\n * ```\n *\n * @example\n * ```ts\n * import { KrakenSpotRestClient } from \"@lynx/kraken-spot-rest\";\n *\n * const kraken = new KrakenSpotRestClient({\n * apiKey: process.env.KRAKEN_API_KEY!,\n * apiSecret: process.env.KRAKEN_API_SECRET!,\n * userAgent: \"my-app/1.0.0\",\n * });\n *\n * const balances = await kraken.accountData.getAccountBalance();\n * console.log(\"USD balance:\", balances[\"ZUSD\"]);\n * ```\n */\nexport class KrakenSpotRestClient extends KrakenRestBase {\n /**\n * Public market data API (time, status, assets, pairs, ticker,\n * OHLC, depth, trades, spreads, etc.).\n */\n readonly marketData: KrakenSpotMarketDataApi;\n\n /**\n * Private account data API (balances, etc.).\n * Requires API key/secret with the appropriate permissions.\n */\n readonly accountData: KrakenSpotAccountDataApi;\n\n /**\n * Private trading API (place / cancel / amend orders, etc.).\n * Requires API key/secret with the appropriate permissions.\n */\n readonly trading: KrakenSpotTradingApi;\n\n /**\n * Funding API (deposit / withdrawal–related endpoints).\n * Requires appropriate \"Funds\" permissions on your API key.\n */\n readonly funding: KrakenSpotFundingApi;\n\n /**\n * Subaccounts API (create and manage trading subaccounts).\n * Requires API key/secret from the master account.\n */\n readonly subaccounts: KrakenSpotSubaccountsApi;\n\n /**\n * Earn API (allocate / deallocate funds to Earn strategies).\n * Requires appropriate \"Earn Funds\" permissions on your API key.\n */\n readonly earn: KrakenSpotEarnApi;\n\n /**\n * Transparency API (pre-/post-trade data, etc.).\n */\n readonly transparency: KrakenSpotTransparencyApi;\n\n constructor(options: KrakenClientOptions = {}) {\n super(options);\n this.marketData = new KrakenSpotMarketDataApi(this);\n this.accountData = new KrakenSpotAccountDataApi(this);\n this.trading = new KrakenSpotTradingApi(this);\n this.funding = new KrakenSpotFundingApi(this);\n this.subaccounts = new KrakenSpotSubaccountsApi(this);\n this.earn = new KrakenSpotEarnApi(this);\n this.transparency = new KrakenSpotTransparencyApi(this);\n }\n}\n","// kraken/base/websocketBase.ts\n\nimport { WebSocket } from 'ws';\n\nexport interface KrakenWebSocketLike {\n readonly readyState: number;\n onopen: ((ev: unknown) => void) | null;\n onclose: ((ev: unknown) => void) | null;\n onerror: ((ev: unknown) => void) | null;\n onmessage: ((ev: { data: unknown }) => void) | null;\n\n close(code?: number, reason?: string): void;\n send(data: string): void;\n}\n\nexport type KrakenWebSocketLikeCtor = new (url: string) => KrakenWebSocketLike;\n\nexport interface KrakenWebsocketLogger {\n debug?(msg: string, meta?: unknown): void;\n info?(msg: string, meta?: unknown): void;\n warn?(msg: string, meta?: unknown): void;\n error?(msg: string, meta?: unknown): void;\n}\n\nexport interface KrakenWebsocketConnectionOptions {\n /** Full WSS URL, e.g. wss://ws.kraken.com/v2 or wss://ws-auth.kraken.com/v2 */\n url: string;\n\n /**\n * Optional session token for authenticated channels.\n * If provided, it will be auto-injected into params.token for requests\n * when `attachAuthToken` is true (default).\n */\n authToken?: string;\n\n /** Constructor for WebSocket implementation (browser or `ws` in Node). */\n WebSocketImpl?: KrakenWebSocketLikeCtor;\n\n /** Optional logger (same shape as REST). */\n logger?: KrakenWebsocketLogger;\n\n /** Automatically reconnect on unexpected close. Default: true. */\n autoReconnect?: boolean;\n\n /** Delay before reconnect attempt (ms). Default: 1_000. */\n reconnectDelayMs?: number;\n\n /** Default timeout for request/ack style calls (ms). Default: 10_000. */\n requestTimeoutMs?: number;\n}\n\n/** Envelope for method/ack style messages. */\nexport interface KrakenWsMethodResponseEnvelope<Result = unknown> {\n method?: string;\n result?: Result;\n success?: boolean;\n error?: string;\n req_id?: number;\n time_in?: string;\n time_out?: string;\n [key: string]: unknown;\n}\n\n/** Generic handler type for any incoming message. */\nexport type KrakenWsMessageHandler = (msg: unknown) => void;\n\ninterface PendingRequest {\n resolve: (msg: KrakenWsMethodResponseEnvelope<unknown>) => void;\n reject: (err: unknown) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Low-level WebSocket v2 connection used by all Spot WS v2 APIs.\n *\n * - Speaks Kraken's `{ method, params, req_id }` envelope\n * - Correlates acks/responses by `req_id`\n * - Exposes a simple message subscription API for streaming data\n */\nexport class KrakenWebsocketBase {\n private readonly url: string;\n private readonly authToken?: string;\n private readonly WebSocketImpl?: KrakenWebSocketLikeCtor;\n private readonly logger?: KrakenWebsocketLogger;\n private readonly autoReconnect: boolean;\n private readonly reconnectDelayMs: number;\n private readonly requestTimeoutMs: number;\n\n private ws: KrakenWebSocketLike | null = null;\n private connectingPromise: Promise<void> | null = null;\n private manuallyClosed = false;\n\n private nextReqId = 1;\n private readonly pending = new Map<number, PendingRequest>();\n private readonly messageHandlers = new Set<KrakenWsMessageHandler>();\n\n constructor(options: KrakenWebsocketConnectionOptions) {\n this.url = options.url;\n this.authToken = options.authToken;\n this.WebSocketImpl =\n options.WebSocketImpl ??\n (typeof WebSocket !== 'undefined'\n ? (WebSocket as unknown as KrakenWebSocketLikeCtor)\n : undefined);\n this.logger = options.logger;\n this.autoReconnect = options.autoReconnect ?? true;\n this.reconnectDelayMs = options.reconnectDelayMs ?? 1_000;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 10_000;\n\n if (!this.WebSocketImpl) {\n throw new Error(\n 'No WebSocket implementation available. ' +\n 'Pass `WebSocketImpl` in KrakenWebsocketConnectionOptions when using Node.js.',\n );\n }\n }\n\n /** Current readyState of the underlying WebSocket (or -1 if not created). */\n get readyState(): number {\n return this.ws?.readyState ?? -1;\n }\n\n /** Connect (or reuse an in-flight connect). */\n async connect(): Promise<void> {\n if (this.ws && this.ws.readyState === 1) {\n return;\n }\n\n if (this.connectingPromise) {\n return this.connectingPromise;\n }\n\n this.manuallyClosed = false;\n\n this.connectingPromise = new Promise<void>((resolve, reject) => {\n try {\n const WS = this.WebSocketImpl!;\n const ws = new WS(this.url);\n this.ws = ws;\n\n ws.onopen = () => {\n this.logger?.info?.('Kraken WS connected', { url: this.url });\n this.connectingPromise = null;\n resolve();\n };\n\n ws.onclose = (ev) => {\n this.logger?.info?.('Kraken WS closed', {\n url: this.url,\n event: ev,\n manuallyClosed: this.manuallyClosed,\n });\n\n this.ws = null;\n this.connectingPromise = null;\n\n // Fail all pending requests\n for (const [reqId, pending] of this.pending) {\n clearTimeout(pending.timeoutId);\n pending.reject(\n new Error(`WebSocket closed before response for req_id ${reqId}`),\n );\n }\n this.pending.clear();\n\n if (!this.manuallyClosed && this.autoReconnect) {\n setTimeout(() => {\n this.logger?.info?.('Kraken WS reconnecting', { url: this.url });\n void this.connect().catch((err) => {\n this.logger?.error?.('Kraken WS reconnect failed', {\n url: this.url,\n error: err,\n });\n });\n }, this.reconnectDelayMs);\n }\n };\n\n ws.onerror = (ev) => {\n this.logger?.error?.('Kraken WS error', { url: this.url, event: ev });\n };\n\n ws.onmessage = (ev) => {\n let parsed: unknown = ev.data;\n if (typeof ev.data === 'string') {\n try {\n parsed = JSON.parse(ev.data);\n } catch (err) {\n this.logger?.warn?.('Failed to parse WS JSON message', {\n data: ev.data,\n error: err,\n });\n }\n }\n\n // First, resolve any pending request waiting on this req_id\n if (\n parsed &&\n typeof parsed === 'object' &&\n 'req_id' in parsed &&\n typeof (parsed as any).req_id === 'number'\n ) {\n const reqId = (parsed as any).req_id as number;\n const pending = this.pending.get(reqId);\n if (pending) {\n this.pending.delete(reqId);\n clearTimeout(pending.timeoutId);\n pending.resolve(\n parsed as KrakenWsMethodResponseEnvelope<unknown>,\n );\n }\n }\n\n // Then fan out to generic handlers (for streaming data, etc.)\n for (const handler of this.messageHandlers) {\n try {\n handler(parsed);\n } catch (err) {\n this.logger?.error?.('WS message handler threw', { error: err });\n }\n }\n };\n } catch (err) {\n this.connectingPromise = null;\n reject(err);\n }\n });\n\n return this.connectingPromise;\n }\n\n /**\n * Close the WebSocket and prevent automatic reconnects\n * until `connect()` is called again.\n */\n close(code?: number, reason?: string): void {\n this.manuallyClosed = true;\n if (this.ws && this.ws.readyState === 1) {\n this.ws.close(code, reason);\n }\n }\n\n /**\n * Register a message handler. Returns an unsubscribe function.\n *\n * Streaming channels (ticker, book, trades, balances, etc.)\n * should typically be consumed via this hook.\n */\n addMessageHandler(handler: KrakenWsMessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Fire-and-forget: send arbitrary JSON over the socket.\n * Use this for pure streaming commands if you don't care\n * about the ack (e.g., manual `subscribe`).\n */\n async sendRaw(message: unknown): Promise<void> {\n // Avoid an async gap if we're already open\n if (!this.ws || this.ws.readyState !== 1) {\n await this.connect();\n }\n\n const ws = this.ws;\n if (!ws || ws.readyState !== 1) {\n throw new Error('WebSocket is not open');\n }\n\n const payload =\n typeof message === 'string' ? message : JSON.stringify(message);\n ws.send(payload);\n }\n\n /**\n * Send a Kraken-style `{ method, params, req_id }` message and\n * await the corresponding ack / response.\n */\n async request<Params extends object | undefined, Result = unknown>(\n method: string,\n params?: Params,\n options?: {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n },\n ): Promise<KrakenWsMethodResponseEnvelope<Result>> {\n // Avoid an async gap if we're already open\n if (!this.ws || this.ws.readyState !== 1) {\n await this.connect();\n }\n\n const reqId = options?.reqId ?? this.nextReqId++;\n const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;\n const attachAuthToken = options?.attachAuthToken ?? true;\n\n const baseParams: Record<string, unknown> = params\n ? { ...(params as Record<string, unknown>) }\n : {};\n\n if (\n attachAuthToken &&\n this.authToken &&\n (baseParams.token === undefined || baseParams.token === null)\n ) {\n baseParams.token = this.authToken;\n }\n\n const envelope = {\n method,\n params: Object.keys(baseParams).length ? baseParams : undefined,\n req_id: reqId,\n };\n\n this.logger?.debug?.('Kraken WS request', { envelope });\n\n return await new Promise<KrakenWsMethodResponseEnvelope<Result>>(\n (resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pending.delete(reqId);\n reject(\n new Error(\n `Kraken WS request timed out after ${timeoutMs}ms (method=${method}, req_id=${reqId})`,\n ),\n );\n }, timeoutMs);\n\n const pendingRequest: PendingRequest = {\n resolve: (msg) =>\n resolve(msg as KrakenWsMethodResponseEnvelope<Result>),\n reject,\n timeoutId,\n };\n\n this.pending.set(reqId, pendingRequest);\n\n try {\n const ws = this.ws;\n\n // ✅ Hard guard: if closed between connect() and here, reject cleanly\n if (!ws || ws.readyState !== 1) {\n clearTimeout(timeoutId);\n this.pending.delete(reqId);\n reject(\n new Error(\n `WebSocket is not open (method=${method}, req_id=${reqId})`,\n ),\n );\n return;\n }\n\n ws.send(JSON.stringify(envelope));\n } catch (err) {\n clearTimeout(timeoutId);\n this.pending.delete(reqId);\n reject(err);\n }\n },\n );\n }\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\n\n/**\n * Kraken Spot WebSocket v2 – Status channel (admin).\n *\n * This channel is special:\n * - You do NOT subscribe to it (no subscribe/unsubscribe flow).\n * - Kraken automatically sends a status message on successful connection\n * and whenever the trading engine status changes.\n *\n * We model:\n * - The message types\n * - A small helper (`onStatus`) that listens for `channel === \"status\"`.\n */\n\n/**\n * Overall trading engine state.\n *\n * - \"online\" – markets operating normally, all order types allowed.\n * - \"maintenance\" – markets offline for maintenance, no new orders/cancels.\n * - \"cancel_only\" – only cancellations allowed, no new orders, no matching.\n * - \"post_only\" – only post-only limit orders + cancels, no matching.\n */\nexport type KrakenWsStatusSystemState =\n | 'online'\n | 'cancel_only'\n | 'maintenance'\n | 'post_only';\n\n/**\n * Payload element of the status channel.\n *\n * Kraken guarantees there is exactly one element in the `data` array.\n */\nexport interface KrakenWsStatusData {\n /**\n * Trading engine state.\n */\n system: KrakenWsStatusSystemState;\n\n /**\n * WebSocket API version, always \"v2\" for this client.\n */\n api_version: 'v2';\n\n /**\n * Unique connection identifier (useful for debugging).\n */\n connection_id: number;\n\n /**\n * Version string of the WebSocket service.\n */\n version: string;\n}\n\n/**\n * Single message on the `status` channel.\n *\n * Example shape:\n * ```json\n * {\n * \"channel\": \"status\",\n * \"type\": \"update\",\n * \"data\": [\n * {\n * \"system\": \"online\",\n * \"api_version\": \"v2\",\n * \"connection_id\": 123456,\n * \"version\": \"2.0.0\"\n * }\n * ]\n * }\n * ```\n */\nexport interface KrakenWsStatusUpdateMessage {\n channel: 'status';\n type: 'update';\n data: KrakenWsStatusData[];\n}\n\n/**\n * Handler for status updates.\n */\nexport type KrakenWsStatusHandler = (msg: KrakenWsStatusUpdateMessage) => void;\n\n/**\n * Attach a handler for status updates.\n *\n * This uses the low-level `addMessageHandler` on KrakenWebsocketBase\n * and filters for `channel === \"status\"` and `type === \"update\"`.\n *\n * Returns an unsubscribe function.\n *\n * @example\n * ```ts\n * const unsubscribe = client.admin.onStatus((msg) => {\n * console.log('Engine status:', msg.data[0].system);\n * });\n * ```\n */\nexport function onStatus(\n ws: KrakenWebsocketBase,\n handler: KrakenWsStatusHandler,\n): () => void {\n return ws.addMessageHandler((raw) => {\n if (!raw || typeof raw !== 'object') return;\n\n const msg = raw as Partial<KrakenWsStatusUpdateMessage>;\n\n if (\n msg.channel === 'status' &&\n msg.type === 'update' &&\n Array.isArray(msg.data)\n ) {\n handler(msg as KrakenWsStatusUpdateMessage);\n }\n });\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Parameters for WS v2 `ping`.\n *\n * NOTE:\n * - Kraken's spec only defines `req_id` at the top level of the message.\n * - `req_id` is handled via KrakenWebsocketBase.request options,\n * so this params object is intentionally empty.\n */\nexport interface KrakenWsPingParams {\n // Intentionally empty for now.\n // If Kraken ever adds fields to ping, they can be added here.\n}\n\n/**\n * Result payload inside the WS envelope for `ping` → `pong`.\n *\n * Kraken's docs only define optional `warnings` in `result`.\n * Most metadata (success, error, time_in, time_out, etc.) is on the outer\n * {@link KrakenWsPingResponse} envelope.\n */\nexport interface KrakenWsPingResult {\n /**\n * Advisory messages, e.g. deprecation or behaviour notices.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from `ping` (the `pong` message).\n */\nexport type KrakenWsPingResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsPingResult>;\n\n/**\n * Options for the `ping` wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsPingOptions {\n /**\n * Optional client-originated request identifier.\n * Will be sent as `req_id` and echoed back in the `pong`.\n */\n reqId?: number;\n\n /**\n * Optional timeout for this request in milliseconds.\n */\n timeoutMs?: number;\n\n /**\n * Whether to attach an auth token (if available) to this request.\n *\n * `ping` is defined on the public WS endpoint, so this is typically\n * left as `false` (the default), but the flag is exposed for symmetry.\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Send an application-level ping and await the corresponding `pong`.\n *\n * This is separate from the WebSocket protocol-level ping/pong frames,\n * and is useful as an application-level liveness check (and to measure\n * end-to-end latency).\n *\n * @example\n * ```ts\n * // Simple liveness check\n * const res = await ws.admin.ping();\n * console.log(\"pong success:\", res.success);\n * ```\n *\n * @example\n * ```ts\n * // With reqId and latency measurement\n * const res = await ws.admin.ping();\n * console.log(\"pong success:\", res.success);\n *\n * // With reqId and latency measurement\n * const res2 = await ws.admin.ping({}, { reqId: 42 });\n *\n * if (res2.success && res2.time_in && res2.time_out) {\n * const latencyMs =\n * new Date(res2.time_out).getTime() - new Date(res2.time_in).getTime();\n * console.log(\"app-level ping latency (ms):\", latencyMs);\n * }\n * ```\n */\nexport async function ping(\n ws: KrakenWebsocketBase,\n params: KrakenWsPingParams = {},\n options: KrakenWsPingOptions = {},\n): Promise<KrakenWsPingResponse> {\n return ws.request<KrakenWsPingParams, KrakenWsPingResult>('ping', params, {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n });\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\n\n/**\n * Kraken Spot WebSocket v2 – Heartbeat message.\n *\n * Heartbeats are sent automatically about once per second when there are\n * no other channel updates. There is no subscribe/unsubscribe: they’re\n * emitted globally once you’re subscribed to any channel.\n */\nexport interface KrakenWsHeartbeatMessage {\n /**\n * Channel name – \"heartbeat\" is the only reliable indicator.\n * The payload intentionally has no other fields per Kraken docs.\n */\n channel: 'heartbeat';\n\n // Kraken might add fields in the future; keep this open.\n [key: string]: unknown;\n}\n\n/**\n * Handler signature for heartbeat messages.\n */\nexport type KrakenWsHeartbeatHandler = (msg: KrakenWsHeartbeatMessage) => void;\n\n/**\n * Register a handler for heartbeat messages.\n *\n * Internally this uses `KrakenWebsocketBase.addMessageHandler` and simply\n * filters on `channel === \"heartbeat\"`.\n *\n * Returns an unsubscribe function that removes this specific handler.\n *\n * @example\n * ```ts\n * // Track last-seen heartbeat\n * let lastHeartbeat = 0;\n *\n * const unsubscribe = onHeartbeat(ws, () => {\n * lastHeartbeat = Date.now();\n * });\n *\n * setInterval(() => {\n * if (Date.now() - lastHeartbeat > 5_000) {\n * console.warn('No heartbeat in > 5s, connection might be stale');\n * }\n * }, 1_000);\n * ```\n */\nexport function onHeartbeat(\n ws: KrakenWebsocketBase,\n handler: KrakenWsHeartbeatHandler,\n): () => void {\n return ws.addMessageHandler((msg) => {\n if (!msg || typeof msg !== 'object') return;\n const anyMsg = msg as { channel?: unknown };\n\n if (anyMsg.channel === 'heartbeat') {\n handler(anyMsg as KrakenWsHeartbeatMessage);\n }\n });\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\nimport * as Status from './status';\nimport * as Ping from './ping';\nimport * as Heartbeat from './heartbeat';\n\n/**\n * Kraken Spot WebSocket v2 – Admin / service utilities.\n *\n * Covers:\n * - status: engine / API status stream\n * - ping: application-level ping/pong\n * - heartbeat: low-level liveness ticks\n */\nexport class KrakenSpotWsAdminApi {\n constructor(private readonly ws: KrakenWebsocketBase) {}\n\n /**\n * Application-level ping → pong.\n *\n * @example\n * ```ts\n * const res = await client.admin.ping({}, { reqId: 123 });\n * console.log('pong?', res.success, res.time_out);\n * ```\n */\n ping(\n params: Ping.KrakenWsPingParams = {},\n options: Ping.KrakenWsPingOptions = {},\n ) {\n return Ping.ping(this.ws, params, options);\n }\n\n /**\n * Subscribe to engine status updates.\n *\n * Returns an unsubscribe function.\n *\n * @example\n * ```ts\n * const unsubscribe = client.admin.onStatus((msg) => {\n * console.log('Engine status:', msg.data[0].system);\n * });\n * ```\n */\n onStatus(handler: Status.KrakenWsStatusHandler) {\n return Status.onStatus(this.ws, handler);\n }\n\n /**\n * Subscribe to heartbeat messages.\n *\n * Returns an unsubscribe function.\n *\n * @example\n * ```ts\n * client.admin.onHeartbeat(() => {\n * console.log('Got heartbeat');\n * });\n * ```\n */\n onHeartbeat(handler: Heartbeat.KrakenWsHeartbeatHandler) {\n return Heartbeat.onHeartbeat(this.ws, handler);\n }\n}\n\n// Re-export types for consumers\nexport type KrakenWsPingParams = Ping.KrakenWsPingParams;\nexport type KrakenWsPingResult = Ping.KrakenWsPingResult;\nexport type KrakenWsPingResponse = Ping.KrakenWsPingResponse;\n\nexport type KrakenWsStatusUpdateMessage = Status.KrakenWsStatusUpdateMessage;\nexport type KrakenWsStatusData = Status.KrakenWsStatusData;\n\nexport type KrakenWsHeartbeatMessage = Heartbeat.KrakenWsHeartbeatMessage;\nexport type KrakenWsHeartbeatHandler = Heartbeat.KrakenWsHeartbeatHandler;\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Event trigger for the ticker channel.\n *\n * - \"bbo\" → update on best-bid-offer changes\n * - \"trades\" → update on every trade (default)\n */\nexport type KrakenWsTickerEventTrigger = 'bbo' | 'trades';\n\n/**\n * Ticker payload (top of book + 24h stats).\n *\n * The ticker element is always the first (and only) item in the `data` array.\n */\nexport interface KrakenWsTickerData {\n /** Best ask price. */\n ask: number;\n\n /** Best ask quantity. */\n ask_qty: number;\n\n /** Best bid price. */\n bid: number;\n\n /** Best bid quantity. */\n bid_qty: number;\n\n /** 24-hour price change (in quote currency). */\n change: number;\n\n /** 24-hour price change (percentage points). */\n change_pct: number;\n\n /** 24-hour highest trade price. */\n high: number;\n\n /** Last traded price (only guaranteed if traded within past 24h). */\n last: number;\n\n /** 24-hour lowest trade price. */\n low: number;\n\n /** The symbol of the currency pair (e.g. \"BTC/USD\"). */\n symbol: string;\n\n /** 24-hour traded volume (in base currency). */\n volume: number;\n\n /** 24-hour volume weighted average price. */\n vwap: number;\n}\n\n/**\n * Snapshot message for the `ticker` channel.\n *\n * `data` will always contain exactly one ticker entry.\n */\nexport interface KrakenWsTickerSnapshotMessage {\n channel: 'ticker';\n type: 'snapshot';\n data: KrakenWsTickerData[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `ticker` channel.\n *\n * `data` will always contain exactly one ticker entry.\n */\nexport interface KrakenWsTickerUpdateMessage {\n channel: 'ticker';\n type: 'update';\n data: KrakenWsTickerData[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible ticker messages.\n */\nexport type KrakenWsTickerMessage =\n | KrakenWsTickerSnapshotMessage\n | KrakenWsTickerUpdateMessage;\n\n/**\n * Parameters for subscribing to the `ticker` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"ticker\" by the helper.\n */\nexport interface KrakenWsTickerSubscribeParams {\n /**\n * A list of currency pairs, e.g. [\"BTC/USD\", \"MATIC/GBP\"].\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * The book event that triggers updates.\n * - \"bbo\" → on best-bid-offer change.\n * - \"trades\" → on trade event (default).\n */\n event_trigger?: KrakenWsTickerEventTrigger;\n\n /**\n * Whether to request an initial snapshot.\n * Default: true.\n */\n snapshot?: boolean;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeTicker wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsTickerSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * For public channels this should generally be false (default).\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for ticker.\n */\nexport interface KrakenWsTickerSubscribeResult {\n channel: 'ticker';\n /**\n * List of subscribed symbols.\n */\n symbol: ReadonlyArray<string>;\n /**\n * Event trigger used for updates.\n */\n event_trigger?: KrakenWsTickerEventTrigger;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for ticker.\n */\nexport type KrakenWsTickerSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsTickerSubscribeResult>;\n\n/**\n * Subscribe to the `ticker` channel.\n *\n * Streams:\n * - a **snapshot** (if `snapshot: true`, default), then\n * - **update** messages on trade events or BBO changes (depending on `event_trigger`).\n *\n * @example\n * ```ts\n * // 1) Subscribe to BTC/USD and ETH/USD ticker\n * const ack = await wsClient.marketData.subscribeTicker(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * event_trigger: \"trades\",\n * },\n * { reqId: 1 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"ticker subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"ticker\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const tmsg = msg as KrakenWsTickerMessage;\n * const ticker = tmsg.data[0]; // always a single element\n *\n * console.log(\n * \"[ticker]\",\n * ticker.symbol,\n * \"bid:\",\n * ticker.bid,\n * \"ask:\",\n * ticker.ask,\n * \"last:\",\n * ticker.last,\n * );\n * }\n * });\n * ```\n */\nexport async function subscribeTicker(\n ws: KrakenWebsocketBase,\n params: KrakenWsTickerSubscribeParams,\n options: KrakenWsTickerSubscribeOptions = {},\n): Promise<KrakenWsTickerSubscribeResponse> {\n const body = {\n channel: 'ticker' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsTickerSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `ticker` channel.\n *\n * NOTE:\n * - Must match the symbols (and optionally event_trigger) you want to remove.\n */\nexport interface KrakenWsTickerUnsubscribeParams {\n /**\n * A list of currency pairs to unsubscribe.\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * The book event that triggers updates.\n * Must match the subscription combination.\n */\n event_trigger?: KrakenWsTickerEventTrigger;\n\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeTicker wrapper.\n */\nexport interface KrakenWsTickerUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for ticker.\n */\nexport interface KrakenWsTickerUnsubscribeResult {\n channel: 'ticker';\n symbol: ReadonlyArray<string>;\n event_trigger?: KrakenWsTickerEventTrigger;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for ticker.\n */\nexport type KrakenWsTickerUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsTickerUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `ticker` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeTicker({\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * });\n *\n * if (!ack.success) {\n * console.error(\"ticker unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeTicker(\n ws: KrakenWebsocketBase,\n params: KrakenWsTickerUnsubscribeParams,\n options: KrakenWsTickerUnsubscribeOptions = {},\n): Promise<KrakenWsTickerUnsubscribeResponse> {\n const body = {\n channel: 'ticker' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsTickerUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Allowed depth values for the book channel.\n */\nexport type KrakenWsBookDepth = 10 | 25 | 100 | 500 | 1000;\n\n/**\n * Single price level entry in the L2 order book.\n */\nexport interface KrakenWsBookLevel {\n /** Price at this level. */\n price: number;\n /** Aggregate quantity at this level. */\n qty: number;\n}\n\n/**\n * Core book payload (used in both snapshot and update).\n *\n * The book element is always the first and only item in the `data` array.\n */\nexport interface KrakenWsBookData {\n /** Ask side levels. */\n asks: KrakenWsBookLevel[];\n /** Bid side levels. */\n bids: KrakenWsBookLevel[];\n /** CRC32 checksum for top 10 bids/asks. */\n checksum: number;\n /** The symbol of the currency pair (e.g. \"BTC/USD\"). */\n symbol: string;\n}\n\n/**\n * Snapshot message for the `book` channel.\n */\nexport interface KrakenWsBookSnapshotMessage {\n channel: 'book';\n type: 'snapshot';\n data: KrakenWsBookData[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `book` channel.\n *\n * Includes a timestamp for the book update.\n */\nexport interface KrakenWsBookUpdateMessage {\n channel: 'book';\n type: 'update';\n data: Array<\n KrakenWsBookData & {\n /**\n * Order book update timestamp (RFC3339 with fractional seconds).\n */\n timestamp: string;\n }\n >;\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible book messages.\n */\nexport type KrakenWsBookMessage =\n | KrakenWsBookSnapshotMessage\n | KrakenWsBookUpdateMessage;\n\n/**\n * Parameters for subscribing to the `book` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"book\" by the helper.\n */\nexport interface KrakenWsBookSubscribeParams {\n /**\n * A list of currency pairs, e.g. [\"BTC/USD\", \"MATIC/GBP\"].\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Number of price levels to receive.\n * Default: 10.\n */\n depth?: KrakenWsBookDepth;\n\n /**\n * Whether to request an initial snapshot.\n * Default: true.\n */\n snapshot?: boolean;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeBook wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsBookSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * For public channels this should generally be false (default).\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for book.\n */\nexport interface KrakenWsBookSubscribeResult {\n channel: 'book';\n symbol: ReadonlyArray<string>;\n depth?: KrakenWsBookDepth;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for book.\n */\nexport type KrakenWsBookSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsBookSubscribeResult>;\n\n/**\n * Subscribe to the `book` (L2 order book) channel.\n *\n * Streams:\n * - a **snapshot** of bids/asks up to `depth` levels, then\n * - **update** messages containing incremental changes + checksum.\n *\n * @example\n * ```ts\n * // 1) Subscribe to BTC/USD and ETH/USD L2 book with 25 levels\n * const ack = await wsClient.marketData.subscribeBook(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * depth: 25,\n * },\n * { reqId: 2 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"book subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"book\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const bmsg = msg as KrakenWsBookMessage;\n * const book = bmsg.data[0]; // always a single element\n *\n * if (bmsg.type === \"snapshot\") {\n * console.log(\n * \"[book snapshot]\",\n * book.symbol,\n * \"bids:\",\n * book.bids.length,\n * \"asks:\",\n * book.asks.length,\n * );\n * } else {\n * console.log(\n * \"[book update]\",\n * book.symbol,\n * \"checksum:\",\n * book.checksum,\n * \"top bid:\",\n * book.bids[0]?.price,\n * \"top ask:\",\n * book.asks[0]?.price,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeBook(\n ws: KrakenWebsocketBase,\n params: KrakenWsBookSubscribeParams,\n options: KrakenWsBookSubscribeOptions = {},\n): Promise<KrakenWsBookSubscribeResponse> {\n const body = {\n channel: 'book' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsBookSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `book` channel.\n *\n * NOTE:\n * - Must match the symbols (and depth, if used) you want to remove.\n */\nexport interface KrakenWsBookUnsubscribeParams {\n /**\n * A list of currency pairs to unsubscribe.\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Number of price levels to unsub.\n * Must match the subscribed depth if specified.\n */\n depth?: KrakenWsBookDepth;\n\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeBook wrapper.\n */\nexport interface KrakenWsBookUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for book.\n */\nexport interface KrakenWsBookUnsubscribeResult {\n channel: 'book';\n symbol: ReadonlyArray<string>;\n depth?: KrakenWsBookDepth;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for book.\n */\nexport type KrakenWsBookUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsBookUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `book` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeBook({\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * depth: 25,\n * });\n *\n * if (!ack.success) {\n * console.error(\"book unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeBook(\n ws: KrakenWebsocketBase,\n params: KrakenWsBookUnsubscribeParams,\n options: KrakenWsBookUnsubscribeOptions = {},\n): Promise<KrakenWsBookUnsubscribeResponse> {\n const body = {\n channel: 'book' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsBookUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Allowed depth values for the level3 channel.\n */\nexport type KrakenWsLevel3Depth = 10 | 100 | 1000;\n\n/**\n * Event type for Level 3 order updates.\n *\n * - \"add\" → new order resting in the book\n * - \"modify\" → quantity modified (typically due to a fill)\n * - \"delete\" → order removed (full fill or cancel)\n */\nexport type KrakenWsLevel3OrderEventType = 'add' | 'modify' | 'delete';\n\n/**\n * Single Level 3 order snapshot entry.\n *\n * Used in the initial snapshot (no event field).\n */\nexport interface KrakenWsLevel3OrderSnapshotEntry {\n /** Kraken order identifier of the order in the book. */\n order_id: string;\n\n /** Limit price of the order. */\n limit_price: number;\n\n /** Remaining visible quantity. */\n order_qty: number;\n\n /** Time the order was inserted or amended (RFC3339). */\n timestamp: string;\n}\n\n/**\n * Single Level 3 order event entry (update).\n *\n * Used in the update stream (adds/modifies/deletes).\n */\nexport interface KrakenWsLevel3OrderEventEntry extends KrakenWsLevel3OrderSnapshotEntry {\n /** Type of order event. */\n event: KrakenWsLevel3OrderEventType;\n}\n\n/**\n * Core Level 3 snapshot payload.\n *\n * The book element is always the first and only item in the `data` array.\n */\nexport interface KrakenWsLevel3SnapshotData {\n /** Symbol of the currency pair, e.g. \"BTC/USD\". */\n symbol: string;\n\n /** List of resting bid orders in the book. */\n bids: KrakenWsLevel3OrderSnapshotEntry[];\n\n /** List of resting ask orders in the book. */\n asks: KrakenWsLevel3OrderSnapshotEntry[];\n\n /** CRC32 checksum for the top 10 price levels on both sides. */\n checksum: number;\n\n /** Time this market data message was generated (RFC3339). */\n timestamp: string;\n}\n\n/**\n * Core Level 3 update payload.\n *\n * The book element is always the first and only item in the `data` array.\n */\nexport interface KrakenWsLevel3UpdateData {\n /** Symbol of the currency pair, e.g. \"BTC/USD\". */\n symbol: string;\n\n /** Time this market data message was generated (RFC3339). */\n timestamp: string;\n\n /** CRC32 checksum for the top 10 price levels on both sides. */\n checksum: number;\n\n /**\n * Order events on bid side.\n *\n * Each entry describes an add/modify/delete event for an order.\n */\n bids: KrakenWsLevel3OrderEventEntry[];\n\n /**\n * Order events on ask side.\n *\n * Each entry describes an add/modify/delete event for an order.\n */\n asks: KrakenWsLevel3OrderEventEntry[];\n}\n\n/**\n * Snapshot message for the `level3` channel.\n */\nexport interface KrakenWsLevel3SnapshotMessage {\n channel: 'level3';\n type: 'snapshot';\n data: KrakenWsLevel3SnapshotData[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `level3` channel.\n */\nexport interface KrakenWsLevel3UpdateMessage {\n channel: 'level3';\n type: 'update';\n data: KrakenWsLevel3UpdateData[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible Level 3 messages.\n */\nexport type KrakenWsLevel3Message =\n | KrakenWsLevel3SnapshotMessage\n | KrakenWsLevel3UpdateMessage;\n\n/**\n * Parameters for subscribing to the `level3` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"level3\" by the helper.\n * - `token` is required (authenticated feed).\n */\nexport interface KrakenWsLevel3SubscribeParams {\n /**\n * A list of currency pairs, e.g. [\"BTC/USD\", \"MATIC/GBP\"].\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Number of price levels to receive.\n * Default: 10.\n */\n depth?: KrakenWsLevel3Depth;\n\n /**\n * Whether to request an initial snapshot.\n * Default: true.\n */\n snapshot?: boolean;\n\n /**\n * Auth session token from the REST API.\n */\n token: string;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeLevel3 wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsLevel3SubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * For authenticated channels, this should generally be true (default).\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for level3.\n */\nexport interface KrakenWsLevel3SubscribeResult {\n channel: 'level3';\n symbol: ReadonlyArray<string>;\n depth?: KrakenWsLevel3Depth;\n snapshot?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for level3.\n */\nexport type KrakenWsLevel3SubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsLevel3SubscribeResult>;\n\n/**\n * Subscribe to the `level3` (L3 order book) channel.\n *\n * Streams:\n * - a **snapshot** of individual orders up to `depth` price levels, then\n * - **update** messages with per-order add/modify/delete events.\n *\n * @example\n * ```ts\n * // 1) Subscribe to BTC/USD L3 book with 100 levels\n * const ack = await wsClient.marketData.subscribeLevel3(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 100,\n * token: myAuthToken,\n * },\n * { reqId: 42 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"level3 subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"level3\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const l3msg = msg as KrakenWsLevel3Message;\n * const book = l3msg.data[0]; // always a single element\n *\n * if (l3msg.type === \"snapshot\") {\n * console.log(\n * \"[level3 snapshot]\",\n * book.symbol,\n * \"bids:\",\n * book.bids.length,\n * \"asks:\",\n * book.asks.length,\n * );\n * } else {\n * console.log(\n * \"[level3 update]\",\n * book.symbol,\n * \"events (bids):\",\n * book.bids.length,\n * \"events (asks):\",\n * book.asks.length,\n * \"checksum:\",\n * book.checksum,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeLevel3(\n ws: KrakenWebsocketBase,\n params: KrakenWsLevel3SubscribeParams,\n options: KrakenWsLevel3SubscribeOptions = {},\n): Promise<KrakenWsLevel3SubscribeResponse> {\n const body = {\n channel: 'level3' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsLevel3SubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n // Authenticated feed by default\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `level3` channel.\n *\n * NOTE:\n * - Must match the symbols (and depth, if used) you want to remove.\n * - `token` is required (authenticated feed).\n */\nexport interface KrakenWsLevel3UnsubscribeParams {\n /**\n * A list of currency pairs to unsubscribe.\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Number of price levels to unsubscribe.\n * Must match the subscribed depth if specified.\n */\n depth?: KrakenWsLevel3Depth;\n\n /**\n * Auth session token from the REST API.\n */\n token: string;\n\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeLevel3 wrapper.\n */\nexport interface KrakenWsLevel3UnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for level3.\n */\nexport interface KrakenWsLevel3UnsubscribeResult {\n channel: 'level3';\n symbol: ReadonlyArray<string>;\n depth?: KrakenWsLevel3Depth;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for level3.\n */\nexport type KrakenWsLevel3UnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsLevel3UnsubscribeResult>;\n\n/**\n * Unsubscribe from the `level3` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeLevel3(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 100,\n * token: myAuthToken,\n * },\n * { reqId: 43 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"level3 unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeLevel3(\n ws: KrakenWebsocketBase,\n params: KrakenWsLevel3UnsubscribeParams,\n options: KrakenWsLevel3UnsubscribeOptions = {},\n): Promise<KrakenWsLevel3UnsubscribeResponse> {\n const body = {\n channel: 'level3' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsLevel3UnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Allowed OHLC intervals in minutes.\n */\nexport type KrakenWsOhlcInterval =\n | 1\n | 5\n | 15\n | 30\n | 60\n | 240\n | 1440\n | 10080\n | 21600;\n\n/**\n * Single OHLC candle entry.\n *\n * Used in both snapshot and update messages.\n */\nexport interface KrakenWsOhlcCandle {\n /** Symbol of the currency pair, e.g. \"BTC/USD\". */\n symbol: string;\n\n /** Opening trade price within the interval. */\n open: number;\n\n /** Highest trade price within the interval. */\n high: number;\n\n /** Lowest trade price within the interval. */\n low: number;\n\n /** Last trade price within the interval. */\n close: number;\n\n /** Volume-weighted average trade price within the interval. */\n vwap: number;\n\n /** Number of trades within the interval. */\n trades: number;\n\n /** Total traded volume (base asset) within the interval. */\n volume: number;\n\n /**\n * Timestamp of the start of the interval (RFC3339 with fractional seconds).\n */\n interval_begin: string;\n\n /**\n * Interval timeframe in minutes.\n */\n interval: KrakenWsOhlcInterval;\n\n /**\n * DEPRECATED: Use `interval_begin`.\n *\n * Timestamp of start of the interval.\n */\n timestamp?: string;\n}\n\n/**\n * Snapshot message for the `ohlc` channel.\n */\nexport interface KrakenWsOhlcSnapshotMessage {\n channel: 'ohlc';\n type: 'snapshot';\n /**\n * List of candle events.\n */\n data: KrakenWsOhlcCandle[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `ohlc` channel.\n */\nexport interface KrakenWsOhlcUpdateMessage {\n channel: 'ohlc';\n type: 'update';\n /**\n * List of candle events.\n */\n data: KrakenWsOhlcCandle[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible OHLC messages.\n */\nexport type KrakenWsOhlcMessage =\n | KrakenWsOhlcSnapshotMessage\n | KrakenWsOhlcUpdateMessage;\n\n/**\n * Parameters for subscribing to the `ohlc` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"ohlc\" by the helper.\n */\nexport interface KrakenWsOhlcSubscribeParams {\n /**\n * A list of currency pairs, e.g. [\"BTC/USD\", \"MATIC/GBP\"].\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Interval timeframe in minutes.\n *\n * If omitted, Kraken will use its default (docs list valid values only).\n */\n interval?: KrakenWsOhlcInterval;\n\n /**\n * Whether to request an initial snapshot.\n * Default: true.\n */\n snapshot?: boolean;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeOhlc wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsOhlcSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * OHLC is a public channel; auth token is not required.\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for ohlc.\n */\nexport interface KrakenWsOhlcSubscribeResult {\n channel: 'ohlc';\n symbol: ReadonlyArray<string>;\n interval?: KrakenWsOhlcInterval;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for ohlc.\n */\nexport type KrakenWsOhlcSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsOhlcSubscribeResult>;\n\n/**\n * Subscribe to the `ohlc` (candles) channel.\n *\n * Streams:\n * - a **snapshot** of recent candles for the requested pairs/interval, then\n * - **update** messages on trade events.\n *\n * @example\n * ```ts\n * // 1) Subscribe to 1-minute BTC/USD and 5-minute ETH/USD candles\n * const ack = await wsClient.marketData.subscribeOhlc(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * interval: 1,\n * },\n * { reqId: 10 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"ohlc subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"ohlc\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const cmsg = msg as KrakenWsOhlcMessage;\n *\n * for (const candle of cmsg.data) {\n * console.log(\n * `[${cmsg.type}]`,\n * candle.symbol,\n * \"interval:\",\n * candle.interval,\n * \"open:\",\n * candle.open,\n * \"high:\",\n * candle.high,\n * \"low:\",\n * candle.low,\n * \"close:\",\n * candle.close,\n * \"volume:\",\n * candle.volume,\n * \"begin:\",\n * candle.interval_begin,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeOhlc(\n ws: KrakenWebsocketBase,\n params: KrakenWsOhlcSubscribeParams,\n options: KrakenWsOhlcSubscribeOptions = {},\n): Promise<KrakenWsOhlcSubscribeResponse> {\n const body = {\n channel: 'ohlc' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsOhlcSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `ohlc` channel.\n *\n * NOTE:\n * - Must match the symbols (and interval, if used) you want to remove.\n */\nexport interface KrakenWsOhlcUnsubscribeParams {\n /**\n * A list of currency pairs to unsubscribe.\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Interval timeframe in minutes (must match the subscribed interval).\n */\n interval?: KrakenWsOhlcInterval;\n\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeOhlc wrapper.\n */\nexport interface KrakenWsOhlcUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for ohlc.\n */\nexport interface KrakenWsOhlcUnsubscribeResult {\n channel: 'ohlc';\n symbol: ReadonlyArray<string>;\n interval?: KrakenWsOhlcInterval;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for ohlc.\n */\nexport type KrakenWsOhlcUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsOhlcUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `ohlc` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeOhlc(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * interval: 1,\n * },\n * { reqId: 11 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"ohlc unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeOhlc(\n ws: KrakenWebsocketBase,\n params: KrakenWsOhlcUnsubscribeParams,\n options: KrakenWsOhlcUnsubscribeOptions = {},\n): Promise<KrakenWsOhlcUnsubscribeResponse> {\n const body = {\n channel: 'ohlc' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsOhlcUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Trade side for the taker order.\n */\nexport type KrakenWsTradeSide = 'buy' | 'sell';\n\n/**\n * Taker order type for a trade event.\n */\nexport type KrakenWsTradeOrderType = 'limit' | 'market';\n\n/**\n * Single trade event from the `trade` channel.\n *\n * Used in both snapshot and update messages.\n */\nexport interface KrakenWsTradeEntry {\n /**\n * Symbol of the currency pair, e.g. \"BTC/USD\".\n */\n symbol: string;\n\n /**\n * Side of the taker order (\"buy\" or \"sell\").\n */\n side: KrakenWsTradeSide;\n\n /**\n * Size of the trade (in base asset).\n */\n qty: number;\n\n /**\n * Average price of the trade.\n */\n price: number;\n\n /**\n * Order type of the taker order (\"limit\" or \"market\").\n */\n ord_type: KrakenWsTradeOrderType;\n\n /**\n * Trade identifier – sequence number, unique per book.\n */\n trade_id: number;\n\n /**\n * Book order update timestamp (RFC3339 with fractional seconds).\n */\n timestamp: string;\n}\n\n/**\n * Snapshot message for the `trade` channel.\n *\n * Snapshot reflects the most recent 50 trades.\n */\nexport interface KrakenWsTradeSnapshotMessage {\n channel: 'trade';\n type: 'snapshot';\n /**\n * List of trade events (most recent 50).\n */\n data: KrakenWsTradeEntry[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `trade` channel.\n *\n * Multiple trades may be batched in a single message.\n */\nexport interface KrakenWsTradeUpdateMessage {\n channel: 'trade';\n type: 'update';\n /**\n * List of trade events.\n */\n data: KrakenWsTradeEntry[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible `trade` channel messages.\n */\nexport type KrakenWsTradeMessage =\n | KrakenWsTradeSnapshotMessage\n | KrakenWsTradeUpdateMessage;\n\n/**\n * Parameters for subscribing to the `trade` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"trade\" by the helper.\n */\nexport interface KrakenWsTradeSubscribeParams {\n /**\n * A list of currency pairs, e.g. [\"BTC/USD\", \"MATIC/GBP\"].\n */\n symbol: ReadonlyArray<string>;\n\n /**\n * Whether to request an initial snapshot.\n * Default: false (Kraken default).\n */\n snapshot?: boolean;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeTrade wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsTradeSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * Trades is a public channel; auth token is not required.\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for `trade`.\n */\nexport interface KrakenWsTradeSubscribeResult {\n channel: 'trade';\n symbol: ReadonlyArray<string>;\n snapshot?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for `trade`.\n */\nexport type KrakenWsTradeSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsTradeSubscribeResult>;\n\n/**\n * Subscribe to the `trade` channel.\n *\n * Streams:\n * - an optional **snapshot** of the most recent 50 trades per symbol, then\n * - **update** messages for new trades as they occur.\n *\n * @example\n * ```ts\n * // 1) Subscribe to trades for BTC/USD and ETH/USD\n * const ack = await wsClient.marketData.subscribeTrade(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * snapshot: true,\n * },\n * { reqId: 1001 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"trade subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"trade\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const tmsg = msg as KrakenWsTradeMessage;\n *\n * for (const trade of tmsg.data) {\n * console.log(\n * `[${tmsg.type}]`,\n * trade.symbol,\n * trade.side,\n * \"qty:\",\n * trade.qty,\n * \"price:\",\n * trade.price,\n * \"ord_type:\",\n * trade.ord_type,\n * \"trade_id:\",\n * trade.trade_id,\n * \"ts:\",\n * trade.timestamp,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeTrade(\n ws: KrakenWebsocketBase,\n params: KrakenWsTradeSubscribeParams,\n options: KrakenWsTradeSubscribeOptions = {},\n): Promise<KrakenWsTradeSubscribeResponse> {\n const body = {\n channel: 'trade' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsTradeSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `trade` channel.\n *\n * NOTE:\n * - Must match the symbols you want to remove.\n */\nexport interface KrakenWsTradeUnsubscribeParams {\n /**\n * A list of currency pairs to unsubscribe.\n */\n symbol: ReadonlyArray<string>;\n\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeTrade wrapper.\n */\nexport interface KrakenWsTradeUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for `trade`.\n */\nexport interface KrakenWsTradeUnsubscribeResult {\n channel: 'trade';\n symbol: ReadonlyArray<string>;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for `trade`.\n */\nexport type KrakenWsTradeUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsTradeUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `trade` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeTrade(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * },\n * { reqId: 1002 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"trade unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeTrade(\n ws: KrakenWebsocketBase,\n params: KrakenWsTradeUnsubscribeParams,\n options: KrakenWsTradeUnsubscribeOptions = {},\n): Promise<KrakenWsTradeUnsubscribeResponse> {\n const body = {\n channel: 'trade' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsTradeUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Status values for assets in the instrument feed.\n */\nexport type KrakenWsInstrumentAssetStatus =\n | 'depositonly'\n | 'disabled'\n | 'enabled'\n | 'fundingtemporarilydisabled'\n | 'withdrawalonly'\n | 'workinprogress';\n\n/**\n * Status values for pairs in the instrument feed.\n */\nexport type KrakenWsInstrumentPairStatus =\n | 'cancel_only'\n | 'delisted'\n | 'limit_only'\n | 'maintenance'\n | 'online'\n | 'post_only'\n | 'reduce_only'\n | 'work_in_progress';\n\n/**\n * Single asset entry in the instrument feed.\n */\nexport interface KrakenWsInstrumentAsset {\n /** Asset identifier (e.g. \"XBT\", \"USD\"). */\n id: string;\n\n /** Flag if asset is borrowable. */\n borrowable: boolean;\n\n /** Valuation as margin collateral (if applicable). */\n collateral_value: number;\n\n /** Interest rate to borrow the asset. */\n margin_rate: number;\n\n /** Maximum precision for asset ledger / balances. */\n precision: number;\n\n /** Recommended display precision. */\n precision_display: number;\n\n /**\n * Multiplier of the tokenised asset (fixed conversion rate of the token).\n * Only meaningful for tokenized assets / xStocks.\n */\n multiplier?: number;\n\n /** Status of asset. */\n status: KrakenWsInstrumentAssetStatus;\n\n /** Allow future extension without breaking typing. */\n [key: string]: unknown;\n}\n\n/**\n * Single pair entry in the instrument feed.\n */\nexport interface KrakenWsInstrumentPair {\n /** Asset identifier of the base currency. */\n base: string;\n\n /** Asset identifier of the quote currency. */\n quote: string;\n\n /** Minimum cost (price * qty) for new orders (string as in docs). */\n cost_min: string;\n\n /** Maximum precision used for cost prices. */\n cost_precision: number;\n\n /** Whether the pair has an index available (e.g. for stop-loss triggers). */\n has_index: boolean;\n\n /** Whether the pair can be traded on margin. */\n marginable: boolean;\n\n /** Initial margin requirement (percent) – marginable pairs only. */\n margin_initial?: number;\n\n /** Limit for long positions – marginable pairs only. */\n position_limit_long?: number;\n\n /** Limit for short positions – marginable pairs only. */\n position_limit_short?: number;\n\n /** Minimum price increment for new orders. */\n price_increment: number;\n\n /** Maximum precision used for order prices. */\n price_precision: number;\n\n /** Minimum quantity increment for new orders. */\n qty_increment: number;\n\n /** Minimum quantity (base currency) for new orders. */\n qty_min: number;\n\n /** Maximum precision used for order quantities. */\n qty_precision: number;\n\n /** Status of pair. */\n status: KrakenWsInstrumentPairStatus;\n\n /** The symbol of the currency pair, e.g. \"BTC/USD\". */\n symbol: string;\n\n /**\n * DEPRECATED: Use `price_increment`.\n * Minimum price increment for new orders.\n */\n tick_size?: number;\n\n [key: string]: unknown;\n}\n\n/**\n * Instrument payload: reference data for active assets and tradable pairs.\n */\nexport interface KrakenWsInstrumentData {\n /** List of assets. */\n assets: KrakenWsInstrumentAsset[];\n /** List of tradable pairs. */\n pairs: KrakenWsInstrumentPair[];\n\n [key: string]: unknown;\n}\n\n/**\n * Snapshot message for the `instrument` channel.\n *\n * Snapshot provides reference data of all active assets and tradable pairs.\n */\nexport interface KrakenWsInstrumentSnapshotMessage {\n channel: 'instrument';\n type: 'snapshot';\n data: KrakenWsInstrumentData;\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Update message for the `instrument` channel.\n *\n * Updates stream changes to assets / pairs over time.\n */\nexport interface KrakenWsInstrumentUpdateMessage {\n channel: 'instrument';\n type: 'update';\n data: KrakenWsInstrumentData;\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible `instrument` channel messages.\n */\nexport type KrakenWsInstrumentMessage =\n | KrakenWsInstrumentSnapshotMessage\n | KrakenWsInstrumentUpdateMessage;\n\n/**\n * Parameters for subscribing to the `instrument` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"instrument\" by the helper.\n */\nexport interface KrakenWsInstrumentSubscribeParams {\n /**\n * If true, include tokenized assets / xStocks in the response.\n * If false or omitted, include crypto spot pairs only.\n */\n include_tokenized_assets?: boolean;\n\n /**\n * Whether to request an initial snapshot.\n * Default: true (Kraken default).\n */\n snapshot?: boolean;\n\n /**\n * Index signature so this type satisfies Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeInstrument wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsInstrumentSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n /**\n * Instrument is a public channel; auth token is not required.\n */\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for `instrument`.\n */\nexport interface KrakenWsInstrumentSubscribeResult {\n channel: 'instrument';\n include_tokenized_assets?: boolean;\n snapshot?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for `instrument`.\n */\nexport type KrakenWsInstrumentSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsInstrumentSubscribeResult>;\n\n/**\n * Subscribe to the `instrument` channel.\n *\n * Streams:\n * - a **snapshot** of all active assets and tradable pairs (by default),\n * - plus **update** messages when reference data changes.\n *\n * @example\n * ```ts\n * // 1) Subscribe to instrument feed (crypto only)\n * const ack = await wsClient.marketData.subscribeInstrument(\n * {\n * snapshot: true,\n * },\n * { reqId: 2001 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"instrument subscribe error:\", ack.error);\n * } else {\n * console.log(\"instrument subscribed:\", ack.result);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"instrument\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const imsg = msg as KrakenWsInstrumentMessage;\n *\n * console.log(`[${imsg.type}] assets:`, imsg.data.assets.length, \"pairs:\", imsg.data.pairs.length);\n *\n * // Example: log the first BTC/USD pair if present\n * const btcUsd = imsg.data.pairs.find((p) => p.symbol === \"BTC/USD\");\n * if (btcUsd) {\n * console.log(\n * \"BTC/USD price_increment:\",\n * btcUsd.price_increment,\n * \"qty_min:\",\n * btcUsd.qty_min,\n * \"marginable:\",\n * btcUsd.marginable,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeInstrument(\n ws: KrakenWebsocketBase,\n params: KrakenWsInstrumentSubscribeParams = {},\n options: KrakenWsInstrumentSubscribeOptions = {},\n): Promise<KrakenWsInstrumentSubscribeResponse> {\n const body = {\n channel: 'instrument' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsInstrumentSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `instrument` channel.\n *\n * NOTE:\n * - Kraken's API only requires `channel` for this unsubscribe.\n * - This is kept as an object for consistency / future extensibility.\n */\nexport interface KrakenWsInstrumentUnsubscribeParams {\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeInstrument wrapper.\n */\nexport interface KrakenWsInstrumentUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for `instrument`.\n */\nexport interface KrakenWsInstrumentUnsubscribeResult {\n channel: 'instrument';\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for `instrument`.\n */\nexport type KrakenWsInstrumentUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsInstrumentUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `instrument` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.unsubscribeInstrument(\n * {},\n * { reqId: 2002 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"instrument unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeInstrument(\n ws: KrakenWebsocketBase,\n params: KrakenWsInstrumentUnsubscribeParams = {},\n options: KrakenWsInstrumentUnsubscribeOptions = {},\n): Promise<KrakenWsInstrumentUnsubscribeResponse> {\n const body = {\n channel: 'instrument' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsInstrumentUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? false,\n },\n );\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\n\nimport * as Ticker from './ticker';\nimport * as Book from './book';\nimport * as Level3 from './level3';\nimport * as Ohlc from './ohlc';\nimport * as Trade from './trade';\nimport * as Instrument from './instrument';\n\n/**\n * Kraken Spot WebSocket v2 – Market Data API.\n *\n * Thin wrapper around public market data channels:\n *\n * - `ticker` – Level 1 (top of book) ticker data\n * - `book` – Level 2 order book\n * - `level3` – Level 3 per-order book (authenticated, on ws-l3)\n * - `ohlc` – Candles (OHLC)\n * - `trade` – Public trade prints\n * - `instrument` – Reference data for assets and tradable pairs\n *\n * Each method here is a thin wrapper over the corresponding\n * `subscribeXxx` / `unsubscribeXxx` helper in this folder.\n */\nexport class KrakenSpotWsMarketDataApi {\n constructor(private readonly ws: KrakenWebsocketBase) {}\n\n // -------------------------\n // TICKER (LEVEL 1)\n // -------------------------\n\n /**\n * Subscribe to the **ticker** (Level 1) channel.\n *\n * Streams:\n * - a snapshot (optional) with current L1 data per symbol\n * - update messages on **trade** or **bbo** events (depending on `event_trigger`)\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeTicker(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * event_trigger: \"trades\",\n * snapshot: true,\n * },\n * { reqId: 1001 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"ticker subscribe error:\", ack.error);\n * }\n * ```\n */\n subscribeTicker(\n params: Ticker.KrakenWsTickerSubscribeParams,\n options: Ticker.KrakenWsTickerSubscribeOptions = {},\n ) {\n return Ticker.subscribeTicker(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the **ticker** channel.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeTicker(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * },\n * { reqId: 1002 },\n * );\n * ```\n */\n unsubscribeTicker(\n params: Ticker.KrakenWsTickerUnsubscribeParams,\n options: Ticker.KrakenWsTickerUnsubscribeOptions = {},\n ) {\n return Ticker.unsubscribeTicker(this.ws, params, options);\n }\n\n // -------------------------\n // BOOK (LEVEL 2)\n // -------------------------\n\n /**\n * Subscribe to the **book** (Level 2) channel.\n *\n * Streams:\n * - a snapshot with up to `depth` levels of bids / asks\n * - updates with changed levels + CRC32 checksum\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeBook(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 100,\n * snapshot: true,\n * },\n * { reqId: 1101 },\n * );\n *\n * if (!ack.success) {\n * console.error(\"book subscribe error:\", ack.error);\n * }\n * ```\n */\n subscribeBook(\n params: Book.KrakenWsBookSubscribeParams,\n options: Book.KrakenWsBookSubscribeOptions = {},\n ) {\n return Book.subscribeBook(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the **book** (Level 2) channel.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeBook(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 100,\n * },\n * { reqId: 1102 },\n * );\n * ```\n */\n unsubscribeBook(\n params: Book.KrakenWsBookUnsubscribeParams,\n options: Book.KrakenWsBookUnsubscribeOptions = {},\n ) {\n return Book.unsubscribeBook(this.ws, params, options);\n }\n\n // -------------------------\n // LEVEL 3 (ORDERS)\n // -------------------------\n\n /**\n * Subscribe to the **level3** (per-order) book channel.\n *\n * This is the most granular order book:\n * per-order resting in the visible book (no hidden size, no in-flight orders).\n *\n * Requires the **ws-l3.kraken.com/v2** endpoint and an auth token.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeLevel3(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 10,\n * snapshot: true,\n * },\n * {\n * reqId: 1201,\n * attachAuthToken: true,\n * },\n * );\n *\n * if (!ack.success) {\n * console.error(\"level3 subscribe error:\", ack.error);\n * }\n * ```\n */\n subscribeLevel3(\n params: Level3.KrakenWsLevel3SubscribeParams,\n options: Level3.KrakenWsLevel3SubscribeOptions = {},\n ) {\n return Level3.subscribeLevel3(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the **level3** channel.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeLevel3(\n * {\n * symbol: [\"BTC/USD\"],\n * depth: 10,\n * },\n * {\n * reqId: 1202,\n * attachAuthToken: true,\n * },\n * );\n * ```\n */\n unsubscribeLevel3(\n params: Level3.KrakenWsLevel3UnsubscribeParams,\n options: Level3.KrakenWsLevel3UnsubscribeOptions = {},\n ) {\n return Level3.unsubscribeLevel3(this.ws, params, options);\n }\n\n // -------------------------\n // OHLC (CANDLES)\n // -------------------------\n\n /**\n * Subscribe to **ohlc** candles.\n *\n * Streams:\n * - a snapshot (optional) of existing candles\n * - update messages on trade events for the given interval.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeOhlc(\n * {\n * symbol: [\"BTC/USD\"],\n * interval: 1, // 1-minute candles\n * snapshot: true,\n * },\n * { reqId: 1301 },\n * );\n * ```\n */\n subscribeOhlc(\n params: Ohlc.KrakenWsOhlcSubscribeParams,\n options: Ohlc.KrakenWsOhlcSubscribeOptions = {},\n ) {\n return Ohlc.subscribeOhlc(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from **ohlc** candles.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeOhlc(\n * {\n * symbol: [\"BTC/USD\"],\n * interval: 1,\n * },\n * { reqId: 1302 },\n * );\n * ```\n */\n unsubscribeOhlc(\n params: Ohlc.KrakenWsOhlcUnsubscribeParams,\n options: Ohlc.KrakenWsOhlcUnsubscribeOptions = {},\n ) {\n return Ohlc.unsubscribeOhlc(this.ws, params, options);\n }\n\n // -------------------------\n // TRADE PRINTS\n // -------------------------\n\n /**\n * Subscribe to public **trade** prints.\n *\n * Streams:\n * - an optional snapshot (most recent 50 trades)\n * - update messages on every new trade.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeTrade(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * snapshot: true,\n * },\n * { reqId: 1401 },\n * );\n * ```\n */\n subscribeTrade(\n params: Trade.KrakenWsTradeSubscribeParams,\n options: Trade.KrakenWsTradeSubscribeOptions = {},\n ) {\n return Trade.subscribeTrade(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from **trade** prints.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeTrade(\n * {\n * symbol: [\"BTC/USD\", \"ETH/USD\"],\n * },\n * { reqId: 1402 },\n * );\n * ```\n */\n unsubscribeTrade(\n params: Trade.KrakenWsTradeUnsubscribeParams,\n options: Trade.KrakenWsTradeUnsubscribeOptions = {},\n ) {\n return Trade.unsubscribeTrade(this.ws, params, options);\n }\n\n // -------------------------\n // INSTRUMENT METADATA\n // -------------------------\n\n /**\n * Subscribe to **instrument** reference data.\n *\n * Streams:\n * - a snapshot of all active assets and tradable pairs\n * - update messages as metadata changes.\n *\n * @example\n * ```ts\n * const ack = await wsClient.marketData.subscribeInstrument(\n * {\n * snapshot: true,\n * include_tokenized_assets: false,\n * },\n * { reqId: 1501 },\n * );\n * ```\n */\n subscribeInstrument(\n params: Instrument.KrakenWsInstrumentSubscribeParams = {},\n options: Instrument.KrakenWsInstrumentSubscribeOptions = {},\n ) {\n return Instrument.subscribeInstrument(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the **instrument** channel.\n *\n * @example\n * ```ts\n * await wsClient.marketData.unsubscribeInstrument(\n * {},\n * { reqId: 1502 },\n * );\n * ```\n */\n unsubscribeInstrument(\n params: Instrument.KrakenWsInstrumentUnsubscribeParams = {},\n options: Instrument.KrakenWsInstrumentUnsubscribeOptions = {},\n ) {\n return Instrument.unsubscribeInstrument(this.ws, params, options);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type re-exports for consumers\n// ---------------------------------------------------------------------------\n\n// Ticker\nexport type KrakenWsTickerData = Ticker.KrakenWsTickerData;\nexport type KrakenWsTickerSnapshotMessage =\n Ticker.KrakenWsTickerSnapshotMessage;\nexport type KrakenWsTickerUpdateMessage = Ticker.KrakenWsTickerUpdateMessage;\nexport type KrakenWsTickerMessage = Ticker.KrakenWsTickerMessage;\nexport type KrakenWsTickerSubscribeParams =\n Ticker.KrakenWsTickerSubscribeParams;\nexport type KrakenWsTickerSubscribeOptions =\n Ticker.KrakenWsTickerSubscribeOptions;\nexport type KrakenWsTickerSubscribeResponse =\n Ticker.KrakenWsTickerSubscribeResponse;\nexport type KrakenWsTickerUnsubscribeParams =\n Ticker.KrakenWsTickerUnsubscribeParams;\nexport type KrakenWsTickerUnsubscribeOptions =\n Ticker.KrakenWsTickerUnsubscribeOptions;\nexport type KrakenWsTickerUnsubscribeResponse =\n Ticker.KrakenWsTickerUnsubscribeResponse;\n\n// Book (Level 2)\nexport type KrakenWsBookLevel = Book.KrakenWsBookLevel;\nexport type KrakenWsBookSnapshotMessage = Book.KrakenWsBookSnapshotMessage;\nexport type KrakenWsBookUpdateMessage = Book.KrakenWsBookUpdateMessage;\nexport type KrakenWsBookMessage = Book.KrakenWsBookMessage;\nexport type KrakenWsBookSubscribeParams = Book.KrakenWsBookSubscribeParams;\nexport type KrakenWsBookSubscribeOptions = Book.KrakenWsBookSubscribeOptions;\nexport type KrakenWsBookSubscribeResponse = Book.KrakenWsBookSubscribeResponse;\nexport type KrakenWsBookUnsubscribeParams = Book.KrakenWsBookUnsubscribeParams;\nexport type KrakenWsBookUnsubscribeOptions =\n Book.KrakenWsBookUnsubscribeOptions;\nexport type KrakenWsBookUnsubscribeResponse =\n Book.KrakenWsBookUnsubscribeResponse;\n\n// Level 3\nexport type KrakenWsLevel3Depth = Level3.KrakenWsLevel3Depth;\nexport type KrakenWsLevel3OrderEventType = Level3.KrakenWsLevel3OrderEventType;\nexport type KrakenWsLevel3SnapshotMessage =\n Level3.KrakenWsLevel3SnapshotMessage;\nexport type KrakenWsLevel3UpdateMessage = Level3.KrakenWsLevel3UpdateMessage;\nexport type KrakenWsLevel3Message = Level3.KrakenWsLevel3Message;\nexport type KrakenWsLevel3SubscribeParams =\n Level3.KrakenWsLevel3SubscribeParams;\nexport type KrakenWsLevel3SubscribeOptions =\n Level3.KrakenWsLevel3SubscribeOptions;\nexport type KrakenWsLevel3SubscribeResponse =\n Level3.KrakenWsLevel3SubscribeResponse;\nexport type KrakenWsLevel3UnsubscribeParams =\n Level3.KrakenWsLevel3UnsubscribeParams;\nexport type KrakenWsLevel3UnsubscribeOptions =\n Level3.KrakenWsLevel3UnsubscribeOptions;\nexport type KrakenWsLevel3UnsubscribeResponse =\n Level3.KrakenWsLevel3UnsubscribeResponse;\n\n// OHLC\nexport type KrakenWsOhlcSnapshotMessage = Ohlc.KrakenWsOhlcSnapshotMessage;\nexport type KrakenWsOhlcUpdateMessage = Ohlc.KrakenWsOhlcUpdateMessage;\nexport type KrakenWsOhlcMessage = Ohlc.KrakenWsOhlcMessage;\nexport type KrakenWsOhlcSubscribeParams = Ohlc.KrakenWsOhlcSubscribeParams;\nexport type KrakenWsOhlcSubscribeOptions = Ohlc.KrakenWsOhlcSubscribeOptions;\nexport type KrakenWsOhlcSubscribeResponse = Ohlc.KrakenWsOhlcSubscribeResponse;\nexport type KrakenWsOhlcUnsubscribeParams = Ohlc.KrakenWsOhlcUnsubscribeParams;\nexport type KrakenWsOhlcUnsubscribeOptions =\n Ohlc.KrakenWsOhlcUnsubscribeOptions;\nexport type KrakenWsOhlcUnsubscribeResponse =\n Ohlc.KrakenWsOhlcUnsubscribeResponse;\n\n// Trade\nexport type KrakenWsTradeSide = Trade.KrakenWsTradeSide;\nexport type KrakenWsTradeOrderType = Trade.KrakenWsTradeOrderType;\nexport type KrakenWsTradeEntry = Trade.KrakenWsTradeEntry;\nexport type KrakenWsTradeSnapshotMessage = Trade.KrakenWsTradeSnapshotMessage;\nexport type KrakenWsTradeUpdateMessage = Trade.KrakenWsTradeUpdateMessage;\nexport type KrakenWsTradeMessage = Trade.KrakenWsTradeMessage;\nexport type KrakenWsTradeSubscribeParams = Trade.KrakenWsTradeSubscribeParams;\nexport type KrakenWsTradeSubscribeOptions = Trade.KrakenWsTradeSubscribeOptions;\nexport type KrakenWsTradeSubscribeResponse =\n Trade.KrakenWsTradeSubscribeResponse;\nexport type KrakenWsTradeUnsubscribeParams =\n Trade.KrakenWsTradeUnsubscribeParams;\nexport type KrakenWsTradeUnsubscribeOptions =\n Trade.KrakenWsTradeUnsubscribeOptions;\nexport type KrakenWsTradeUnsubscribeResponse =\n Trade.KrakenWsTradeUnsubscribeResponse;\n\n// Instrument\nexport type KrakenWsInstrumentAssetStatus =\n Instrument.KrakenWsInstrumentAssetStatus;\nexport type KrakenWsInstrumentPairStatus =\n Instrument.KrakenWsInstrumentPairStatus;\nexport type KrakenWsInstrumentAsset = Instrument.KrakenWsInstrumentAsset;\nexport type KrakenWsInstrumentPair = Instrument.KrakenWsInstrumentPair;\nexport type KrakenWsInstrumentData = Instrument.KrakenWsInstrumentData;\nexport type KrakenWsInstrumentSnapshotMessage =\n Instrument.KrakenWsInstrumentSnapshotMessage;\nexport type KrakenWsInstrumentUpdateMessage =\n Instrument.KrakenWsInstrumentUpdateMessage;\nexport type KrakenWsInstrumentMessage = Instrument.KrakenWsInstrumentMessage;\nexport type KrakenWsInstrumentSubscribeParams =\n Instrument.KrakenWsInstrumentSubscribeParams;\nexport type KrakenWsInstrumentSubscribeOptions =\n Instrument.KrakenWsInstrumentSubscribeOptions;\nexport type KrakenWsInstrumentSubscribeResponse =\n Instrument.KrakenWsInstrumentSubscribeResponse;\nexport type KrakenWsInstrumentUnsubscribeParams =\n Instrument.KrakenWsInstrumentUnsubscribeParams;\nexport type KrakenWsInstrumentUnsubscribeOptions =\n Instrument.KrakenWsInstrumentUnsubscribeOptions;\nexport type KrakenWsInstrumentUnsubscribeResponse =\n Instrument.KrakenWsInstrumentUnsubscribeResponse;\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Exec type for executions channel events.\n */\nexport type KrakenWsExecutionType =\n | 'pending_new'\n | 'new'\n | 'trade'\n | 'filled'\n | 'iceberg_refill'\n | 'canceled'\n | 'expired'\n | 'amended'\n | 'restated'\n | 'status';\n\n/**\n * Order status on executions events.\n */\nexport type KrakenWsOrderStatus =\n | 'pending_new'\n | 'new'\n | 'partially_filled'\n | 'filled'\n | 'canceled'\n | 'expired';\n\n/**\n * Liquidity indicator (maker / taker).\n */\nexport type KrakenWsLiquidityIndicator = 'm' | 't';\n\n/**\n * Position status for margin orders.\n */\nexport type KrakenWsPositionStatus = 'opened' | 'closing' | 'closed';\n\n/**\n * Trigger reference price.\n */\nexport type KrakenWsTriggerReference = 'index' | 'last';\n\n/**\n * Trigger price type.\n */\nexport type KrakenWsPriceType = 'static' | 'pct' | 'quote';\n\n/**\n * Trigger status on triggered orders.\n */\nexport type KrakenWsTriggerStatus = 'triggered' | 'untriggered';\n\n/**\n * Time-in-force values used on executions stream (upper-case).\n */\nexport type KrakenWsExecutionTimeInForce = 'GTC' | 'GTD' | 'IOC';\n\n/**\n * Fee entry for trade events.\n */\nexport interface KrakenWsExecutionFeeEntry {\n /** The fee currency. */\n asset: string;\n /** The fee amount. */\n qty: number;\n}\n\n/**\n * Trigger parameters on execution reports (for triggered order types).\n */\nexport interface KrakenWsExecutionTriggers {\n /** The reference price tracked for triggering orders. */\n reference?: KrakenWsTriggerReference;\n /**\n * Trigger price amount (static or relative), used with `price_type`.\n */\n price?: number;\n /**\n * Units for the trigger price.\n */\n price_type?: KrakenWsPriceType;\n\n /**\n * Current value of the effective trigger price (after applying relative logic).\n */\n actual_price?: number;\n\n /**\n * Peak / trough price on trailing-stop / trailing-stop-limit.\n */\n peak_price?: number;\n\n /**\n * On trigger activation, the value of the reference last price that triggered\n * the order.\n */\n last_price?: number;\n\n /**\n * Trigger status.\n */\n status?: KrakenWsTriggerStatus;\n\n /**\n * On trigger activation, the timestamp of the trigger event.\n */\n timestamp?: string;\n}\n\n/**\n * Contingent (secondary close order template) information on executions.\n */\nexport interface KrakenWsExecutionContingent {\n /**\n * Order type of the secondary close orders created on each fill.\n */\n order_type?:\n | 'limit'\n | 'stop-loss'\n | 'stop-loss-limit'\n | 'take-profit'\n | 'take-profit-limit'\n | 'trailing-stop'\n | 'trailing-stop-limit';\n\n /**\n * Trigger price for secondary orders (triggered types only).\n */\n trigger_price?: number;\n\n /**\n * Trigger price units for secondary orders.\n */\n trigger_price_type?: KrakenWsPriceType;\n\n /**\n * Limit price for secondary orders (limit-types only).\n */\n limit_price?: number;\n\n /**\n * Limit price units for secondary orders.\n */\n limit_price_type?: KrakenWsPriceType;\n}\n\n/**\n * Execution report structure for entries in the `executions` channel\n * `data` array.\n *\n * NOTE:\n * - Fields are often conditional based on `exec_type`.\n * - Most are optional here to account for different shapes per event.\n */\nexport interface KrakenWsExecutionReport {\n // --- Identification / core order fields ---\n\n /** Unique order identifier generated by Kraken. */\n order_id?: string;\n\n /** Optional client identifier associated with the order. */\n cl_ord_id?: string;\n\n /** Optional numeric, client identifier associated with one or more orders. */\n order_userref?: number;\n\n /** The symbol of the currency pair (e.g. \"BTC/USD\"). */\n symbol?: string;\n\n /** Side of the order. */\n side?: 'buy' | 'sell';\n\n /** The execution model of the order. */\n order_type?:\n | 'limit'\n | 'market'\n | 'iceberg'\n | 'stop-loss'\n | 'stop-loss-limit'\n | 'take-profit'\n | 'take-profit-limit'\n | 'trailing-stop'\n | 'trailing-stop-limit'\n | 'settle-position';\n\n /** Describes current state of the order. */\n order_status?: KrakenWsOrderStatus;\n\n /** Event type, determines what fields are present. */\n exec_type?: KrakenWsExecutionType;\n\n /** Time of the event. */\n timestamp?: string;\n\n /** Scheduled start time of the order. */\n effective_time?: string;\n\n /** Scheduled expiration time of the order. */\n expire_time?: string;\n\n /** Time-in-force for the order. */\n time_in_force?: KrakenWsExecutionTimeInForce;\n\n // --- Order quantity / price / margin flags ---\n\n /** Client order quantity (base asset quantity). */\n order_qty?: number;\n\n /** Display quantity for iceberg order types. */\n display_qty?: number;\n\n /** For iceberg orders, the next display quantity. */\n display_qty_remain?: number;\n\n /** Limit price (for limit-type orders). */\n limit_price?: number;\n\n /** Indicates if the order can be funded on margin. */\n margin?: boolean;\n\n /** Indicates if the execution is on margin. (trade events only) */\n margin_borrow?: boolean;\n\n /** Indicates a reduce-only order. */\n reduce_only?: boolean;\n\n /** Indicates a post-only order. */\n post_only?: boolean;\n\n /** Indicates if the order has market price protection. */\n no_mpp?: boolean;\n\n /** Position status on margin orders. */\n position_status?: KrakenWsPositionStatus;\n\n // --- Execution / fill information ---\n\n /** Order's average fill price. */\n avg_price?: number;\n\n /** Client order quantity in quote currency (if supplied). */\n cash_order_qty?: number;\n\n /** Execution identifier (trade events only). */\n exec_id?: string;\n\n /** Quantity filled in this event (trade events only). */\n last_qty?: number;\n\n /** Average price in this trade event (trade events only). */\n last_price?: number;\n\n /** Value of an individual execution (trade events only). */\n cost?: number;\n\n /** The order cumulative value executed. */\n cum_cost?: number;\n\n /** The order cumulative executed quantity. */\n cum_qty?: number;\n\n /** Liquidity indicator, 't' taker, 'm' maker. */\n liquidity_ind?: KrakenWsLiquidityIndicator;\n\n /** Trade identifier. */\n trade_id?: number;\n\n /** Indicates if the order has been liquidated by the engine. */\n liquidated?: boolean;\n\n /** Referral order transaction id that created this order. */\n ord_ref_id?: string;\n\n // --- Fees ---\n\n /**\n * The fees paid on this trade event (quote currency currently).\n * Trade events only.\n */\n fees?: KrakenWsExecutionFeeEntry[];\n\n /** Preferred currency for paying fees (fcib / fciq). */\n fee_ccy_pref?: string;\n\n /** Total fee paid in USD. */\n fee_usd_equiv?: number;\n\n // --- Trigger / contingent info ---\n\n /** Trigger parameters for triggered order types. */\n triggers?: KrakenWsExecutionTriggers;\n\n /** Template for secondary close orders. */\n contingent?: KrakenWsExecutionContingent;\n\n // --- Miscellaneous flags / identifiers ---\n\n /** Indicates if the order has been amended. */\n amended?: boolean;\n\n /** Indicates if the order has been liquidated. */\n // (already defined as `liquidated`)\n\n /** Engine / business reason on certain events. */\n reason?: string;\n\n /** For institutional accounts, identifies trader / sub-account for STP. */\n sender_sub_id?: string;\n\n /** User/sub-account identifier when `users=all` is used. */\n user?: string;\n\n /** Optional external partner order id. */\n ext_ord_id?: string;\n\n /** Optional external partner execution id. */\n ext_exec_id?: string;\n\n /** Deprecated: cancellation reason. */\n cancel_reason?: string;\n\n /** Deprecated: stop price (use `triggers`). */\n stop_price?: number;\n\n /** Deprecated: trigger reference (use `triggers`). */\n trigger?: KrakenWsTriggerReference;\n\n /** Deprecated: triggered price (use `triggers`). */\n triggered_price?: number;\n}\n\n/**\n * Message payload for the `executions` channel (snapshot or update).\n */\nexport interface KrakenWsExecutionsMessage {\n channel: 'executions';\n type: 'snapshot' | 'update';\n data: KrakenWsExecutionReport[];\n /** Subscription message sequence number. */\n sequence: number;\n}\n\n/**\n * Parameters for subscribing to the `executions` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"executions\" by the helper.\n * - `token` is optional here; KrakenWebsocketBase can inject it from\n * the connection options when `attachAuthToken` is true.\n */\nexport interface KrakenWsExecutionsSubscribeParams {\n /**\n * If true, the last 50 order fills will be included in snapshot.\n * Default: false.\n */\n snap_trades?: boolean;\n\n /**\n * If true, open orders will be included in snapshot.\n * Default: true.\n */\n snap_orders?: boolean;\n\n /**\n * If true, all possible status transitions will be sent.\n * If false, only open/close transitions: new, filled, canceled, expired.\n * Default: true.\n */\n order_status?: boolean;\n\n /**\n * For xstocks: if true, display in terms of underlying equity.\n * Default: true.\n */\n rebased?: boolean;\n\n /**\n * If true, the rate-limit counter is included in the stream.\n * Default: false.\n */\n ratecounter?: boolean;\n\n /**\n * Master accounts only:\n * - \"all\" → events for master and subaccounts (no snapshot).\n */\n users?: 'all';\n\n /**\n * Deprecated: use `snap_trades`.\n */\n snapshot_trades?: boolean;\n\n /**\n * Deprecated: use `snap_orders` / `snap_trades`.\n */\n snapshot?: boolean;\n\n /**\n * Session token. Optional here, base may inject it automatically.\n */\n token?: string;\n\n /**\n * Index signature to satisfy Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeExecutions wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsExecutionsSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for executions.\n * (Kraken’s subscribe ack has a small result body; we keep it generic\n * but always include `channel`.)\n */\nexport interface KrakenWsExecutionsSubscribeResult {\n channel: 'executions';\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for executions.\n */\nexport type KrakenWsExecutionsSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsExecutionsSubscribeResult>;\n\n/**\n * Subscribe to the `executions` channel (order status + fills for this account).\n *\n * This sends a WS v2 `subscribe` request with `channel: \"executions\"`.\n * The returned Promise resolves with the subscribe **ack** envelope.\n * Streaming snapshot/update messages will then arrive on the underlying\n * WebSocket and should be routed via your global message handler.\n *\n * @example\n * ```ts\n * // 1) Send subscribe request\n * const ack = await wsClient.userData.executions.subscribe({\n * snap_trades: true,\n * snap_orders: true,\n * order_status: true,\n * });\n *\n * if (!ack.success) {\n * console.error(\"executions subscribe error:\", ack.error);\n * }\n *\n * // 2) Somewhere in your WS router:\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n * if (msg.channel === \"executions\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const execMsg = msg as KrakenWsExecutionsMessage;\n * for (const report of execMsg.data) {\n * console.log(\"[exec]\", report.exec_type, report.order_id, report.order_status);\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeExecutions(\n ws: KrakenWebsocketBase,\n params: KrakenWsExecutionsSubscribeParams,\n options: KrakenWsExecutionsSubscribeOptions = {},\n): Promise<KrakenWsExecutionsSubscribeResponse> {\n const body = {\n channel: 'executions' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsExecutionsSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `executions` channel.\n *\n * NOTE:\n * - `channel` is set to \"executions\" by the helper.\n * - `token` is optional here; base may inject it automatically.\n */\nexport interface KrakenWsExecutionsUnsubscribeParams {\n token?: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeExecutions wrapper.\n */\nexport interface KrakenWsExecutionsUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for executions.\n */\nexport interface KrakenWsExecutionsUnsubscribeResult {\n channel: 'executions';\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for executions.\n */\nexport type KrakenWsExecutionsUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsExecutionsUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `executions` channel.\n *\n * This sends a WS v2 `unsubscribe` request with `channel: \"executions\"`.\n *\n * @example\n * ```ts\n * const ack = await wsClient.userData.executions.unsubscribe();\n *\n * if (!ack.success) {\n * console.error(\"executions unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeExecutions(\n ws: KrakenWebsocketBase,\n params: KrakenWsExecutionsUnsubscribeParams = {},\n options: KrakenWsExecutionsUnsubscribeOptions = {},\n): Promise<KrakenWsExecutionsUnsubscribeResponse> {\n const body = {\n channel: 'executions' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsExecutionsUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Wallet type for balances channel.\n */\nexport type KrakenWsBalanceWalletType = 'spot' | 'earn';\n\n/**\n * Wallet identifier in snapshot.\n */\nexport type KrakenWsBalanceWalletId =\n | 'main'\n | 'flex'\n | 'bonded'\n | 'flexible'\n | 'liquid'\n | 'locked'\n | 'closed';\n\n/**\n * Wallet identifier in update events.\n */\nexport type KrakenWsBalanceUpdateWalletId =\n | 'main'\n | 'bonded'\n | 'flexible'\n | 'liquid'\n | 'locked';\n\n/**\n * Balance event type in updates.\n */\nexport type KrakenWsBalanceEventType =\n | 'deposit'\n | 'withdrawal'\n | 'trade'\n | 'margin'\n | 'adjustment'\n | 'rollover'\n | 'credit'\n | 'transfer'\n | 'settled'\n | 'staking'\n | 'sale'\n | 'reserve'\n | 'conversion'\n | 'dividend'\n | 'reward'\n | 'creator_fee';\n\n/**\n * Balance event subtype in updates.\n */\nexport type KrakenWsBalanceEventSubtype =\n | 'spotfromfutures'\n | 'spottofutures'\n | 'stakingfromspot'\n | 'spotfromstaking'\n | 'stakingtospot'\n | 'spottostaking';\n\n/**\n * Balance event category in updates.\n */\nexport type KrakenWsBalanceEventCategory =\n | 'deposit'\n | 'withdrawal'\n | 'trade'\n | 'margin-trade'\n | 'margin-settle'\n | 'margin-conversion'\n | 'conversion'\n | 'credit'\n | 'marginrollover'\n | 'staking-rewards'\n | 'instant'\n | 'equity-trade'\n | 'airdrop'\n | 'equity-dividend'\n | 'reward-bonus'\n | 'nft'\n | 'block-trade';\n\n/**\n * Wallet entry for each asset in the snapshot.\n */\nexport interface KrakenWsBalanceWalletEntry {\n /**\n * Balance of asset in this wallet.\n */\n balance: number;\n\n /**\n * Wallet type: spot / earn.\n */\n type: KrakenWsBalanceWalletType;\n\n /**\n * Wallet identifier.\n */\n id: KrakenWsBalanceWalletId;\n}\n\n/**\n * Snapshot entry for each asset in the balances snapshot.\n */\nexport interface KrakenWsBalancesSnapshotAsset {\n /**\n * The asset symbol code (e.g. \"BTC\", \"USD\").\n */\n asset: string;\n\n /**\n * Asset class (currently \"currency\", placeholder for future expansion).\n */\n asset_class: string;\n\n /**\n * Total amount of asset held across all wallet types.\n */\n balance: number;\n\n /**\n * List of wallets holding this asset.\n */\n wallets: KrakenWsBalanceWalletEntry[];\n}\n\n/**\n * Snapshot message payload for the `balances` channel.\n */\nexport interface KrakenWsBalancesSnapshotMessage {\n channel: 'balances';\n type: 'snapshot';\n data: KrakenWsBalancesSnapshotAsset[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Ledger transaction entry in balances update messages.\n */\nexport interface KrakenWsBalanceLedgerTransaction {\n /**\n * The asset symbol code.\n */\n asset: string;\n\n /**\n * Asset class (currently \"currency\").\n */\n asset_class: string;\n\n /**\n * The amount of asset change in this event.\n */\n amount: number;\n\n /**\n * The total amount of this asset held in account after the event.\n */\n balance: number;\n\n /**\n * The fee paid on the transaction.\n */\n fee: number;\n\n /**\n * Identifier for this account ledger entry.\n */\n ledger_id: string;\n\n /**\n * Reference identifier for the balance event (e.g. trade_id for trades).\n */\n ref_id: string;\n\n /**\n * Time of the balance change (RFC3339).\n */\n timestamp: string;\n\n /**\n * Broad type of the balance event.\n */\n type: KrakenWsBalanceEventType;\n\n /**\n * Specific subtype of the balance event.\n */\n subtype?: KrakenWsBalanceEventSubtype;\n\n /**\n * Categorization of the balance event.\n */\n category?: KrakenWsBalanceEventCategory;\n\n /**\n * Wallet type (spot / earn).\n */\n wallet_type: KrakenWsBalanceWalletType;\n\n /**\n * Wallet identifier, depending on wallet type.\n */\n wallet_id: KrakenWsBalanceUpdateWalletId;\n\n /**\n * Published when subscription uses `users=all` (master + subaccounts).\n */\n user?: string;\n}\n\n/**\n * Update message payload for the `balances` channel.\n */\nexport interface KrakenWsBalancesUpdateMessage {\n channel: 'balances';\n type: 'update';\n data: KrakenWsBalanceLedgerTransaction[];\n /**\n * Subscription message sequence number.\n */\n sequence: number;\n}\n\n/**\n * Union of possible balances channel messages.\n */\nexport type KrakenWsBalancesMessage =\n | KrakenWsBalancesSnapshotMessage\n | KrakenWsBalancesUpdateMessage;\n\n/**\n * Parameters for subscribing to the `balances` channel.\n *\n * NOTE:\n * - `channel` is automatically set to \"balances\" by the helper.\n * - `token` is optional here; KrakenWebsocketBase can inject it from\n * the connection options when `attachAuthToken` is true.\n */\nexport interface KrakenWsBalancesSubscribeParams {\n /**\n * Request a snapshot after subscribing.\n * Default: true.\n */\n snapshot?: boolean;\n\n /**\n * For xstocks: if true, display in terms of underlying equity;\n * otherwise in terms of SPV tokens.\n * Default: true.\n */\n rebased?: boolean;\n\n /**\n * Master accounts only:\n * - \"all\" → events for master and subaccounts are streamed.\n * (No snapshot is provided.)\n */\n users?: 'all';\n\n /**\n * Session token. Optional: base may inject it automatically.\n */\n token?: string;\n\n /**\n * Index signature to satisfy Record<string, unknown>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for subscribeBalances wrapper – mapped to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsBalancesSubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the subscribe ack envelope for balances.\n */\nexport interface KrakenWsBalancesSubscribeResult {\n channel: 'balances';\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from subscribe (ack) for balances.\n */\nexport type KrakenWsBalancesSubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsBalancesSubscribeResult>;\n\n/**\n * Subscribe to the `balances` channel.\n *\n * Streams:\n * - a **snapshot** of all assets and wallets (unless `snapshot: false` or `users: \"all\"`),\n * - then **update** messages for each completed ledger transaction.\n *\n * @example\n * ```ts\n * // 1) Send subscribe request\n * const ack = await wsClient.userData.balances.subscribe({\n * snapshot: true,\n * });\n *\n * if (!ack.success) {\n * console.error(\"balances subscribe error:\", ack.error);\n * }\n *\n * // 2) In your WS router:\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"balances\" && msg.type === \"snapshot\") {\n * const snap = msg as KrakenWsBalancesSnapshotMessage;\n * for (const asset of snap.data) {\n * console.log(\n * \"[balances snapshot]\",\n * asset.asset,\n * \"total:\",\n * asset.balance,\n * );\n * for (const w of asset.wallets) {\n * console.log(\" wallet\", w.type, w.id, \"=\", w.balance);\n * }\n * }\n * }\n *\n * if (msg.channel === \"balances\" && msg.type === \"update\") {\n * const upd = msg as KrakenWsBalancesUpdateMessage;\n * for (const tx of upd.data) {\n * console.log(\n * \"[balances update]\",\n * tx.asset,\n * tx.type,\n * \"delta:\",\n * tx.amount,\n * \"new balance:\",\n * tx.balance,\n * );\n * }\n * }\n * });\n * ```\n */\nexport async function subscribeBalances(\n ws: KrakenWebsocketBase,\n params: KrakenWsBalancesSubscribeParams = {},\n options: KrakenWsBalancesSubscribeOptions = {},\n): Promise<KrakenWsBalancesSubscribeResponse> {\n const body = {\n channel: 'balances' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsBalancesSubscribeResult>(\n 'subscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n\n/**\n * Parameters for unsubscribing from the `balances` channel.\n *\n * NOTE:\n * - `channel` is set to \"balances\" by the helper.\n * - `token` is optional here; base may inject it automatically.\n */\nexport interface KrakenWsBalancesUnsubscribeParams {\n token?: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for unsubscribeBalances wrapper.\n */\nexport interface KrakenWsBalancesUnsubscribeOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the unsubscribe ack envelope for balances.\n */\nexport interface KrakenWsBalancesUnsubscribeResult {\n channel: 'balances';\n [key: string]: unknown;\n}\n\n/**\n * Full WS envelope returned from unsubscribe (ack) for balances.\n */\nexport type KrakenWsBalancesUnsubscribeResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsBalancesUnsubscribeResult>;\n\n/**\n * Unsubscribe from the `balances` channel.\n *\n * This sends a WS v2 `unsubscribe` request with `channel: \"balances\"`.\n *\n * @example\n * ```ts\n * const ack = await wsClient.userData.balances.unsubscribe();\n *\n * if (!ack.success) {\n * console.error(\"balances unsubscribe error:\", ack.error);\n * }\n * ```\n */\nexport async function unsubscribeBalances(\n ws: KrakenWebsocketBase,\n params: KrakenWsBalancesUnsubscribeParams = {},\n options: KrakenWsBalancesUnsubscribeOptions = {},\n): Promise<KrakenWsBalancesUnsubscribeResponse> {\n const body = {\n channel: 'balances' as const,\n ...params,\n };\n\n return ws.request<typeof body, KrakenWsBalancesUnsubscribeResult>(\n 'unsubscribe',\n body,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken ?? true,\n },\n );\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\nimport * as Executions from './executions';\nimport * as Balances from './balances';\n\n/**\n * Kraken Spot WebSocket v2 user-data API.\n *\n * Authenticated, account-specific streams:\n * - `executions` – order lifecycle + fills\n * - `balances` – balances snapshot + ledger-based updates\n *\n * Typically exposed from your top-level Spot WS client as:\n *\n * ```ts\n * export class KrakenSpotWebsocketClient extends KrakenWebsocketBase {\n * readonly userTrading: KrakenSpotWsUserTradingApi;\n * readonly userData: KrakenSpotWsUserDataApi;\n *\n * constructor(options: KrakenWebsocketOptions) {\n * super(options);\n * this.userTrading = new KrakenSpotWsUserTradingApi(this);\n * this.userData = new KrakenSpotWsUserDataApi(this);\n * }\n * }\n * ```\n */\nexport class KrakenSpotWsUserDataApi {\n constructor(private readonly ws: KrakenWebsocketBase) {}\n\n // ---------------------------------------------------------------------------\n // executions\n // ---------------------------------------------------------------------------\n\n /**\n * Subscribe to the `executions` channel.\n *\n * Streams:\n * - a **snapshot** of open orders + recent trades (configurable), then\n * - **update** events for order lifecycle + fills.\n *\n * @example\n * ```ts\n * // 1) Send subscribe request\n * const ack = await wsClient.userData.subscribeExecutions({\n * snap_trades: true,\n * snap_orders: true,\n * order_status: true,\n * });\n *\n * if (!ack.success) {\n * console.error(\"executions subscribe error:\", ack.error);\n * }\n *\n * // 2) In your WS router:\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"executions\" && (msg.type === \"snapshot\" || msg.type === \"update\")) {\n * const execMsg = msg as Executions.KrakenWsExecutionsMessage;\n * for (const report of execMsg.data) {\n * console.log(\n * \"[exec]\",\n * report.exec_type,\n * report.order_id,\n * report.order_status,\n * \"cum_qty:\",\n * report.cum_qty,\n * );\n * }\n * }\n * });\n * ```\n */\n subscribeExecutions(\n params: Executions.KrakenWsExecutionsSubscribeParams,\n options?: Executions.KrakenWsExecutionsSubscribeOptions,\n ) {\n return Executions.subscribeExecutions(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the `executions` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.userData.unsubscribeExecutions();\n *\n * if (!ack.success) {\n * console.error(\"executions unsubscribe error:\", ack.error);\n * }\n * ```\n */\n unsubscribeExecutions(\n params?: Executions.KrakenWsExecutionsUnsubscribeParams,\n options?: Executions.KrakenWsExecutionsUnsubscribeOptions,\n ) {\n return Executions.unsubscribeExecutions(this.ws, params ?? {}, options);\n }\n\n // ---------------------------------------------------------------------------\n // balances\n // ---------------------------------------------------------------------------\n\n /**\n * Subscribe to the `balances` channel.\n *\n * Streams:\n * - a **snapshot** of all assets + wallets (unless `snapshot: false`\n * or `users: \"all\"`), then\n * - **update** events for every ledger-derived balance change.\n *\n * @example\n * ```ts\n * // 1) Subscribe and request a snapshot\n * const ack = await wsClient.userData.subscribeBalances({\n * snapshot: true,\n * });\n *\n * if (!ack.success) {\n * console.error(\"balances subscribe error:\", ack.error);\n * }\n *\n * // 2) Handle stream messages\n * ws.onMessage((raw) => {\n * const msg = JSON.parse(raw);\n *\n * if (msg.channel === \"balances\" && msg.type === \"snapshot\") {\n * const snap = msg as Balances.KrakenWsBalancesSnapshotMessage;\n * for (const asset of snap.data) {\n * console.log(\"[balances snapshot]\", asset.asset, \"total:\", asset.balance);\n * for (const w of asset.wallets) {\n * console.log(\" wallet\", w.type, w.id, \"=\", w.balance);\n * }\n * }\n * }\n *\n * if (msg.channel === \"balances\" && msg.type === \"update\") {\n * const upd = msg as Balances.KrakenWsBalancesUpdateMessage;\n * for (const tx of upd.data) {\n * console.log(\n * \"[balances update]\",\n * tx.asset,\n * tx.type,\n * \"delta:\",\n * tx.amount,\n * \"new balance:\",\n * tx.balance,\n * );\n * }\n * }\n * });\n * ```\n */\n subscribeBalances(\n params: Balances.KrakenWsBalancesSubscribeParams = {},\n options?: Balances.KrakenWsBalancesSubscribeOptions,\n ) {\n return Balances.subscribeBalances(this.ws, params, options);\n }\n\n /**\n * Unsubscribe from the `balances` channel.\n *\n * @example\n * ```ts\n * const ack = await wsClient.userData.unsubscribeBalances();\n *\n * if (!ack.success) {\n * console.error(\"balances unsubscribe error:\", ack.error);\n * }\n * ```\n */\n unsubscribeBalances(\n params?: Balances.KrakenWsBalancesUnsubscribeParams,\n options?: Balances.KrakenWsBalancesUnsubscribeOptions,\n ) {\n return Balances.unsubscribeBalances(this.ws, params ?? {}, options);\n }\n}\n\n// -----------------------------------------------------------------------------\n// Re-export types for consumers\n// -----------------------------------------------------------------------------\n\n// Executions\nexport type KrakenWsExecutionType = Executions.KrakenWsExecutionType;\nexport type KrakenWsOrderStatus = Executions.KrakenWsOrderStatus;\nexport type KrakenWsLiquidityIndicator = Executions.KrakenWsLiquidityIndicator;\nexport type KrakenWsPositionStatus = Executions.KrakenWsPositionStatus;\nexport type KrakenWsTriggerReference = Executions.KrakenWsTriggerReference;\nexport type KrakenWsPriceType = Executions.KrakenWsPriceType;\nexport type KrakenWsTriggerStatus = Executions.KrakenWsTriggerStatus;\nexport type KrakenWsExecutionTimeInForce =\n Executions.KrakenWsExecutionTimeInForce;\n\nexport type KrakenWsExecutionFeeEntry = Executions.KrakenWsExecutionFeeEntry;\nexport type KrakenWsExecutionTriggers = Executions.KrakenWsExecutionTriggers;\nexport type KrakenWsExecutionContingent =\n Executions.KrakenWsExecutionContingent;\nexport type KrakenWsExecutionReport = Executions.KrakenWsExecutionReport;\nexport type KrakenWsExecutionsMessage = Executions.KrakenWsExecutionsMessage;\n\nexport type KrakenWsExecutionsSubscribeParams =\n Executions.KrakenWsExecutionsSubscribeParams;\nexport type KrakenWsExecutionsSubscribeOptions =\n Executions.KrakenWsExecutionsSubscribeOptions;\nexport type KrakenWsExecutionsSubscribeResult =\n Executions.KrakenWsExecutionsSubscribeResult;\nexport type KrakenWsExecutionsSubscribeResponse =\n Executions.KrakenWsExecutionsSubscribeResponse;\n\nexport type KrakenWsExecutionsUnsubscribeParams =\n Executions.KrakenWsExecutionsUnsubscribeParams;\nexport type KrakenWsExecutionsUnsubscribeOptions =\n Executions.KrakenWsExecutionsUnsubscribeOptions;\nexport type KrakenWsExecutionsUnsubscribeResult =\n Executions.KrakenWsExecutionsUnsubscribeResult;\nexport type KrakenWsExecutionsUnsubscribeResponse =\n Executions.KrakenWsExecutionsUnsubscribeResponse;\n\n// Balances\nexport type KrakenWsBalanceWalletType = Balances.KrakenWsBalanceWalletType;\nexport type KrakenWsBalanceWalletId = Balances.KrakenWsBalanceWalletId;\nexport type KrakenWsBalanceUpdateWalletId =\n Balances.KrakenWsBalanceUpdateWalletId;\nexport type KrakenWsBalanceEventType = Balances.KrakenWsBalanceEventType;\nexport type KrakenWsBalanceEventSubtype = Balances.KrakenWsBalanceEventSubtype;\nexport type KrakenWsBalanceEventCategory =\n Balances.KrakenWsBalanceEventCategory;\n\nexport type KrakenWsBalanceWalletEntry = Balances.KrakenWsBalanceWalletEntry;\nexport type KrakenWsBalancesSnapshotAsset =\n Balances.KrakenWsBalancesSnapshotAsset;\nexport type KrakenWsBalancesSnapshotMessage =\n Balances.KrakenWsBalancesSnapshotMessage;\nexport type KrakenWsBalanceLedgerTransaction =\n Balances.KrakenWsBalanceLedgerTransaction;\nexport type KrakenWsBalancesUpdateMessage =\n Balances.KrakenWsBalancesUpdateMessage;\nexport type KrakenWsBalancesMessage = Balances.KrakenWsBalancesMessage;\n\nexport type KrakenWsBalancesSubscribeParams =\n Balances.KrakenWsBalancesSubscribeParams;\nexport type KrakenWsBalancesSubscribeOptions =\n Balances.KrakenWsBalancesSubscribeOptions;\nexport type KrakenWsBalancesSubscribeResult =\n Balances.KrakenWsBalancesSubscribeResult;\nexport type KrakenWsBalancesSubscribeResponse =\n Balances.KrakenWsBalancesSubscribeResponse;\n\nexport type KrakenWsBalancesUnsubscribeParams =\n Balances.KrakenWsBalancesUnsubscribeParams;\nexport type KrakenWsBalancesUnsubscribeOptions =\n Balances.KrakenWsBalancesUnsubscribeOptions;\nexport type KrakenWsBalancesUnsubscribeResult =\n Balances.KrakenWsBalancesUnsubscribeResult;\nexport type KrakenWsBalancesUnsubscribeResponse =\n Balances.KrakenWsBalancesUnsubscribeResponse;\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\nexport type KrakenWsOrderSide = 'buy' | 'sell';\n\nexport type KrakenWsOrderType =\n | 'limit'\n | 'market'\n | 'iceberg'\n | 'stop-loss'\n | 'stop-loss-limit'\n | 'take-profit'\n | 'take-profit-limit'\n | 'trailing-stop'\n | 'trailing-stop-limit'\n | 'settle-position';\n\nexport type KrakenWsTriggerReference = 'index' | 'last';\nexport type KrakenWsPriceType = 'static' | 'pct' | 'quote';\nexport type KrakenWsTimeInForce = 'gtc' | 'gtd' | 'ioc';\nexport type KrakenWsFeePreference = 'base' | 'quote';\nexport type KrakenWsStpType = 'cancel_newest' | 'cancel_oldest' | 'cancel_both';\n\n/**\n * Trigger parameters for triggered order types.\n */\nexport interface KrakenWsAddOrderTriggers {\n /**\n * Reference price to track for triggering orders.\n * Default is \"last\".\n */\n reference?: KrakenWsTriggerReference;\n\n /**\n * Amount for the trigger price (static or relative).\n */\n price: number;\n\n /**\n * Units for the trigger price. Default is \"static\".\n */\n price_type?: KrakenWsPriceType;\n}\n\n/**\n * Conditional template for secondary close orders (OTO).\n */\nexport interface KrakenWsAddOrderConditional {\n /**\n * Order type of the secondary close orders.\n */\n order_type:\n | 'limit'\n | 'stop-loss'\n | 'stop-loss-limit'\n | 'take-profit'\n | 'take-profit-limit'\n | 'trailing-stop'\n | 'trailing-stop-limit';\n\n /**\n * Limit price for secondary orders that support a limit price.\n */\n limit_price?: number;\n\n /**\n * Units for the limit price on the secondary orders.\n * Only available for trailing-stop-limit.\n */\n limit_price_type?: KrakenWsPriceType;\n\n /**\n * Trigger price amount for secondary orders (static or relative).\n */\n trigger_price?: number;\n\n /**\n * Units for the trigger price on the secondary orders.\n */\n trigger_price_type?: KrakenWsPriceType;\n\n /**\n * Deprecated, use trigger_price.\n */\n stop_price?: number;\n\n /**\n * Display quantity (iceberg-style) for the secondary order.\n */\n display_qty?: number;\n\n /**\n * Fee preference base or quote currency.\n */\n fee_preference?: KrakenWsFeePreference;\n\n /**\n * Deprecated, accepted but ignored.\n */\n no_mpp?: boolean;\n\n /**\n * Self trade prevention mode for secondary orders.\n */\n stp_type?: KrakenWsStpType;\n\n /**\n * Order volume expressed in quote currency (for buy market orders).\n */\n cash_order_qty?: number;\n}\n\n/**\n * Parameters for WS v2 add_order.\n *\n * NOTE:\n * - `token` is optional because `KrakenWebsocketBase` can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsAddOrderParams {\n order_type: KrakenWsOrderType;\n side: KrakenWsOrderSide;\n order_qty: number;\n symbol: string;\n\n limit_price?: number;\n limit_price_type?: KrakenWsPriceType;\n triggers?: KrakenWsAddOrderTriggers;\n time_in_force?: KrakenWsTimeInForce;\n margin?: boolean;\n post_only?: boolean;\n reduce_only?: boolean;\n effective_time?: string;\n expire_time?: string;\n deadline?: string;\n cl_ord_id?: string;\n order_userref?: number;\n\n conditional?: KrakenWsAddOrderConditional;\n\n fee_preference?: KrakenWsFeePreference;\n no_mpp?: boolean;\n stp_type?: KrakenWsStpType;\n cash_order_qty?: number;\n validate?: boolean;\n sender_sub_id?: string;\n\n /**\n * Deprecated single-field trigger support.\n * Prefer the `triggers` object.\n */\n stop_price?: number;\n trigger?: KrakenWsTriggerReference;\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for addOrder wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsAddOrderOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for add_order.\n */\nexport interface KrakenWsAddOrderResult {\n /**\n * Unique order identifier generated by Kraken.\n */\n order_id: string;\n\n /**\n * Optional client order ID (cl_ord_id) as sent in the request.\n */\n cl_ord_id?: string;\n\n /**\n * Optional user reference ID as sent in the request.\n */\n order_userref?: number;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from add_order.\n */\nexport type KrakenWsAddOrderResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsAddOrderResult>;\n\n/**\n * Send a single new order into the exchange via WS v2.\n *\n * Kraken docs: method = \"add_order\" (authenticated)\n */\nexport async function addOrder(\n ws: KrakenWebsocketBase,\n params: KrakenWsAddOrderParams,\n options: KrakenWsAddOrderOptions = {},\n): Promise<KrakenWsAddOrderResponse> {\n return ws.request<KrakenWsAddOrderParams, KrakenWsAddOrderResult>(\n 'add_order',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\nimport type { KrakenWsPriceType } from './addOrder';\n\n/**\n * Parameters for WS v2 amend_order.\n *\n * Either `order_id` or `cl_ord_id` must be provided (but not both).\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsAmendOrderParams {\n /**\n * Kraken order identifier to amend.\n * Either `order_id` or `cl_ord_id` is required.\n */\n order_id?: string;\n\n /**\n * Client order identifier to amend.\n * Either `order_id` or `cl_ord_id` is required.\n */\n cl_ord_id?: string;\n\n /**\n * New order quantity in terms of the base asset.\n */\n order_qty: number;\n\n /**\n * For iceberg orders only:\n * The new quantity to show in the book while the rest remains hidden.\n * Minimum value is 1/15 of remaining order quantity.\n */\n display_qty?: number;\n\n /**\n * New limit price restriction on the order (for order types that support it).\n */\n limit_price?: number;\n\n /**\n * Units for `limit_price`. Currently only available on trailing-stop-limit.\n */\n limit_price_type?: KrakenWsPriceType;\n\n /**\n * Optional parameter for limit price amends.\n * If true, the limit price change will be rejected if the order\n * cannot be posted passively in the book.\n */\n post_only?: boolean;\n\n /**\n * For triggered order types only:\n * New trigger price to activate the order.\n */\n trigger_price?: number;\n\n /**\n * Units for `trigger_price` (for triggered order types only).\n */\n trigger_price_type?: KrakenWsPriceType;\n\n /**\n * Deadline for this amend, in RFC3339 format with millisecond precision.\n * Range of valid offsets from \"now\" is 500 ms to 60 s.\n */\n deadline?: string;\n\n /**\n * Symbol is required on amends for non-crypto pairs (e.g. xstocks).\n */\n symbol?: string;\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for amendOrder wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsAmendOrderOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for amend_order.\n */\nexport interface KrakenWsAmendOrderResult {\n /**\n * Unique Kraken identifier generated for this amend transaction.\n */\n amend_id: string;\n\n /**\n * The Kraken identifier, if populated in the request.\n */\n order_id?: string;\n\n /**\n * The client identifier, if populated in the request.\n */\n cl_ord_id?: string;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from amend_order.\n */\nexport type KrakenWsAmendOrderResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsAmendOrderResult>;\n\n/**\n * Amend an existing order in-place via WS v2.\n *\n * - Order identifiers (Kraken + client) stay the same.\n * - Queue priority is preserved where possible.\n * - If the new quantity is less than the filled quantity, the rest is canceled.\n *\n * Kraken docs: method = \"amend_order\" (authenticated)\n */\nexport async function amendOrder(\n ws: KrakenWebsocketBase,\n params: KrakenWsAmendOrderParams,\n options: KrakenWsAmendOrderOptions = {},\n): Promise<KrakenWsAmendOrderResponse> {\n // Light runtime guard to match docs: exactly one of order_id / cl_ord_id.\n const hasOrderId = !!params.order_id;\n const hasClOrdId = !!params.cl_ord_id;\n\n if ((hasOrderId && hasClOrdId) || (!hasOrderId && !hasClOrdId)) {\n throw new Error(\n 'Kraken WS amend_order: exactly one of `order_id` or `cl_ord_id` must be provided',\n );\n }\n\n return ws.request<KrakenWsAmendOrderParams, KrakenWsAmendOrderResult>(\n 'amend_order',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\nimport type {\n KrakenWsFeePreference,\n KrakenWsTriggerReference,\n KrakenWsAddOrderTriggers,\n} from './addOrder';\n\n/**\n * Parameters for WS v2 edit_order.\n *\n * NOTE:\n * - `order_id` and `symbol` are required.\n * - This is the legacy edit endpoint; for new integrations, prefer `amendOrder`\n * where possible (better semantics, preserves queue where possible, etc.).\n *\n * Caveats from Kraken:\n * - Triggered stop-loss / take-profit orders are not supported.\n * - Orders with conditional close terms are not supported.\n * - Orders where executed volume > new volume are rejected.\n * - `cl_ord_id` is NOT supported.\n * - Queue position is not maintained.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsEditOrderParams {\n /**\n * The Kraken identifier for the order to be edited.\n */\n order_id: string;\n\n /**\n * The original symbol identifier for the pair, e.g. \"BTC/USD\".\n * Note: the symbol cannot be changed.\n */\n symbol: string;\n\n /**\n * New order quantity in terms of the base asset.\n */\n order_qty?: number;\n\n /**\n * For iceberg orders only: quantity to show in the book while the rest of\n * the order quantity remains hidden.\n *\n * Minimum value is 1 / 15 of order_qty.\n */\n display_qty?: number;\n\n /**\n * Fee preference base or quote currency. `quote` is the default for buy\n * orders, `base` is the default for sell orders.\n */\n fee_preference?: KrakenWsFeePreference;\n\n /**\n * Limit price for order types that support limit price restriction.\n */\n limit_price?: number;\n\n /**\n * Deprecated: use `limit_price` instead.\n */\n price?: number;\n\n /**\n * Deprecated: disables Market Price Protection (MPP) if true (accepted but ignored).\n */\n no_mpp?: boolean;\n\n /**\n * User defined reference to be placed on the edited order.\n * This does NOT identify the order to be edited; use `order_id`.\n */\n order_userref?: number;\n\n /**\n * Cancels the order if it will take liquidity on arrival.\n * (Orders with limit price only.)\n */\n post_only?: boolean;\n\n /**\n * Reduces an existing margin position without opening an opposite long or\n * short position worth more than the current value of your leveraged assets.\n */\n reduce_only?: boolean;\n\n /**\n * Trigger parameters (for triggered order types only).\n */\n triggers?: KrakenWsAddOrderTriggers;\n\n /**\n * Deprecated: use `triggers.reference` instead.\n */\n trigger?: KrakenWsTriggerReference;\n\n /**\n * Deprecated: use `triggers.price` instead.\n */\n stop_price?: number;\n\n /**\n * Validate-only mode. If true, the order will be validated but not\n * sent to the matching engine.\n */\n validate?: boolean;\n\n /**\n * Deadline for this edit, RFC3339 with millisecond precision.\n * Range of valid offsets (from current time) is 500ms to 60s;\n * default is 5s.\n */\n deadline?: string;\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n\n /**\n * Required so this satisfies Record<string, unknown> for ws.request<>.\n */\n [key: string]: unknown;\n}\n\n/**\n * Options for editOrder wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsEditOrderOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for edit_order.\n */\nexport interface KrakenWsEditOrderResult {\n /**\n * Unique ID of the new edited order.\n */\n order_id: string;\n\n /**\n * ID of the original order that was edited (and cancelled).\n */\n original_order_id: string;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from edit_order.\n */\nexport type KrakenWsEditOrderResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsEditOrderResult>;\n\n/**\n * Edit (replace) an existing order via WS v2.\n *\n * This is the legacy edit endpoint:\n * - The original order is cancelled.\n * - A new order is created with adjusted parameters.\n * - A new `order_id` is returned.\n *\n * For new integrations, prefer `amendOrder` which:\n * - preserves queue position where possible,\n * - supports more order types / conditions,\n * - keeps the same order identifiers.\n *\n * Kraken docs: method = \"edit_order\" (authenticated)\n */\nexport async function editOrder(\n ws: KrakenWebsocketBase,\n params: KrakenWsEditOrderParams,\n options: KrakenWsEditOrderOptions = {},\n): Promise<KrakenWsEditOrderResponse> {\n return ws.request<KrakenWsEditOrderParams, KrakenWsEditOrderResult>(\n 'edit_order',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Parameters for WS v2 cancel_order.\n *\n * At least one of `order_id`, `cl_ord_id`, or `order_userref` must be\n * provided, and each (when present) must contain at least one element.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsCancelOrderParams {\n /**\n * A list of Kraken order_id identifiers.\n */\n order_id?: string[];\n\n /**\n * A list of client cl_ord_id identifiers.\n */\n cl_ord_id?: string[];\n\n /**\n * A list of client order_userref identifiers.\n */\n order_userref?: number[];\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for cancelOrder wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsCancelOrderOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for cancel_order.\n *\n * Note: when cancelling multiple orders, Kraken will send multiple\n * individual responses (one per order). This type represents a single\n * cancel response.\n */\nexport interface KrakenWsCancelOrderResult {\n /**\n * Kraken identifier of the cancelled order.\n */\n order_id: string;\n\n /**\n * Optional client identifier of the cancelled order.\n */\n cl_ord_id?: string;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from cancel_order.\n */\nexport type KrakenWsCancelOrderResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsCancelOrderResult>;\n\n/**\n * Cancel one or more open orders via WS v2.\n *\n * When cancelling multiple orders, Kraken will stream a separate\n * `cancel_order` response per order. This helper resolves on the first\n * response; additional responses can be observed via message handlers\n * on the underlying WebSocket connection.\n *\n * Kraken docs: method = \"cancel_order\" (authenticated)\n */\nexport async function cancelOrder(\n ws: KrakenWebsocketBase,\n params: KrakenWsCancelOrderParams,\n options: KrakenWsCancelOrderOptions = {},\n): Promise<KrakenWsCancelOrderResponse> {\n const hasOrderIds =\n Array.isArray(params.order_id) && params.order_id.length > 0;\n const hasClOrdIds =\n Array.isArray(params.cl_ord_id) && params.cl_ord_id.length > 0;\n const hasUserrefs =\n Array.isArray(params.order_userref) && params.order_userref.length > 0;\n\n if (!hasOrderIds && !hasClOrdIds && !hasUserrefs) {\n throw new Error(\n 'Kraken WS cancel_order: at least one of `order_id`, `cl_ord_id`, or `order_userref` must contain at least one entry',\n );\n }\n\n return ws.request<KrakenWsCancelOrderParams, KrakenWsCancelOrderResult>(\n 'cancel_order',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Parameters for WS v2 cancel_all.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsCancelAllParams {\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for cancelAll wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsCancelAllOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for cancel_all.\n */\nexport interface KrakenWsCancelAllResult {\n /**\n * Number of orders cancelled.\n */\n count: number;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from cancel_all.\n */\nexport type KrakenWsCancelAllResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsCancelAllResult>;\n\n/**\n * Cancel all open orders via WS v2 (including untriggered orders\n * and orders resting in the book).\n *\n * Kraken docs: method = \"cancel_all\" (authenticated)\n */\nexport async function cancelAll(\n ws: KrakenWebsocketBase,\n params: KrakenWsCancelAllParams = {},\n options: KrakenWsCancelAllOptions = {},\n): Promise<KrakenWsCancelAllResponse> {\n return ws.request<KrakenWsCancelAllParams, KrakenWsCancelAllResult>(\n 'cancel_all',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Parameters for WS v2 cancel_all_orders_after.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsCancelAllOrdersAfterParams {\n /**\n * Duration (in seconds) to set/extend the timer.\n *\n * - Must be >= 0 and < 86400.\n * - 0 disables the mechanism.\n */\n timeout: number;\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for cancelAllOrdersAfter wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsCancelAllOrdersAfterOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for cancel_all_orders_after.\n */\nexport interface KrakenWsCancelAllOrdersAfterResult {\n /**\n * Current engine time.\n */\n currentTime: string;\n\n /**\n * Time when all orders will be expired in the engine.\n */\n triggerTime: string;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from cancel_all_orders_after.\n */\nexport type KrakenWsCancelAllOrdersAfterResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsCancelAllOrdersAfterResult>;\n\n/**\n * Configure the \"Dead Man's Switch\" timer that cancels all orders\n * after a given number of seconds of no refresh.\n *\n * - Send `timeout > 0` to enable/extend the timer.\n * - Send `timeout = 0` to disable the mechanism.\n *\n * Kraken docs: method = \"cancel_all_orders_after\" (authenticated)\n */\nexport async function cancelAllOrdersAfter(\n ws: KrakenWebsocketBase,\n params: KrakenWsCancelAllOrdersAfterParams,\n options: KrakenWsCancelAllOrdersAfterOptions = {},\n): Promise<KrakenWsCancelAllOrdersAfterResponse> {\n if (!Number.isFinite(params.timeout)) {\n throw new Error(\n 'Kraken WS cancel_all_orders_after: `timeout` must be a finite number (seconds)',\n );\n }\n if (params.timeout < 0 || params.timeout >= 86400) {\n throw new Error(\n 'Kraken WS cancel_all_orders_after: `timeout` must be >= 0 and < 86400 seconds',\n );\n }\n\n return ws.request<\n KrakenWsCancelAllOrdersAfterParams,\n KrakenWsCancelAllOrdersAfterResult\n >('cancel_all_orders_after', params, {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n });\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\nimport type {\n KrakenWsOrderSide,\n KrakenWsOrderType,\n KrakenWsTimeInForce,\n KrakenWsPriceType,\n KrakenWsTriggerReference,\n KrakenWsAddOrderConditional,\n KrakenWsAddOrderTriggers,\n KrakenWsFeePreference,\n KrakenWsStpType,\n} from './addOrder';\n\n/**\n * Single order entry inside a WS v2 batch_add request.\n *\n * All orders in the batch share the same `symbol` (pair), defined at the\n * top-level params.\n */\nexport interface KrakenWsBatchAddOrderEntry {\n /**\n * Execution side of the order.\n */\n side: KrakenWsOrderSide;\n\n /**\n * Order type (limit, market, stop-loss, etc.).\n */\n order_type: KrakenWsOrderType;\n\n /**\n * Order quantity in terms of the base asset.\n */\n order_qty: number;\n\n /**\n * Order volume expressed in quote currency (market orders only).\n */\n cash_order_qty?: number;\n\n /**\n * Time-in-force for the order.\n */\n time_in_force?: KrakenWsTimeInForce;\n\n /**\n * Use margin funding with maximum leverage for the pair (up to 5x).\n */\n margin?: boolean;\n\n /**\n * Cancels the order if it would take liquidity on arrival.\n * (Limit orders only.)\n */\n post_only?: boolean;\n\n /**\n * Reduce an existing margin position without opening a larger\n * opposite position.\n */\n reduce_only?: boolean;\n\n /**\n * Scheduled start time (precision to seconds, RFC3339).\n */\n effective_time?: string;\n\n /**\n * Expiration time (GTD orders only, RFC3339).\n */\n expire_time?: string;\n\n /**\n * Fee preference base or quote currency.\n */\n fee_preference?: KrakenWsFeePreference;\n\n /**\n * Limit price for order types that support it.\n */\n limit_price?: number;\n\n /**\n * Units for the limit price. Currently only available on trailing-stop\n * / trailing-stop-limit orders.\n */\n limit_price_type?: KrakenWsPriceType;\n\n /**\n * Deprecated: disables Market Price Protection if true (accepted but ignored).\n */\n no_mpp?: boolean;\n\n /**\n * Alphanumeric client order identifier (mutually exclusive with order_userref).\n */\n cl_ord_id?: string;\n\n /**\n * Optional non-unique numeric identifier (mutually exclusive with cl_ord_id).\n */\n order_userref?: number;\n\n /**\n * For iceberg orders only: quantity to show in the book.\n */\n display_qty?: number;\n\n /**\n * Self Trade Prevention mode.\n */\n stp_type?: KrakenWsStpType;\n\n /**\n * Trigger parameters (for triggered order types).\n */\n triggers?: KrakenWsAddOrderTriggers;\n\n /**\n * Sub-account / trader identifier for enhanced STP.\n */\n sender_sub_id?: string;\n\n /**\n * Deprecated: use triggers.price / triggers.price_type instead.\n */\n stop_price?: number;\n\n /**\n * Deprecated: use triggers.reference instead.\n */\n trigger?: KrakenWsTriggerReference;\n\n /**\n * Conditional template used to generate secondary close orders (OTO).\n */\n conditional?: KrakenWsAddOrderConditional;\n}\n\n/**\n * Parameters for WS v2 batch_add.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsBatchAddParams {\n /**\n * The symbol (pair) for all orders in the batch, e.g. \"BTC/USD\".\n */\n symbol: string;\n\n /**\n * A list of orders in the batch.\n * Must contain between 2 and 15 orders (inclusive).\n */\n orders: KrakenWsBatchAddOrderEntry[];\n\n /**\n * Deadline for the entire batch, in RFC3339 format with millisecond precision.\n * Protects against latency on time-sensitive orders.\n */\n deadline?: string;\n\n /**\n * If true, validate only; do not trade in the matching engine.\n */\n validate?: boolean;\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for batchAdd wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsBatchAddOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result entry inside the WS envelope for batch_add.\n *\n * The order of these entries matches the order of the orders in the request.\n */\nexport interface KrakenWsBatchAddOrderResultEntry {\n /**\n * Unique order identifier generated by Kraken.\n */\n order_id: string;\n\n /**\n * Optional client identifier specified in the batch_add parameters.\n */\n cl_ord_id?: string;\n\n /**\n * Optional user reference specified in the batch_add parameters.\n */\n order_userref?: number;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from batch_add.\n * `result` is an array of per-order results.\n */\nexport type KrakenWsBatchAddResponse = KrakenWsMethodResponseEnvelope<\n KrakenWsBatchAddOrderResultEntry[]\n>;\n\n/**\n * Send a batch of 2–15 orders in a single WS v2 request.\n *\n * - Validation is performed on the whole batch first; if one order fails\n * validation, the entire batch is rejected.\n * - On submission, if a specific order fails pre-match checks (e.g. funding),\n * that order is rejected but the rest of the batch may proceed.\n * - All orders are limited to a single pair, specified by `symbol`.\n *\n * Kraken docs: method = \"batch_add\" (authenticated)\n */\nexport async function batchAdd(\n ws: KrakenWebsocketBase,\n params: KrakenWsBatchAddParams,\n options: KrakenWsBatchAddOptions = {},\n): Promise<KrakenWsBatchAddResponse> {\n if (!Array.isArray(params.orders) || params.orders.length < 2) {\n throw new Error(\n 'Kraken WS batch_add: `orders` must contain at least 2 entries',\n );\n }\n if (params.orders.length > 15) {\n throw new Error(\n 'Kraken WS batch_add: `orders` must not contain more than 15 entries',\n );\n }\n\n for (const [index, order] of params.orders.entries()) {\n if (order.cl_ord_id && typeof order.order_userref === 'number') {\n throw new Error(\n `Kraken WS batch_add: order at index ${index} must not specify both cl_ord_id and order_userref`,\n );\n }\n }\n\n return ws.request<KrakenWsBatchAddParams, KrakenWsBatchAddOrderResultEntry[]>(\n 'batch_add',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import {\n KrakenWebsocketBase,\n KrakenWsMethodResponseEnvelope,\n} from '../../../base/websocketBase';\n\n/**\n * Parameters for WS v2 batch_cancel.\n *\n * - `orders` is required and must contain between 2 and 50 identifiers.\n * - Each entry can be either a Kraken `order_id` or a client `order_userref`\n * (Kraken docs model both as strings here).\n * - `cl_ord_id` can optionally supply additional client identifiers.\n *\n * NOTE:\n * - `token` is optional because KrakenWebsocketBase can inject it from\n * the connection options.\n * - `req_id` is handled by KrakenWebsocketBase.request; do not include it here.\n */\nexport interface KrakenWsBatchCancelParams {\n /**\n * A list containing either client order_userref or Kraken order_id\n * identifiers.\n *\n * Must contain between 2 and 50 entries (inclusive).\n */\n orders: string[];\n\n /**\n * A list of client cl_ord_id identifiers.\n */\n cl_ord_id?: string[];\n\n /**\n * Session token. Optional: if omitted, KrakenWebsocketBase will inject\n * the connection's authToken (when present).\n */\n token?: string;\n}\n\n/**\n * Options for batchCancel wrapper – maps directly to KrakenWebsocketBase.request.\n */\nexport interface KrakenWsBatchCancelOptions {\n reqId?: number;\n timeoutMs?: number;\n attachAuthToken?: boolean;\n}\n\n/**\n * Result payload inside the WS envelope for batch_cancel.\n */\nexport interface KrakenWsBatchCancelResult {\n /**\n * Number of orders cancelled.\n */\n count: number;\n\n /**\n * Advisory messages about deprecated fields or upcoming changes.\n */\n warnings?: string[];\n}\n\n/**\n * Full WS envelope returned from batch_cancel.\n */\nexport type KrakenWsBatchCancelResponse =\n KrakenWsMethodResponseEnvelope<KrakenWsBatchCancelResult>;\n\n/**\n * Cancel multiple orders (2–50 identifiers) in a single WS v2 request.\n *\n * - `orders` may contain Kraken `order_id` or client `order_userref`\n * identifiers (as strings).\n * - `cl_ord_id` may contain additional client identifiers.\n *\n * Kraken docs: method = \"batch_cancel\" (authenticated)\n */\nexport async function batchCancel(\n ws: KrakenWebsocketBase,\n params: KrakenWsBatchCancelParams,\n options: KrakenWsBatchCancelOptions = {},\n): Promise<KrakenWsBatchCancelResponse> {\n if (!Array.isArray(params.orders) || params.orders.length < 2) {\n throw new Error(\n 'Kraken WS batch_cancel: `orders` must contain at least 2 identifiers',\n );\n }\n if (params.orders.length > 50) {\n throw new Error(\n 'Kraken WS batch_cancel: `orders` must not contain more than 50 identifiers',\n );\n }\n\n return ws.request<KrakenWsBatchCancelParams, KrakenWsBatchCancelResult>(\n 'batch_cancel',\n params,\n {\n reqId: options.reqId,\n timeoutMs: options.timeoutMs,\n attachAuthToken: options.attachAuthToken,\n },\n );\n}\n","import type { KrakenWebsocketBase } from '../../../base/websocketBase';\nimport * as AddOrder from './addOrder';\nimport * as AmendOrder from './amendOrder';\nimport * as EditOrder from './editOrder';\nimport * as CancelOrder from './cancelOrder';\nimport * as CancelAll from './cancelAll';\nimport * as CancelAllOrdersAfter from './cancelAllOrdersAfter';\nimport * as BatchAdd from './batchAdd';\nimport * as BatchCancel from './batchCancel';\n\n/**\n * User trading RPC methods over WebSocket v2 (auth WS).\n *\n * Exposes the WS v2 trading RPCs:\n * - add_order\n * - amend_order\n * - edit_order (legacy)\n * - cancel_order\n * - cancel_all\n * - cancel_all_orders_after (Dead Man's Switch)\n * - batch_add\n * - batch_cancel\n */\nexport class KrakenSpotWsUserTradingApi {\n constructor(private readonly ws: KrakenWebsocketBase) {}\n\n // ---------------------------------------------------------------------------\n // add_order\n // ---------------------------------------------------------------------------\n\n /**\n * Send a single new order into the exchange.\n *\n * This wraps the WS v2 `add_order` method.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.addOrder({\n * order_type: \"limit\",\n * side: \"buy\",\n * symbol: \"BTC/USD\",\n * order_qty: 0.01,\n * limit_price: 30000,\n * time_in_force: \"gtc\",\n * cl_ord_id: \"arb-20250501-0001\",\n * });\n *\n * if (res.success) {\n * console.log(\"order_id:\", res.result?.order_id);\n * console.log(\"cl_ord_id:\", res.result?.cl_ord_id);\n * } else {\n * console.error(\"add_order error:\", res.error);\n * }\n * ```\n */\n addOrder(\n params: AddOrder.KrakenWsAddOrderParams,\n options?: AddOrder.KrakenWsAddOrderOptions,\n ) {\n return AddOrder.addOrder(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // amend_order\n // ---------------------------------------------------------------------------\n\n /**\n * Amend an existing order in-place.\n *\n * Either `order_id` or `cl_ord_id` must be provided (but not both).\n * Queue priority is preserved where possible.\n *\n * For new integrations, this is preferred over `editOrder`.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.amendOrder({\n * order_id: \"OFGKYQ-FHPCQ-HUQFEK\",\n * order_qty: 0.008, // new quantity\n * limit_price: 29500, // new limit price\n * deadline: \"2025-05-01T12:34:56.123Z\",\n * });\n *\n * if (res.success) {\n * console.log(\"amend_id:\", res.result?.amend_id);\n * } else {\n * console.error(\"amend_order error:\", res.error);\n * }\n * ```\n */\n amendOrder(\n params: AmendOrder.KrakenWsAmendOrderParams,\n options?: AmendOrder.KrakenWsAmendOrderOptions,\n ) {\n return AmendOrder.amendOrder(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // edit_order (legacy)\n // ---------------------------------------------------------------------------\n\n /**\n * Edit (replace) an existing order.\n *\n * This is the **legacy** edit endpoint:\n * - The original order is cancelled.\n * - A new order is created with adjusted parameters.\n * - A new `order_id` is returned.\n *\n * Caveats (from Kraken docs):\n * - Triggered stop-loss / take-profit orders are not supported.\n * - Orders with conditional close terms attached are not supported.\n * - Orders where executed volume > new volume are rejected.\n * - `cl_ord_id` is **not** supported.\n * - Queue position is **not** maintained.\n *\n * Prefer {@link amendOrder} for new integrations where possible.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.editOrder({\n * order_id: \"OFGKYQ-FHPCQ-HUQFEK\",\n * symbol: \"BTC/USD\",\n * order_qty: 0.01,\n * limit_price: 30050,\n * validate: false,\n * });\n *\n * if (res.success) {\n * console.log(\"new order_id:\", res.result?.order_id);\n * console.log(\"original:\", res.result?.original_order_id);\n * } else {\n * console.error(\"edit_order error:\", res.error);\n * }\n * ```\n */\n editOrder(\n params: EditOrder.KrakenWsEditOrderParams,\n options?: EditOrder.KrakenWsEditOrderOptions,\n ) {\n return EditOrder.editOrder(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // cancel_order\n // ---------------------------------------------------------------------------\n\n /**\n * Cancel one or more open orders.\n *\n * Provide at least one of:\n * - `order_id`: list of Kraken order IDs\n * - `cl_ord_id`: list of client order IDs\n * - `order_userref`: list of client numeric references\n *\n * When cancelling multiple orders, Kraken will stream separate `cancel_order`\n * responses for each order on the WS connection. This method resolves on the\n * first response for the batch.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.cancelOrder({\n * order_id: [\"OFGKYQ-FHPCQ-HUQFEK\"],\n * });\n *\n * if (res.success) {\n * console.log(\"cancelled order:\", res.result?.order_id);\n * } else {\n * console.error(\"cancel_order error:\", res.error);\n * }\n * ```\n */\n cancelOrder(\n params: CancelOrder.KrakenWsCancelOrderParams,\n options?: CancelOrder.KrakenWsCancelOrderOptions,\n ) {\n return CancelOrder.cancelOrder(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // cancel_all\n // ---------------------------------------------------------------------------\n\n /**\n * Cancel **all** open orders, including untriggered orders and orders\n * resting in the book.\n *\n * Details of the individual cancelled orders will also be streamed\n * on the executions channel.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.cancelAll();\n *\n * if (res.success) {\n * console.log(\"orders cancelled:\", res.result?.count);\n * } else {\n * console.error(\"cancel_all error:\", res.error);\n * }\n * ```\n */\n cancelAll(\n params?: CancelAll.KrakenWsCancelAllParams,\n options?: CancelAll.KrakenWsCancelAllOptions,\n ) {\n return CancelAll.cancelAll(this.ws, params ?? {}, options);\n }\n\n // ---------------------------------------------------------------------------\n // cancel_all_orders_after (Dead Man's Switch)\n // ---------------------------------------------------------------------------\n\n /**\n * Configure the \"Dead Man's Switch\" timer that cancels all orders\n * after a given number of seconds without refresh.\n *\n * - Send `timeout > 0` to enable/extend the timer.\n * - Send `timeout = 0` to disable the mechanism.\n *\n * Recommended pattern:\n * - Call every 15–30 seconds with `timeout = 60`.\n *\n * @example\n * ```ts\n * // Enable with 60s timeout\n * const res = await wsClient.userTrading.cancelAllOrdersAfter({\n * timeout: 60,\n * });\n *\n * if (res.success) {\n * console.log(\"currentTime:\", res.result?.currentTime);\n * console.log(\"triggerTime:\", res.result?.triggerTime);\n * } else {\n * console.error(\"cancel_all_orders_after error:\", res.error);\n * }\n * ```\n */\n cancelAllOrdersAfter(\n params: CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterParams,\n options?: CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterOptions,\n ) {\n return CancelAllOrdersAfter.cancelAllOrdersAfter(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // batch_add\n // ---------------------------------------------------------------------------\n\n /**\n * Send a batch of 2–15 orders for a single symbol.\n *\n * Behaviour:\n * - Validation is performed on the **entire batch** first; if one order fails\n * validation, the entire batch is rejected.\n * - On engine submission, individual orders can still be rejected\n * (e.g. for funding) while the rest of the batch proceeds.\n * - All orders in the batch share the same `symbol`.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.batchAdd({\n * symbol: \"BTC/USD\",\n * validate: false,\n * orders: [\n * {\n * side: \"buy\",\n * order_type: \"limit\",\n * order_qty: 0.01,\n * limit_price: 30000,\n * time_in_force: \"gtc\",\n * cl_ord_id: \"batch-1-buy\",\n * },\n * {\n * side: \"sell\",\n * order_type: \"limit\",\n * order_qty: 0.01,\n * limit_price: 31000,\n * time_in_force: \"gtc\",\n * cl_ord_id: \"batch-1-sell\",\n * },\n * ],\n * });\n *\n * if (res.success) {\n * for (const entry of res.result ?? []) {\n * console.log(\"order_id:\", entry.order_id, \"cl_ord_id:\", entry.cl_ord_id);\n * }\n * } else {\n * console.error(\"batch_add error:\", res.error);\n * }\n * ```\n */\n batchAdd(\n params: BatchAdd.KrakenWsBatchAddParams,\n options?: BatchAdd.KrakenWsBatchAddOptions,\n ) {\n return BatchAdd.batchAdd(this.ws, params, options);\n }\n\n // ---------------------------------------------------------------------------\n // batch_cancel\n // ---------------------------------------------------------------------------\n\n /**\n * Cancel multiple orders (2–50 identifiers) in a single WS v2 request.\n *\n * - `orders` may contain Kraken `order_id` or client `order_userref`\n * identifiers (as strings).\n * - `cl_ord_id` may contain additional client identifiers.\n *\n * @example\n * ```ts\n * const res = await wsClient.userTrading.batchCancel({\n * orders: [\"OFGKYQ-FHPCQ-HUQFEK\", \"123456\"], // order_id or order_userref\n * cl_ord_id: [\"batch-1-buy\", \"batch-1-sell\"],\n * });\n *\n * if (res.success) {\n * console.log(\"cancelled count:\", res.result?.count);\n * } else {\n * console.error(\"batch_cancel error:\", res.error);\n * }\n * ```\n */\n batchCancel(\n params: BatchCancel.KrakenWsBatchCancelParams,\n options?: BatchCancel.KrakenWsBatchCancelOptions,\n ) {\n return BatchCancel.batchCancel(this.ws, params, options);\n }\n}\n\n// -----------------------------------------------------------------------------\n// Re-export types for consumers\n// -----------------------------------------------------------------------------\n\nexport type KrakenWsOrderSide = AddOrder.KrakenWsOrderSide;\nexport type KrakenWsOrderType = AddOrder.KrakenWsOrderType;\nexport type KrakenWsTimeInForce = AddOrder.KrakenWsTimeInForce;\nexport type KrakenWsFeePreference = AddOrder.KrakenWsFeePreference;\nexport type KrakenWsStpType = AddOrder.KrakenWsStpType;\nexport type KrakenWsPriceType = AddOrder.KrakenWsPriceType;\nexport type KrakenWsTriggerReference = AddOrder.KrakenWsTriggerReference;\nexport type KrakenWsAddOrderTriggers = AddOrder.KrakenWsAddOrderTriggers;\nexport type KrakenWsAddOrderConditional = AddOrder.KrakenWsAddOrderConditional;\n\nexport type KrakenWsAddOrderParams = AddOrder.KrakenWsAddOrderParams;\nexport type KrakenWsAddOrderOptions = AddOrder.KrakenWsAddOrderOptions;\nexport type KrakenWsAddOrderResult = AddOrder.KrakenWsAddOrderResult;\nexport type KrakenWsAddOrderResponse = AddOrder.KrakenWsAddOrderResponse;\n\nexport type KrakenWsAmendOrderParams = AmendOrder.KrakenWsAmendOrderParams;\nexport type KrakenWsAmendOrderOptions = AmendOrder.KrakenWsAmendOrderOptions;\nexport type KrakenWsAmendOrderResult = AmendOrder.KrakenWsAmendOrderResult;\nexport type KrakenWsAmendOrderResponse = AmendOrder.KrakenWsAmendOrderResponse;\n\nexport type KrakenWsEditOrderParams = EditOrder.KrakenWsEditOrderParams;\nexport type KrakenWsEditOrderOptions = EditOrder.KrakenWsEditOrderOptions;\nexport type KrakenWsEditOrderResult = EditOrder.KrakenWsEditOrderResult;\nexport type KrakenWsEditOrderResponse = EditOrder.KrakenWsEditOrderResponse;\n\nexport type KrakenWsCancelOrderParams = CancelOrder.KrakenWsCancelOrderParams;\nexport type KrakenWsCancelOrderOptions = CancelOrder.KrakenWsCancelOrderOptions;\nexport type KrakenWsCancelOrderResult = CancelOrder.KrakenWsCancelOrderResult;\nexport type KrakenWsCancelOrderResponse =\n CancelOrder.KrakenWsCancelOrderResponse;\n\nexport type KrakenWsCancelAllParams = CancelAll.KrakenWsCancelAllParams;\nexport type KrakenWsCancelAllOptions = CancelAll.KrakenWsCancelAllOptions;\nexport type KrakenWsCancelAllResult = CancelAll.KrakenWsCancelAllResult;\nexport type KrakenWsCancelAllResponse = CancelAll.KrakenWsCancelAllResponse;\n\nexport type KrakenWsCancelAllOrdersAfterParams =\n CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterParams;\nexport type KrakenWsCancelAllOrdersAfterOptions =\n CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterOptions;\nexport type KrakenWsCancelAllOrdersAfterResult =\n CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterResult;\nexport type KrakenWsCancelAllOrdersAfterResponse =\n CancelAllOrdersAfter.KrakenWsCancelAllOrdersAfterResponse;\n\nexport type KrakenWsBatchAddParams = BatchAdd.KrakenWsBatchAddParams;\nexport type KrakenWsBatchAddOptions = BatchAdd.KrakenWsBatchAddOptions;\nexport type KrakenWsBatchAddOrderEntry = BatchAdd.KrakenWsBatchAddOrderEntry;\nexport type KrakenWsBatchAddOrderResultEntry =\n BatchAdd.KrakenWsBatchAddOrderResultEntry;\nexport type KrakenWsBatchAddResponse = BatchAdd.KrakenWsBatchAddResponse;\n\nexport type KrakenWsBatchCancelParams = BatchCancel.KrakenWsBatchCancelParams;\nexport type KrakenWsBatchCancelOptions = BatchCancel.KrakenWsBatchCancelOptions;\nexport type KrakenWsBatchCancelResult = BatchCancel.KrakenWsBatchCancelResult;\nexport type KrakenWsBatchCancelResponse =\n BatchCancel.KrakenWsBatchCancelResponse;\n","import {\n KrakenWebsocketBase,\n KrakenWebsocketConnectionOptions,\n KrakenWebsocketLogger,\n} from '../../base/websocketBase';\nimport { KrakenSpotWsAdminApi } from './admin';\nimport { KrakenSpotWsMarketDataApi } from './market-data';\nimport { KrakenSpotWsUserDataApi } from './user-data';\nimport { KrakenSpotWsUserTradingApi } from './user-trading';\n\nexport interface KrakenSpotWebsocketClientOptions {\n publicUrl?: string;\n privateUrl?: string;\n authToken?: string;\n\n WebSocketImpl?: KrakenWebsocketConnectionOptions['WebSocketImpl'];\n autoReconnect?: boolean;\n reconnectDelayMs?: number;\n requestTimeoutMs?: number;\n\n logger?: KrakenWebsocketLogger;\n}\n\n/**\n * Top-level Spot Websocket v2 client.\n */\nexport class KrakenSpotWebsocketV2Client {\n readonly publicConnection: KrakenWebsocketBase;\n readonly privateConnection: KrakenWebsocketBase;\n\n readonly admin: KrakenSpotWsAdminApi;\n readonly marketData: KrakenSpotWsMarketDataApi;\n readonly userData: KrakenSpotWsUserDataApi;\n readonly userTrading: KrakenSpotWsUserTradingApi;\n\n constructor(options: KrakenSpotWebsocketClientOptions = {}) {\n const {\n publicUrl = 'wss://ws.kraken.com/v2',\n privateUrl = 'wss://ws-auth.kraken.com/v2',\n authToken,\n WebSocketImpl,\n autoReconnect,\n reconnectDelayMs,\n requestTimeoutMs,\n logger,\n } = options;\n\n const baseOpts: Omit<KrakenWebsocketConnectionOptions, 'url'> = {\n authToken: undefined,\n WebSocketImpl,\n autoReconnect,\n reconnectDelayMs,\n requestTimeoutMs,\n logger,\n };\n\n this.publicConnection = new KrakenWebsocketBase({\n ...baseOpts,\n url: publicUrl,\n });\n\n this.privateConnection = new KrakenWebsocketBase({\n ...baseOpts,\n url: privateUrl,\n authToken,\n });\n\n this.admin = new KrakenSpotWsAdminApi(this.publicConnection);\n this.marketData = new KrakenSpotWsMarketDataApi(this.publicConnection);\n this.userData = new KrakenSpotWsUserDataApi(this.privateConnection);\n this.userTrading = new KrakenSpotWsUserTradingApi(this.privateConnection);\n }\n}\n"]}