@lynx-crypto/kraken-api 0.2.0 → 1.1.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 +353 -209
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2049 -489
- package/dist/index.d.ts +2049 -489
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +54 -5
package/README.md
CHANGED
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
[](https://github.com/lynx-laboratory/kraken-api/commits/master)
|
|
9
9
|
[](./LICENSE.md)
|
|
10
10
|
|
|
11
|
-
TypeScript client for **Kraken
|
|
11
|
+
A modern, strongly-typed TypeScript client for the **Kraken Spot API**, providing both **REST** and **WebSocket v2** access in a single package.
|
|
12
12
|
|
|
13
13
|
- **REST API** (public + private endpoints)
|
|
14
14
|
- **WebSocket v2** (public market-data + authenticated user-data/trading)
|
|
15
|
+
- **Bulk historical CSV datasets** (OHLCVT + Trades) via Kraken’s official Google Drive downloads
|
|
15
16
|
|
|
16
17
|
See [Kraken Official Documentation](https://docs.kraken.com/api/docs/category/guides)
|
|
17
18
|
|
|
@@ -22,85 +23,329 @@ See [Kraken Official Documentation](https://docs.kraken.com/api/docs/category/gu
|
|
|
22
23
|
|
|
23
24
|
---
|
|
24
25
|
|
|
25
|
-
##
|
|
26
|
+
## Features
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
`npm i @lynx-crypto/kraken-api`
|
|
28
|
+
### Spot REST API
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
- Public market data (time, assets, pairs, ticker, OHLC, order book, trades, spreads)
|
|
31
|
+
- Private account data (balances, orders, trades, ledgers, export reports)
|
|
32
|
+
- Trading endpoints (add/amend/edit/cancel orders, batch operations)
|
|
33
|
+
- Funding endpoints (deposits, withdrawals, transfers)
|
|
34
|
+
- Earn endpoints (strategies, allocations, status)
|
|
35
|
+
- Subaccounts (master account operations)
|
|
36
|
+
- Transparency endpoints (pre-trade / post-trade data)
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
`pnpm add @lynx-crypto/kraken-api`
|
|
38
|
+
### Spot WebSocket v2 API
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
- Public streams (ticker, trades, book, OHLC, instruments)
|
|
41
|
+
- Private user streams (balances, executions)
|
|
42
|
+
- Private trading RPC methods
|
|
43
|
+
- Automatic request/response correlation (`req_id`)
|
|
44
|
+
- Optional auto-reconnect with backoff
|
|
45
|
+
- Works in Node.js (via `ws`) or browser environments
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
### Bulk historical CSV datasets (OHLCVT + Trades)
|
|
48
|
+
|
|
49
|
+
Support for Kraken’s downloadable historical datasets:
|
|
50
|
+
|
|
51
|
+
- OHLCVT (open/high/low/close/volume/trades)
|
|
52
|
+
- Trades (time and sales)
|
|
53
|
+
|
|
54
|
+
Data source (Kraken Support):
|
|
55
|
+
|
|
56
|
+
- https://support.kraken.com/sections/360009899492-csv-data
|
|
57
|
+
- https://support.kraken.com/articles/360047124832-downloadable-historical-ohlcvt-open-high-low-close-volume-trades-data
|
|
58
|
+
- https://support.kraken.com/articles/360047543791-downloadable-historical-market-data-time-and-sales-
|
|
59
|
+
|
|
60
|
+
Bulk workflow:
|
|
61
|
+
|
|
62
|
+
- Download ZIPs (seamless via Drive API, or manually)
|
|
63
|
+
- Extract ZIPs into a stable on-disk layout
|
|
64
|
+
- Query extracted CSVs (streaming)
|
|
39
65
|
|
|
40
66
|
---
|
|
41
67
|
|
|
42
|
-
##
|
|
68
|
+
## Installation
|
|
43
69
|
|
|
44
|
-
|
|
70
|
+
Using Yarn:
|
|
45
71
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
KrakenSpotWebsocketV2Client,
|
|
50
|
-
} from '@lynx-crypto/kraken-api';
|
|
51
|
-
```
|
|
72
|
+
'''sh
|
|
73
|
+
yarn add @lynx-crypto/kraken-api
|
|
74
|
+
'''
|
|
52
75
|
|
|
53
|
-
|
|
76
|
+
Using npm:
|
|
54
77
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
KrakenSpotWebsocketV2Client,
|
|
59
|
-
} = require('@lynx-crypto/kraken-api');
|
|
60
|
-
```
|
|
78
|
+
'''sh
|
|
79
|
+
npm install @lynx-crypto/kraken-api
|
|
80
|
+
'''
|
|
61
81
|
|
|
62
82
|
---
|
|
63
83
|
|
|
64
|
-
##
|
|
84
|
+
## Requirements
|
|
65
85
|
|
|
66
|
-
|
|
86
|
+
- Node.js 18+ recommended
|
|
87
|
+
- TypeScript 4.9+ recommended
|
|
88
|
+
- For private endpoints:
|
|
89
|
+
- Kraken API key and secret
|
|
90
|
+
- Appropriate permissions enabled in Kraken
|
|
91
|
+
- “WebSocket interface” enabled for private WS usage
|
|
92
|
+
- For bulk downloads (optional):
|
|
93
|
+
- A Google Drive API key for seamless downloads (manual ZIP placement is supported)
|
|
67
94
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Environment Variables (for private usage)
|
|
98
|
+
|
|
99
|
+
'''bash
|
|
100
|
+
KRAKEN_API_KEY="your_api_key"
|
|
101
|
+
KRAKEN_API_SECRET="your_api_secret"
|
|
102
|
+
'''
|
|
103
|
+
|
|
104
|
+
## Environment Variables (optional, for bulk downloads)
|
|
105
|
+
|
|
106
|
+
'''bash
|
|
74
107
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
108
|
+
# If set, bulk downloads can be performed via the Google Drive API.
|
|
109
|
+
|
|
110
|
+
# If not set, ZIPs can be downloaded manually and placed into the expected folders.
|
|
111
|
+
|
|
112
|
+
LYNX_CRYPTO_KRAKEN_API_GOOGLE_DRIVE_API_KEY="your_google_drive_api_key"
|
|
113
|
+
'''
|
|
114
|
+
|
|
115
|
+
---
|
|
78
116
|
|
|
79
|
-
|
|
80
|
-
|
|
117
|
+
## Package Exports
|
|
118
|
+
|
|
119
|
+
### REST
|
|
120
|
+
|
|
121
|
+
- `KrakenSpotRestClient`
|
|
122
|
+
|
|
123
|
+
Sub-APIs available on the client:
|
|
124
|
+
|
|
125
|
+
- `marketData`
|
|
126
|
+
- `accountData`
|
|
127
|
+
- `trading`
|
|
128
|
+
- `funding`
|
|
129
|
+
- `subaccounts`
|
|
130
|
+
- `earn`
|
|
131
|
+
- `transparency`
|
|
132
|
+
|
|
133
|
+
### WebSocket
|
|
134
|
+
|
|
135
|
+
- `KrakenSpotWebsocketV2Client`
|
|
136
|
+
- `KrakenWebsocketBase` (advanced / custom integrations)
|
|
137
|
+
|
|
138
|
+
Typed channel namespaces:
|
|
139
|
+
|
|
140
|
+
- `admin`
|
|
141
|
+
- `marketData`
|
|
142
|
+
- `userData`
|
|
143
|
+
- `userTrading`
|
|
144
|
+
|
|
145
|
+
### Bulk
|
|
146
|
+
|
|
147
|
+
- `KrakenBulkClient`
|
|
148
|
+
|
|
149
|
+
All public request/response and stream payloads are exported as TypeScript types.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## REST Usage
|
|
154
|
+
|
|
155
|
+
### Public REST example (no authentication)
|
|
156
|
+
|
|
157
|
+
'''ts
|
|
158
|
+
import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
|
|
81
159
|
|
|
82
|
-
|
|
83
|
-
|
|
160
|
+
async function main() {
|
|
161
|
+
const kraken = new KrakenSpotRestClient({
|
|
162
|
+
userAgent: 'example-app/1.0.0',
|
|
84
163
|
});
|
|
85
|
-
```
|
|
86
164
|
|
|
87
|
-
|
|
165
|
+
const time = await kraken.marketData.getServerTime();
|
|
166
|
+
console.log('Kraken time:', time.rfc1123);
|
|
167
|
+
}
|
|
88
168
|
|
|
89
|
-
(
|
|
169
|
+
main().catch((err) => {
|
|
170
|
+
console.error(err);
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
});
|
|
173
|
+
'''
|
|
90
174
|
|
|
91
|
-
|
|
92
|
-
const serverTime = await kraken.public.getServerTime();
|
|
93
|
-
console.log(serverTime);
|
|
94
|
-
```
|
|
175
|
+
### Private REST example (authenticated)
|
|
95
176
|
|
|
96
|
-
|
|
177
|
+
'''ts
|
|
178
|
+
import 'dotenv/config';
|
|
179
|
+
import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
|
|
97
180
|
|
|
98
|
-
(
|
|
181
|
+
function requireEnv(name: string): string {
|
|
182
|
+
const v = process.env[name];
|
|
183
|
+
if (!v) throw new Error(`Missing env var: ${name}`);
|
|
184
|
+
return v;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function main() {
|
|
188
|
+
const kraken = new KrakenSpotRestClient({
|
|
189
|
+
userAgent: 'example-app/1.0.0',
|
|
190
|
+
apiKey: requireEnv('KRAKEN_API_KEY'),
|
|
191
|
+
apiSecret: requireEnv('KRAKEN_API_SECRET'),
|
|
192
|
+
});
|
|
99
193
|
|
|
100
|
-
```ts
|
|
101
194
|
const balances = await kraken.accountData.getAccountBalance();
|
|
102
|
-
console.log('
|
|
103
|
-
|
|
195
|
+
console.log('Asset count:', Object.keys(balances).length);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
main().catch((err) => {
|
|
199
|
+
console.error(err);
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
});
|
|
202
|
+
'''
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## WebSocket v2 Usage
|
|
207
|
+
|
|
208
|
+
### Public WebSocket (market data)
|
|
209
|
+
|
|
210
|
+
'''ts
|
|
211
|
+
import { KrakenSpotWebsocketV2Client } from '@lynx-crypto/kraken-api';
|
|
212
|
+
|
|
213
|
+
async function main() {
|
|
214
|
+
const wsClient = new KrakenSpotWebsocketV2Client({
|
|
215
|
+
autoReconnect: false,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await wsClient.publicConnection.connect();
|
|
219
|
+
|
|
220
|
+
const ack = await wsClient.marketData.subscribeTrade(
|
|
221
|
+
{ symbol: ['BTC/USD'], snapshot: true },
|
|
222
|
+
{ reqId: 1 },
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (!ack.success) {
|
|
226
|
+
throw new Error(`Subscribe failed: ${ack.error}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const unsubscribe = wsClient.publicConnection.addMessageHandler((msg) => {
|
|
230
|
+
console.log(JSON.stringify(msg));
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
unsubscribe();
|
|
235
|
+
wsClient.publicConnection.close(1000, 'example done');
|
|
236
|
+
}, 20_000);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
main().catch((err) => {
|
|
240
|
+
console.error(err);
|
|
241
|
+
process.exitCode = 1;
|
|
242
|
+
});
|
|
243
|
+
'''
|
|
244
|
+
|
|
245
|
+
### Private WebSocket (balances / executions)
|
|
246
|
+
|
|
247
|
+
Authenticated WebSocket usage requires a token obtained via REST.
|
|
248
|
+
|
|
249
|
+
'''ts
|
|
250
|
+
import 'dotenv/config';
|
|
251
|
+
import {
|
|
252
|
+
KrakenSpotRestClient,
|
|
253
|
+
KrakenSpotWebsocketV2Client,
|
|
254
|
+
} from '@lynx-crypto/kraken-api';
|
|
255
|
+
|
|
256
|
+
function requireEnv(name: string): string {
|
|
257
|
+
const v = process.env[name];
|
|
258
|
+
if (!v) throw new Error(`Missing env var: ${name}`);
|
|
259
|
+
return v;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async function main() {
|
|
263
|
+
const rest = new KrakenSpotRestClient({
|
|
264
|
+
userAgent: 'example-app/1.0.0',
|
|
265
|
+
apiKey: requireEnv('KRAKEN_API_KEY'),
|
|
266
|
+
apiSecret: requireEnv('KRAKEN_API_SECRET'),
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const { token } = await rest.trading.getWebSocketsToken();
|
|
270
|
+
|
|
271
|
+
const wsClient = new KrakenSpotWebsocketV2Client({
|
|
272
|
+
authToken: token,
|
|
273
|
+
autoReconnect: false,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
await wsClient.privateConnection.connect();
|
|
277
|
+
|
|
278
|
+
const ack = await wsClient.userData.subscribeBalances({}, { reqId: 10 });
|
|
279
|
+
|
|
280
|
+
if (!ack.success) {
|
|
281
|
+
throw new Error(`Subscribe failed: ${ack.error}`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const off = wsClient.privateConnection.addMessageHandler((msg) => {
|
|
285
|
+
console.log(JSON.stringify(msg));
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
off();
|
|
290
|
+
wsClient.privateConnection.close(1000, 'example done');
|
|
291
|
+
}, 30_000);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
main().catch((err) => {
|
|
295
|
+
console.error(err);
|
|
296
|
+
process.exitCode = 1;
|
|
297
|
+
});
|
|
298
|
+
'''
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Bulk historical data (OHLCVT + Trades)
|
|
303
|
+
|
|
304
|
+
Bulk data is managed by `KrakenBulkClient`. It supports:
|
|
305
|
+
|
|
306
|
+
- Downloading complete and quarterly ZIPs
|
|
307
|
+
- Extracting ZIPs into a stable directory layout
|
|
308
|
+
- Listing available pairs (and OHLC intervals)
|
|
309
|
+
- Streaming query results from extracted CSVs
|
|
310
|
+
|
|
311
|
+
### Storage layout
|
|
312
|
+
|
|
313
|
+
A `storageDir` is provided when constructing the client (examples use `.bulk-data`). The library stores ZIPs and extracted CSVs under dataset-specific folders:
|
|
314
|
+
|
|
315
|
+
'''txt
|
|
316
|
+
<storageDir>/
|
|
317
|
+
ohlcvt/
|
|
318
|
+
zips/
|
|
319
|
+
complete/complete.zip
|
|
320
|
+
quarterly/<YYYYQn>.zip
|
|
321
|
+
extracted/
|
|
322
|
+
complete/
|
|
323
|
+
quarterly/<YYYYQn>/
|
|
324
|
+
trades/
|
|
325
|
+
zips/
|
|
326
|
+
complete/complete.zip
|
|
327
|
+
quarterly/<YYYYQn>.zip
|
|
328
|
+
extracted/
|
|
329
|
+
complete/
|
|
330
|
+
quarterly/<YYYYQn>/
|
|
331
|
+
'''
|
|
332
|
+
|
|
333
|
+
Recommended:
|
|
334
|
+
|
|
335
|
+
- Add the storage directory to `.gitignore` (e.g. `.bulk-data/`).
|
|
336
|
+
|
|
337
|
+
### Downloading ZIPs (two options)
|
|
338
|
+
|
|
339
|
+
1. Seamless downloads (Drive API)
|
|
340
|
+
|
|
341
|
+
- Set `LYNX_CRYPTO_KRAKEN_API_GOOGLE_DRIVE_API_KEY`.
|
|
342
|
+
- Run the bulk download examples (see below).
|
|
343
|
+
|
|
344
|
+
2. Manual ZIP placement (no API key)
|
|
345
|
+
|
|
346
|
+
- Download the ZIP(s) from Kraken’s support pages.
|
|
347
|
+
- Place the ZIP(s) into the expected `zips/complete/` or `zips/quarterly/` folders.
|
|
348
|
+
- Run extraction and query examples as usual (extraction/query do not require an API key).
|
|
104
349
|
|
|
105
350
|
---
|
|
106
351
|
|
|
@@ -117,27 +362,27 @@ This library supports Kraken-style rate limiting with optional automatic retries
|
|
|
117
362
|
|
|
118
363
|
Example:
|
|
119
364
|
|
|
120
|
-
|
|
365
|
+
'''ts
|
|
121
366
|
const kraken = new KrakenSpotRestClient({
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
367
|
+
apiKey: process.env.KRAKEN_API_KEY,
|
|
368
|
+
apiSecret: process.env.KRAKEN_API_SECRET,
|
|
369
|
+
rateLimit: {
|
|
370
|
+
mode: 'auto',
|
|
371
|
+
tier: 'starter',
|
|
372
|
+
retryOnRateLimit: true,
|
|
373
|
+
maxRetries: 5,
|
|
374
|
+
// restCostFn: (path) => (path.includes("Ledgers") ? 2 : 1),
|
|
375
|
+
},
|
|
131
376
|
});
|
|
132
|
-
|
|
377
|
+
'''
|
|
133
378
|
|
|
134
379
|
Disable built-in throttling:
|
|
135
380
|
|
|
136
|
-
|
|
381
|
+
'''ts
|
|
137
382
|
rateLimit: {
|
|
138
|
-
|
|
383
|
+
mode: 'off',
|
|
139
384
|
}
|
|
140
|
-
|
|
385
|
+
'''
|
|
141
386
|
|
|
142
387
|
### Redis rate limiting (multi-process / multi-container)
|
|
143
388
|
|
|
@@ -147,7 +392,7 @@ For cross-process coordination, you can use the Redis-backed token bucket limite
|
|
|
147
392
|
|
|
148
393
|
Example (you provide the Redis client + EVAL wrapper):
|
|
149
394
|
|
|
150
|
-
|
|
395
|
+
'''ts
|
|
151
396
|
import { KrakenSpotRestClient } from '@lynx-crypto/kraken-api';
|
|
152
397
|
import { RedisTokenBucketLimiter } from '@lynx-crypto/kraken-api/base/redisRateLimit';
|
|
153
398
|
|
|
@@ -155,26 +400,26 @@ import { RedisTokenBucketLimiter } from '@lynx-crypto/kraken-api/base/redisRateL
|
|
|
155
400
|
// - 0 means "proceed now"
|
|
156
401
|
// - >0 means "wait this many ms then retry"
|
|
157
402
|
const evalRedis = async (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
403
|
+
key: string,
|
|
404
|
+
maxCounter: number,
|
|
405
|
+
decayPerSec: number,
|
|
406
|
+
cost: number,
|
|
407
|
+
ttlSeconds: number,
|
|
408
|
+
minWaitMs: number,
|
|
164
409
|
): Promise<number> => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
410
|
+
// Example shape (pseudo-code):
|
|
411
|
+
// return await redis.eval(luaScript, { keys: [key], arguments: [maxCounter, decayPerSec, cost, ttlSeconds, minWaitMs] });
|
|
412
|
+
return 0;
|
|
168
413
|
};
|
|
169
414
|
|
|
170
415
|
const kraken = new KrakenSpotRestClient({
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
416
|
+
apiKey: process.env.KRAKEN_API_KEY,
|
|
417
|
+
apiSecret: process.env.KRAKEN_API_SECRET,
|
|
418
|
+
rateLimit: {
|
|
419
|
+
mode: 'auto',
|
|
420
|
+
tier: 'starter',
|
|
421
|
+
retryOnRateLimit: true,
|
|
422
|
+
maxRetries: 5,
|
|
178
423
|
|
|
179
424
|
// Cross-process limiter (Redis):
|
|
180
425
|
redis: {
|
|
@@ -187,9 +432,10 @@ const kraken = new KrakenSpotRestClient({
|
|
|
187
432
|
evalRedis,
|
|
188
433
|
}),
|
|
189
434
|
},
|
|
190
|
-
|
|
435
|
+
|
|
436
|
+
},
|
|
191
437
|
});
|
|
192
|
-
|
|
438
|
+
'''
|
|
193
439
|
|
|
194
440
|
Notes:
|
|
195
441
|
|
|
@@ -198,142 +444,40 @@ Notes:
|
|
|
198
444
|
|
|
199
445
|
---
|
|
200
446
|
|
|
201
|
-
##
|
|
447
|
+
## Examples
|
|
202
448
|
|
|
203
|
-
|
|
449
|
+
The repository includes a comprehensive [examples](./examples) directory:
|
|
204
450
|
|
|
205
|
-
-
|
|
206
|
-
-
|
|
451
|
+
- REST (public + safe private endpoints)
|
|
452
|
+
- WebSocket v2 public streams
|
|
453
|
+
- WebSocket v2 private streams (balances, executions)
|
|
454
|
+
- Bulk historical data (OHLCVT + Trades): download, extract, list pairs/intervals, query
|
|
207
455
|
|
|
208
|
-
|
|
456
|
+
Bulk examples live under:
|
|
209
457
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// publicUrl: "wss://ws.kraken.com/v2",
|
|
213
|
-
// privateUrl: "wss://ws-auth.kraken.com/v2",
|
|
458
|
+
- [./examples/bulk/ohlcvt](./examples/bulk/ohlcvt)
|
|
459
|
+
- [./examples/bulk/trades](./examples/bulk/trades)
|
|
214
460
|
|
|
215
|
-
|
|
461
|
+
A minimal bulk flow:
|
|
216
462
|
|
|
217
|
-
|
|
218
|
-
// reconnectDelayMs: 1_000,
|
|
219
|
-
// requestTimeoutMs: 10_000,
|
|
463
|
+
- Download (or manually place ZIPs) → Extract → Query
|
|
220
464
|
|
|
221
|
-
|
|
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
|
-
```
|
|
239
|
-
|
|
240
|
-
---
|
|
241
|
-
|
|
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`
|
|
270
|
-
|
|
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
|
|
465
|
+
Examples are designed to be:
|
|
292
466
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
```ts
|
|
298
|
-
ws.privateConnection.addMessageHandler((msg) => {
|
|
299
|
-
if (msg?.channel === 'balances') {
|
|
300
|
-
console.log(msg.data);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
```
|
|
467
|
+
- Runnable
|
|
468
|
+
- Safe by default
|
|
469
|
+
- Self-contained
|
|
470
|
+
- Easy to copy into your own project
|
|
304
471
|
|
|
305
472
|
---
|
|
306
473
|
|
|
307
|
-
##
|
|
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:
|
|
474
|
+
## Design Philosophy
|
|
333
475
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
476
|
+
- Explicit APIs over magic
|
|
477
|
+
- Strong typing without sacrificing usability
|
|
478
|
+
- Clear separation of REST vs WebSocket concerns
|
|
479
|
+
- No hidden background workers
|
|
480
|
+
- Safe defaults, especially for trading operations
|
|
337
481
|
|
|
338
482
|
---
|
|
339
483
|
|