@lynx-crypto/kraken-api 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,98 +8,247 @@
8
8
  [![last commit](https://img.shields.io/github/last-commit/lynx-laboratory/kraken-api?branch=master)](https://github.com/lynx-laboratory/kraken-api/commits/master)
9
9
  [![license](https://img.shields.io/github/license/lynx-laboratory/kraken-api)](./LICENSE.md)
10
10
 
11
- TypeScript client for **Kraken SPOT**:
12
-
11
+ A modern, strongly-typed TypeScript client for the **Kraken Spot API**, providing both **REST** and **WebSocket v2** access in a single package.
13
12
  - **REST API** (public + private endpoints)
14
13
  - **WebSocket v2** (public market-data + authenticated user-data/trading)
15
14
 
16
15
  See [Kraken Official Documentation](https://docs.kraken.com/api/docs/category/guides)
17
16
 
18
17
  ## Important
19
-
20
18
  - This package is currently **SPOT only**. It does **not** implement Kraken Futures.
21
19
  - Unofficial project. Not affiliated with Kraken.
22
20
 
23
21
  ---
24
22
 
25
- ## Install
23
+ ## Features
24
+
25
+ ### Spot REST API
26
+ - Public market data (time, assets, pairs, ticker, OHLC, order book, trades, spreads)
27
+ - Private account data (balances, orders, trades, ledgers, export reports)
28
+ - Trading endpoints (add/amend/edit/cancel orders, batch operations)
29
+ - Funding endpoints (deposits, withdrawals, transfers)
30
+ - Earn endpoints (strategies, allocations, status)
31
+ - Subaccounts (master account operations)
32
+ - Transparency endpoints (pre-trade / post-trade data)
33
+
34
+ ### Spot WebSocket v2 API
35
+ - Public streams (ticker, trades, book, OHLC, instruments)
36
+ - Private user streams (balances, executions)
37
+ - Private trading RPC methods
38
+ - Automatic request/response correlation (`req_id`)
39
+ - Optional auto-reconnect with backoff
40
+ - Works in Node.js (via `ws`) or browser environments
26
41
 
27
- NPM:
28
- `npm i @lynx-crypto/kraken-api`
42
+ ---
29
43
 
30
- Yarn:
31
- `yarn add @lynx-crypto/kraken-api`
44
+ ## Installation
32
45
 
33
- pnpm:
34
- `pnpm add @lynx-crypto/kraken-api`
46
+ Using Yarn:
35
47
 
36
- ### Node support
48
+ ```sh
49
+ yarn add @lynx-crypto/kraken-api
50
+ ```
37
51
 
38
- - Node >= 18 recommended (uses built-in fetch / AbortController)
52
+ Using npm:
53
+
54
+ ```sh
55
+ npm install @lynx-crypto/kraken-api
56
+ ```
39
57
 
40
58
  ---
41
59
 
42
- ## Quick start
60
+ ## Requirements
43
61
 
44
- ESM:
62
+ - Node.js 18+ recommended
63
+ - TypeScript 4.9+ recommended
64
+ - For private endpoints:
65
+ - Kraken API key and secret
66
+ - Appropriate permissions enabled in Kraken
67
+ - “WebSocket interface” enabled for private WS usage
45
68
 
46
- ```ts
47
- import {
48
- KrakenSpotRestClient,
49
- KrakenSpotWebsocketV2Client,
50
- } from '@lynx-crypto/kraken-api';
51
- ```
69
+ ---
52
70
 
53
- CJS:
71
+ ## Environment Variables (for private usage)
54
72
 
55
- ```js
56
- const {
57
- KrakenSpotRestClient,
58
- KrakenSpotWebsocketV2Client,
59
- } = require('@lynx-crypto/kraken-api');
73
+ ```bash
74
+ KRAKEN_API_KEY="your_api_key"
75
+ KRAKEN_API_SECRET="your_api_secret"
60
76
  ```
61
77
 
62
78
  ---
63
79
 
64
- ## REST (Spot)
80
+ ## Package Exports
81
+
82
+ ### REST
83
+ - `KrakenSpotRestClient`
84
+
85
+ Sub-APIs available on the client:
86
+ - `marketData`
87
+ - `accountData`
88
+ - `trading`
89
+ - `funding`
90
+ - `subaccounts`
91
+ - `earn`
92
+ - `transparency`
65
93
 
66
- ### Create a REST client
94
+ ### WebSocket
95
+ - `KrakenSpotWebsocketV2Client`
96
+ - `KrakenWebsocketBase` (advanced / custom integrations)
97
+
98
+ Typed channel namespaces:
99
+ - `admin`
100
+ - `marketData`
101
+ - `userData`
102
+ - `userTrading`
103
+
104
+ All public request/response and stream payloads are exported as TypeScript types.
105
+
106
+ ---
107
+ ## REST Usage
108
+
109
+ ### Public REST example (no authentication)
67
110
 
68
111
  ```ts
69
- const kraken = new KrakenSpotRestClient({
70
- // Optional:
71
- // baseUrl: "https://api.kraken.com",
72
- // timeoutMs: 10_000,
73
- // userAgent: "my-app/1.0.0",
112
+ import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
74
113
 
75
- // Required for private endpoints:
76
- apiKey: process.env.KRAKEN_API_KEY,
77
- apiSecret: process.env.KRAKEN_API_SECRET,
114
+ async function main() {
115
+ const kraken = new KrakenSpotRestClient({
116
+ userAgent: 'example-app/1.0.0',
117
+ });
78
118
 
79
- // Optional logger:
80
- // logger: console,
119
+ const time = await kraken.marketData.getServerTime();
120
+ console.log('Kraken time:', time.rfc1123);
121
+ }
81
122
 
82
- // Optional rate limiting:
83
- // rateLimit: { mode: "auto" },
123
+ main().catch((err) => {
124
+ console.error(err);
125
+ process.exitCode = 1;
84
126
  });
85
127
  ```
86
128
 
87
- ### Public endpoint example
129
+ ### Private REST example (authenticated)
130
+
131
+ ```ts
132
+ import 'dotenv/config';
133
+ import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
134
+
135
+ function requireEnv(name: string): string {
136
+ const v = process.env[name];
137
+ if (!v) throw new Error(`Missing env var: ${name}`);
138
+ return v;
139
+ }
88
140
 
89
- (Exact public endpoints depend on what you’ve implemented under src/spot/rest.)
141
+ async function main() {
142
+ const kraken = new KrakenSpotRestClient({
143
+ userAgent: 'example-app/1.0.0',
144
+ apiKey: requireEnv('KRAKEN_API_KEY'),
145
+ apiSecret: requireEnv('KRAKEN_API_SECRET'),
146
+ });
147
+
148
+ const balances = await kraken.accountData.getAccountBalance();
149
+ console.log('Asset count:', Object.keys(balances).length);
150
+ }
151
+
152
+ main().catch((err) => {
153
+ console.error(err);
154
+ process.exitCode = 1;
155
+ });
156
+ ```
157
+
158
+ ---
159
+
160
+ ## WebSocket v2 Usage
161
+
162
+ ### Public WebSocket (market data)
90
163
 
91
164
  ```ts
92
- const serverTime = await kraken.public.getServerTime();
93
- console.log(serverTime);
165
+ import { KrakenSpotWebsocketV2Client } from '@lynx-crypto/kraken-api';
166
+
167
+ async function main() {
168
+ const wsClient = new KrakenSpotWebsocketV2Client({
169
+ autoReconnect: false,
170
+ });
171
+
172
+ await wsClient.publicConnection.connect();
173
+
174
+ const ack = await wsClient.marketData.subscribeTrade(
175
+ { symbol: ['BTC/USD'], snapshot: true },
176
+ { reqId: 1 },
177
+ );
178
+
179
+ if (!ack.success) {
180
+ throw new Error(`Subscribe failed: ${ack.error}`);
181
+ }
182
+
183
+ const unsubscribe = wsClient.publicConnection.addMessageHandler((msg) => {
184
+ console.log(JSON.stringify(msg));
185
+ });
186
+
187
+ setTimeout(() => {
188
+ unsubscribe();
189
+ wsClient.publicConnection.close(1000, 'example done');
190
+ }, 20_000);
191
+ }
192
+
193
+ main().catch((err) => {
194
+ console.error(err);
195
+ process.exitCode = 1;
196
+ });
94
197
  ```
95
198
 
96
- ### Private endpoint example
199
+ ### Private WebSocket (balances / executions)
97
200
 
98
- (Exact private endpoints depend on what you’ve implemented under src/spot/rest.)
201
+ Authenticated WebSocket usage requires a token obtained via REST.
99
202
 
100
203
  ```ts
101
- const balances = await kraken.accountData.getAccountBalance();
102
- console.log('USD:', balances['ZUSD']);
204
+ import 'dotenv/config';
205
+ import {
206
+ KrakenSpotRestClient,
207
+ KrakenSpotWebsocketV2Client,
208
+ } from '@lynx-crypto/kraken-api';
209
+
210
+ function requireEnv(name: string): string {
211
+ const v = process.env[name];
212
+ if (!v) throw new Error(`Missing env var: ${name}`);
213
+ return v;
214
+ }
215
+
216
+ async function main() {
217
+ const rest = new KrakenSpotRestClient({
218
+ userAgent: 'example-app/1.0.0',
219
+ apiKey: requireEnv('KRAKEN_API_KEY'),
220
+ apiSecret: requireEnv('KRAKEN_API_SECRET'),
221
+ });
222
+
223
+ const { token } = await rest.trading.getWebSocketsToken();
224
+
225
+ const wsClient = new KrakenSpotWebsocketV2Client({
226
+ authToken: token,
227
+ autoReconnect: false,
228
+ });
229
+
230
+ await wsClient.privateConnection.connect();
231
+
232
+ const ack = await wsClient.userData.subscribeBalances({}, { reqId: 10 });
233
+
234
+ if (!ack.success) {
235
+ throw new Error(`Subscribe failed: ${ack.error}`);
236
+ }
237
+
238
+ const off = wsClient.privateConnection.addMessageHandler((msg) => {
239
+ console.log(JSON.stringify(msg));
240
+ });
241
+
242
+ setTimeout(() => {
243
+ off();
244
+ wsClient.privateConnection.close(1000, 'example done');
245
+ }, 30_000);
246
+ }
247
+
248
+ main().catch((err) => {
249
+ console.error(err);
250
+ process.exitCode = 1;
251
+ });
103
252
  ```
104
253
 
105
254
  ---
@@ -198,142 +347,30 @@ Notes:
198
347
 
199
348
  ---
200
349
 
201
- ## WebSocket v2 (Spot)
202
-
203
- This package provides a top-level v2 WS client that creates:
204
-
205
- - a public connection (market data + admin)
206
- - a private/auth connection (user-data + user-trading)
207
-
208
- ### Create a WS v2 client
209
-
210
- ```ts
211
- const ws = new KrakenSpotWebsocketV2Client({
212
- // publicUrl: "wss://ws.kraken.com/v2",
213
- // privateUrl: "wss://ws-auth.kraken.com/v2",
350
+ ## Examples
214
351
 
215
- authToken: process.env.KRAKEN_WS_AUTH_TOKEN,
352
+ The repository includes a comprehensive [examples](./examples) directory:
216
353
 
217
- // autoReconnect: true,
218
- // reconnectDelayMs: 1_000,
219
- // requestTimeoutMs: 10_000,
354
+ - REST (public + safe private endpoints)
355
+ - WebSocket v2 public streams
356
+ - WebSocket v2 private streams (balances, executions)
357
+ - Clean lifecycle examples (connect → subscribe → receive → close)
220
358
 
221
- // logger: console,
222
- // WebSocketImpl: WebSocket,
223
- });
224
- ```
225
-
226
- Available sub-APIs:
227
-
228
- - `ws.admin`
229
- - `ws.marketData`
230
- - `ws.userData`
231
- - `ws.userTrading`
232
-
233
- ### Connect
234
-
235
- ```ts
236
- await ws.publicConnection.connect();
237
- await ws.privateConnection.connect();
238
- ```
359
+ Examples are designed to be:
360
+ - Runnable
361
+ - Safe by default
362
+ - Self-contained
363
+ - Easy to copy into your own project
239
364
 
240
365
  ---
241
366
 
242
- ## WS routing: receiving streaming messages
243
-
244
- ```ts
245
- const unsubscribe = ws.publicConnection.addMessageHandler((msg) => {
246
- // route by msg.channel / msg.type
247
- });
248
-
249
- // later
250
- unsubscribe();
251
- ```
252
-
253
- ---
254
-
255
- ## WS v2: Admin
256
-
257
- ```ts
258
- const pong = await ws.admin.ping({ reqId: 123 });
259
- if (!pong.success) console.error('ping failed:', pong.error);
260
- ```
261
-
262
- ---
263
-
264
- ## WS v2: User Data (authenticated)
265
-
266
- Implemented channels:
267
-
268
- - `executions`
269
- - `balances`
367
+ ## Design Philosophy
270
368
 
271
- ### Executions example
272
-
273
- ```ts
274
- const ack = await ws.userData.subscribeExecutions({
275
- snap_trades: true,
276
- snap_orders: true,
277
- order_status: true,
278
- });
279
- ```
280
-
281
- ```ts
282
- ws.privateConnection.addMessageHandler((msg) => {
283
- if (msg?.channel === 'executions') {
284
- for (const report of msg.data ?? []) {
285
- console.log(report.order_id, report.order_status);
286
- }
287
- }
288
- });
289
- ```
290
-
291
- ### Balances example
292
-
293
- ```ts
294
- const ack2 = await ws.userData.subscribeBalances({ snapshot: true });
295
- ```
296
-
297
- ```ts
298
- ws.privateConnection.addMessageHandler((msg) => {
299
- if (msg?.channel === 'balances') {
300
- console.log(msg.data);
301
- }
302
- });
303
- ```
304
-
305
- ---
306
-
307
- ## WS v2: User Trading (authenticated RPC)
308
-
309
- Implemented RPCs:
310
-
311
- - `add_order`
312
- - `amend_order`
313
- - `cancel_order`
314
- - `cancel_all`
315
- - `cancel_all_orders_after`
316
- - `batch_add`
317
- - `batch_cancel`
318
-
319
- Add order:
320
-
321
- ```ts
322
- const res = await ws.userTrading.addOrder({
323
- order_type: 'limit',
324
- side: 'buy',
325
- symbol: 'BTC/USD',
326
- order_qty: 0.01,
327
- limit_price: 30000,
328
- time_in_force: 'gtc',
329
- });
330
- ```
331
-
332
- Dead Man’s Switch:
333
-
334
- ```ts
335
- await ws.userTrading.cancelAllOrdersAfter({ timeout: 60 });
336
- ```
369
+ - Explicit APIs over magic
370
+ - Strong typing without sacrificing usability
371
+ - Clear separation of REST vs WebSocket concerns
372
+ - No hidden background workers
373
+ - Safe defaults, especially for trading operations
337
374
 
338
375
  ---
339
376
 
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var crypto=require('crypto'),ws=require('ws');var y=class{constructor(e,r){this.maxCounter=e;this.decayPerSec=r;}counter=0;lastTs=Date.now();queue=[];draining=false;schedule(e,r){let n=Math.max(0,r?.cost??1);return new Promise((s,o)=>{this.queue.push({fn:e,resolve:s,reject:o,cost:n}),this.drain();})}decayNow(){let e=Date.now(),r=(e-this.lastTs)/1e3;r>0&&(this.counter=Math.max(0,this.counter-r*this.decayPerSec),this.lastTs=e);}async drain(){if(!this.draining){this.draining=true;try{for(;this.queue.length>0;){this.decayNow();let e=this.queue[0];if(this.counter+e.cost<=this.maxCounter){this.queue.shift(),this.counter+=e.cost;try{let o=await e.fn();e.resolve(o);}catch(o){e.reject(o);}continue}let n=(this.counter+e.cost-this.maxCounter)/this.decayPerSec,s=Math.max(50,Math.ceil(n*1e3));await w(s);}}finally{this.draining=false;}}}};function I(t){switch(t){case "pro":return {maxCounter:20,decayPerSec:1};case "intermediate":return {maxCounter:20,decayPerSec:.5};case "starter":default:return {maxCounter:15,decayPerSec:.33}}}function L(t){return t.includes("TradesHistory")||t.includes("Ledgers")||t.includes("TradeBalance")?2:1}function v(t){return t.includes("/AddOrder")||t.includes("/CancelOrder")||t.includes("/CancelAll")||t.includes("/EditOrder")||t.includes("/AddOrderBatch")||t.includes("/CancelOrderBatch")}function w(t){return new Promise(e=>setTimeout(e,t))}function D(t){let e=t*.2;return Math.max(0,Math.floor(t+(Math.random()*2-1)*e))}function M(t){let e=t.match(/EService:\s*Throttled:\s*(\d+)/i);if(!e)return null;let r=Number(e[1]);return Number.isFinite(r)?r:null}var g=class extends Error{name="KrakenApiError";endpoint;httpStatus;httpStatusText;krakenErrorCodes;rawBody;constructor(e,r={}){super(e),Object.setPrototypeOf(this,new.target.prototype),this.endpoint=r.endpoint,this.httpStatus=r.httpStatus,this.httpStatusText=r.httpStatusText,this.krakenErrorCodes=r.krakenErrorCodes,this.rawBody=r.rawBody;}};var h=class{baseUrl;timeoutMs;userAgent;apiKey;apiSecret;logger;lastNonce;lastMs=0;restLimiter;tradingLimiter;rateLimitOptions;restCostFn;tradingCostFn;constructor(e={}){this.baseUrl=e.baseUrl??"https://api.kraken.com",this.timeoutMs=e.timeoutMs??1e4,this.userAgent=e.userAgent,this.apiKey=e.apiKey,this.apiSecret=e.apiSecret,this.logger=e.logger;let r=e.rateLimit??{},n=r.mode??"auto",s=r.tier??"starter";if(this.rateLimitOptions={retryOnRateLimit:r.retryOnRateLimit??true,maxRetries:r.maxRetries??5},this.restCostFn=r.restCostFn??L,this.tradingCostFn=r.tradingCostFn??(()=>1),e.limiter?.rest&&(this.restLimiter=e.limiter.rest),e.limiter?.trading&&(this.tradingLimiter=e.limiter.trading),n!=="off"){if(!this.restLimiter){let{maxCounter:o,decayPerSec:a}=I(s);this.restLimiter=new y(o,a);}this.tradingLimiter||(this.tradingLimiter=new y(10,1));}}createNonce(){let e=Date.now();return this.lastNonce===void 0?(this.lastNonce=BigInt(e)*1000n,this.lastMs=e,this.lastNonce.toString()):(e>this.lastMs?(this.lastNonce=BigInt(e)*1000n,this.lastMs=e):this.lastNonce=this.lastNonce+1n,this.lastNonce.toString())}async publicGet(e,r){let n=new URL(e,this.baseUrl);if(r)for(let[s,o]of Object.entries(r))n.searchParams.set(s,String(o));return this.logger?.debug?.("Kraken REST public GET request",{endpoint:e,url:n.toString(),query:r}),this.scheduleWithRetry(e,async()=>{let s=new AbortController,o=setTimeout(()=>s.abort(),this.timeoutMs);try{let a=await fetch(n,{method:"GET",signal:s.signal,headers:this.userAgent?{"User-Agent":this.userAgent}:void 0});if(!a.ok)throw this.logger?.error?.("Kraken REST HTTP error",{endpoint:e,status:a.status,statusText:a.statusText}),new g(`HTTP error from Kraken: ${a.status} ${a.statusText}`,{endpoint:e,httpStatus:a.status,httpStatusText:a.statusText});let i;try{i=await a.json();}catch(l){throw this.logger?.error?.("Kraken REST JSON parse error",{endpoint:e,error:l}),new g("Failed to parse Kraken response JSON",{endpoint:e,httpStatus:a.status})}if(i.error?.length)throw this.logger?.warn?.("Kraken REST API error",{endpoint:e,krakenErrors:i.error}),new g(`Kraken API error: ${i.error.join(", ")}`,{endpoint:e,httpStatus:a.status,krakenErrorCodes:i.error,rawBody:i});return this.logger?.debug?.("Kraken REST public GET success",{endpoint:e}),i.result}finally{clearTimeout(o);}})}async privatePost(e,r){if(!this.apiKey||!this.apiSecret)throw new g("Missing apiKey or apiSecret for Kraken private API call",{endpoint:e});let n=new URL(e,this.baseUrl);return this.scheduleWithRetry(e,async()=>{let s=this.createNonce(),o=new URLSearchParams;if(o.set("nonce",s),r)for(let[K,p]of Object.entries(r))p!==void 0&&o.set(K,String(p));let a=o.toString(),i=e,l=crypto.createHash("sha256").update(s+a).digest(),d=Buffer.from(this.apiSecret,"base64"),m=crypto.createHmac("sha512",d).update(i+l).digest("base64");this.logger?.debug?.("Kraken REST private POST request",{endpoint:e,url:n.toString(),hasParams:!!r});let k=new AbortController,u=setTimeout(()=>k.abort(),this.timeoutMs);try{let K=await fetch(n,{method:"POST",signal:k.signal,headers:{"Content-Type":"application/x-www-form-urlencoded","API-Key":this.apiKey,"API-Sign":m,...this.userAgent?{"User-Agent":this.userAgent}:{}},body:a});if(!K.ok)throw this.logger?.error?.("Kraken REST private HTTP error",{endpoint:e,status:K.status,statusText:K.statusText}),new g(`HTTP error from Kraken private API: ${K.status} ${K.statusText}`,{endpoint:e,httpStatus:K.status,httpStatusText:K.statusText});let p;try{p=await K.json();}catch(b){throw this.logger?.error?.("Kraken REST private JSON parse error",{endpoint:e,error:b}),new g("Failed to parse Kraken private API response JSON",{endpoint:e,httpStatus:K.status})}if(p.error?.length)throw this.logger?.warn?.("Kraken REST private API error",{endpoint:e,krakenErrors:p.error}),new g(`Kraken private API error: ${p.error.join(", ")}`,{endpoint:e,httpStatus:K.status,krakenErrorCodes:p.error,rawBody:p});return this.logger?.debug?.("Kraken REST private POST success",{endpoint:e}),p.result}finally{clearTimeout(u);}})}async privatePostBinary(e,r){if(!this.apiKey||!this.apiSecret)throw new Error("KrakenRestBase: apiKey and apiSecret are required for private endpoints");let n=new URL(e,this.baseUrl);return this.scheduleWithRetry(e,async()=>{let s=this.createNonce(),a=new URLSearchParams({nonce:s,...r??{}}).toString(),i=this.signPrivateRequest(e,s,a);this.logger?.debug?.("[KrakenRestBase] privatePostBinary request",{url:n.toString(),path:e,body:r});let l={"API-Key":this.apiKey,"API-Sign":i,"User-Agent":this.userAgent??"lynx-crypto-kraken-client/0.1.0","Content-Type":"application/x-www-form-urlencoded"},d=await fetch(n.toString(),{method:"POST",headers:l,body:a});if(!d.ok){let k=await d.text().catch(()=>"");throw this.logger?.error?.("[KrakenRestBase] privatePostBinary HTTP error",{status:d.status,statusText:d.statusText,body:k}),new Error(`Kraken privatePostBinary failed: ${d.status} ${d.statusText} \u2013 ${k}`)}if((d.headers.get("content-type")??"").includes("application/json")){let k=await d.json().catch(()=>null);if(!k)throw new Error("Kraken privatePostBinary: expected JSON body for error response");let u=k.error??[];if(u.length>0){let K=`Kraken API error: ${u.join(", ")}`;this.logger?.error?.("[KrakenRestBase] Kraken API error (binary response)",{errors:u});let p=new Error(K);throw p.krakenErrors=u,p}throw new Error("Kraken privatePostBinary: expected binary data but got JSON without errors")}let m=await d.arrayBuffer();return this.logger?.debug?.("[KrakenRestBase] privatePostBinary success",{bytes:m.byteLength}),m})}signPrivateRequest(e,r,n){if(!this.apiSecret)throw new Error("KrakenRestBase: apiSecret is required for private endpoints");let s=Buffer.from(this.apiSecret,"base64"),o=crypto.createHash("sha256").update(r+n).digest();return crypto.createHmac("sha512",s).update(e+o).digest("base64")}async scheduleWithRetry(e,r){let n=v(e)?this.tradingLimiter:this.restLimiter,s=v(e)?this.tradingCostFn(e):this.restCostFn(e),o=()=>n?n.schedule(r,{cost:s}):r();if(!this.rateLimitOptions.retryOnRateLimit)return o();let a=this.rateLimitOptions.maxRetries,i=0;for(;;)try{return await o()}catch(l){i++;let d=l?.message??(typeof l=="string"?l:"")??"",c=l?.krakenErrorCodes??l?.krakenErrors,m=d.includes("EAPI:Rate limit exceeded")||Array.isArray(c)&&c.some(b=>b.includes("EAPI:Rate limit exceeded")),k=(()=>{let b=M(d);if(b)return b;if(Array.isArray(c))for(let G of c){let C=M(G);if(C)return C}return null})(),u=l?.httpStatus===429;if(!(m||k!==null||u)||i>a)throw l;let p=0;if(k!==null){let b=Math.floor(Date.now()/1e3);p=Math.max(0,k-b)*1e3;}else {let b=250*Math.pow(2,i-1);p=Math.min(b,1e4);}p=D(p),this.logger?.warn?.("Kraken rate limited; retrying",{endpoint:e,attempt:i,waitMs:p,reason:u?"HTTP 429":k?"EService: Throttled":"EAPI: Rate limit exceeded"}),await w(p);}}};function F(t){return t.publicGet("/0/public/Time")}function H(t){return t.publicGet("/0/public/SystemStatus")}function j(t,e){let r={};return e?.asset&&e.asset.length>0&&(r.asset=e.asset.join(",")),e?.aclass&&(r.aclass=e.aclass),t.publicGet("/0/public/Assets",r)}function Q(t,e){let r={};return e?.pair?.length&&(r.pair=e.pair.join(",")),e?.aclass_base&&(r.aclass_base=e.aclass_base),e?.info&&(r.info=e.info),e?.country_code&&(r.country_code=e.country_code),t.publicGet("/0/public/AssetPairs",r)}function N(t,e){let r={};return e?.pair?.length&&(r.pair=e.pair.join(",")),e?.asset_class&&(r.asset_class=e.asset_class),t.publicGet("/0/public/Ticker",r)}async function V(t,e){let r={pair:e.pair};e.interval!==void 0&&(r.interval=String(e.interval)),e.since!==void 0&&(r.since=String(e.since)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/OHLC",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,ohlc:a}}function z(t,e){let r={pair:e.pair};return e.count!==void 0&&(r.count=String(e.count)),e.asset_class&&(r.asset_class=e.asset_class),t.publicGet("/0/public/Depth",r)}async function $(t,e){let r={pair:e.pair};e.since!==void 0&&(r.since=String(e.since)),e.count!==void 0&&(r.count=String(e.count)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/Trades",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,trades:a}}async function J(t,e){let r={pair:e.pair};e.since!==void 0&&(r.since=String(e.since)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/Spread",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,spreads:a}}var x=class{constructor(e){this.base=e;}getServerTime(){return F(this.base)}getSystemStatus(){return H(this.base)}getAssetInfo(e){return j(this.base,e)}getTradableAssetPairs(e){return Q(this.base,e)}getTickerInformation(e){return N(this.base,e)}getOhlcData(e){return V(this.base,e)}getOrderBook(e){return z(this.base,e)}getRecentTrades(e){return $(this.base,e)}getRecentSpreads(e){return J(this.base,e)}};function Y(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/Balance",r)}function X(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/BalanceEx",r)}function Z(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/CreditLines",r)}function ee(t,e){let r={};return e?.asset&&(r.asset=e.asset),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradeBalance",r)}function re(t,e){let r={};return e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.userref!==void 0&&(r.userref=String(e.userref)),e?.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OpenOrders",r)}function te(t,e){let r={};return e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.userref!==void 0&&(r.userref=String(e.userref)),e?.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.closetime&&(r.closetime=e.closetime),e?.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e?.without_count!==void 0&&(r.without_count=e.without_count?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/ClosedOrders",r)}function ne(t,e){let r={};return e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.userref!==void 0&&(r.userref=String(e.userref)),Array.isArray(e.txid)?r.txid=e.txid.join(","):r.txid=e.txid,e.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryOrders",r)}function se(t,e){let r={order_id:e.order_id};return e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OrderAmends",r)}function ae(t,e){let r={};return e?.type&&(r.type=e.type),e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e?.ledgers!==void 0&&(r.ledgers=e.ledgers?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradesHistory",r)}function oe(t,e){let r={};return Array.isArray(e.txid)?r.txid=e.txid.join(","):r.txid=e.txid,e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryTrades",r)}function ie(t,e){let r={};return e?.txid!==void 0&&(r.txid=Array.isArray(e.txid)?e.txid.join(","):e.txid),e?.docalcs!==void 0&&(r.docalcs=e.docalcs?"true":"false"),e?.consolidation&&(r.consolidation=e.consolidation),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OpenPositions",r)}function de(t,e){let r={};return e?.asset!==void 0&&(r.asset=Array.isArray(e.asset)?e.asset.join(","):e.asset),e?.aclass&&(r.aclass=e.aclass),e?.type&&(r.type=e.type),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.without_count!==void 0&&(r.without_count=e.without_count?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/Ledgers",r)}function ce(t,e){let r={};return Array.isArray(e.id)?r.id=e.id.join(","):r.id=e.id,e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryLedgers",r)}function le(t,e){let r={};return e?.pair!==void 0&&(r.pair=Array.isArray(e.pair)?e.pair.join(","):e.pair),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradeVolume",r)}function pe(t,e){let r={report:e.report,description:e.description};return e.format&&(r.format=e.format),e.fields&&(r.fields=e.fields),e.starttm!==void 0&&(r.starttm=String(e.starttm)),e.endtm!==void 0&&(r.endtm=String(e.endtm)),t.privatePost("/0/private/AddExport",r)}function ue(t,e){let r={report:e.report};return t.privatePost("/0/private/ExportStatus",r)}function ke(t,e){let r={id:e.id};return t.privatePostBinary("/0/private/RetrieveExport",r)}function Ke(t,e){let r={id:e.id,type:e.type};return t.privatePost("/0/private/RemoveExport",r)}var W=class{constructor(e){this.base=e;}getAccountBalance(e){return Y(this.base,e)}getExtendedBalance(e){return X(this.base,e)}getCreditLines(e){return Z(this.base,e)}getTradeBalance(e){return ee(this.base,e)}getOpenOrders(e){return re(this.base,e)}getClosedOrders(e){return te(this.base,e)}queryOrdersInfo(e){return ne(this.base,e)}getOrderAmends(e){return se(this.base,e)}getTradesHistory(e){return ae(this.base,e)}queryTradesInfo(e){return oe(this.base,e)}getOpenPositions(e){return ie(this.base,e)}getLedgersInfo(e){return de(this.base,e)}queryLedgers(e){return ce(this.base,e)}getTradeVolume(e){return le(this.base,e)}requestExportReport(e){return pe(this.base,e)}getExportReportStatus(e){return ue(this.base,e)}retrieveExportReport(e){return ke(this.base,e)}deleteExportReport(e){return Ke(this.base,e)}};function me(t,e){if(e.userref!==void 0&&e.cl_ord_id)throw new Error("KrakenAddOrderParams: userref and cl_ord_id are mutually exclusive");let r={ordertype:e.ordertype,type:e.type,volume:e.volume,pair:e.pair};return e.userref!==void 0&&(r.userref=String(e.userref)),e.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e.displayvol&&(r.displayvol=e.displayvol),e.asset_class&&(r.asset_class=e.asset_class),e.price!==void 0&&(r.price=e.price),e.price2!==void 0&&(r.price2=e.price2),e.trigger&&(r.trigger=e.trigger),e.leverage!==void 0&&(r.leverage=e.leverage),e.reduce_only!==void 0&&(r.reduce_only=e.reduce_only?"true":"false"),e.stptype&&(r.stptype=e.stptype),e.oflags&&(r.oflags=e.oflags),e.timeinforce&&(r.timeinforce=e.timeinforce),e.starttm!==void 0&&(r.starttm=e.starttm),e.expiretm!==void 0&&(r.expiretm=e.expiretm),e.deadline!==void 0&&(r.deadline=e.deadline),e.validate!==void 0&&(r.validate=e.validate?"true":"false"),e.close&&(r["close[ordertype]"]=e.close.ordertype,e.close.price!==void 0&&(r["close[price]"]=e.close.price),e.close.price2!==void 0&&(r["close[price2]"]=e.close.price2)),t.privatePost("/0/private/AddOrder",r)}function be(t,e){if(!e.txid&&!e.cl_ord_id)throw new Error("KrakenAmendOrderParams: either txid or cl_ord_id must be provided");let r={};return e.txid&&(r.txid=e.txid),e.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e.order_qty!==void 0&&(r.order_qty=e.order_qty),e.display_qty!==void 0&&(r.display_qty=e.display_qty),e.limit_price!==void 0&&(r.limit_price=e.limit_price),e.trigger_price!==void 0&&(r.trigger_price=e.trigger_price),e.pair!==void 0&&(r.pair=e.pair),e.post_only!==void 0&&(r.post_only=e.post_only?"true":"false"),e.deadline!==void 0&&(r.deadline=e.deadline),t.privatePost("/0/private/AmendOrder",r)}function ge(t,e){let{txid:r,userref:n,cl_ord_id:s}=e,o=(r!==void 0?1:0)+(n!==void 0?1:0)+(s!==void 0?1:0);if(o===0)throw new Error("KrakenCancelOrderParams: one of txid, userref, or cl_ord_id must be provided");if(o>1)throw new Error("KrakenCancelOrderParams: txid, userref, and cl_ord_id are mutually exclusive; provide exactly one");let a={};return n!==void 0?a.txid=String(n):s!==void 0?a.cl_ord_id=Array.isArray(s)?s.join(","):s:r!==void 0&&(a.txid=Array.isArray(r)?r.join(","):r),t.privatePost("/0/private/CancelOrder",a)}function ye(t){return t.privatePost("/0/private/CancelAll",{})}function fe(t,e){let r={timeout:String(e.timeout)};return t.privatePost("/0/private/CancelAllOrdersAfter",r)}function he(t){return t.privatePost("/0/private/GetWebSocketsToken",{})}function xe(t,e){let{orders:r,pair:n,asset_class:s,deadline:o,validate:a}=e;if(!Array.isArray(r)||r.length<2||r.length>15)throw new Error(`KrakenAddOrderBatchParams: orders must contain between 2 and 15 items (got ${r.length})`);for(let[d,c]of r.entries())if(c.userref!==void 0&&c.cl_ord_id!==void 0)throw new Error(`KrakenAddOrderBatchParams: order[${d}] cannot have both userref and cl_ord_id`);let i={pair:n};s&&(i.asset_class=s),o!==void 0&&(i.deadline=o),a!==void 0&&(i.validate=a?"true":"false");let l=r.map(d=>{let c={ordertype:d.ordertype,type:d.type,volume:d.volume};return d.userref!==void 0&&(c.userref=String(d.userref)),d.cl_ord_id!==void 0&&(c.cl_ord_id=d.cl_ord_id),d.displayvol!==void 0&&(c.displayvol=d.displayvol),d.price!==void 0&&(c.price=d.price),d.price2!==void 0&&(c.price2=d.price2),d.trigger!==void 0&&(c.trigger=d.trigger),d.leverage!==void 0&&(c.leverage=d.leverage),d.reduce_only!==void 0&&(c.reduce_only=d.reduce_only?"true":"false"),d.stptype!==void 0&&(c.stptype=d.stptype),d.oflags!==void 0&&(c.oflags=d.oflags),d.timeinforce!==void 0&&(c.timeinforce=d.timeinforce),d.starttm!==void 0&&(c.starttm=d.starttm),d.expiretm!==void 0&&(c.expiretm=d.expiretm),c});return i.orders=JSON.stringify(l),t.privatePost("/0/private/AddOrderBatch",i)}function We(t,e){let{orders:r,clOrdIds:n}=e,s=r?.length??0,o=n?.length??0,a=s+o;if(a===0)throw new Error("KrakenCancelOrderBatchParams: at least one txid/userref or cl_ord_id is required");if(a>50)throw new Error(`KrakenCancelOrderBatchParams: maximum 50 total ids/references allowed, got ${a}`);let i={};if(r&&r.length>0){let l=r.map(d=>({txid:String(d.txid)}));i.orders=JSON.stringify(l);}if(n&&n.length>0){let l=n.map(d=>({cl_ord_id:d}));i.cl_ord_ids=JSON.stringify(l);}return t.privatePost("/0/private/CancelOrderBatch",i)}function Oe(t,e){let r={txid:String(e.txid),pair:e.pair};return e.userref!==void 0&&(r.userref=String(e.userref)),e.volume!==void 0&&(r.volume=e.volume),e.displayvol!==void 0&&(r.displayvol=e.displayvol),e.asset_class!==void 0&&(r.asset_class=e.asset_class),e.price!==void 0&&(r.price=e.price),e.price2!==void 0&&(r.price2=e.price2),e.oflags!==void 0&&(r.oflags=e.oflags),e.deadline!==void 0&&(r.deadline=e.deadline),e.cancel_response!==void 0&&(r.cancel_response=e.cancel_response?"true":"false"),e.validate!==void 0&&(r.validate=e.validate?"true":"false"),t.privatePost("/0/private/EditOrder",r)}var O=class{constructor(e){this.base=e;}addOrder(e){return me(this.base,e)}amendOrder(e){return be(this.base,e)}cancelOrder(e){return ge(this.base,e)}cancelAllOrders(){return ye(this.base)}cancelAllOrdersAfter(e){return fe(this.base,e)}getWebSocketsToken(){return he(this.base)}addOrderBatch(e){return xe(this.base,e)}cancelOrderBatch(e){return We(this.base,e)}editOrder(e){return Oe(this.base,e)}};function Re(t,e){let r={asset:e.asset};return e.aclass!==void 0&&(r.aclass=e.aclass),e.rebase_multiplier!==void 0&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/DepositMethods",r)}function Ae(t,e){let r={asset:e.asset,method:e.method};return e.aclass!==void 0&&(r.aclass=e.aclass),e.new!==void 0&&(r.new=e.new?"true":"false"),e.amount!==void 0&&(r.amount=String(e.amount)),t.privatePost("/0/private/DepositAddresses",r)}function Te(t,e={}){let r={};return e.asset&&(r.asset=e.asset),e.aclass&&(r.aclass=e.aclass),e.method&&(r.method=e.method),e.start!==void 0&&(r.start=String(e.start)),e.end!==void 0&&(r.end=String(e.end)),e.cursor&&(r.cursor=e.cursor),e.limit!==void 0&&(r.limit=String(e.limit)),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/DepositStatus",r)}function Pe(t,e){let r={asset:e.asset};return e.aclass&&(r.aclass=e.aclass),e.network&&(r.network=e.network),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/WithdrawMethods",r)}function Se(t,e){let r={asset:e.asset};return e.aclass&&(r.aclass=e.aclass),e.method&&(r.method=e.method),e.key&&(r.key=e.key),e.verified!==void 0&&(r.verified=e.verified?"true":"false"),t.privatePost("/0/private/WithdrawAddresses",r)}function Be(t,e){let r={asset:e.asset,key:e.key,amount:String(e.amount)};return t.privatePost("/0/private/WithdrawInfo",r)}function _e(t,e){let{asset:r,aclass:n,key:s,address:o,amount:a,max_fee:i,rebase_multiplier:l}=e,d={asset:r,key:s,amount:String(a)};return n&&(d.aclass=n),o&&(d.address=o),i!==void 0&&(d.max_fee=String(i)),l&&(d.rebase_multiplier=l),t.privatePost("/0/private/Withdraw",d)}async function Ee(t,e={}){let{asset:r,aclass:n,method:s,start:o,end:a,cursor:i,limit:l,rebase_multiplier:d}=e,c={};return r&&(c.asset=r),n&&(c.aclass=n),s&&(c.method=s),o!==void 0&&(c.start=o),a!==void 0&&(c.end=a),i!==void 0&&(c.cursor=i),l!==void 0&&(c.limit=l),d&&(c.rebase_multiplier=d),t.privatePost("/0/private/WithdrawStatus",c)}function ve(t,e){let{asset:r,refid:n}=e,s={asset:r,refid:n};return t.privatePost("/0/private/WithdrawCancel",s)}function we(t,e){let{asset:r,from:n,to:s,amount:o}=e,a={asset:r,from:n,to:s,amount:String(o)};return t.privatePost("/0/private/WalletTransfer",a)}var R=class{constructor(e){this.base=e;}getDepositMethods(e){return Re(this.base,e)}getDepositAddresses(e){return Ae(this.base,e)}getDepositStatus(e={}){return Te(this.base,e)}getWithdrawMethods(e){return Pe(this.base,e)}getWithdrawAddresses(e){return Se(this.base,e)}getWithdrawInfo(e){return Be(this.base,e)}withdrawFunds(e){return _e(this.base,e)}getWithdrawStatus(e={}){return Ee(this.base,e)}withdrawCancel(e){return ve(this.base,e)}walletTransfer(e){return we(this.base,e)}};async function Me(t,e){let{username:r,email:n}=e,s={username:r,email:n};return t.privatePost("/0/private/CreateSubaccount",s)}async function Ge(t,e){let{asset:r,asset_class:n,amount:s,from:o,to:a}=e,i={asset:r,amount:String(s),from:o,to:a};return n&&(i.asset_class=n),t.privatePost("/0/private/AccountTransfer",i)}var A=class{constructor(e){this.base=e;}createSubaccount(e){return Me(this.base,e)}accountTransfer(e){return Ge(this.base,e)}};async function Ce(t,e){let{amount:r,strategy_id:n}=e,s={amount:String(r),strategy_id:n};return t.privatePost("/0/private/Earn/Allocate",s)}async function Ie(t,e){let{amount:r,strategy_id:n}=e,s={amount:String(r),strategy_id:n};return t.privatePost("/0/private/Earn/Deallocate",s)}async function Le(t,e){let{strategy_id:r}=e,n={strategy_id:r};return t.privatePost("/0/private/Earn/AllocateStatus",n)}async function De(t,e){let{strategy_id:r}=e,n={strategy_id:r};return t.privatePost("/0/private/Earn/DeallocateStatus",n)}async function qe(t,e={}){let{ascending:r,asset:n,cursor:s,limit:o,lock_type:a}=e,i={};return r!=null&&(i.ascending=r),n!=null&&(i.asset=n),s!=null&&(i.cursor=s),o!=null&&(i.limit=o),a&&a.length>0&&(i.lock_type=JSON.stringify(a)),t.privatePost("/0/private/Earn/Strategies",i)}async function Ue(t,e={}){let{ascending:r,converted_asset:n,hide_zero_allocations:s}=e,o={};return r!=null&&(o.ascending=r),n!=null&&(o.converted_asset=n),s!=null&&(o.hide_zero_allocations=s),t.privatePost("/0/private/Earn/Allocations",o)}var T=class{constructor(e){this.base=e;}allocateFunds(e){return Ce(this.base,e)}deallocateFunds(e){return Ie(this.base,e)}getAllocationStatus(e){return Le(this.base,e)}getDeallocationStatus(e){return De(this.base,e)}listStrategies(e={}){return qe(this.base,e)}listAllocations(e={}){return Ue(this.base,e)}};async function Fe(t,e){let{symbol:r}=e,s={symbol:typeof r=="string"?r:r.join(",")};return t.publicGet("/0/public/PreTrade",s)}async function He(t,e={}){let{symbol:r,from_ts:n,to_ts:s,count:o}=e,a={};return r&&(a.symbol=r),n&&(a.from_ts=n),s&&(a.to_ts=s),o!==void 0&&(a.count=o),t.publicGet("/0/public/PostTrade",a)}var P=class{constructor(e){this.base=e;}getPreTradeData(e){return Fe(this.base,e)}getPostTradeData(e={}){return He(this.base,e)}};var je=class extends h{marketData;accountData;trading;funding;subaccounts;earn;transparency;constructor(e={}){super(e),this.marketData=new x(this),this.accountData=new W(this),this.trading=new O(this),this.funding=new R(this),this.subaccounts=new A(this),this.earn=new T(this),this.transparency=new P(this);}};var f=class{url;authToken;WebSocketImpl;logger;autoReconnect;reconnectDelayMs;requestTimeoutMs;ws=null;connectingPromise=null;manuallyClosed=false;nextReqId=1;pending=new Map;messageHandlers=new Set;reconnectAttempts=0;constructor(e){if(this.url=e.url,this.authToken=e.authToken,this.WebSocketImpl=e.WebSocketImpl??(typeof ws.WebSocket<"u"?ws.WebSocket:void 0),this.logger=e.logger,this.autoReconnect=e.autoReconnect??true,this.reconnectDelayMs=e.reconnectDelayMs??1e3,this.requestTimeoutMs=e.requestTimeoutMs??1e4,!this.WebSocketImpl)throw new Error("No WebSocket implementation available. Pass `WebSocketImpl` in KrakenWebsocketConnectionOptions when using Node.js.")}get readyState(){return this.ws?.readyState??-1}async connect(){if(!(this.ws&&this.ws.readyState===1))return this.connectingPromise?this.connectingPromise:(this.manuallyClosed=false,this.connectingPromise=new Promise((e,r)=>{try{let n=this.WebSocketImpl,s=new n(this.url);this.ws=s,s.onopen=()=>{this.reconnectAttempts=0,this.logger?.info?.("Kraken WS connected",{url:this.url}),this.connectingPromise=null,e();},s.onclose=o=>{this.logger?.info?.("Kraken WS closed",{url:this.url,event:o,manuallyClosed:this.manuallyClosed}),this.ws=null,this.connectingPromise=null;for(let[a,i]of this.pending)clearTimeout(i.timeoutId),i.reject(new Error(`WebSocket closed before response for req_id ${a}`));if(this.pending.clear(),!this.manuallyClosed&&this.autoReconnect){this.reconnectAttempts++;let a=this.reconnectDelayMs,i=Math.min(3e4,a*Math.pow(2,this.reconnectAttempts-1)),l=this.reconnectAttempts>=4?5e3:0,d=Math.max(l,i),c=Math.max(0,Math.floor(d*(.8+Math.random()*.4)));setTimeout(()=>{this.logger?.info?.("Kraken WS reconnecting",{url:this.url,attempt:this.reconnectAttempts,delayMs:c}),this.connect().catch(m=>{this.logger?.error?.("Kraken WS reconnect failed",{url:this.url,error:m});});},c);}},s.onerror=o=>{this.logger?.error?.("Kraken WS error",{url:this.url,event:o});},s.onmessage=o=>{let a=o.data;if(typeof o.data=="string")try{a=JSON.parse(o.data);}catch(i){this.logger?.warn?.("Failed to parse WS JSON message",{data:o.data,error:i});}if(a&&typeof a=="object"&&"req_id"in a&&typeof a.req_id=="number"){let i=a.req_id,l=this.pending.get(i);l&&(this.pending.delete(i),clearTimeout(l.timeoutId),l.resolve(a));}for(let i of this.messageHandlers)try{i(a);}catch(l){this.logger?.error?.("WS message handler threw",{error:l});}};}catch(n){this.connectingPromise=null,r(n);}}),this.connectingPromise)}close(e,r){this.manuallyClosed=true,this.ws&&this.ws.readyState===1&&this.ws.close(e,r);}addMessageHandler(e){return this.messageHandlers.add(e),()=>this.messageHandlers.delete(e)}async sendRaw(e){(!this.ws||this.ws.readyState!==1)&&await this.connect();let r=this.ws;if(!r||r.readyState!==1)throw new Error("WebSocket is not open");let n=typeof e=="string"?e:JSON.stringify(e);r.send(n);}async request(e,r,n){(!this.ws||this.ws.readyState!==1)&&await this.connect();let s=n?.reqId??this.nextReqId++,o=n?.timeoutMs??this.requestTimeoutMs,a=n?.attachAuthToken??true,i=r?{...r}:{};a&&this.authToken&&(i.token===void 0||i.token===null)&&(i.token=this.authToken);let l={method:e,params:Object.keys(i).length?i:void 0,req_id:s};return this.logger?.debug?.("Kraken WS request",{envelope:l}),await new Promise((d,c)=>{let m=setTimeout(()=>{this.pending.delete(s),c(new Error(`Kraken WS request timed out after ${o}ms (method=${e}, req_id=${s})`));},o),k={resolve:u=>d(u),reject:c,timeoutId:m};this.pending.set(s,k);try{let u=this.ws;if(!u||u.readyState!==1){clearTimeout(m),this.pending.delete(s),c(new Error(`WebSocket is not open (method=${e}, req_id=${s})`));return}u.send(JSON.stringify(l));}catch(u){clearTimeout(m),this.pending.delete(s),c(u);}})}};function Ne(t,e){return t.addMessageHandler(r=>{if(!r||typeof r!="object")return;let n=r;n.channel==="status"&&n.type==="update"&&Array.isArray(n.data)&&e(n);})}async function Ve(t,e={},r={}){return t.request("ping",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}function ze(t,e){return t.addMessageHandler(r=>{if(!r||typeof r!="object")return;let n=r;n.channel==="heartbeat"&&e(n);})}var S=class{constructor(e){this.ws=e;}ping(e={},r={}){return Ve(this.ws,e,r)}onStatus(e){return Ne(this.ws,e)}onHeartbeat(e){return ze(this.ws,e)}};async function $e(t,e,r={}){let n={channel:"ticker",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Je(t,e,r={}){let n={channel:"ticker",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Ye(t,e,r={}){let n={channel:"book",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Xe(t,e,r={}){let n={channel:"book",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Ze(t,e,r={}){let n={channel:"level3",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function er(t,e,r={}){let n={channel:"level3",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function rr(t,e,r={}){let n={channel:"ohlc",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function tr(t,e,r={}){let n={channel:"ohlc",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function nr(t,e,r={}){let n={channel:"trade",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function sr(t,e,r={}){let n={channel:"trade",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function ar(t,e={},r={}){let n={channel:"instrument",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function or(t,e={},r={}){let n={channel:"instrument",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}var B=class{constructor(e){this.ws=e;}subscribeTicker(e,r={}){return $e(this.ws,e,r)}unsubscribeTicker(e,r={}){return Je(this.ws,e,r)}subscribeBook(e,r={}){return Ye(this.ws,e,r)}unsubscribeBook(e,r={}){return Xe(this.ws,e,r)}subscribeLevel3(e,r={}){return Ze(this.ws,e,r)}unsubscribeLevel3(e,r={}){return er(this.ws,e,r)}subscribeOhlc(e,r={}){return rr(this.ws,e,r)}unsubscribeOhlc(e,r={}){return tr(this.ws,e,r)}subscribeTrade(e,r={}){return nr(this.ws,e,r)}unsubscribeTrade(e,r={}){return sr(this.ws,e,r)}subscribeInstrument(e={},r={}){return ar(this.ws,e,r)}unsubscribeInstrument(e={},r={}){return or(this.ws,e,r)}};async function ir(t,e,r={}){let n={channel:"executions",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function dr(t,e={},r={}){let n={channel:"executions",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function cr(t,e={},r={}){let n={channel:"balances",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function lr(t,e={},r={}){let n={channel:"balances",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}var _=class{constructor(e){this.ws=e;}subscribeExecutions(e,r){return ir(this.ws,e,r)}unsubscribeExecutions(e,r){return dr(this.ws,e??{},r)}subscribeBalances(e={},r){return cr(this.ws,e,r)}unsubscribeBalances(e,r){return lr(this.ws,e??{},r)}};async function pr(t,e,r={}){return t.request("add_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function ur(t,e,r={}){let n=!!e.order_id,s=!!e.cl_ord_id;if(n&&s||!n&&!s)throw new Error("Kraken WS amend_order: exactly one of `order_id` or `cl_ord_id` must be provided");return t.request("amend_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function kr(t,e,r={}){return t.request("edit_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function Kr(t,e,r={}){let n=Array.isArray(e.order_id)&&e.order_id.length>0,s=Array.isArray(e.cl_ord_id)&&e.cl_ord_id.length>0,o=Array.isArray(e.order_userref)&&e.order_userref.length>0;if(!n&&!s&&!o)throw new Error("Kraken WS cancel_order: at least one of `order_id`, `cl_ord_id`, or `order_userref` must contain at least one entry");return t.request("cancel_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function mr(t,e={},r={}){return t.request("cancel_all",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function br(t,e,r={}){if(!Number.isFinite(e.timeout))throw new Error("Kraken WS cancel_all_orders_after: `timeout` must be a finite number (seconds)");if(e.timeout<0||e.timeout>=86400)throw new Error("Kraken WS cancel_all_orders_after: `timeout` must be >= 0 and < 86400 seconds");return t.request("cancel_all_orders_after",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function gr(t,e,r={}){if(!Array.isArray(e.orders)||e.orders.length<2)throw new Error("Kraken WS batch_add: `orders` must contain at least 2 entries");if(e.orders.length>15)throw new Error("Kraken WS batch_add: `orders` must not contain more than 15 entries");for(let[n,s]of e.orders.entries())if(s.cl_ord_id&&typeof s.order_userref=="number")throw new Error(`Kraken WS batch_add: order at index ${n} must not specify both cl_ord_id and order_userref`);return t.request("batch_add",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function yr(t,e,r={}){if(!Array.isArray(e.orders)||e.orders.length<2)throw new Error("Kraken WS batch_cancel: `orders` must contain at least 2 identifiers");if(e.orders.length>50)throw new Error("Kraken WS batch_cancel: `orders` must not contain more than 50 identifiers");return t.request("batch_cancel",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}var E=class{constructor(e){this.ws=e;}addOrder(e,r){return pr(this.ws,e,r)}amendOrder(e,r){return ur(this.ws,e,r)}editOrder(e,r){return kr(this.ws,e,r)}cancelOrder(e,r){return Kr(this.ws,e,r)}cancelAll(e,r){return mr(this.ws,e??{},r)}cancelAllOrdersAfter(e,r){return br(this.ws,e,r)}batchAdd(e,r){return gr(this.ws,e,r)}batchCancel(e,r){return yr(this.ws,e,r)}};var fr=class{publicConnection;privateConnection;admin;marketData;userData;userTrading;constructor(e={}){let{publicUrl:r="wss://ws.kraken.com/v2",privateUrl:n="wss://ws-auth.kraken.com/v2",authToken:s,WebSocketImpl:o,autoReconnect:a,reconnectDelayMs:i,requestTimeoutMs:l,logger:d}=e,c={authToken:void 0,WebSocketImpl:o,autoReconnect:a,reconnectDelayMs:i,requestTimeoutMs:l,logger:d};this.publicConnection=new f({...c,url:r}),this.privateConnection=new f({...c,url:n,authToken:s}),this.admin=new S(this.publicConnection),this.marketData=new B(this.publicConnection),this.userData=new _(this.privateConnection),this.userTrading=new E(this.privateConnection);}};
2
- exports.KrakenSpotRestClient=je;exports.KrakenSpotWebsocketV2Client=fr;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var crypto=require('crypto'),ws=require('ws');var f=class{constructor(e,r){this.maxCounter=e;this.decayPerSec=r;}counter=0;lastTs=Date.now();queue=[];draining=false;schedule(e,r){let n=Math.max(0,r?.cost??1);return new Promise((s,o)=>{this.queue.push({fn:e,resolve:s,reject:o,cost:n}),this.drain();})}decayNow(){let e=Date.now(),r=(e-this.lastTs)/1e3;r>0&&(this.counter=Math.max(0,this.counter-r*this.decayPerSec),this.lastTs=e);}async drain(){if(!this.draining){this.draining=true;try{for(;this.queue.length>0;){this.decayNow();let e=this.queue[0];if(this.counter+e.cost<=this.maxCounter){this.queue.shift(),this.counter+=e.cost;try{let o=await e.fn();e.resolve(o);}catch(o){e.reject(o);}continue}let n=(this.counter+e.cost-this.maxCounter)/this.decayPerSec,s=Math.max(50,Math.ceil(n*1e3));await w(s);}}finally{this.draining=false;}}}};function I(t){switch(t){case "pro":return {maxCounter:20,decayPerSec:1};case "intermediate":return {maxCounter:20,decayPerSec:.5};case "starter":default:return {maxCounter:15,decayPerSec:.33}}}function L(t){return t.includes("TradesHistory")||t.includes("Ledgers")||t.includes("TradeBalance")?2:1}function v(t){return t.includes("/AddOrder")||t.includes("/CancelOrder")||t.includes("/CancelAll")||t.includes("/EditOrder")||t.includes("/AddOrderBatch")||t.includes("/CancelOrderBatch")}function w(t){return new Promise(e=>setTimeout(e,t))}function D(t){let e=t*.2;return Math.max(0,Math.floor(t+(Math.random()*2-1)*e))}function M(t){let e=t.match(/EService:\s*Throttled:\s*(\d+)/i);if(!e)return null;let r=Number(e[1]);return Number.isFinite(r)?r:null}var b=class extends Error{name="KrakenApiError";endpoint;httpStatus;httpStatusText;krakenErrorCodes;rawBody;constructor(e,r={}){super(e),Object.setPrototypeOf(this,new.target.prototype),this.endpoint=r.endpoint,this.httpStatus=r.httpStatus,this.httpStatusText=r.httpStatusText,this.krakenErrorCodes=r.krakenErrorCodes,this.rawBody=r.rawBody;}};var h=class{baseUrl;timeoutMs;userAgent;apiKey;apiSecret;logger;lastNonce;lastMs=0;restLimiter;tradingLimiter;rateLimitOptions;restCostFn;tradingCostFn;constructor(e={}){this.baseUrl=e.baseUrl??"https://api.kraken.com",this.timeoutMs=e.timeoutMs??1e4,this.userAgent=e.userAgent,this.apiKey=e.apiKey,this.apiSecret=e.apiSecret,this.logger=e.logger;let r=e.rateLimit??{},n=r.mode??"auto",s=r.tier??"starter";if(this.rateLimitOptions={retryOnRateLimit:r.retryOnRateLimit??true,maxRetries:r.maxRetries??5},this.restCostFn=r.restCostFn??L,this.tradingCostFn=r.tradingCostFn??(()=>1),e.limiter?.rest&&(this.restLimiter=e.limiter.rest),e.limiter?.trading&&(this.tradingLimiter=e.limiter.trading),n!=="off"){if(!this.restLimiter){let{maxCounter:o,decayPerSec:a}=I(s);this.restLimiter=new f(o,a);}this.tradingLimiter||(this.tradingLimiter=new f(10,1));}}createNonce(){let e=Date.now();return this.lastNonce===void 0?(this.lastNonce=BigInt(e)*1000n,this.lastMs=e,this.lastNonce.toString()):(e>this.lastMs?(this.lastNonce=BigInt(e)*1000n,this.lastMs=e):this.lastNonce=this.lastNonce+1n,this.lastNonce.toString())}async publicGet(e,r){let n=new URL(e,this.baseUrl);if(r)for(let[s,o]of Object.entries(r))n.searchParams.set(s,String(o));return this.logger?.debug?.("Kraken REST public GET request",{endpoint:e,url:n.toString(),query:r}),this.scheduleWithRetry(e,async()=>{let s=new AbortController,o=setTimeout(()=>s.abort(),this.timeoutMs);try{let a=await fetch(n,{method:"GET",signal:s.signal,headers:this.userAgent?{"User-Agent":this.userAgent}:void 0});if(!a.ok)throw this.logger?.error?.("Kraken REST HTTP error",{endpoint:e,status:a.status,statusText:a.statusText}),new b(`HTTP error from Kraken: ${a.status} ${a.statusText}`,{endpoint:e,httpStatus:a.status,httpStatusText:a.statusText});let i;try{i=await a.json();}catch(l){throw this.logger?.error?.("Kraken REST JSON parse error",{endpoint:e,error:l}),new b("Failed to parse Kraken response JSON",{endpoint:e,httpStatus:a.status})}if(i.error?.length)throw this.logger?.warn?.("Kraken REST API error",{endpoint:e,krakenErrors:i.error}),new b(`Kraken API error: ${i.error.join(", ")}`,{endpoint:e,httpStatus:a.status,krakenErrorCodes:i.error,rawBody:i});return this.logger?.debug?.("Kraken REST public GET success",{endpoint:e}),i.result}finally{clearTimeout(o);}})}async privatePost(e,r){if(!this.apiKey||!this.apiSecret)throw new b("Missing apiKey or apiSecret for Kraken private API call",{endpoint:e});let n=new URL(e,this.baseUrl);return this.scheduleWithRetry(e,async()=>{let s=this.createNonce(),o=new URLSearchParams;if(o.set("nonce",s),r)for(let[p,K]of Object.entries(r))K!==void 0&&o.set(p,String(K));let a=o.toString(),i=crypto.createHash("sha256").update(s+a).digest(),l=Buffer.from(this.apiSecret,"base64"),d=crypto.createHmac("sha512",l);d.update(e),d.update(i);let c=d.digest("base64");this.logger?.debug?.("Kraken REST private POST request",{endpoint:e,url:n.toString(),hasParams:!!r});let k=new AbortController,u=setTimeout(()=>k.abort(),this.timeoutMs);try{let p=await fetch(n,{method:"POST",signal:k.signal,headers:{"Content-Type":"application/x-www-form-urlencoded","API-Key":this.apiKey,"API-Sign":c,...this.userAgent?{"User-Agent":this.userAgent}:{}},body:a});if(!p.ok)throw this.logger?.error?.("Kraken REST private HTTP error",{endpoint:e,status:p.status,statusText:p.statusText}),new b(`HTTP error from Kraken private API: ${p.status} ${p.statusText}`,{endpoint:e,httpStatus:p.status,httpStatusText:p.statusText});let K;try{K=await p.json();}catch(m){throw this.logger?.error?.("Kraken REST private JSON parse error",{endpoint:e,error:m}),new b("Failed to parse Kraken private API response JSON",{endpoint:e,httpStatus:p.status})}if(K.error?.length)throw this.logger?.warn?.("Kraken REST private API error",{endpoint:e,krakenErrors:K.error}),new b(`Kraken private API error: ${K.error.join(", ")}`,{endpoint:e,httpStatus:p.status,krakenErrorCodes:K.error,rawBody:K});return this.logger?.debug?.("Kraken REST private POST success",{endpoint:e}),K.result}finally{clearTimeout(u);}})}async privatePostBinary(e,r){if(!this.apiKey||!this.apiSecret)throw new Error("KrakenRestBase: apiKey and apiSecret are required for private endpoints");let n=new URL(e,this.baseUrl);return this.scheduleWithRetry(e,async()=>{let s=this.createNonce(),a=new URLSearchParams({nonce:s,...r??{}}).toString(),i=this.signPrivateRequest(e,s,a);this.logger?.debug?.("[KrakenRestBase] privatePostBinary request",{url:n.toString(),path:e,body:r});let l={"API-Key":this.apiKey,"API-Sign":i,"User-Agent":this.userAgent??"lynx-crypto-kraken-client/0.1.0","Content-Type":"application/x-www-form-urlencoded"},d=await fetch(n.toString(),{method:"POST",headers:l,body:a});if(!d.ok){let u=await d.text().catch(()=>"");throw this.logger?.error?.("[KrakenRestBase] privatePostBinary HTTP error",{status:d.status,statusText:d.statusText,body:u}),new Error(`Kraken privatePostBinary failed: ${d.status} ${d.statusText} \u2013 ${u}`)}if((d.headers.get("content-type")??"").includes("application/json")){let u=await d.json().catch(()=>null);if(!u)throw new Error("Kraken privatePostBinary: expected JSON body for error response");let p=u.error??[];if(p.length>0){let K=`Kraken API error: ${p.join(", ")}`;this.logger?.error?.("[KrakenRestBase] Kraken API error (binary response)",{errors:p});let m=new Error(K);throw m.krakenErrors=p,m}throw new Error("Kraken privatePostBinary: expected binary data but got JSON without errors")}let k=await d.arrayBuffer();return this.logger?.debug?.("[KrakenRestBase] privatePostBinary success",{bytes:k.byteLength}),k})}signPrivateRequest(e,r,n){if(!this.apiSecret)throw new Error("KrakenRestBase: apiSecret is required for private endpoints");let s=Buffer.from(this.apiSecret,"base64"),o=crypto.createHash("sha256").update(r+n).digest(),a=crypto.createHmac("sha512",s);return a.update(e),a.update(o),a.digest("base64")}async scheduleWithRetry(e,r){let n=v(e)?this.tradingLimiter:this.restLimiter,s=v(e)?this.tradingCostFn(e):this.restCostFn(e),o=()=>n?n.schedule(r,{cost:s}):r();if(!this.rateLimitOptions.retryOnRateLimit)return o();let a=this.rateLimitOptions.maxRetries,i=0;for(;;)try{return await o()}catch(l){i++;let d=l?.message??(typeof l=="string"?l:"")??"",c=l?.krakenErrorCodes??l?.krakenErrors,k=d.includes("EAPI:Rate limit exceeded")||Array.isArray(c)&&c.some(g=>g.includes("EAPI:Rate limit exceeded")),u=(()=>{let g=M(d);if(g)return g;if(Array.isArray(c))for(let G of c){let C=M(G);if(C)return C}return null})(),p=l?.httpStatus===429;if(!(k||u!==null||p)||i>a)throw l;let m=0;if(u!==null){let g=Math.floor(Date.now()/1e3);m=Math.max(0,u-g)*1e3;}else {let g=250*Math.pow(2,i-1);m=Math.min(g,1e4);}m=D(m),this.logger?.warn?.("Kraken rate limited; retrying",{endpoint:e,attempt:i,waitMs:m,reason:p?"HTTP 429":u?"EService: Throttled":"EAPI: Rate limit exceeded"}),await w(m);}}};function F(t){return t.publicGet("/0/public/Time")}function H(t){return t.publicGet("/0/public/SystemStatus")}function j(t,e){let r={};return e?.asset&&e.asset.length>0&&(r.asset=e.asset.join(",")),e?.aclass&&(r.aclass=e.aclass),t.publicGet("/0/public/Assets",r)}function Q(t,e){let r={};return e?.pair?.length&&(r.pair=e.pair.join(",")),e?.aclass_base&&(r.aclass_base=e.aclass_base),e?.info&&(r.info=e.info),e?.country_code&&(r.country_code=e.country_code),t.publicGet("/0/public/AssetPairs",r)}function N(t,e){let r={};return e?.pair?.length&&(r.pair=e.pair.join(",")),e?.asset_class&&(r.asset_class=e.asset_class),t.publicGet("/0/public/Ticker",r)}async function V(t,e){let r={pair:e.pair};e.interval!==void 0&&(r.interval=String(e.interval)),e.since!==void 0&&(r.since=String(e.since)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/OHLC",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,ohlc:a}}function z(t,e){let r={pair:e.pair};return e.count!==void 0&&(r.count=String(e.count)),e.asset_class&&(r.asset_class=e.asset_class),t.publicGet("/0/public/Depth",r)}async function $(t,e){let r={pair:e.pair};e.since!==void 0&&(r.since=String(e.since)),e.count!==void 0&&(r.count=String(e.count)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/Trades",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,trades:a}}async function J(t,e){let r={pair:e.pair};e.since!==void 0&&(r.since=String(e.since)),e.asset_class&&(r.asset_class=e.asset_class);let n=await t.publicGet("/0/public/Spread",r),{last:s,...o}=n,a={};for(let[i,l]of Object.entries(o))a[i]=l;return {last:s,spreads:a}}var x=class{constructor(e){this.base=e;}getServerTime(){return F(this.base)}getSystemStatus(){return H(this.base)}getAssetInfo(e){return j(this.base,e)}getTradableAssetPairs(e){return Q(this.base,e)}getTickerInformation(e){return N(this.base,e)}getOhlcData(e){return V(this.base,e)}getOrderBook(e){return z(this.base,e)}getRecentTrades(e){return $(this.base,e)}getRecentSpreads(e){return J(this.base,e)}};function Y(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/Balance",r)}function X(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/BalanceEx",r)}function Z(t,e){let r={};return e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/CreditLines",r)}function ee(t,e){let r={};return e?.asset&&(r.asset=e.asset),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradeBalance",r)}function re(t,e){let r={};return e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.userref!==void 0&&(r.userref=String(e.userref)),e?.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OpenOrders",r)}function te(t,e){let r={};return e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.userref!==void 0&&(r.userref=String(e.userref)),e?.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.closetime&&(r.closetime=e.closetime),e?.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e?.without_count!==void 0&&(r.without_count=e.without_count?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/ClosedOrders",r)}function ne(t,e){let r={};return e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.userref!==void 0&&(r.userref=String(e.userref)),Array.isArray(e.txid)?r.txid=e.txid.join(","):r.txid=e.txid,e.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryOrders",r)}function se(t,e){let r={order_id:e.order_id};return e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OrderAmends",r)}function ae(t,e){let r={};return e?.type&&(r.type=e.type),e?.trades!==void 0&&(r.trades=e.trades?"true":"false"),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.consolidate_taker!==void 0&&(r.consolidate_taker=e.consolidate_taker?"true":"false"),e?.ledgers!==void 0&&(r.ledgers=e.ledgers?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradesHistory",r)}function oe(t,e){let r={};return Array.isArray(e.txid)?r.txid=e.txid.join(","):r.txid=e.txid,e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryTrades",r)}function ie(t,e){let r={};return e?.txid!==void 0&&(r.txid=Array.isArray(e.txid)?e.txid.join(","):e.txid),e?.docalcs!==void 0&&(r.docalcs=e.docalcs?"true":"false"),e?.consolidation&&(r.consolidation=e.consolidation),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/OpenPositions",r)}function de(t,e){let r={};return e?.asset!==void 0&&(r.asset=Array.isArray(e.asset)?e.asset.join(","):e.asset),e?.aclass&&(r.aclass=e.aclass),e?.type&&(r.type=e.type),e?.start!==void 0&&(r.start=String(e.start)),e?.end!==void 0&&(r.end=String(e.end)),e?.ofs!==void 0&&(r.ofs=String(e.ofs)),e?.without_count!==void 0&&(r.without_count=e.without_count?"true":"false"),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/Ledgers",r)}function ce(t,e){let r={};return Array.isArray(e.id)?r.id=e.id.join(","):r.id=e.id,e.trades!==void 0&&(r.trades=e.trades?"true":"false"),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/QueryLedgers",r)}function le(t,e){let r={};return e?.pair!==void 0&&(r.pair=Array.isArray(e.pair)?e.pair.join(","):e.pair),e?.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/TradeVolume",r)}function pe(t,e){let r={report:e.report,description:e.description};return e.format&&(r.format=e.format),e.fields&&(r.fields=e.fields),e.starttm!==void 0&&(r.starttm=String(e.starttm)),e.endtm!==void 0&&(r.endtm=String(e.endtm)),t.privatePost("/0/private/AddExport",r)}function ue(t,e){let r={report:e.report};return t.privatePost("/0/private/ExportStatus",r)}function ke(t,e){let r={id:e.id};return t.privatePostBinary("/0/private/RetrieveExport",r)}function Ke(t,e){let r={id:e.id,type:e.type};return t.privatePost("/0/private/RemoveExport",r)}var W=class{constructor(e){this.base=e;}getAccountBalance(e){return Y(this.base,e)}getExtendedBalance(e){return X(this.base,e)}getCreditLines(e){return Z(this.base,e)}getTradeBalance(e){return ee(this.base,e)}getOpenOrders(e){return re(this.base,e)}getClosedOrders(e){return te(this.base,e)}queryOrdersInfo(e){return ne(this.base,e)}getOrderAmends(e){return se(this.base,e)}getTradesHistory(e){return ae(this.base,e)}queryTradesInfo(e){return oe(this.base,e)}getOpenPositions(e){return ie(this.base,e)}getLedgersInfo(e){return de(this.base,e)}queryLedgers(e){return ce(this.base,e)}getTradeVolume(e){return le(this.base,e)}requestExportReport(e){return pe(this.base,e)}getExportReportStatus(e){return ue(this.base,e)}retrieveExportReport(e){return ke(this.base,e)}deleteExportReport(e){return Ke(this.base,e)}};function me(t,e){if(e.userref!==void 0&&e.cl_ord_id)throw new Error("KrakenAddOrderParams: userref and cl_ord_id are mutually exclusive");let r={ordertype:e.ordertype,type:e.type,volume:e.volume,pair:e.pair};return e.userref!==void 0&&(r.userref=String(e.userref)),e.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e.displayvol&&(r.displayvol=e.displayvol),e.asset_class&&(r.asset_class=e.asset_class),e.price!==void 0&&(r.price=e.price),e.price2!==void 0&&(r.price2=e.price2),e.trigger&&(r.trigger=e.trigger),e.leverage!==void 0&&(r.leverage=e.leverage),e.reduce_only!==void 0&&(r.reduce_only=e.reduce_only?"true":"false"),e.stptype&&(r.stptype=e.stptype),e.oflags&&(r.oflags=e.oflags),e.timeinforce&&(r.timeinforce=e.timeinforce),e.starttm!==void 0&&(r.starttm=e.starttm),e.expiretm!==void 0&&(r.expiretm=e.expiretm),e.deadline!==void 0&&(r.deadline=e.deadline),e.validate!==void 0&&(r.validate=e.validate?"true":"false"),e.close&&(r["close[ordertype]"]=e.close.ordertype,e.close.price!==void 0&&(r["close[price]"]=e.close.price),e.close.price2!==void 0&&(r["close[price2]"]=e.close.price2)),t.privatePost("/0/private/AddOrder",r)}function be(t,e){if(!e.txid&&!e.cl_ord_id)throw new Error("KrakenAmendOrderParams: either txid or cl_ord_id must be provided");let r={};return e.txid&&(r.txid=e.txid),e.cl_ord_id&&(r.cl_ord_id=e.cl_ord_id),e.order_qty!==void 0&&(r.order_qty=e.order_qty),e.display_qty!==void 0&&(r.display_qty=e.display_qty),e.limit_price!==void 0&&(r.limit_price=e.limit_price),e.trigger_price!==void 0&&(r.trigger_price=e.trigger_price),e.pair!==void 0&&(r.pair=e.pair),e.post_only!==void 0&&(r.post_only=e.post_only?"true":"false"),e.deadline!==void 0&&(r.deadline=e.deadline),t.privatePost("/0/private/AmendOrder",r)}function ge(t,e){let{txid:r,userref:n,cl_ord_id:s}=e,o=(r!==void 0?1:0)+(n!==void 0?1:0)+(s!==void 0?1:0);if(o===0)throw new Error("KrakenCancelOrderParams: one of txid, userref, or cl_ord_id must be provided");if(o>1)throw new Error("KrakenCancelOrderParams: txid, userref, and cl_ord_id are mutually exclusive; provide exactly one");let a={};return n!==void 0?a.txid=String(n):s!==void 0?a.cl_ord_id=Array.isArray(s)?s.join(","):s:r!==void 0&&(a.txid=Array.isArray(r)?r.join(","):r),t.privatePost("/0/private/CancelOrder",a)}function ye(t){return t.privatePost("/0/private/CancelAll",{})}function fe(t,e){let r={timeout:String(e.timeout)};return t.privatePost("/0/private/CancelAllOrdersAfter",r)}function he(t){return t.privatePost("/0/private/GetWebSocketsToken",{})}function xe(t,e){let{orders:r,pair:n,asset_class:s,deadline:o,validate:a}=e;if(!Array.isArray(r)||r.length<2||r.length>15)throw new Error(`KrakenAddOrderBatchParams: orders must contain between 2 and 15 items (got ${r.length})`);for(let[d,c]of r.entries())if(c.userref!==void 0&&c.cl_ord_id!==void 0)throw new Error(`KrakenAddOrderBatchParams: order[${d}] cannot have both userref and cl_ord_id`);let i={pair:n};s&&(i.asset_class=s),o!==void 0&&(i.deadline=o),a!==void 0&&(i.validate=a?"true":"false");let l=r.map(d=>{let c={ordertype:d.ordertype,type:d.type,volume:d.volume};return d.userref!==void 0&&(c.userref=String(d.userref)),d.cl_ord_id!==void 0&&(c.cl_ord_id=d.cl_ord_id),d.displayvol!==void 0&&(c.displayvol=d.displayvol),d.price!==void 0&&(c.price=d.price),d.price2!==void 0&&(c.price2=d.price2),d.trigger!==void 0&&(c.trigger=d.trigger),d.leverage!==void 0&&(c.leverage=d.leverage),d.reduce_only!==void 0&&(c.reduce_only=d.reduce_only?"true":"false"),d.stptype!==void 0&&(c.stptype=d.stptype),d.oflags!==void 0&&(c.oflags=d.oflags),d.timeinforce!==void 0&&(c.timeinforce=d.timeinforce),d.starttm!==void 0&&(c.starttm=d.starttm),d.expiretm!==void 0&&(c.expiretm=d.expiretm),c});return i.orders=JSON.stringify(l),t.privatePost("/0/private/AddOrderBatch",i)}function We(t,e){let{orders:r,clOrdIds:n}=e,s=r?.length??0,o=n?.length??0,a=s+o;if(a===0)throw new Error("KrakenCancelOrderBatchParams: at least one txid/userref or cl_ord_id is required");if(a>50)throw new Error(`KrakenCancelOrderBatchParams: maximum 50 total ids/references allowed, got ${a}`);let i={};if(r&&r.length>0){let l=r.map(d=>({txid:String(d.txid)}));i.orders=JSON.stringify(l);}if(n&&n.length>0){let l=n.map(d=>({cl_ord_id:d}));i.cl_ord_ids=JSON.stringify(l);}return t.privatePost("/0/private/CancelOrderBatch",i)}function Oe(t,e){let r={txid:String(e.txid),pair:e.pair};return e.userref!==void 0&&(r.userref=String(e.userref)),e.volume!==void 0&&(r.volume=e.volume),e.displayvol!==void 0&&(r.displayvol=e.displayvol),e.asset_class!==void 0&&(r.asset_class=e.asset_class),e.price!==void 0&&(r.price=e.price),e.price2!==void 0&&(r.price2=e.price2),e.oflags!==void 0&&(r.oflags=e.oflags),e.deadline!==void 0&&(r.deadline=e.deadline),e.cancel_response!==void 0&&(r.cancel_response=e.cancel_response?"true":"false"),e.validate!==void 0&&(r.validate=e.validate?"true":"false"),t.privatePost("/0/private/EditOrder",r)}var O=class{constructor(e){this.base=e;}addOrder(e){return me(this.base,e)}amendOrder(e){return be(this.base,e)}cancelOrder(e){return ge(this.base,e)}cancelAllOrders(){return ye(this.base)}cancelAllOrdersAfter(e){return fe(this.base,e)}getWebSocketsToken(){return he(this.base)}addOrderBatch(e){return xe(this.base,e)}cancelOrderBatch(e){return We(this.base,e)}editOrder(e){return Oe(this.base,e)}};function Re(t,e){let r={asset:e.asset};return e.aclass!==void 0&&(r.aclass=e.aclass),e.rebase_multiplier!==void 0&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/DepositMethods",r)}function Ae(t,e){let r={asset:e.asset,method:e.method};return e.aclass!==void 0&&(r.aclass=e.aclass),e.new!==void 0&&(r.new=e.new?"true":"false"),e.amount!==void 0&&(r.amount=String(e.amount)),t.privatePost("/0/private/DepositAddresses",r)}function Te(t,e={}){let r={};return e.asset&&(r.asset=e.asset),e.aclass&&(r.aclass=e.aclass),e.method&&(r.method=e.method),e.start!==void 0&&(r.start=String(e.start)),e.end!==void 0&&(r.end=String(e.end)),e.cursor&&(r.cursor=e.cursor),e.limit!==void 0&&(r.limit=String(e.limit)),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/DepositStatus",r)}function Pe(t,e){let r={asset:e.asset};return e.aclass&&(r.aclass=e.aclass),e.network&&(r.network=e.network),e.rebase_multiplier&&(r.rebase_multiplier=e.rebase_multiplier),t.privatePost("/0/private/WithdrawMethods",r)}function Se(t,e){let r={asset:e.asset};return e.aclass&&(r.aclass=e.aclass),e.method&&(r.method=e.method),e.key&&(r.key=e.key),e.verified!==void 0&&(r.verified=e.verified?"true":"false"),t.privatePost("/0/private/WithdrawAddresses",r)}function Be(t,e){let r={asset:e.asset,key:e.key,amount:String(e.amount)};return t.privatePost("/0/private/WithdrawInfo",r)}function _e(t,e){let{asset:r,aclass:n,key:s,address:o,amount:a,max_fee:i,rebase_multiplier:l}=e,d={asset:r,key:s,amount:String(a)};return n&&(d.aclass=n),o&&(d.address=o),i!==void 0&&(d.max_fee=String(i)),l&&(d.rebase_multiplier=l),t.privatePost("/0/private/Withdraw",d)}async function Ee(t,e={}){let{asset:r,aclass:n,method:s,start:o,end:a,cursor:i,limit:l,rebase_multiplier:d}=e,c={};return r&&(c.asset=r),n&&(c.aclass=n),s&&(c.method=s),o!==void 0&&(c.start=o),a!==void 0&&(c.end=a),i!==void 0&&(c.cursor=i),l!==void 0&&(c.limit=l),d&&(c.rebase_multiplier=d),t.privatePost("/0/private/WithdrawStatus",c)}function ve(t,e){let{asset:r,refid:n}=e,s={asset:r,refid:n};return t.privatePost("/0/private/WithdrawCancel",s)}function we(t,e){let{asset:r,from:n,to:s,amount:o}=e,a={asset:r,from:n,to:s,amount:String(o)};return t.privatePost("/0/private/WalletTransfer",a)}var R=class{constructor(e){this.base=e;}getDepositMethods(e){return Re(this.base,e)}getDepositAddresses(e){return Ae(this.base,e)}getDepositStatus(e={}){return Te(this.base,e)}getWithdrawMethods(e){return Pe(this.base,e)}getWithdrawAddresses(e){return Se(this.base,e)}getWithdrawInfo(e){return Be(this.base,e)}withdrawFunds(e){return _e(this.base,e)}getWithdrawStatus(e={}){return Ee(this.base,e)}withdrawCancel(e){return ve(this.base,e)}walletTransfer(e){return we(this.base,e)}};async function Me(t,e){let{username:r,email:n}=e,s={username:r,email:n};return t.privatePost("/0/private/CreateSubaccount",s)}async function Ge(t,e){let{asset:r,asset_class:n,amount:s,from:o,to:a}=e,i={asset:r,amount:String(s),from:o,to:a};return n&&(i.asset_class=n),t.privatePost("/0/private/AccountTransfer",i)}var A=class{constructor(e){this.base=e;}createSubaccount(e){return Me(this.base,e)}accountTransfer(e){return Ge(this.base,e)}};async function Ce(t,e){let{amount:r,strategy_id:n}=e,s={amount:String(r),strategy_id:n};return t.privatePost("/0/private/Earn/Allocate",s)}async function Ie(t,e){let{amount:r,strategy_id:n}=e,s={amount:String(r),strategy_id:n};return t.privatePost("/0/private/Earn/Deallocate",s)}async function Le(t,e){let{strategy_id:r}=e,n={strategy_id:r};return t.privatePost("/0/private/Earn/AllocateStatus",n)}async function De(t,e){let{strategy_id:r}=e,n={strategy_id:r};return t.privatePost("/0/private/Earn/DeallocateStatus",n)}async function qe(t,e={}){let{ascending:r,asset:n,cursor:s,limit:o,lock_type:a}=e,i={};return r!=null&&(i.ascending=r),n!=null&&(i.asset=n),s!=null&&(i.cursor=s),o!=null&&(i.limit=o),a&&a.length>0&&(i.lock_type=JSON.stringify(a)),t.privatePost("/0/private/Earn/Strategies",i)}async function Ue(t,e={}){let{ascending:r,converted_asset:n,hide_zero_allocations:s}=e,o={};return r!=null&&(o.ascending=r),n!=null&&(o.converted_asset=n),s!=null&&(o.hide_zero_allocations=s),t.privatePost("/0/private/Earn/Allocations",o)}var T=class{constructor(e){this.base=e;}allocateFunds(e){return Ce(this.base,e)}deallocateFunds(e){return Ie(this.base,e)}getAllocationStatus(e){return Le(this.base,e)}getDeallocationStatus(e){return De(this.base,e)}listStrategies(e={}){return qe(this.base,e)}listAllocations(e={}){return Ue(this.base,e)}};async function Fe(t,e){let{symbol:r}=e,s={symbol:typeof r=="string"?r:r.join(",")};return t.publicGet("/0/public/PreTrade",s)}async function He(t,e={}){let{symbol:r,from_ts:n,to_ts:s,count:o}=e,a={};return r&&(a.symbol=r),n&&(a.from_ts=n),s&&(a.to_ts=s),o!==void 0&&(a.count=o),t.publicGet("/0/public/PostTrade",a)}var P=class{constructor(e){this.base=e;}getPreTradeData(e){return Fe(this.base,e)}getPostTradeData(e={}){return He(this.base,e)}};var je=class extends h{marketData;accountData;trading;funding;subaccounts;earn;transparency;constructor(e={}){super(e),this.marketData=new x(this),this.accountData=new W(this),this.trading=new O(this),this.funding=new R(this),this.subaccounts=new A(this),this.earn=new T(this),this.transparency=new P(this);}};var y=class{url;authToken;WebSocketImpl;logger;autoReconnect;reconnectDelayMs;requestTimeoutMs;ws=null;connectingPromise=null;manuallyClosed=false;nextReqId=1;pending=new Map;messageHandlers=new Set;reconnectAttempts=0;constructor(e){if(this.url=e.url,this.authToken=e.authToken,this.WebSocketImpl=e.WebSocketImpl??(typeof ws.WebSocket<"u"?ws.WebSocket:void 0),this.logger=e.logger,this.autoReconnect=e.autoReconnect??true,this.reconnectDelayMs=e.reconnectDelayMs??1e3,this.requestTimeoutMs=e.requestTimeoutMs??1e4,!this.WebSocketImpl)throw new Error("No WebSocket implementation available. Pass `WebSocketImpl` in KrakenWebsocketConnectionOptions when using Node.js.")}get readyState(){return this.ws?.readyState??-1}async connect(){if(!(this.ws&&this.ws.readyState===1))return this.connectingPromise?this.connectingPromise:(this.manuallyClosed=false,this.connectingPromise=new Promise((e,r)=>{try{let n=this.WebSocketImpl,s=new n(this.url);this.ws=s,s.onopen=()=>{this.reconnectAttempts=0,this.logger?.info?.("Kraken WS connected",{url:this.url}),this.connectingPromise=null,e();},s.onclose=o=>{this.logger?.info?.("Kraken WS closed",{url:this.url,event:o,manuallyClosed:this.manuallyClosed}),this.ws=null,this.connectingPromise=null;for(let[a,i]of this.pending)clearTimeout(i.timeoutId),i.reject(new Error(`WebSocket closed before response for req_id ${a}`));if(this.pending.clear(),!this.manuallyClosed&&this.autoReconnect){this.reconnectAttempts++;let a=this.reconnectDelayMs,i=Math.min(3e4,a*Math.pow(2,this.reconnectAttempts-1)),l=this.reconnectAttempts>=4?5e3:0,d=Math.max(l,i),c=Math.max(0,Math.floor(d*(.8+Math.random()*.4)));setTimeout(()=>{this.logger?.info?.("Kraken WS reconnecting",{url:this.url,attempt:this.reconnectAttempts,delayMs:c}),this.connect().catch(k=>{this.logger?.error?.("Kraken WS reconnect failed",{url:this.url,error:k});});},c);}},s.onerror=o=>{this.logger?.error?.("Kraken WS error",{url:this.url,event:o});},s.onmessage=o=>{let a=o.data;if(typeof o.data=="string")try{a=JSON.parse(o.data);}catch(i){this.logger?.warn?.("Failed to parse WS JSON message",{data:o.data,error:i});}if(a&&typeof a=="object"&&"req_id"in a&&typeof a.req_id=="number"){let i=a.req_id,l=this.pending.get(i);l&&(this.pending.delete(i),clearTimeout(l.timeoutId),l.resolve(a));}for(let i of this.messageHandlers)try{i(a);}catch(l){this.logger?.error?.("WS message handler threw",{error:l});}};}catch(n){this.connectingPromise=null,r(n);}}),this.connectingPromise)}close(e,r){this.manuallyClosed=true,this.ws&&this.ws.readyState===1&&this.ws.close(e,r);}addMessageHandler(e){return this.messageHandlers.add(e),()=>this.messageHandlers.delete(e)}async sendRaw(e){(!this.ws||this.ws.readyState!==1)&&await this.connect();let r=this.ws;if(!r||r.readyState!==1)throw new Error("WebSocket is not open");let n=typeof e=="string"?e:JSON.stringify(e);r.send(n);}async request(e,r,n){(!this.ws||this.ws.readyState!==1)&&await this.connect();let s=n?.reqId??this.nextReqId++,o=n?.timeoutMs??this.requestTimeoutMs,a=n?.attachAuthToken??true,i=r?{...r}:{};a&&this.authToken&&(i.token===void 0||i.token===null)&&(i.token=this.authToken);let l={method:e,params:Object.keys(i).length?i:void 0,req_id:s};return this.logger?.debug?.("Kraken WS request",{envelope:l}),await new Promise((d,c)=>{let k=setTimeout(()=>{this.pending.delete(s),c(new Error(`Kraken WS request timed out after ${o}ms (method=${e}, req_id=${s})`));},o),u={resolve:p=>d(p),reject:c,timeoutId:k};this.pending.set(s,u);try{let p=this.ws;if(!p||p.readyState!==1){clearTimeout(k),this.pending.delete(s),c(new Error(`WebSocket is not open (method=${e}, req_id=${s})`));return}p.send(JSON.stringify(l));}catch(p){clearTimeout(k),this.pending.delete(s),c(p);}})}};function Ne(t,e){return t.addMessageHandler(r=>{if(!r||typeof r!="object")return;let n=r;n.channel==="status"&&n.type==="update"&&Array.isArray(n.data)&&e(n);})}async function Ve(t,e={},r={}){return t.request("ping",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}function ze(t,e){return t.addMessageHandler(r=>{if(!r||typeof r!="object")return;let n=r;n.channel==="heartbeat"&&e(n);})}var S=class{constructor(e){this.ws=e;}ping(e={},r={}){return Ve(this.ws,e,r)}onStatus(e){return Ne(this.ws,e)}onHeartbeat(e){return ze(this.ws,e)}};async function $e(t,e,r={}){let n={channel:"ticker",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Je(t,e,r={}){let n={channel:"ticker",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Ye(t,e,r={}){let n={channel:"book",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Xe(t,e,r={}){let n={channel:"book",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function Ze(t,e,r={}){let n={channel:"level3",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function er(t,e,r={}){let n={channel:"level3",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function rr(t,e,r={}){let n={channel:"ohlc",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function tr(t,e,r={}){let n={channel:"ohlc",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function nr(t,e,r={}){let n={channel:"trade",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function sr(t,e,r={}){let n={channel:"trade",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function ar(t,e={},r={}){let n={channel:"instrument",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}async function or(t,e={},r={}){let n={channel:"instrument",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??false})}var B=class{constructor(e){this.ws=e;}subscribeTicker(e,r={}){return $e(this.ws,e,r)}unsubscribeTicker(e,r={}){return Je(this.ws,e,r)}subscribeBook(e,r={}){return Ye(this.ws,e,r)}unsubscribeBook(e,r={}){return Xe(this.ws,e,r)}subscribeLevel3(e,r={}){return Ze(this.ws,e,r)}unsubscribeLevel3(e,r={}){return er(this.ws,e,r)}subscribeOhlc(e,r={}){return rr(this.ws,e,r)}unsubscribeOhlc(e,r={}){return tr(this.ws,e,r)}subscribeTrade(e,r={}){return nr(this.ws,e,r)}unsubscribeTrade(e,r={}){return sr(this.ws,e,r)}subscribeInstrument(e={},r={}){return ar(this.ws,e,r)}unsubscribeInstrument(e={},r={}){return or(this.ws,e,r)}};async function ir(t,e,r={}){let n={channel:"executions",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function dr(t,e={},r={}){let n={channel:"executions",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function cr(t,e={},r={}){let n={channel:"balances",...e};return t.request("subscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}async function lr(t,e={},r={}){let n={channel:"balances",...e};return t.request("unsubscribe",n,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken??true})}var _=class{constructor(e){this.ws=e;}subscribeExecutions(e,r){return ir(this.ws,e,r)}unsubscribeExecutions(e,r){return dr(this.ws,e??{},r)}subscribeBalances(e={},r){return cr(this.ws,e,r)}unsubscribeBalances(e,r){return lr(this.ws,e??{},r)}};async function pr(t,e,r={}){return t.request("add_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function ur(t,e,r={}){let n=!!e.order_id,s=!!e.cl_ord_id;if(n&&s||!n&&!s)throw new Error("Kraken WS amend_order: exactly one of `order_id` or `cl_ord_id` must be provided");return t.request("amend_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function kr(t,e,r={}){return t.request("edit_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function Kr(t,e,r={}){let n=Array.isArray(e.order_id)&&e.order_id.length>0,s=Array.isArray(e.cl_ord_id)&&e.cl_ord_id.length>0,o=Array.isArray(e.order_userref)&&e.order_userref.length>0;if(!n&&!s&&!o)throw new Error("Kraken WS cancel_order: at least one of `order_id`, `cl_ord_id`, or `order_userref` must contain at least one entry");return t.request("cancel_order",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function mr(t,e={},r={}){return t.request("cancel_all",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function br(t,e,r={}){if(!Number.isFinite(e.timeout))throw new Error("Kraken WS cancel_all_orders_after: `timeout` must be a finite number (seconds)");if(e.timeout<0||e.timeout>=86400)throw new Error("Kraken WS cancel_all_orders_after: `timeout` must be >= 0 and < 86400 seconds");return t.request("cancel_all_orders_after",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function gr(t,e,r={}){if(!Array.isArray(e.orders)||e.orders.length<2)throw new Error("Kraken WS batch_add: `orders` must contain at least 2 entries");if(e.orders.length>15)throw new Error("Kraken WS batch_add: `orders` must not contain more than 15 entries");for(let[n,s]of e.orders.entries())if(s.cl_ord_id&&typeof s.order_userref=="number")throw new Error(`Kraken WS batch_add: order at index ${n} must not specify both cl_ord_id and order_userref`);return t.request("batch_add",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}async function yr(t,e,r={}){if(!Array.isArray(e.orders)||e.orders.length<2)throw new Error("Kraken WS batch_cancel: `orders` must contain at least 2 identifiers");if(e.orders.length>50)throw new Error("Kraken WS batch_cancel: `orders` must not contain more than 50 identifiers");return t.request("batch_cancel",e,{reqId:r.reqId,timeoutMs:r.timeoutMs,attachAuthToken:r.attachAuthToken})}var E=class{constructor(e){this.ws=e;}addOrder(e,r){return pr(this.ws,e,r)}amendOrder(e,r){return ur(this.ws,e,r)}editOrder(e,r){return kr(this.ws,e,r)}cancelOrder(e,r){return Kr(this.ws,e,r)}cancelAll(e,r){return mr(this.ws,e??{},r)}cancelAllOrdersAfter(e,r){return br(this.ws,e,r)}batchAdd(e,r){return gr(this.ws,e,r)}batchCancel(e,r){return yr(this.ws,e,r)}};var fr=class{publicConnection;privateConnection;admin;marketData;userData;userTrading;constructor(e={}){let{publicUrl:r="wss://ws.kraken.com/v2",privateUrl:n="wss://ws-auth.kraken.com/v2",authToken:s,WebSocketImpl:o,autoReconnect:a,reconnectDelayMs:i,requestTimeoutMs:l,logger:d}=e,c={authToken:void 0,WebSocketImpl:o,autoReconnect:a,reconnectDelayMs:i,requestTimeoutMs:l,logger:d};this.publicConnection=new y({...c,url:r}),this.privateConnection=new y({...c,url:n,authToken:s}),this.admin=new S(this.publicConnection),this.marketData=new B(this.publicConnection),this.userData=new _(this.privateConnection),this.userTrading=new E(this.privateConnection);}};
2
+ exports.KrakenSpotAccountDataApi=W;exports.KrakenSpotEarnApi=T;exports.KrakenSpotFundingApi=R;exports.KrakenSpotMarketDataApi=x;exports.KrakenSpotRestClient=je;exports.KrakenSpotSubaccountsApi=A;exports.KrakenSpotTradingApi=O;exports.KrakenSpotTransparencyApi=P;exports.KrakenSpotWebsocketV2Client=fr;exports.KrakenWebsocketBase=y;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map