@siebly/kraken-api 0.0.9
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/LICENSE.md +7 -0
- package/README.md +624 -0
- package/dist/cjs/DerivativesClient.d.ts +657 -0
- package/dist/cjs/DerivativesClient.js +726 -0
- package/dist/cjs/DerivativesClient.js.map +1 -0
- package/dist/cjs/InstitutionalClient.d.ts +183 -0
- package/dist/cjs/InstitutionalClient.js +266 -0
- package/dist/cjs/InstitutionalClient.js.map +1 -0
- package/dist/cjs/PartnerClient.d.ts +257 -0
- package/dist/cjs/PartnerClient.js +344 -0
- package/dist/cjs/PartnerClient.js.map +1 -0
- package/dist/cjs/SpotClient.d.ts +547 -0
- package/dist/cjs/SpotClient.js +607 -0
- package/dist/cjs/SpotClient.js.map +1 -0
- package/dist/cjs/WebsocketAPIClient.d.ts +95 -0
- package/dist/cjs/WebsocketAPIClient.js +136 -0
- package/dist/cjs/WebsocketAPIClient.js.map +1 -0
- package/dist/cjs/WebsocketClient.d.ts +120 -0
- package/dist/cjs/WebsocketClient.js +669 -0
- package/dist/cjs/WebsocketClient.js.map +1 -0
- package/dist/cjs/index.d.ts +24 -0
- package/dist/cjs/index.js +41 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/BaseRestClient.d.ts +66 -0
- package/dist/cjs/lib/BaseRestClient.js +548 -0
- package/dist/cjs/lib/BaseRestClient.js.map +1 -0
- package/dist/cjs/lib/BaseWSClient.d.ts +230 -0
- package/dist/cjs/lib/BaseWSClient.js +935 -0
- package/dist/cjs/lib/BaseWSClient.js.map +1 -0
- package/dist/cjs/lib/misc-util.d.ts +1 -0
- package/dist/cjs/lib/misc-util.js +7 -0
- package/dist/cjs/lib/misc-util.js.map +1 -0
- package/dist/cjs/lib/requestUtils.d.ts +68 -0
- package/dist/cjs/lib/requestUtils.js +82 -0
- package/dist/cjs/lib/requestUtils.js.map +1 -0
- package/dist/cjs/lib/webCryptoAPI.d.ts +15 -0
- package/dist/cjs/lib/webCryptoAPI.js +85 -0
- package/dist/cjs/lib/webCryptoAPI.js.map +1 -0
- package/dist/cjs/lib/websocket/WsStore.d.ts +75 -0
- package/dist/cjs/lib/websocket/WsStore.js +303 -0
- package/dist/cjs/lib/websocket/WsStore.js.map +1 -0
- package/dist/cjs/lib/websocket/WsStore.types.d.ts +51 -0
- package/dist/cjs/lib/websocket/WsStore.types.js +14 -0
- package/dist/cjs/lib/websocket/WsStore.types.js.map +1 -0
- package/dist/cjs/lib/websocket/logger.d.ts +7 -0
- package/dist/cjs/lib/websocket/logger.js +16 -0
- package/dist/cjs/lib/websocket/logger.js.map +1 -0
- package/dist/cjs/lib/websocket/rest-client-cache.d.ts +22 -0
- package/dist/cjs/lib/websocket/rest-client-cache.js +66 -0
- package/dist/cjs/lib/websocket/rest-client-cache.js.map +1 -0
- package/dist/cjs/lib/websocket/websocket-util.d.ts +76 -0
- package/dist/cjs/lib/websocket/websocket-util.js +59 -0
- package/dist/cjs/lib/websocket/websocket-util.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types/request/derivatives.types.d.ts +186 -0
- package/dist/cjs/types/request/derivatives.types.js +6 -0
- package/dist/cjs/types/request/derivatives.types.js.map +1 -0
- package/dist/cjs/types/request/institutional.types.d.ts +313 -0
- package/dist/cjs/types/request/institutional.types.js +4 -0
- package/dist/cjs/types/request/institutional.types.js.map +1 -0
- package/dist/cjs/types/request/partner.types.d.ts +291 -0
- package/dist/cjs/types/request/partner.types.js +4 -0
- package/dist/cjs/types/request/partner.types.js.map +1 -0
- package/dist/cjs/types/request/spot.types.d.ts +324 -0
- package/dist/cjs/types/request/spot.types.js +6 -0
- package/dist/cjs/types/request/spot.types.js.map +1 -0
- package/dist/cjs/types/request/wsapi.types.d.ts +90 -0
- package/dist/cjs/types/request/wsapi.types.js +6 -0
- package/dist/cjs/types/request/wsapi.types.js.map +1 -0
- package/dist/cjs/types/response/derivatives.types.d.ts +712 -0
- package/dist/cjs/types/response/derivatives.types.js +6 -0
- package/dist/cjs/types/response/derivatives.types.js.map +1 -0
- package/dist/cjs/types/response/institutional.types.d.ts +318 -0
- package/dist/cjs/types/response/institutional.types.js +4 -0
- package/dist/cjs/types/response/institutional.types.js.map +1 -0
- package/dist/cjs/types/response/partner.types.d.ts +332 -0
- package/dist/cjs/types/response/partner.types.js +4 -0
- package/dist/cjs/types/response/partner.types.js.map +1 -0
- package/dist/cjs/types/response/shared.types.d.ts +27 -0
- package/dist/cjs/types/response/shared.types.js +3 -0
- package/dist/cjs/types/response/shared.types.js.map +1 -0
- package/dist/cjs/types/response/spot.types.d.ts +590 -0
- package/dist/cjs/types/response/spot.types.js +6 -0
- package/dist/cjs/types/response/spot.types.js.map +1 -0
- package/dist/cjs/types/response/ws.d.ts +11 -0
- package/dist/cjs/types/response/ws.js +3 -0
- package/dist/cjs/types/response/ws.js.map +1 -0
- package/dist/cjs/types/response/wsapi.types.d.ts +44 -0
- package/dist/cjs/types/response/wsapi.types.js +6 -0
- package/dist/cjs/types/response/wsapi.types.js.map +1 -0
- package/dist/cjs/types/websockets/ws-api.d.ts +71 -0
- package/dist/cjs/types/websockets/ws-api.js +18 -0
- package/dist/cjs/types/websockets/ws-api.js.map +1 -0
- package/dist/cjs/types/websockets/ws-events.d.ts +11 -0
- package/dist/cjs/types/websockets/ws-events.js +11 -0
- package/dist/cjs/types/websockets/ws-events.js.map +1 -0
- package/dist/cjs/types/websockets/ws-general.d.ts +67 -0
- package/dist/cjs/types/websockets/ws-general.js +3 -0
- package/dist/cjs/types/websockets/ws-general.js.map +1 -0
- package/dist/cjs/types/websockets/ws-subscriptions.d.ts +11 -0
- package/dist/cjs/types/websockets/ws-subscriptions.js +31 -0
- package/dist/cjs/types/websockets/ws-subscriptions.js.map +1 -0
- package/dist/mjs/DerivativesClient.d.ts +657 -0
- package/dist/mjs/DerivativesClient.js +722 -0
- package/dist/mjs/DerivativesClient.js.map +1 -0
- package/dist/mjs/InstitutionalClient.d.ts +183 -0
- package/dist/mjs/InstitutionalClient.js +262 -0
- package/dist/mjs/InstitutionalClient.js.map +1 -0
- package/dist/mjs/PartnerClient.d.ts +257 -0
- package/dist/mjs/PartnerClient.js +340 -0
- package/dist/mjs/PartnerClient.js.map +1 -0
- package/dist/mjs/SpotClient.d.ts +547 -0
- package/dist/mjs/SpotClient.js +603 -0
- package/dist/mjs/SpotClient.js.map +1 -0
- package/dist/mjs/WebsocketAPIClient.d.ts +95 -0
- package/dist/mjs/WebsocketAPIClient.js +132 -0
- package/dist/mjs/WebsocketAPIClient.js.map +1 -0
- package/dist/mjs/WebsocketClient.d.ts +120 -0
- package/dist/mjs/WebsocketClient.js +665 -0
- package/dist/mjs/WebsocketClient.js.map +1 -0
- package/dist/mjs/index.d.ts +24 -0
- package/dist/mjs/index.js +25 -0
- package/dist/mjs/index.js.map +1 -0
- package/dist/mjs/lib/BaseRestClient.d.ts +66 -0
- package/dist/mjs/lib/BaseRestClient.js +541 -0
- package/dist/mjs/lib/BaseRestClient.js.map +1 -0
- package/dist/mjs/lib/BaseWSClient.d.ts +230 -0
- package/dist/mjs/lib/BaseWSClient.js +928 -0
- package/dist/mjs/lib/BaseWSClient.js.map +1 -0
- package/dist/mjs/lib/misc-util.d.ts +1 -0
- package/dist/mjs/lib/misc-util.js +4 -0
- package/dist/mjs/lib/misc-util.js.map +1 -0
- package/dist/mjs/lib/requestUtils.d.ts +68 -0
- package/dist/mjs/lib/requestUtils.js +76 -0
- package/dist/mjs/lib/requestUtils.js.map +1 -0
- package/dist/mjs/lib/webCryptoAPI.d.ts +15 -0
- package/dist/mjs/lib/webCryptoAPI.js +80 -0
- package/dist/mjs/lib/webCryptoAPI.js.map +1 -0
- package/dist/mjs/lib/websocket/WsStore.d.ts +75 -0
- package/dist/mjs/lib/websocket/WsStore.js +298 -0
- package/dist/mjs/lib/websocket/WsStore.js.map +1 -0
- package/dist/mjs/lib/websocket/WsStore.types.d.ts +51 -0
- package/dist/mjs/lib/websocket/WsStore.types.js +11 -0
- package/dist/mjs/lib/websocket/WsStore.types.js.map +1 -0
- package/dist/mjs/lib/websocket/logger.d.ts +7 -0
- package/dist/mjs/lib/websocket/logger.js +13 -0
- package/dist/mjs/lib/websocket/logger.js.map +1 -0
- package/dist/mjs/lib/websocket/rest-client-cache.d.ts +22 -0
- package/dist/mjs/lib/websocket/rest-client-cache.js +62 -0
- package/dist/mjs/lib/websocket/rest-client-cache.js.map +1 -0
- package/dist/mjs/lib/websocket/websocket-util.d.ts +76 -0
- package/dist/mjs/lib/websocket/websocket-util.js +54 -0
- package/dist/mjs/lib/websocket/websocket-util.js.map +1 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/types/request/derivatives.types.d.ts +186 -0
- package/dist/mjs/types/request/derivatives.types.js +5 -0
- package/dist/mjs/types/request/derivatives.types.js.map +1 -0
- package/dist/mjs/types/request/institutional.types.d.ts +313 -0
- package/dist/mjs/types/request/institutional.types.js +3 -0
- package/dist/mjs/types/request/institutional.types.js.map +1 -0
- package/dist/mjs/types/request/partner.types.d.ts +291 -0
- package/dist/mjs/types/request/partner.types.js +3 -0
- package/dist/mjs/types/request/partner.types.js.map +1 -0
- package/dist/mjs/types/request/spot.types.d.ts +324 -0
- package/dist/mjs/types/request/spot.types.js +5 -0
- package/dist/mjs/types/request/spot.types.js.map +1 -0
- package/dist/mjs/types/request/wsapi.types.d.ts +90 -0
- package/dist/mjs/types/request/wsapi.types.js +5 -0
- package/dist/mjs/types/request/wsapi.types.js.map +1 -0
- package/dist/mjs/types/response/derivatives.types.d.ts +712 -0
- package/dist/mjs/types/response/derivatives.types.js +5 -0
- package/dist/mjs/types/response/derivatives.types.js.map +1 -0
- package/dist/mjs/types/response/institutional.types.d.ts +318 -0
- package/dist/mjs/types/response/institutional.types.js +3 -0
- package/dist/mjs/types/response/institutional.types.js.map +1 -0
- package/dist/mjs/types/response/partner.types.d.ts +332 -0
- package/dist/mjs/types/response/partner.types.js +3 -0
- package/dist/mjs/types/response/partner.types.js.map +1 -0
- package/dist/mjs/types/response/shared.types.d.ts +27 -0
- package/dist/mjs/types/response/shared.types.js +2 -0
- package/dist/mjs/types/response/shared.types.js.map +1 -0
- package/dist/mjs/types/response/spot.types.d.ts +590 -0
- package/dist/mjs/types/response/spot.types.js +5 -0
- package/dist/mjs/types/response/spot.types.js.map +1 -0
- package/dist/mjs/types/response/ws.d.ts +11 -0
- package/dist/mjs/types/response/ws.js +2 -0
- package/dist/mjs/types/response/ws.js.map +1 -0
- package/dist/mjs/types/response/wsapi.types.d.ts +44 -0
- package/dist/mjs/types/response/wsapi.types.js +5 -0
- package/dist/mjs/types/response/wsapi.types.js.map +1 -0
- package/dist/mjs/types/websockets/ws-api.d.ts +71 -0
- package/dist/mjs/types/websockets/ws-api.js +15 -0
- package/dist/mjs/types/websockets/ws-api.js.map +1 -0
- package/dist/mjs/types/websockets/ws-events.d.ts +11 -0
- package/dist/mjs/types/websockets/ws-events.js +8 -0
- package/dist/mjs/types/websockets/ws-events.js.map +1 -0
- package/dist/mjs/types/websockets/ws-general.d.ts +67 -0
- package/dist/mjs/types/websockets/ws-general.js +2 -0
- package/dist/mjs/types/websockets/ws-general.js.map +1 -0
- package/dist/mjs/types/websockets/ws-subscriptions.d.ts +11 -0
- package/dist/mjs/types/websockets/ws-subscriptions.js +28 -0
- package/dist/mjs/types/websockets/ws-subscriptions.js.map +1 -0
- package/llms.txt +10925 -0
- package/package.json +89 -0
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebsocketClient = void 0;
|
|
4
|
+
const BaseWSClient_js_1 = require("./lib/BaseWSClient.js");
|
|
5
|
+
const misc_util_js_1 = require("./lib/misc-util.js");
|
|
6
|
+
const webCryptoAPI_js_1 = require("./lib/webCryptoAPI.js");
|
|
7
|
+
const rest_client_cache_js_1 = require("./lib/websocket/rest-client-cache.js");
|
|
8
|
+
const websocket_util_js_1 = require("./lib/websocket/websocket-util.js");
|
|
9
|
+
const ws_api_js_1 = require("./types/websockets/ws-api.js");
|
|
10
|
+
const ws_subscriptions_js_1 = require("./types/websockets/ws-subscriptions.js");
|
|
11
|
+
const WS_LOGGER_CATEGORY_ID = 'kraken-ws';
|
|
12
|
+
const WS_LOGGER_CATEGORY = {
|
|
13
|
+
category: WS_LOGGER_CATEGORY_ID,
|
|
14
|
+
};
|
|
15
|
+
class WebsocketClient extends BaseWSClient_js_1.BaseWebsocketClient {
|
|
16
|
+
restClientCache = new rest_client_cache_js_1.RestClientCache();
|
|
17
|
+
wsChallengeCache = new Map();
|
|
18
|
+
constructor(options, logger) {
|
|
19
|
+
super({ ...options, wsLoggerCategory: WS_LOGGER_CATEGORY_ID }, logger);
|
|
20
|
+
this.restClientCache.setLogger(this.logger, WS_LOGGER_CATEGORY);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library.
|
|
24
|
+
*
|
|
25
|
+
* Returns array of promises that individually resolve when each connection is successfully opened.
|
|
26
|
+
*/
|
|
27
|
+
connectAll() {
|
|
28
|
+
return [this.connect(websocket_util_js_1.WS_KEY_MAP.spotPrivateV2)];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ensures the WS API connection is active and ready.
|
|
32
|
+
*
|
|
33
|
+
* You do not need to call this, but if you call this before making any WS API requests,
|
|
34
|
+
* it can accelerate the first request (by preparing the connection in advance).
|
|
35
|
+
*/
|
|
36
|
+
connectWSAPI(wsKey, skipAuth) {
|
|
37
|
+
if (skipAuth) {
|
|
38
|
+
return this.assertIsConnected(wsKey);
|
|
39
|
+
}
|
|
40
|
+
/** This call automatically ensures the connection is active AND authenticated before resolving */
|
|
41
|
+
return this.assertIsAuthenticated(wsKey);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Request subscription to one or more topics. Pass topics as either an array of strings, or array of objects (if the topic has parameters).
|
|
45
|
+
* Objects should be formatted as {topic: string, params: object}.
|
|
46
|
+
*
|
|
47
|
+
* - Subscriptions are automatically routed to the correct websocket connection.
|
|
48
|
+
* - Authentication/connection is automatic.
|
|
49
|
+
* - Resubscribe after network issues is automatic.
|
|
50
|
+
*
|
|
51
|
+
* Call `unsubscribe(topics)` to remove topics
|
|
52
|
+
*/
|
|
53
|
+
subscribe(requests, wsKey) {
|
|
54
|
+
if (!Array.isArray(requests)) {
|
|
55
|
+
this.subscribeTopicsForWsKey([requests], wsKey);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (requests.length) {
|
|
59
|
+
this.subscribeTopicsForWsKey(requests, wsKey);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Unsubscribe from one or more topics. Similar to subscribe() but in reverse.
|
|
64
|
+
*
|
|
65
|
+
* - Requests are automatically routed to the correct websocket connection.
|
|
66
|
+
* - These topics will be removed from the topic cache, so they won't be subscribed to again.
|
|
67
|
+
*/
|
|
68
|
+
unsubscribe(requests, wsKey) {
|
|
69
|
+
if (!Array.isArray(requests)) {
|
|
70
|
+
this.unsubscribeTopicsForWsKey([requests], wsKey);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (requests.length) {
|
|
74
|
+
this.unsubscribeTopicsForWsKey(requests, wsKey);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async sendWSAPIRequest(wsKey, operation, params, requestFlags) {
|
|
78
|
+
/**
|
|
79
|
+
* Base Info:
|
|
80
|
+
* - https://docs.kraken.com/api/docs/websocket-v2/add_order
|
|
81
|
+
*
|
|
82
|
+
* Currently only supported for Spot markets
|
|
83
|
+
*/
|
|
84
|
+
this.logger.trace(`sendWSAPIRequest(): assert "${wsKey}" is connected`, {
|
|
85
|
+
...WS_LOGGER_CATEGORY,
|
|
86
|
+
});
|
|
87
|
+
await this.assertIsConnected(wsKey);
|
|
88
|
+
// Some commands don't require authentication.
|
|
89
|
+
if (requestFlags?.authIsOptional !== true) {
|
|
90
|
+
this.logger.trace('sendWSAPIRequest(): assertIsAuthenticated(${wsKey})...');
|
|
91
|
+
await this.assertIsAuthenticated(wsKey);
|
|
92
|
+
this.logger.trace('sendWSAPIRequest(): assertIsAuthenticated(${wsKey}) ok');
|
|
93
|
+
}
|
|
94
|
+
const requestEvent = {
|
|
95
|
+
method: operation,
|
|
96
|
+
params: params,
|
|
97
|
+
req_id: this.getNewRequestId(),
|
|
98
|
+
};
|
|
99
|
+
// Sign request
|
|
100
|
+
const signedEvent = await this.signWSAPIRequest(requestEvent);
|
|
101
|
+
// Store deferred promise
|
|
102
|
+
const promiseRef = (0, websocket_util_js_1.getPromiseRefForWSAPIRequest)(wsKey, requestEvent);
|
|
103
|
+
const deferredPromise = this.getWsStore().createDeferredPromise(wsKey, promiseRef, false);
|
|
104
|
+
// Enrich returned promise with request context for easier debugging
|
|
105
|
+
deferredPromise.promise
|
|
106
|
+
?.then((res) => {
|
|
107
|
+
if (!Array.isArray(res)) {
|
|
108
|
+
res.request = {
|
|
109
|
+
wsKey: wsKey,
|
|
110
|
+
...signedEvent,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return res;
|
|
114
|
+
})
|
|
115
|
+
.catch((e) => {
|
|
116
|
+
if (typeof e === 'string') {
|
|
117
|
+
this.logger.error('unexpcted string', { e });
|
|
118
|
+
return e;
|
|
119
|
+
}
|
|
120
|
+
e.request = {
|
|
121
|
+
wsKey: wsKey,
|
|
122
|
+
operation,
|
|
123
|
+
payload: signedEvent.params,
|
|
124
|
+
};
|
|
125
|
+
return e;
|
|
126
|
+
});
|
|
127
|
+
// Send event
|
|
128
|
+
const throwExceptions = true;
|
|
129
|
+
this.tryWsSend(wsKey, JSON.stringify(signedEvent), throwExceptions);
|
|
130
|
+
this.logger.trace(`sendWSAPIRequest(): sent "${operation}" event with promiseRef(${promiseRef})`, signedEvent);
|
|
131
|
+
// Return deferred promise, so caller can await this call
|
|
132
|
+
return deferredPromise.promise;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* Internal methods - not intended for public use
|
|
137
|
+
*
|
|
138
|
+
*/
|
|
139
|
+
getRestClientOptions() {
|
|
140
|
+
return {
|
|
141
|
+
...this.options,
|
|
142
|
+
...this.options.restOptions,
|
|
143
|
+
apiKey: this.options.apiKey,
|
|
144
|
+
apiSecret: this.options.apiSecret,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Note: implementing this method will wipe the WsStore state for this WsKey, once this method returns
|
|
149
|
+
*/
|
|
150
|
+
isCustomReconnectionNeeded() {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
async triggerCustomReconnectionWorkflow() {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
async getWsUrl(wsKey) {
|
|
157
|
+
if (this.options.wsUrl) {
|
|
158
|
+
return this.options.wsUrl;
|
|
159
|
+
}
|
|
160
|
+
switch (wsKey) {
|
|
161
|
+
/**
|
|
162
|
+
* https://docs.kraken.com/api/docs/guides/spot-ws-intro/
|
|
163
|
+
*
|
|
164
|
+
* Note: Kraken's v2 WebSockets clean up a number idiosyncrasies and ambiguities from v1 with the overall aim to enable easier integration with applications. It is intended that v1 will be maintained but future enhancements will be developed in v2.
|
|
165
|
+
*
|
|
166
|
+
* Given the above, we are only integrating with V2 for now.
|
|
167
|
+
*
|
|
168
|
+
* V2 SpotWebSocket Reference: https://docs.kraken.com/api/docs/websocket-v2/add_order/
|
|
169
|
+
*/
|
|
170
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPublicV2: {
|
|
171
|
+
return 'wss://ws.kraken.com/v2';
|
|
172
|
+
}
|
|
173
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPrivateV2: {
|
|
174
|
+
return 'wss://ws-auth.kraken.com/v2';
|
|
175
|
+
}
|
|
176
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPublicV2: {
|
|
177
|
+
return 'wss://beta-ws.kraken.com/v2';
|
|
178
|
+
}
|
|
179
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2: {
|
|
180
|
+
return 'wss://beta-ws-auth.kraken.com/v2';
|
|
181
|
+
}
|
|
182
|
+
// Uses the same URL, but we maintain separate connections for easier management
|
|
183
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPublicV1:
|
|
184
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1: {
|
|
185
|
+
if (this.options.testnet) {
|
|
186
|
+
return 'wss://demo-futures.kraken.com/ws/v1';
|
|
187
|
+
}
|
|
188
|
+
return 'wss://futures.kraken.com/ws/v1';
|
|
189
|
+
}
|
|
190
|
+
default: {
|
|
191
|
+
throw (0, misc_util_js_1.neverGuard)(wsKey, `Unhandled WsKey "${wsKey}"`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
sendPingEvent(wsKey) {
|
|
196
|
+
// let pingChannel: WsRequestPing['channel'];
|
|
197
|
+
switch (wsKey) {
|
|
198
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPublicV1:
|
|
199
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1: {
|
|
200
|
+
const ws = this.getWsStore().get(wsKey)?.ws;
|
|
201
|
+
if (ws) {
|
|
202
|
+
ws.ping();
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPublicV2:
|
|
207
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPrivateV2:
|
|
208
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPublicV2:
|
|
209
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2: {
|
|
210
|
+
// Spot: https://docs.kraken.com/api/docs/websocket-v2/ping
|
|
211
|
+
return this.tryWsSend(wsKey, `{ "method": "ping", "req_id": ${this.getNewRequestId()} }`);
|
|
212
|
+
}
|
|
213
|
+
default: {
|
|
214
|
+
throw (0, misc_util_js_1.neverGuard)(wsKey, `Unhandled WsKey "${wsKey}"`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
sendPongEvent(wsKey) {
|
|
219
|
+
try {
|
|
220
|
+
this.logger.trace('Sending upstream ws PONGFRAME: ', {
|
|
221
|
+
...WS_LOGGER_CATEGORY,
|
|
222
|
+
wsMessage: 'PONGFRAME',
|
|
223
|
+
wsKey,
|
|
224
|
+
});
|
|
225
|
+
if (!wsKey) {
|
|
226
|
+
throw new Error('Cannot send PONGFRAME, no wsKey provided');
|
|
227
|
+
}
|
|
228
|
+
const wsState = this.getWsStore().get(wsKey);
|
|
229
|
+
if (!wsState || !wsState?.ws) {
|
|
230
|
+
throw new Error(`Cannot send PONGFRAME, ${wsKey} socket not connected yet`);
|
|
231
|
+
}
|
|
232
|
+
// Send a protocol layer pong
|
|
233
|
+
wsState.ws.pong();
|
|
234
|
+
}
|
|
235
|
+
catch (e) {
|
|
236
|
+
this.logger.error('Failed to send WS PONG', {
|
|
237
|
+
...WS_LOGGER_CATEGORY,
|
|
238
|
+
wsMessage: 'PONGFRAME',
|
|
239
|
+
wsKey,
|
|
240
|
+
exception: e,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// NOT IN USE for kraken
|
|
245
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
246
|
+
isWsPing(_msg) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
isWsPong(msg) {
|
|
250
|
+
// Pre-parsed in resolveEmittableEvents into "pong" eventType:
|
|
251
|
+
if (msg?.eventType) {
|
|
252
|
+
if (msg?.eventType === 'pong') {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Parse incoming events into categories, before emitting to the user
|
|
260
|
+
*/
|
|
261
|
+
resolveEmittableEvents(wsKey, event) {
|
|
262
|
+
const results = [];
|
|
263
|
+
try {
|
|
264
|
+
const parsed = JSON.parse(event.data);
|
|
265
|
+
// derivatives sends 'challenge' on successful auth-init (used for sign during subscribe)
|
|
266
|
+
const responseEvents = [
|
|
267
|
+
// spot confirmation for subscription success
|
|
268
|
+
'subscribe',
|
|
269
|
+
'unsubscribe',
|
|
270
|
+
'info',
|
|
271
|
+
// derivatives confirmation for subscription success
|
|
272
|
+
'subscribed',
|
|
273
|
+
'unsubscribed',
|
|
274
|
+
];
|
|
275
|
+
const authenticatedEvents = ['challenge'];
|
|
276
|
+
const derivativesEventAction = parsed.event || parsed.feed;
|
|
277
|
+
const spotEventAction = parsed.method ||
|
|
278
|
+
parsed.type ||
|
|
279
|
+
parsed.event ||
|
|
280
|
+
parsed?.header?.data ||
|
|
281
|
+
parsed.channel;
|
|
282
|
+
const eventAction = spotEventAction || derivativesEventAction;
|
|
283
|
+
const promiseRef = [wsKey, eventAction, parsed?.req_id].join('_');
|
|
284
|
+
// WS API
|
|
285
|
+
if (ws_api_js_1.WS_API_Operations.includes(eventAction)) {
|
|
286
|
+
const isError = parsed.success !== true;
|
|
287
|
+
// WS API Exception
|
|
288
|
+
if (isError) {
|
|
289
|
+
try {
|
|
290
|
+
this.getWsStore().rejectDeferredPromise(wsKey, promiseRef, {
|
|
291
|
+
wsKey,
|
|
292
|
+
...parsed,
|
|
293
|
+
}, true);
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
this.logger.error('Exception trying to reject WSAPI promise', {
|
|
297
|
+
wsKey,
|
|
298
|
+
promiseRef,
|
|
299
|
+
parsedEvent: parsed,
|
|
300
|
+
error: e,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
results.push({
|
|
304
|
+
eventType: 'exception',
|
|
305
|
+
event: parsed,
|
|
306
|
+
isWSAPIResponse: true,
|
|
307
|
+
});
|
|
308
|
+
return results;
|
|
309
|
+
}
|
|
310
|
+
// WS API Success
|
|
311
|
+
try {
|
|
312
|
+
this.getWsStore().resolveDeferredPromise(wsKey, promiseRef, {
|
|
313
|
+
wsKey,
|
|
314
|
+
...parsed,
|
|
315
|
+
}, true);
|
|
316
|
+
}
|
|
317
|
+
catch (e) {
|
|
318
|
+
this.logger.error('Exception trying to resolve WSAPI promise', {
|
|
319
|
+
wsKey,
|
|
320
|
+
promiseRef,
|
|
321
|
+
parsedEvent: parsed,
|
|
322
|
+
error: e,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
results.push({
|
|
326
|
+
eventType: 'response',
|
|
327
|
+
event: parsed,
|
|
328
|
+
isWSAPIResponse: true,
|
|
329
|
+
});
|
|
330
|
+
return results;
|
|
331
|
+
} // end of WS API response processing
|
|
332
|
+
if (typeof eventAction === 'string') {
|
|
333
|
+
if (parsed.success === false) {
|
|
334
|
+
results.push({
|
|
335
|
+
eventType: 'exception',
|
|
336
|
+
event: parsed,
|
|
337
|
+
});
|
|
338
|
+
return results;
|
|
339
|
+
}
|
|
340
|
+
// exceptions with derivatives v1 WS. E.g. { event: 'alert', message: 'Bad websocket message' }
|
|
341
|
+
if (eventAction === 'alert') {
|
|
342
|
+
results.push({
|
|
343
|
+
eventType: 'exception',
|
|
344
|
+
event: parsed,
|
|
345
|
+
});
|
|
346
|
+
return results;
|
|
347
|
+
}
|
|
348
|
+
// Most events use event: "update" or "snapshot" for topic updates
|
|
349
|
+
if (['update', 'snapshot'].includes(eventAction)) {
|
|
350
|
+
results.push({
|
|
351
|
+
eventType: 'message',
|
|
352
|
+
event: parsed,
|
|
353
|
+
});
|
|
354
|
+
return results;
|
|
355
|
+
}
|
|
356
|
+
// These are request/reply pattern events (e.g. after subscribing to topics or authenticating)
|
|
357
|
+
// e.g. "method":"subscribe"
|
|
358
|
+
if (responseEvents.includes(eventAction)) {
|
|
359
|
+
results.push({
|
|
360
|
+
eventType: 'response',
|
|
361
|
+
event: parsed,
|
|
362
|
+
});
|
|
363
|
+
return results;
|
|
364
|
+
}
|
|
365
|
+
// derivatives events include the "feed" property to identify the channel name
|
|
366
|
+
if (typeof parsed.feed === 'string') {
|
|
367
|
+
results.push({
|
|
368
|
+
eventType: 'message',
|
|
369
|
+
event: parsed,
|
|
370
|
+
});
|
|
371
|
+
return results;
|
|
372
|
+
}
|
|
373
|
+
// Request/reply pattern for authentication success
|
|
374
|
+
if (authenticatedEvents.includes(eventAction)) {
|
|
375
|
+
if (wsKey === websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1) {
|
|
376
|
+
const challenge = parsed.message;
|
|
377
|
+
if (challenge) {
|
|
378
|
+
this.logger.trace(`Stored challenge for derivatives auth on wsKey "${wsKey}": "${challenge}"`);
|
|
379
|
+
this.wsChallengeCache.set(wsKey, challenge);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
results.push({
|
|
383
|
+
eventType: 'authenticated',
|
|
384
|
+
event: parsed,
|
|
385
|
+
});
|
|
386
|
+
return results;
|
|
387
|
+
}
|
|
388
|
+
if (eventAction === 'heartbeat' || eventAction === 'pong') {
|
|
389
|
+
results.push({
|
|
390
|
+
eventType: 'pong',
|
|
391
|
+
event: parsed,
|
|
392
|
+
});
|
|
393
|
+
return results;
|
|
394
|
+
}
|
|
395
|
+
this.logger.error(`!! Unhandled string "eventAction" "${eventAction}". Defaulting to "message" channel... Parsed:`, parsed);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
this.logger.error(`!! Unhandled non-string "eventAction" "${eventAction}". Defaulting to "message" channel... Parsed:`, parsed);
|
|
399
|
+
}
|
|
400
|
+
results.push({
|
|
401
|
+
eventType: 'message',
|
|
402
|
+
event: parsed,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
catch (e) {
|
|
406
|
+
results.push({
|
|
407
|
+
event: {
|
|
408
|
+
message: 'Failed to parse event data due to exception',
|
|
409
|
+
exception: e,
|
|
410
|
+
eventData: event.data,
|
|
411
|
+
},
|
|
412
|
+
eventType: 'exception',
|
|
413
|
+
});
|
|
414
|
+
this.logger.error('Failed to parse event data due to exception: ', {
|
|
415
|
+
exception: e,
|
|
416
|
+
eventData: event.data,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
return results;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Determines if a topic is for a private channel, using a hardcoded list of strings
|
|
423
|
+
*/
|
|
424
|
+
isPrivateTopicRequest(request) {
|
|
425
|
+
const topicName = request?.topic?.toLowerCase();
|
|
426
|
+
if (!topicName) {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
if (ws_subscriptions_js_1.WS_SPOT_PRIVATE_TOPICS.includes(topicName)) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
if (ws_subscriptions_js_1.WS_DERIVATIVES_PRIVATE_TOPICS.includes(topicName)) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Not in use for Kraken
|
|
439
|
+
*/
|
|
440
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
441
|
+
getWsMarketForWsKey(_wsKey) {
|
|
442
|
+
return 'futures';
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Whether key represents a private connection. Feeds into automatic auth on connect.
|
|
446
|
+
*/
|
|
447
|
+
getPrivateWSKeys() {
|
|
448
|
+
return [
|
|
449
|
+
websocket_util_js_1.WS_KEY_MAP.spotPrivateV2,
|
|
450
|
+
websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2,
|
|
451
|
+
websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1,
|
|
452
|
+
];
|
|
453
|
+
}
|
|
454
|
+
isAuthOnConnectWsKey(wsKey) {
|
|
455
|
+
return this.getPrivateWSKeys().includes(wsKey);
|
|
456
|
+
}
|
|
457
|
+
/** Force subscription requests to be sent in smaller batches, if a number is returned */
|
|
458
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
459
|
+
getMaxTopicsPerSubscribeEvent(_wsKey) {
|
|
460
|
+
return 1;
|
|
461
|
+
}
|
|
462
|
+
authPrivateConnectionsOnConnect(wsKey) {
|
|
463
|
+
// derivatives require you to send a challenge on connect
|
|
464
|
+
if (wsKey === websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1) {
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
return this.options.authPrivateConnectionsOnConnect;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* @returns one or more correctly structured request events for performing a operations over WS. This can vary per exchange spec.
|
|
471
|
+
*/
|
|
472
|
+
async getWsRequestEvents(wsKey, operation, requests) {
|
|
473
|
+
const wsRequestEvents = [];
|
|
474
|
+
const wsRequestBuildingErrors = [];
|
|
475
|
+
// Previously used to track topics in a request. Keeping this for subscribe/unsubscribe requests, no need for incremental values
|
|
476
|
+
for (const topicRequest of requests) {
|
|
477
|
+
const req_id = this.getNewRequestId();
|
|
478
|
+
switch (wsKey) {
|
|
479
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPublicV2:
|
|
480
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPrivateV2:
|
|
481
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPublicV2:
|
|
482
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2: {
|
|
483
|
+
const wsEvent = {
|
|
484
|
+
method: operation,
|
|
485
|
+
params: {
|
|
486
|
+
channel: topicRequest.topic,
|
|
487
|
+
...topicRequest.payload,
|
|
488
|
+
},
|
|
489
|
+
req_id: req_id,
|
|
490
|
+
};
|
|
491
|
+
if (this.options.authPrivateRequests &&
|
|
492
|
+
(wsKey === websocket_util_js_1.WS_KEY_MAP.spotPrivateV2 ||
|
|
493
|
+
wsKey === websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2)) {
|
|
494
|
+
// Get token from REST client cache
|
|
495
|
+
const tokenResult = await this.restClientCache.fetchSpotWebSocketToken(this.getRestClientOptions(), this.options.requestOptions);
|
|
496
|
+
if (!tokenResult?.token) {
|
|
497
|
+
wsRequestBuildingErrors.push(new Error(`No WS auth token could be retrieved for private spot WS request for topic "${topicRequest.topic}"`));
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
wsEvent.params.token = tokenResult.token;
|
|
501
|
+
}
|
|
502
|
+
// Cache midflight subs on the req ID
|
|
503
|
+
// Enrich response with subs for that req ID
|
|
504
|
+
const midflightWsEvent = {
|
|
505
|
+
requestKey: wsEvent.req_id,
|
|
506
|
+
requestEvent: wsEvent,
|
|
507
|
+
};
|
|
508
|
+
wsRequestEvents.push({
|
|
509
|
+
...midflightWsEvent,
|
|
510
|
+
});
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
// No auth needed, it's public topics only here
|
|
514
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPublicV1: {
|
|
515
|
+
const wsEvent = {
|
|
516
|
+
event: operation,
|
|
517
|
+
feed: topicRequest.topic,
|
|
518
|
+
...topicRequest.payload,
|
|
519
|
+
req_id: req_id,
|
|
520
|
+
};
|
|
521
|
+
// Cache midflight subs on the req ID
|
|
522
|
+
// Enrich response with subs for that req ID
|
|
523
|
+
const midflightWsEvent = {
|
|
524
|
+
requestKey: wsEvent.req_id,
|
|
525
|
+
requestEvent: wsEvent,
|
|
526
|
+
};
|
|
527
|
+
wsRequestEvents.push({
|
|
528
|
+
...midflightWsEvent,
|
|
529
|
+
});
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1: {
|
|
533
|
+
const wsEvent = {
|
|
534
|
+
event: operation,
|
|
535
|
+
feed: topicRequest.topic,
|
|
536
|
+
...topicRequest.payload,
|
|
537
|
+
req_id: req_id,
|
|
538
|
+
};
|
|
539
|
+
// https://docs.kraken.com/api/docs/guides/futures-websockets
|
|
540
|
+
// Authenticated requests must include both the original challenge message (original_challenge) and the signed (signed_challenge) in JSON format.
|
|
541
|
+
if (!this.wsChallengeCache.has(wsKey)) {
|
|
542
|
+
this.logger.trace(`No challenge key cached for wsKey ${wsKey}, asserting authentication...`, { ...WS_LOGGER_CATEGORY, wsKey });
|
|
543
|
+
await this.assertIsAuthenticated(wsKey);
|
|
544
|
+
}
|
|
545
|
+
const challengeKey = this.wsChallengeCache.get(wsKey);
|
|
546
|
+
if (!challengeKey) {
|
|
547
|
+
this.logger.error(`Auth-check passed but no challenge key could be retrieved from cache for wsKey ${wsKey}`, { ...WS_LOGGER_CATEGORY, wsKey });
|
|
548
|
+
throw new Error('No challenge key cached, cannot send authenticated request');
|
|
549
|
+
}
|
|
550
|
+
wsEvent.original_challenge = challengeKey;
|
|
551
|
+
wsEvent.api_key = this.options.apiKey;
|
|
552
|
+
const hashedChallenge = await (0, webCryptoAPI_js_1.hashMessage)(challengeKey, 'binary', 'SHA-256');
|
|
553
|
+
if (!this.options.apiSecret) {
|
|
554
|
+
throw new Error('API Secret missing, cannot sign challenge for authenticated WS request');
|
|
555
|
+
}
|
|
556
|
+
const challengeSign = await this.signMessage(hashedChallenge, this.options.apiSecret, 'base64', 'SHA-512', {
|
|
557
|
+
isSecretB64Encoded: true,
|
|
558
|
+
isInputBinaryString: true,
|
|
559
|
+
});
|
|
560
|
+
wsEvent.signed_challenge = challengeSign;
|
|
561
|
+
// Cache midflight subs on the req ID
|
|
562
|
+
// Enrich response with subs for that req ID
|
|
563
|
+
const midflightWsEvent = {
|
|
564
|
+
requestKey: wsEvent.req_id,
|
|
565
|
+
requestEvent: wsEvent,
|
|
566
|
+
};
|
|
567
|
+
wsRequestEvents.push({
|
|
568
|
+
...midflightWsEvent,
|
|
569
|
+
});
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
default: {
|
|
573
|
+
throw (0, misc_util_js_1.neverGuard)(wsKey, `Unhandled WsKey "${wsKey}"`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (wsRequestBuildingErrors.length) {
|
|
578
|
+
const label = wsRequestBuildingErrors.length === requests.length ? 'all' : 'some';
|
|
579
|
+
this.logger.error(`Failed to build/send ${wsRequestBuildingErrors.length} event(s) for ${label} WS requests due to exceptions`, {
|
|
580
|
+
...WS_LOGGER_CATEGORY,
|
|
581
|
+
wsRequestBuildingErrors,
|
|
582
|
+
wsRequestBuildingErrorsStringified: JSON.stringify(wsRequestBuildingErrors, null, 2),
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
return wsRequestEvents;
|
|
586
|
+
}
|
|
587
|
+
async signMessage(paramsStr, secret, method, algorithm, options) {
|
|
588
|
+
if (typeof this.options.customSignMessageFn === 'function') {
|
|
589
|
+
return this.options.customSignMessageFn(paramsStr, secret);
|
|
590
|
+
}
|
|
591
|
+
return await (0, webCryptoAPI_js_1.signMessage)(paramsStr, secret, method, algorithm, options);
|
|
592
|
+
}
|
|
593
|
+
async getWsAuthRequestEvent(wsKey, eventToAuth) {
|
|
594
|
+
try {
|
|
595
|
+
switch (wsKey) {
|
|
596
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPrivateV2:
|
|
597
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPrivateV2: {
|
|
598
|
+
// Not needed here, handled automatically with request during subscribe
|
|
599
|
+
this.logger.trace(`getWsAuthRequestEvent(${wsKey}): no auth request required for private WS...`);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
case websocket_util_js_1.WS_KEY_MAP.spotPublicV2:
|
|
603
|
+
case websocket_util_js_1.WS_KEY_MAP.spotBetaPublicV2:
|
|
604
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPublicV1: {
|
|
605
|
+
// Public WS - no auth
|
|
606
|
+
this.logger.trace(`getWsAuthRequestEvent(${wsKey}): no auth required for public WS...`);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
case websocket_util_js_1.WS_KEY_MAP.derivativesPrivateV1: {
|
|
610
|
+
// cleanup old challenge key (in case we were reconnected)
|
|
611
|
+
this.wsChallengeCache.delete(wsKey);
|
|
612
|
+
// https://docs.kraken.com/api/docs/futures-api/websocket/challenge/
|
|
613
|
+
this.logger.trace(`getWsAuthRequestEvent(${wsKey}): preparing auth challenge request...`, { ...WS_LOGGER_CATEGORY, wsKey });
|
|
614
|
+
const challengeRequest = {
|
|
615
|
+
event: 'challenge',
|
|
616
|
+
api_key: this.options.apiKey,
|
|
617
|
+
};
|
|
618
|
+
return challengeRequest;
|
|
619
|
+
}
|
|
620
|
+
default: {
|
|
621
|
+
throw (0, misc_util_js_1.neverGuard)(wsKey, `Unhandled WsKey "${wsKey}"`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
catch (e) {
|
|
626
|
+
this.logger.error(`getWsAuthRequestEvent(${wsKey}): Exception preparing auth request: `, {
|
|
627
|
+
wsKey,
|
|
628
|
+
eventToAuth,
|
|
629
|
+
exception: e,
|
|
630
|
+
exceptionBody: e?.body,
|
|
631
|
+
stack: e?.stack,
|
|
632
|
+
});
|
|
633
|
+
throw e;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
*
|
|
638
|
+
* @param requestEvent
|
|
639
|
+
* @returns A signed updated WS API request object, ready to be sent
|
|
640
|
+
*/
|
|
641
|
+
async signWSAPIRequest(requestEvent) {
|
|
642
|
+
if (!this.options.apiSecret) {
|
|
643
|
+
throw new Error('API Secret missing');
|
|
644
|
+
}
|
|
645
|
+
// Get token from REST client cache
|
|
646
|
+
const tokenResult = await this.restClientCache.fetchSpotWebSocketToken(this.getRestClientOptions(), this.options.requestOptions);
|
|
647
|
+
if (!tokenResult?.token) {
|
|
648
|
+
const error = new Error(`No WS auth token could be retrieved for private spot WS request for topic "${requestEvent.method}"`);
|
|
649
|
+
error.cause = tokenResult;
|
|
650
|
+
throw error;
|
|
651
|
+
}
|
|
652
|
+
const authParams = {};
|
|
653
|
+
if (tokenResult.token) {
|
|
654
|
+
authParams.token = tokenResult.token;
|
|
655
|
+
}
|
|
656
|
+
if (requestEvent.method === 'add_order') {
|
|
657
|
+
// authParams.broker = APIIDMain;
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
...requestEvent,
|
|
661
|
+
params: {
|
|
662
|
+
...requestEvent.params,
|
|
663
|
+
...authParams,
|
|
664
|
+
},
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
exports.WebsocketClient = WebsocketClient;
|
|
669
|
+
//# sourceMappingURL=WebsocketClient.js.map
|