@lynx-crypto/kraken-api 0.1.2 → 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 +274 -231
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1776 -489
- package/dist/index.d.ts +1776 -489
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +35 -3
package/README.md
CHANGED
|
@@ -8,326 +8,369 @@
|
|
|
8
8
|
[](https://github.com/lynx-laboratory/kraken-api/commits/master)
|
|
9
9
|
[](./LICENSE.md)
|
|
10
10
|
|
|
11
|
-
TypeScript client for **Kraken
|
|
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
|
-
|
|
19
|
-
|
|
17
|
+
## Important
|
|
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
|
-
##
|
|
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
|
-
|
|
42
|
+
---
|
|
28
43
|
|
|
29
|
-
|
|
30
|
-
npm i @lynx-crypto/kraken-api
|
|
31
|
-
```
|
|
44
|
+
## Installation
|
|
32
45
|
|
|
33
|
-
Yarn:
|
|
46
|
+
Using Yarn:
|
|
34
47
|
|
|
35
|
-
```
|
|
48
|
+
```sh
|
|
36
49
|
yarn add @lynx-crypto/kraken-api
|
|
37
50
|
```
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
Using npm:
|
|
40
53
|
|
|
54
|
+
```sh
|
|
55
|
+
npm install @lynx-crypto/kraken-api
|
|
41
56
|
```
|
|
42
|
-
pnpm add @lynx-crypto/kraken-api
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Node support
|
|
46
|
-
|
|
47
|
-
- Node >= 18 recommended (uses built-in fetch / AbortController)
|
|
48
57
|
|
|
49
58
|
---
|
|
50
59
|
|
|
51
|
-
##
|
|
60
|
+
## Requirements
|
|
52
61
|
|
|
53
|
-
|
|
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
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
import { KrakenSpotRestClient, KrakenSpotWebsocketV2Client } from "@lynx-crypto/kraken-api";
|
|
57
|
-
```
|
|
69
|
+
---
|
|
58
70
|
|
|
59
|
-
|
|
71
|
+
## Environment Variables (for private usage)
|
|
60
72
|
|
|
61
|
-
```
|
|
62
|
-
|
|
73
|
+
```bash
|
|
74
|
+
KRAKEN_API_KEY="your_api_key"
|
|
75
|
+
KRAKEN_API_SECRET="your_api_secret"
|
|
63
76
|
```
|
|
64
77
|
|
|
65
78
|
---
|
|
66
79
|
|
|
67
|
-
##
|
|
80
|
+
## Package Exports
|
|
68
81
|
|
|
69
|
-
###
|
|
82
|
+
### REST
|
|
83
|
+
- `KrakenSpotRestClient`
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
Sub-APIs available on the client:
|
|
86
|
+
- `marketData`
|
|
87
|
+
- `accountData`
|
|
88
|
+
- `trading`
|
|
89
|
+
- `funding`
|
|
90
|
+
- `subaccounts`
|
|
91
|
+
- `earn`
|
|
92
|
+
- `transparency`
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
### WebSocket
|
|
95
|
+
- `KrakenSpotWebsocketV2Client`
|
|
96
|
+
- `KrakenWebsocketBase` (advanced / custom integrations)
|
|
81
97
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
Typed channel namespaces:
|
|
99
|
+
- `admin`
|
|
100
|
+
- `marketData`
|
|
101
|
+
- `userData`
|
|
102
|
+
- `userTrading`
|
|
86
103
|
|
|
87
|
-
|
|
104
|
+
All public request/response and stream payloads are exported as TypeScript types.
|
|
88
105
|
|
|
89
|
-
|
|
106
|
+
---
|
|
107
|
+
## REST Usage
|
|
90
108
|
|
|
91
|
-
|
|
109
|
+
### Public REST example (no authentication)
|
|
92
110
|
|
|
93
111
|
```ts
|
|
94
|
-
|
|
95
|
-
```
|
|
112
|
+
import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
|
|
96
113
|
|
|
97
|
-
|
|
114
|
+
async function main() {
|
|
115
|
+
const kraken = new KrakenSpotRestClient({
|
|
116
|
+
userAgent: 'example-app/1.0.0',
|
|
117
|
+
});
|
|
98
118
|
|
|
99
|
-
|
|
119
|
+
const time = await kraken.marketData.getServerTime();
|
|
120
|
+
console.log('Kraken time:', time.rfc1123);
|
|
121
|
+
}
|
|
100
122
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
123
|
+
main().catch((err) => {
|
|
124
|
+
console.error(err);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
});
|
|
127
|
+
```
|
|
104
128
|
|
|
105
|
-
|
|
129
|
+
### Private REST example (authenticated)
|
|
106
130
|
|
|
107
|
-
|
|
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
|
+
}
|
|
140
|
+
|
|
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
|
+
```
|
|
108
157
|
|
|
109
|
-
|
|
158
|
+
---
|
|
110
159
|
|
|
111
|
-
|
|
112
|
-
- a **private/auth connection** (user-data + user-trading)
|
|
160
|
+
## WebSocket v2 Usage
|
|
113
161
|
|
|
114
|
-
###
|
|
162
|
+
### Public WebSocket (market data)
|
|
115
163
|
|
|
116
164
|
```ts
|
|
117
|
-
|
|
118
|
-
// Optional override URLs:
|
|
119
|
-
// publicUrl: "wss://ws.kraken.com/v2",
|
|
120
|
-
// privateUrl: "wss://ws-auth.kraken.com/v2",
|
|
121
|
-
|
|
122
|
-
// IMPORTANT: private WS requires a session token
|
|
123
|
-
authToken: process.env.KRAKEN_WS_AUTH_TOKEN,
|
|
124
|
-
|
|
125
|
-
// Optional connection tuning:
|
|
126
|
-
// autoReconnect: true,
|
|
127
|
-
// reconnectDelayMs: 1_000,
|
|
128
|
-
// requestTimeoutMs: 10_000,
|
|
129
|
-
|
|
130
|
-
// Optional logger:
|
|
131
|
-
// logger: console,
|
|
132
|
-
|
|
133
|
-
// Optional WS implementation:
|
|
134
|
-
// - In Node, ws is used by default.
|
|
135
|
-
// - In browsers, pass the browser WebSocket if needed.
|
|
136
|
-
// WebSocketImpl: WebSocket,
|
|
137
|
-
});
|
|
138
|
-
```
|
|
165
|
+
import { KrakenSpotWebsocketV2Client } from '@lynx-crypto/kraken-api';
|
|
139
166
|
|
|
140
|
-
|
|
167
|
+
async function main() {
|
|
168
|
+
const wsClient = new KrakenSpotWebsocketV2Client({
|
|
169
|
+
autoReconnect: false,
|
|
170
|
+
});
|
|
141
171
|
|
|
142
|
-
|
|
143
|
-
- `ws.marketData` (public connection)
|
|
144
|
-
- `ws.userData` (private connection)
|
|
145
|
-
- `ws.userTrading` (private connection)
|
|
172
|
+
await wsClient.publicConnection.connect();
|
|
146
173
|
|
|
147
|
-
|
|
174
|
+
const ack = await wsClient.marketData.subscribeTrade(
|
|
175
|
+
{ symbol: ['BTC/USD'], snapshot: true },
|
|
176
|
+
{ reqId: 1 },
|
|
177
|
+
);
|
|
148
178
|
|
|
149
|
-
|
|
179
|
+
if (!ack.success) {
|
|
180
|
+
throw new Error(`Subscribe failed: ${ack.error}`);
|
|
181
|
+
}
|
|
150
182
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```
|
|
183
|
+
const unsubscribe = wsClient.publicConnection.addMessageHandler((msg) => {
|
|
184
|
+
console.log(JSON.stringify(msg));
|
|
185
|
+
});
|
|
155
186
|
|
|
156
|
-
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
unsubscribe();
|
|
189
|
+
wsClient.publicConnection.close(1000, 'example done');
|
|
190
|
+
}, 20_000);
|
|
191
|
+
}
|
|
157
192
|
|
|
158
|
-
|
|
193
|
+
main().catch((err) => {
|
|
194
|
+
console.error(err);
|
|
195
|
+
process.exitCode = 1;
|
|
196
|
+
});
|
|
197
|
+
```
|
|
159
198
|
|
|
160
|
-
|
|
199
|
+
### Private WebSocket (balances / executions)
|
|
161
200
|
|
|
162
|
-
|
|
201
|
+
Authenticated WebSocket usage requires a token obtained via REST.
|
|
163
202
|
|
|
164
203
|
```ts
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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;
|
|
169
251
|
});
|
|
170
|
-
|
|
171
|
-
// later:
|
|
172
|
-
unsubscribe();
|
|
173
252
|
```
|
|
174
253
|
|
|
175
254
|
---
|
|
176
255
|
|
|
177
|
-
##
|
|
256
|
+
## REST rate limiting & retries
|
|
257
|
+
|
|
258
|
+
This library supports Kraken-style rate limiting with optional automatic retries:
|
|
178
259
|
|
|
179
|
-
|
|
260
|
+
- Lightweight in-memory token bucket limiter by default
|
|
261
|
+
- Automatic retries are configurable
|
|
262
|
+
- Handles:
|
|
263
|
+
- EAPI:Rate limit exceeded
|
|
264
|
+
- EService: Throttled: <unix timestamp>
|
|
265
|
+
- HTTP 429 Too Many Requests
|
|
180
266
|
|
|
181
267
|
Example:
|
|
182
268
|
|
|
183
269
|
```ts
|
|
184
|
-
const
|
|
185
|
-
|
|
270
|
+
const kraken = new KrakenSpotRestClient({
|
|
271
|
+
apiKey: process.env.KRAKEN_API_KEY,
|
|
272
|
+
apiSecret: process.env.KRAKEN_API_SECRET,
|
|
273
|
+
rateLimit: {
|
|
274
|
+
mode: 'auto',
|
|
275
|
+
tier: 'starter',
|
|
276
|
+
retryOnRateLimit: true,
|
|
277
|
+
maxRetries: 5,
|
|
278
|
+
// restCostFn: (path) => (path.includes("Ledgers") ? 2 : 1),
|
|
279
|
+
},
|
|
280
|
+
});
|
|
186
281
|
```
|
|
187
282
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
## WS v2: Market Data (public)
|
|
191
|
-
|
|
192
|
-
Market data subscriptions live on ws.marketData (public connection).
|
|
193
|
-
(Exact channel helpers depend on your implemented market-data modules.)
|
|
283
|
+
Disable built-in throttling:
|
|
194
284
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
---
|
|
285
|
+
```ts
|
|
286
|
+
rateLimit: {
|
|
287
|
+
mode: 'off';
|
|
288
|
+
}
|
|
289
|
+
```
|
|
201
290
|
|
|
202
|
-
|
|
291
|
+
### Redis rate limiting (multi-process / multi-container)
|
|
203
292
|
|
|
204
|
-
|
|
293
|
+
If you run multiple Node processes, Docker containers, or workers, they all share the same Kraken IP-level limits. In-memory rate limiting only protects a single process.
|
|
205
294
|
|
|
206
|
-
|
|
295
|
+
For cross-process coordination, you can use the Redis-backed token bucket limiter.
|
|
207
296
|
|
|
208
|
-
|
|
209
|
-
- balances (balance snapshots + ledger-derived updates)
|
|
297
|
+
Example (you provide the Redis client + EVAL wrapper):
|
|
210
298
|
|
|
211
|
-
|
|
299
|
+
```ts
|
|
300
|
+
import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
|
|
301
|
+
import { RedisTokenBucketLimiter } from '@lynx-crypto/kraken-api/base/redisRateLimit';
|
|
302
|
+
|
|
303
|
+
// Your Redis EVAL wrapper should return a number:
|
|
304
|
+
// - 0 means "proceed now"
|
|
305
|
+
// - >0 means "wait this many ms then retry"
|
|
306
|
+
const evalRedis = async (
|
|
307
|
+
key: string,
|
|
308
|
+
maxCounter: number,
|
|
309
|
+
decayPerSec: number,
|
|
310
|
+
cost: number,
|
|
311
|
+
ttlSeconds: number,
|
|
312
|
+
minWaitMs: number,
|
|
313
|
+
): Promise<number> => {
|
|
314
|
+
// Example shape (pseudo-code):
|
|
315
|
+
// return await redis.eval(luaScript, { keys: [key], arguments: [maxCounter, decayPerSec, cost, ttlSeconds, minWaitMs] });
|
|
316
|
+
return 0;
|
|
317
|
+
};
|
|
212
318
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
319
|
+
const kraken = new KrakenSpotRestClient({
|
|
320
|
+
apiKey: process.env.KRAKEN_API_KEY,
|
|
321
|
+
apiSecret: process.env.KRAKEN_API_SECRET,
|
|
322
|
+
rateLimit: {
|
|
323
|
+
mode: 'auto',
|
|
324
|
+
tier: 'starter',
|
|
325
|
+
retryOnRateLimit: true,
|
|
326
|
+
maxRetries: 5,
|
|
327
|
+
|
|
328
|
+
// Cross-process limiter (Redis):
|
|
329
|
+
redis: {
|
|
330
|
+
limiter: new RedisTokenBucketLimiter({
|
|
331
|
+
key: 'kraken:rest:global',
|
|
332
|
+
maxCounter: 15,
|
|
333
|
+
decayPerSec: 0.33,
|
|
334
|
+
ttlSeconds: 30,
|
|
335
|
+
minWaitMs: 50,
|
|
336
|
+
evalRedis,
|
|
337
|
+
}),
|
|
338
|
+
},
|
|
339
|
+
},
|
|
218
340
|
});
|
|
219
|
-
|
|
220
|
-
if (!ack.success) console.error("executions subscribe error:", ack.error);
|
|
221
341
|
```
|
|
222
342
|
|
|
223
|
-
|
|
343
|
+
Notes:
|
|
224
344
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (msg?.channel === "executions" && (msg.type === "snapshot" || msg.type === "update")) {
|
|
228
|
-
for (const report of msg.data ?? []) {
|
|
229
|
-
console.log("[exec]", report.exec_type, report.order_id, report.order_status);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Example (balances):
|
|
236
|
-
|
|
237
|
-
````ts
|
|
238
|
-
const ack2 = await ws.userData.subscribeBalances({ snapshot: true });
|
|
239
|
-
if (!ack2.success) console.error("balances subscribe error:", ack2.error);
|
|
240
|
-
|
|
241
|
-
ws.privateConnection.addMessageHandler((msg: any) => {
|
|
242
|
-
if (msg?.channel === "balances" && msg.type === "snapshot") {
|
|
243
|
-
for (const asset of msg.data ?? []) {
|
|
244
|
-
console.log("[balances snapshot]", asset.asset, "total:", asset.balance);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (msg?.channel === "balances" && msg.type === "update") {
|
|
248
|
-
for (const tx of msg.data ?? []) {
|
|
249
|
-
console.log("[balances update]", tx.asset, tx.type, "delta:", tx.amount, "new:", tx.balance);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
});
|
|
345
|
+
- Redis is optional. Only use it when you need cross-process coordination.
|
|
346
|
+
- If Redis is down / eval fails, the request fails (no silent bypass).
|
|
253
347
|
|
|
254
348
|
---
|
|
255
349
|
|
|
256
|
-
##
|
|
350
|
+
## Examples
|
|
257
351
|
|
|
258
|
-
|
|
352
|
+
The repository includes a comprehensive [examples](./examples) directory:
|
|
259
353
|
|
|
260
|
-
|
|
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)
|
|
261
358
|
|
|
262
|
-
|
|
263
|
-
-
|
|
264
|
-
-
|
|
265
|
-
-
|
|
266
|
-
-
|
|
267
|
-
- `cancel_all_orders_after` (Dead Man’s Switch)
|
|
268
|
-
- `batch_add`
|
|
269
|
-
- `batch_cancel`
|
|
270
|
-
|
|
271
|
-
Add order:
|
|
272
|
-
```ts
|
|
273
|
-
const res = await ws.userTrading.addOrder({
|
|
274
|
-
order_type: "limit",
|
|
275
|
-
side: "buy",
|
|
276
|
-
symbol: "BTC/USD",
|
|
277
|
-
order_qty: 0.01,
|
|
278
|
-
limit_price: 30000,
|
|
279
|
-
time_in_force: "gtc",
|
|
280
|
-
cl_ord_id: "demo-0001",
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (res.success) console.log("order_id:", res.result?.order_id);
|
|
285
|
-
else console.error("add_order error:", res.error);
|
|
286
|
-
````
|
|
287
|
-
|
|
288
|
-
Dead Man’s Switch:
|
|
289
|
-
|
|
290
|
-
```
|
|
291
|
-
// recommended: refresh every 15–30s with timeout=60
|
|
292
|
-
await ws.userTrading.cancelAllOrdersAfter({ timeout: 60 });
|
|
293
|
-
```
|
|
359
|
+
Examples are designed to be:
|
|
360
|
+
- Runnable
|
|
361
|
+
- Safe by default
|
|
362
|
+
- Self-contained
|
|
363
|
+
- Easy to copy into your own project
|
|
294
364
|
|
|
295
365
|
---
|
|
296
366
|
|
|
297
|
-
##
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
-
|
|
302
|
-
|
|
303
|
-
-
|
|
304
|
-
Default: 10_000
|
|
305
|
-
- `userAgent?: string`
|
|
306
|
-
- `apiKey?: string`
|
|
307
|
-
Required for private endpoints
|
|
308
|
-
- `apiSecret?: string` (base64)
|
|
309
|
-
Required for private endpoints
|
|
310
|
-
- `logger?: KrakenLogger`
|
|
311
|
-
debug/info/warn/error(msg, meta?)
|
|
312
|
-
|
|
313
|
-
### KrakenSpotWebsocketV2Client options
|
|
314
|
-
|
|
315
|
-
- `publicUrl?: string`
|
|
316
|
-
Default: wss://ws.kraken.com/v2
|
|
317
|
-
- `privateUrl?: string`
|
|
318
|
-
Default: wss://ws-auth.kraken.com/v2
|
|
319
|
-
- `authToken?: string`
|
|
320
|
-
Required for authenticated/private connection features
|
|
321
|
-
- `WebSocketImpl?: constructor`
|
|
322
|
-
Optional override (browser / custom WS)
|
|
323
|
-
- `autoReconnect?: boolean`
|
|
324
|
-
Default: true
|
|
325
|
-
- `reconnectDelayMs?: number`
|
|
326
|
-
Default: 1000
|
|
327
|
-
- `requestTimeoutMs?: number`
|
|
328
|
-
Default: 10_000
|
|
329
|
-
- `logger?: KrakenWebsocketLogger`
|
|
330
|
-
debug/info/warn/error(msg, meta?)
|
|
367
|
+
## Design Philosophy
|
|
368
|
+
|
|
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
|
|
331
374
|
|
|
332
375
|
---
|
|
333
376
|
|
|
@@ -349,11 +392,11 @@ Build:
|
|
|
349
392
|
|
|
350
393
|
## Security notes
|
|
351
394
|
|
|
352
|
-
- Keep API keys
|
|
353
|
-
- Use least-privilege API key permissions
|
|
395
|
+
- Keep API keys and secrets out of source control
|
|
396
|
+
- Use least-privilege API key permissions
|
|
354
397
|
|
|
355
398
|
---
|
|
356
399
|
|
|
357
400
|
## License
|
|
358
401
|
|
|
359
|
-
MIT (see LICENSE)
|
|
402
|
+
MIT (see LICENSE.md)
|