ccxt 4.3.85 → 4.3.87
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 +8 -5
- package/dist/ccxt.browser.min.js +15 -15
- package/dist/cjs/ccxt.js +7 -1
- package/dist/cjs/src/abstract/hashkey.js +9 -0
- package/dist/cjs/src/base/Exchange.js +1 -1
- package/dist/cjs/src/base/errors.js +8 -1
- package/dist/cjs/src/binance.js +4 -2
- package/dist/cjs/src/bingx.js +7 -1
- package/dist/cjs/src/bitfinex.js +2 -2
- package/dist/cjs/src/hashkey.js +4327 -0
- package/dist/cjs/src/hyperliquid.js +85 -65
- package/dist/cjs/src/indodax.js +37 -9
- package/dist/cjs/src/kraken.js +37 -6
- package/dist/cjs/src/krakenfutures.js +12 -10
- package/dist/cjs/src/pro/ascendex.js +45 -5
- package/dist/cjs/src/pro/bingx.js +13 -12
- package/dist/cjs/src/pro/bitget.js +164 -19
- package/dist/cjs/src/pro/hashkey.js +839 -0
- package/dist/cjs/src/pro/hyperliquid.js +123 -0
- package/dist/cjs/src/pro/mexc.js +13 -7
- package/dist/cjs/src/pro/p2b.js +34 -7
- package/dist/cjs/src/pro/poloniex.js +36 -3
- package/dist/cjs/src/pro/poloniexfutures.js +1 -0
- package/dist/cjs/src/pro/probit.js +2 -0
- package/dist/cjs/src/pro/upbit.js +48 -3
- package/dist/cjs/src/pro/vertex.js +1 -0
- package/dist/cjs/src/pro/wazirx.js +3 -0
- package/dist/cjs/src/pro/whitebit.js +9 -0
- package/dist/cjs/src/pro/woo.js +1 -0
- package/dist/cjs/src/pro/woofipro.js +1 -0
- package/dist/cjs/src/pro/xt.js +1 -0
- package/dist/cjs/src/upbit.js +1 -1
- package/js/ccxt.d.ts +9 -3
- package/js/ccxt.js +7 -3
- package/js/src/abstract/hashkey.d.ts +70 -0
- package/js/src/abstract/hashkey.js +11 -0
- package/js/src/base/Exchange.js +1 -1
- package/js/src/base/errorHierarchy.d.ts +1 -0
- package/js/src/base/errorHierarchy.js +1 -0
- package/js/src/base/errors.d.ts +5 -1
- package/js/src/base/errors.js +8 -2
- package/js/src/binance.js +4 -2
- package/js/src/bingx.js +7 -1
- package/js/src/bitfinex.js +2 -2
- package/js/src/hashkey.d.ts +178 -0
- package/js/src/hashkey.js +4328 -0
- package/js/src/hyperliquid.d.ts +3 -0
- package/js/src/hyperliquid.js +85 -65
- package/js/src/indodax.js +37 -9
- package/js/src/kraken.js +37 -6
- package/js/src/krakenfutures.js +12 -10
- package/js/src/pro/ascendex.d.ts +2 -0
- package/js/src/pro/ascendex.js +45 -5
- package/js/src/pro/bingx.js +13 -12
- package/js/src/pro/bitget.d.ts +8 -0
- package/js/src/pro/bitget.js +165 -20
- package/js/src/pro/hashkey.d.ts +34 -0
- package/js/src/pro/hashkey.js +840 -0
- package/js/src/pro/hyperliquid.d.ts +7 -1
- package/js/src/pro/hyperliquid.js +123 -0
- package/js/src/pro/mexc.js +13 -7
- package/js/src/pro/p2b.d.ts +1 -0
- package/js/src/pro/p2b.js +34 -7
- package/js/src/pro/poloniex.d.ts +1 -0
- package/js/src/pro/poloniex.js +36 -3
- package/js/src/pro/poloniexfutures.js +1 -0
- package/js/src/pro/probit.js +2 -0
- package/js/src/pro/upbit.d.ts +1 -0
- package/js/src/pro/upbit.js +48 -3
- package/js/src/pro/vertex.js +1 -0
- package/js/src/pro/wazirx.js +3 -0
- package/js/src/pro/whitebit.js +9 -0
- package/js/src/pro/woo.js +1 -0
- package/js/src/pro/woofipro.js +1 -0
- package/js/src/pro/xt.js +1 -0
- package/js/src/upbit.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var hashkey$1 = require('../hashkey.js');
|
|
4
|
+
var Cache = require('../base/ws/Cache.js');
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
class hashkey extends hashkey$1 {
|
|
9
|
+
describe() {
|
|
10
|
+
return this.deepExtend(super.describe(), {
|
|
11
|
+
'has': {
|
|
12
|
+
'ws': true,
|
|
13
|
+
'watchBalance': true,
|
|
14
|
+
'watchMyTrades': true,
|
|
15
|
+
'watchOHLCV': true,
|
|
16
|
+
'watchOrderBook': true,
|
|
17
|
+
'watchOrders': true,
|
|
18
|
+
'watchTicker': true,
|
|
19
|
+
'watchTrades': true,
|
|
20
|
+
'watchPositions': false,
|
|
21
|
+
},
|
|
22
|
+
'urls': {
|
|
23
|
+
'api': {
|
|
24
|
+
'ws': {
|
|
25
|
+
'public': 'wss://stream-glb.hashkey.com/quote/ws/v1',
|
|
26
|
+
'private': 'wss://stream-glb.hashkey.com/api/v1/ws',
|
|
27
|
+
},
|
|
28
|
+
'test': {
|
|
29
|
+
'ws': {
|
|
30
|
+
'public': 'wss://stream-glb.sim.hashkeydev.com/quote/ws/v1',
|
|
31
|
+
'private': 'wss://stream-glb.sim.hashkeydev.com/api/v1/ws',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
'options': {
|
|
37
|
+
'listenKeyRefreshRate': 3600000,
|
|
38
|
+
'listenKey': undefined,
|
|
39
|
+
'watchBalance': {
|
|
40
|
+
'fetchBalanceSnapshot': true,
|
|
41
|
+
'awaitBalanceSnapshot': false, // whether to wait for the balance snapshot before providing updates
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
'streaming': {
|
|
45
|
+
'keepAlive': 10000,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async wathPublic(market, topic, messageHash, params = {}) {
|
|
50
|
+
const request = {
|
|
51
|
+
'symbol': market['id'],
|
|
52
|
+
'topic': topic,
|
|
53
|
+
'event': 'sub',
|
|
54
|
+
};
|
|
55
|
+
const url = this.urls['api']['ws']['public'];
|
|
56
|
+
return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
|
|
57
|
+
}
|
|
58
|
+
async watchPrivate(messageHash) {
|
|
59
|
+
const listenKey = await this.authenticate();
|
|
60
|
+
const url = this.getPrivateUrl(listenKey);
|
|
61
|
+
return await this.watch(url, messageHash, undefined, messageHash);
|
|
62
|
+
}
|
|
63
|
+
getPrivateUrl(listenKey) {
|
|
64
|
+
return this.urls['api']['ws']['private'] + '/' + listenKey;
|
|
65
|
+
}
|
|
66
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
67
|
+
/**
|
|
68
|
+
* @method
|
|
69
|
+
* @name hashkey#watchOHLCV
|
|
70
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
71
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#public-stream
|
|
72
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
73
|
+
* @param {string} timeframe the length of time each candle represents
|
|
74
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
75
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
76
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
77
|
+
* @param {bool} [params.binary] true or false - default false
|
|
78
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
79
|
+
*/
|
|
80
|
+
await this.loadMarkets();
|
|
81
|
+
const market = this.market(symbol);
|
|
82
|
+
symbol = market['symbol'];
|
|
83
|
+
const interval = this.safeString(this.timeframes, timeframe, timeframe);
|
|
84
|
+
const topic = 'kline_' + interval;
|
|
85
|
+
const messageHash = 'ohlcv:' + symbol + ':' + timeframe;
|
|
86
|
+
const ohlcv = await this.wathPublic(market, topic, messageHash, params);
|
|
87
|
+
if (this.newUpdates) {
|
|
88
|
+
limit = ohlcv.getLimit(symbol, limit);
|
|
89
|
+
}
|
|
90
|
+
return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
|
|
91
|
+
}
|
|
92
|
+
handleOHLCV(client, message) {
|
|
93
|
+
//
|
|
94
|
+
// {
|
|
95
|
+
// "symbol": "DOGEUSDT",
|
|
96
|
+
// "symbolName": "DOGEUSDT",
|
|
97
|
+
// "topic": "kline",
|
|
98
|
+
// "params": {
|
|
99
|
+
// "realtimeInterval": "24h",
|
|
100
|
+
// "klineType": "1m"
|
|
101
|
+
// },
|
|
102
|
+
// "data": [
|
|
103
|
+
// {
|
|
104
|
+
// "t": 1722861660000,
|
|
105
|
+
// "s": "DOGEUSDT",
|
|
106
|
+
// "sn": "DOGEUSDT",
|
|
107
|
+
// "c": "0.08389",
|
|
108
|
+
// "h": "0.08389",
|
|
109
|
+
// "l": "0.08389",
|
|
110
|
+
// "o": "0.08389",
|
|
111
|
+
// "v": "0"
|
|
112
|
+
// }
|
|
113
|
+
// ],
|
|
114
|
+
// "f": true,
|
|
115
|
+
// "sendTime": 1722861664258,
|
|
116
|
+
// "shared": false
|
|
117
|
+
// }
|
|
118
|
+
//
|
|
119
|
+
const marketId = this.safeString(message, 'symbol');
|
|
120
|
+
const market = this.safeMarket(marketId);
|
|
121
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
122
|
+
if (!(symbol in this.ohlcvs)) {
|
|
123
|
+
this.ohlcvs[symbol] = {};
|
|
124
|
+
}
|
|
125
|
+
const params = this.safeDict(message, 'params');
|
|
126
|
+
const klineType = this.safeString(params, 'klineType');
|
|
127
|
+
const timeframe = this.findTimeframe(klineType);
|
|
128
|
+
if (!(timeframe in this.ohlcvs[symbol])) {
|
|
129
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
130
|
+
this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit);
|
|
131
|
+
}
|
|
132
|
+
const data = this.safeList(message, 'data', []);
|
|
133
|
+
const stored = this.ohlcvs[symbol][timeframe];
|
|
134
|
+
for (let i = 0; i < data.length; i++) {
|
|
135
|
+
const candle = this.safeDict(data, i, {});
|
|
136
|
+
const parsed = this.parseWsOHLCV(candle, market);
|
|
137
|
+
stored.append(parsed);
|
|
138
|
+
}
|
|
139
|
+
const messageHash = 'ohlcv:' + symbol + ':' + timeframe;
|
|
140
|
+
client.resolve(stored, messageHash);
|
|
141
|
+
}
|
|
142
|
+
parseWsOHLCV(ohlcv, market = undefined) {
|
|
143
|
+
//
|
|
144
|
+
// {
|
|
145
|
+
// "t": 1722861660000,
|
|
146
|
+
// "s": "DOGEUSDT",
|
|
147
|
+
// "sn": "DOGEUSDT",
|
|
148
|
+
// "c": "0.08389",
|
|
149
|
+
// "h": "0.08389",
|
|
150
|
+
// "l": "0.08389",
|
|
151
|
+
// "o": "0.08389",
|
|
152
|
+
// "v": "0"
|
|
153
|
+
// }
|
|
154
|
+
//
|
|
155
|
+
return [
|
|
156
|
+
this.safeInteger(ohlcv, 't'),
|
|
157
|
+
this.safeNumber(ohlcv, 'o'),
|
|
158
|
+
this.safeNumber(ohlcv, 'h'),
|
|
159
|
+
this.safeNumber(ohlcv, 'l'),
|
|
160
|
+
this.safeNumber(ohlcv, 'c'),
|
|
161
|
+
this.safeNumber(ohlcv, 'v'),
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
async watchTicker(symbol, params = {}) {
|
|
165
|
+
/**
|
|
166
|
+
* @method
|
|
167
|
+
* @name hahskey#watchTicker
|
|
168
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
169
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#public-stream
|
|
170
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
171
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
172
|
+
* @param {bool} [params.binary] true or false - default false
|
|
173
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
174
|
+
*/
|
|
175
|
+
await this.loadMarkets();
|
|
176
|
+
const market = this.market(symbol);
|
|
177
|
+
symbol = market['symbol'];
|
|
178
|
+
const topic = 'realtimes';
|
|
179
|
+
const messageHash = 'ticker:' + symbol;
|
|
180
|
+
return await this.wathPublic(market, topic, messageHash, params);
|
|
181
|
+
}
|
|
182
|
+
handleTicker(client, message) {
|
|
183
|
+
//
|
|
184
|
+
// {
|
|
185
|
+
// "symbol": "ETHUSDT",
|
|
186
|
+
// "symbolName": "ETHUSDT",
|
|
187
|
+
// "topic": "realtimes",
|
|
188
|
+
// "params": {
|
|
189
|
+
// "realtimeInterval": "24h"
|
|
190
|
+
// },
|
|
191
|
+
// "data": [
|
|
192
|
+
// {
|
|
193
|
+
// "t": 1722864411064,
|
|
194
|
+
// "s": "ETHUSDT",
|
|
195
|
+
// "sn": "ETHUSDT",
|
|
196
|
+
// "c": "2195",
|
|
197
|
+
// "h": "2918.85",
|
|
198
|
+
// "l": "2135.5",
|
|
199
|
+
// "o": "2915.78",
|
|
200
|
+
// "v": "666.5019",
|
|
201
|
+
// "qv": "1586902.757079",
|
|
202
|
+
// "m": "-0.2472",
|
|
203
|
+
// "e": 301
|
|
204
|
+
// }
|
|
205
|
+
// ],
|
|
206
|
+
// "f": false,
|
|
207
|
+
// "sendTime": 1722864411086,
|
|
208
|
+
// "shared": false
|
|
209
|
+
// }
|
|
210
|
+
//
|
|
211
|
+
const data = this.safeList(message, 'data', []);
|
|
212
|
+
const ticker = this.parseTicker(this.safeDict(data, 0));
|
|
213
|
+
const symbol = ticker['symbol'];
|
|
214
|
+
const messageHash = 'ticker:' + symbol;
|
|
215
|
+
this.tickers[symbol] = ticker;
|
|
216
|
+
client.resolve(this.tickers[symbol], messageHash);
|
|
217
|
+
}
|
|
218
|
+
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
219
|
+
/**
|
|
220
|
+
* @method
|
|
221
|
+
* @name hashkey#watchTrades
|
|
222
|
+
* @description watches information on multiple trades made in a market
|
|
223
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#public-stream
|
|
224
|
+
* @param {string} symbol unified market symbol of the market trades were made in
|
|
225
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
226
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
227
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
228
|
+
* @param {bool} [params.binary] true or false - default false
|
|
229
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
230
|
+
*/
|
|
231
|
+
await this.loadMarkets();
|
|
232
|
+
const market = this.market(symbol);
|
|
233
|
+
symbol = market['symbol'];
|
|
234
|
+
const topic = 'trade';
|
|
235
|
+
const messageHash = 'trades:' + symbol;
|
|
236
|
+
const trades = await this.wathPublic(market, topic, messageHash, params);
|
|
237
|
+
if (this.newUpdates) {
|
|
238
|
+
limit = trades.getLimit(symbol, limit);
|
|
239
|
+
}
|
|
240
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
241
|
+
}
|
|
242
|
+
handleTrades(client, message) {
|
|
243
|
+
//
|
|
244
|
+
// {
|
|
245
|
+
// "symbol": "ETHUSDT",
|
|
246
|
+
// "symbolName": "ETHUSDT",
|
|
247
|
+
// "topic": "trade",
|
|
248
|
+
// "params": {
|
|
249
|
+
// "realtimeInterval": "24h"
|
|
250
|
+
// },
|
|
251
|
+
// "data": [
|
|
252
|
+
// {
|
|
253
|
+
// "v": "1745922896272048129",
|
|
254
|
+
// "t": 1722866228075,
|
|
255
|
+
// "p": "2340.41",
|
|
256
|
+
// "q": "0.0132",
|
|
257
|
+
// "m": true
|
|
258
|
+
// },
|
|
259
|
+
// ...
|
|
260
|
+
// ],
|
|
261
|
+
// "f": true,
|
|
262
|
+
// "sendTime": 1722869464248,
|
|
263
|
+
// "channelId": "668498fffeba4108-00000001-00113184-562e27d215e43f9c-c188b319",
|
|
264
|
+
// "shared": false
|
|
265
|
+
// }
|
|
266
|
+
//
|
|
267
|
+
const marketId = this.safeString(message, 'symbol');
|
|
268
|
+
const market = this.safeMarket(marketId);
|
|
269
|
+
const symbol = market['symbol'];
|
|
270
|
+
if (!(symbol in this.trades)) {
|
|
271
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
272
|
+
this.trades[symbol] = new Cache.ArrayCache(limit);
|
|
273
|
+
}
|
|
274
|
+
const stored = this.trades[symbol];
|
|
275
|
+
let data = this.safeList(message, 'data');
|
|
276
|
+
if (data !== undefined) {
|
|
277
|
+
data = this.sortBy(data, 't');
|
|
278
|
+
for (let i = 0; i < data.length; i++) {
|
|
279
|
+
const trade = this.safeDict(data, i);
|
|
280
|
+
const parsed = this.parseWsTrade(trade, market);
|
|
281
|
+
stored.append(parsed);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const messageHash = 'trades' + ':' + symbol;
|
|
285
|
+
client.resolve(stored, messageHash);
|
|
286
|
+
}
|
|
287
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
288
|
+
/**
|
|
289
|
+
* @method
|
|
290
|
+
* @name alpaca#watchOrderBook
|
|
291
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
292
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#public-stream
|
|
293
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
294
|
+
* @param {int} [limit] the maximum amount of order book entries to return.
|
|
295
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
296
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
297
|
+
*/
|
|
298
|
+
await this.loadMarkets();
|
|
299
|
+
const market = this.market(symbol);
|
|
300
|
+
symbol = market['symbol'];
|
|
301
|
+
const topic = 'depth';
|
|
302
|
+
const messageHash = 'orderbook:' + symbol;
|
|
303
|
+
const orderbook = await this.wathPublic(market, topic, messageHash, params);
|
|
304
|
+
return orderbook.limit();
|
|
305
|
+
}
|
|
306
|
+
handleOrderBook(client, message) {
|
|
307
|
+
//
|
|
308
|
+
// {
|
|
309
|
+
// "symbol": "ETHUSDT",
|
|
310
|
+
// "symbolName": "ETHUSDT",
|
|
311
|
+
// "topic": "depth",
|
|
312
|
+
// "params": { "realtimeInterval": "24h" },
|
|
313
|
+
// "data": [
|
|
314
|
+
// {
|
|
315
|
+
// "e": 301,
|
|
316
|
+
// "s": "ETHUSDT",
|
|
317
|
+
// "t": 1722873144371,
|
|
318
|
+
// "v": "84661262_18",
|
|
319
|
+
// "b": [
|
|
320
|
+
// [ "1650", "0.0864" ],
|
|
321
|
+
// ...
|
|
322
|
+
// ],
|
|
323
|
+
// "a": [
|
|
324
|
+
// ["4085", "0.0074" ],
|
|
325
|
+
// ...
|
|
326
|
+
// ],
|
|
327
|
+
// "o": 0
|
|
328
|
+
// }
|
|
329
|
+
// ],
|
|
330
|
+
// "f": false,
|
|
331
|
+
// "sendTime": 1722873144589,
|
|
332
|
+
// "channelId": "2265aafffe68b588-00000001-0011510c-9e9ca710b1500854-551830bd",
|
|
333
|
+
// "shared": false
|
|
334
|
+
// }
|
|
335
|
+
//
|
|
336
|
+
const marketId = this.safeString(message, 'symbol');
|
|
337
|
+
const symbol = this.safeSymbol(marketId);
|
|
338
|
+
const messageHash = 'orderbook:' + symbol;
|
|
339
|
+
if (!(symbol in this.orderbooks)) {
|
|
340
|
+
this.orderbooks[symbol] = this.orderBook({});
|
|
341
|
+
}
|
|
342
|
+
const orderbook = this.orderbooks[symbol];
|
|
343
|
+
const data = this.safeList(message, 'data', []);
|
|
344
|
+
const dataEntry = this.safeDict(data, 0);
|
|
345
|
+
const timestamp = this.safeInteger(dataEntry, 't');
|
|
346
|
+
const snapshot = this.parseOrderBook(dataEntry, symbol, timestamp, 'b', 'a');
|
|
347
|
+
orderbook.reset(snapshot);
|
|
348
|
+
orderbook['nonce'] = this.safeInteger(message, 'id');
|
|
349
|
+
this.orderbooks[symbol] = orderbook;
|
|
350
|
+
client.resolve(orderbook, messageHash);
|
|
351
|
+
}
|
|
352
|
+
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
353
|
+
/**
|
|
354
|
+
* @method
|
|
355
|
+
* @name hashkey#watchOrders
|
|
356
|
+
* @description watches information on multiple orders made by the user
|
|
357
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#private-stream
|
|
358
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
359
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
360
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
361
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
362
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
363
|
+
*/
|
|
364
|
+
await this.loadMarkets();
|
|
365
|
+
let messageHash = 'orders';
|
|
366
|
+
if (symbol !== undefined) {
|
|
367
|
+
symbol = this.symbol(symbol);
|
|
368
|
+
messageHash = messageHash + ':' + symbol;
|
|
369
|
+
}
|
|
370
|
+
const orders = await this.watchPrivate(messageHash);
|
|
371
|
+
if (this.newUpdates) {
|
|
372
|
+
limit = orders.getLimit(symbol, limit);
|
|
373
|
+
}
|
|
374
|
+
return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
|
|
375
|
+
}
|
|
376
|
+
handleOrder(client, message) {
|
|
377
|
+
//
|
|
378
|
+
// swap
|
|
379
|
+
// {
|
|
380
|
+
// "e": "contractExecutionReport",
|
|
381
|
+
// "E": "1723037391181",
|
|
382
|
+
// "s": "ETHUSDT-PERPETUAL",
|
|
383
|
+
// "c": "1723037389677",
|
|
384
|
+
// "S": "BUY_OPEN",
|
|
385
|
+
// "o": "LIMIT",
|
|
386
|
+
// "f": "IOC",
|
|
387
|
+
// "q": "1",
|
|
388
|
+
// "p": "2561.75",
|
|
389
|
+
// "X": "FILLED",
|
|
390
|
+
// "i": "1747358716129257216",
|
|
391
|
+
// "l": "1",
|
|
392
|
+
// "z": "1",
|
|
393
|
+
// "L": "2463.36",
|
|
394
|
+
// "n": "0.001478016",
|
|
395
|
+
// "N": "USDT",
|
|
396
|
+
// "u": true,
|
|
397
|
+
// "w": true,
|
|
398
|
+
// "m": false,
|
|
399
|
+
// "O": "1723037391140",
|
|
400
|
+
// "Z": "2463.36",
|
|
401
|
+
// "C": false,
|
|
402
|
+
// "v": "5",
|
|
403
|
+
// "reqAmt": "0",
|
|
404
|
+
// "d": "1747358716255075840",
|
|
405
|
+
// "r": "0",
|
|
406
|
+
// "V": "2463.36",
|
|
407
|
+
// "P": "0",
|
|
408
|
+
// "lo": false,
|
|
409
|
+
// "lt": ""
|
|
410
|
+
// }
|
|
411
|
+
//
|
|
412
|
+
if (this.orders === undefined) {
|
|
413
|
+
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
414
|
+
this.orders = new Cache.ArrayCacheBySymbolById(limit);
|
|
415
|
+
}
|
|
416
|
+
const parsed = this.parseWsOrder(message);
|
|
417
|
+
const orders = this.orders;
|
|
418
|
+
orders.append(parsed);
|
|
419
|
+
const messageHash = 'orders';
|
|
420
|
+
client.resolve(orders, messageHash);
|
|
421
|
+
const symbol = parsed['symbol'];
|
|
422
|
+
const symbolSpecificMessageHash = messageHash + ':' + symbol;
|
|
423
|
+
client.resolve(orders, symbolSpecificMessageHash);
|
|
424
|
+
}
|
|
425
|
+
parseWsOrder(order, market = undefined) {
|
|
426
|
+
const marketId = this.safeString(order, 's');
|
|
427
|
+
market = this.safeMarket(marketId, market);
|
|
428
|
+
const timestamp = this.safeInteger(order, 'O');
|
|
429
|
+
let side = this.safeStringLower(order, 'S');
|
|
430
|
+
let reduceOnly = undefined;
|
|
431
|
+
[side, reduceOnly] = this.parseOrderSideAndReduceOnly(side);
|
|
432
|
+
let type = this.parseOrderType(this.safeString(order, 'o'));
|
|
433
|
+
let timeInForce = this.safeString(order, 'f');
|
|
434
|
+
let postOnly = undefined;
|
|
435
|
+
[type, timeInForce, postOnly] = this.parseOrderTypeTimeInForceAndPostOnly(type, timeInForce);
|
|
436
|
+
if (market['contract']) { // swap orders are always have type 'LIMIT', thus we can not define the correct type
|
|
437
|
+
type = undefined;
|
|
438
|
+
}
|
|
439
|
+
return this.safeOrder({
|
|
440
|
+
'id': this.safeString(order, 'i'),
|
|
441
|
+
'clientOrderId': this.safeString(order, 'c'),
|
|
442
|
+
'datetime': this.iso8601(timestamp),
|
|
443
|
+
'timestamp': timestamp,
|
|
444
|
+
'lastTradeTimestamp': undefined,
|
|
445
|
+
'lastUpdateTimestamp': undefined,
|
|
446
|
+
'status': this.parseOrderStatus(this.safeString(order, 'X')),
|
|
447
|
+
'symbol': market['symbol'],
|
|
448
|
+
'type': type,
|
|
449
|
+
'timeInForce': timeInForce,
|
|
450
|
+
'side': side,
|
|
451
|
+
'price': this.safeString(order, 'p'),
|
|
452
|
+
'average': this.safeString(order, 'V'),
|
|
453
|
+
'amount': this.omitZero(this.safeString(order, 'q')),
|
|
454
|
+
'filled': this.safeString(order, 'z'),
|
|
455
|
+
'remaining': this.safeString(order, 'r'),
|
|
456
|
+
'stopPrice': undefined,
|
|
457
|
+
'triggerPrice': undefined,
|
|
458
|
+
'takeProfitPrice': undefined,
|
|
459
|
+
'stopLossPrice': undefined,
|
|
460
|
+
'cost': this.omitZero(this.safeString(order, 'Z')),
|
|
461
|
+
'trades': undefined,
|
|
462
|
+
'fee': {
|
|
463
|
+
'currency': this.safeCurrencyCode(this.safeString(order, 'N')),
|
|
464
|
+
'amount': this.omitZero(this.safeString(order, 'n')),
|
|
465
|
+
},
|
|
466
|
+
'reduceOnly': reduceOnly,
|
|
467
|
+
'postOnly': postOnly,
|
|
468
|
+
'info': order,
|
|
469
|
+
}, market);
|
|
470
|
+
}
|
|
471
|
+
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
472
|
+
/**
|
|
473
|
+
* @method
|
|
474
|
+
* @name hashkey#watchMyTrades
|
|
475
|
+
* @description watches information on multiple trades made by the user
|
|
476
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#private-stream
|
|
477
|
+
* @param {string} symbol unified market symbol of the market trades were made in
|
|
478
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
479
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
480
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
481
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
482
|
+
*/
|
|
483
|
+
await this.loadMarkets();
|
|
484
|
+
let messageHash = 'myTrades';
|
|
485
|
+
if (symbol !== undefined) {
|
|
486
|
+
symbol = this.symbol(symbol);
|
|
487
|
+
messageHash += ':' + symbol;
|
|
488
|
+
}
|
|
489
|
+
const trades = await this.watchPrivate(messageHash);
|
|
490
|
+
if (this.newUpdates) {
|
|
491
|
+
limit = trades.getLimit(symbol, limit);
|
|
492
|
+
}
|
|
493
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
494
|
+
}
|
|
495
|
+
handleMyTrade(client, message, subscription = {}) {
|
|
496
|
+
//
|
|
497
|
+
// {
|
|
498
|
+
// "e": "ticketInfo",
|
|
499
|
+
// "E": "1723037391156",
|
|
500
|
+
// "s": "ETHUSDT-PERPETUAL",
|
|
501
|
+
// "q": "1.00",
|
|
502
|
+
// "t": "1723037391147",
|
|
503
|
+
// "p": "2463.36",
|
|
504
|
+
// "T": "1747358716187197441",
|
|
505
|
+
// "o": "1747358716129257216",
|
|
506
|
+
// "c": "1723037389677",
|
|
507
|
+
// "a": "1735619524953226496",
|
|
508
|
+
// "m": false,
|
|
509
|
+
// "S": "BUY"
|
|
510
|
+
// }
|
|
511
|
+
//
|
|
512
|
+
if (this.myTrades === undefined) {
|
|
513
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
514
|
+
this.myTrades = new Cache.ArrayCacheBySymbolById(limit);
|
|
515
|
+
}
|
|
516
|
+
const tradesArray = this.myTrades;
|
|
517
|
+
const parsed = this.parseWsTrade(message);
|
|
518
|
+
tradesArray.append(parsed);
|
|
519
|
+
this.myTrades = tradesArray;
|
|
520
|
+
const messageHash = 'myTrades';
|
|
521
|
+
client.resolve(tradesArray, messageHash);
|
|
522
|
+
const symbol = parsed['symbol'];
|
|
523
|
+
const symbolSpecificMessageHash = messageHash + ':' + symbol;
|
|
524
|
+
client.resolve(tradesArray, symbolSpecificMessageHash);
|
|
525
|
+
}
|
|
526
|
+
parseWsTrade(trade, market = undefined) {
|
|
527
|
+
//
|
|
528
|
+
// watchTrades
|
|
529
|
+
// {
|
|
530
|
+
// "v": "1745922896272048129",
|
|
531
|
+
// "t": 1722866228075,
|
|
532
|
+
// "p": "2340.41",
|
|
533
|
+
// "q": "0.0132",
|
|
534
|
+
// "m": true
|
|
535
|
+
// }
|
|
536
|
+
//
|
|
537
|
+
// watchMyTrades
|
|
538
|
+
// {
|
|
539
|
+
// "e": "ticketInfo",
|
|
540
|
+
// "E": "1723037391156",
|
|
541
|
+
// "s": "ETHUSDT-PERPETUAL",
|
|
542
|
+
// "q": "1.00",
|
|
543
|
+
// "t": "1723037391147",
|
|
544
|
+
// "p": "2463.36",
|
|
545
|
+
// "T": "1747358716187197441",
|
|
546
|
+
// "o": "1747358716129257216",
|
|
547
|
+
// "c": "1723037389677",
|
|
548
|
+
// "a": "1735619524953226496",
|
|
549
|
+
// "m": false,
|
|
550
|
+
// "S": "BUY"
|
|
551
|
+
// }
|
|
552
|
+
//
|
|
553
|
+
const marketId = this.safeString(trade, 's');
|
|
554
|
+
market = this.safeMarket(marketId, market);
|
|
555
|
+
const timestamp = this.safeInteger(trade, 't');
|
|
556
|
+
const isMaker = this.safeBool(trade, 'm');
|
|
557
|
+
let takerOrMaker = undefined;
|
|
558
|
+
if (isMaker !== undefined) {
|
|
559
|
+
if (isMaker) {
|
|
560
|
+
takerOrMaker = 'maker';
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
takerOrMaker = 'taker';
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return this.safeTrade({
|
|
567
|
+
'id': this.safeString2(trade, 'v', 'T'),
|
|
568
|
+
'timestamp': timestamp,
|
|
569
|
+
'datetime': this.iso8601(timestamp),
|
|
570
|
+
'symbol': market['symbol'],
|
|
571
|
+
'side': this.safeStringLower(trade, 'S'),
|
|
572
|
+
'price': this.safeString(trade, 'p'),
|
|
573
|
+
'amount': this.safeString(trade, 'q'),
|
|
574
|
+
'cost': undefined,
|
|
575
|
+
'takerOrMaker': takerOrMaker,
|
|
576
|
+
'type': undefined,
|
|
577
|
+
'order': this.safeString(trade, 'o'),
|
|
578
|
+
'fee': undefined,
|
|
579
|
+
'info': trade,
|
|
580
|
+
}, market);
|
|
581
|
+
}
|
|
582
|
+
async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
|
|
583
|
+
/**
|
|
584
|
+
* @method
|
|
585
|
+
* @name hashkey#watchPositions
|
|
586
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#private-stream
|
|
587
|
+
* @description watch all open positions
|
|
588
|
+
* @param {string[]|undefined} symbols list of unified market symbols
|
|
589
|
+
* @param {object} params extra parameters specific to the exchange API endpoint
|
|
590
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
|
|
591
|
+
*/
|
|
592
|
+
await this.loadMarkets();
|
|
593
|
+
const listenKey = await this.authenticate();
|
|
594
|
+
symbols = this.marketSymbols(symbols);
|
|
595
|
+
const messageHash = 'positions';
|
|
596
|
+
const messageHashes = [];
|
|
597
|
+
if (symbols === undefined) {
|
|
598
|
+
messageHashes.push(messageHash);
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
602
|
+
const symbol = symbols[i];
|
|
603
|
+
messageHashes.push(messageHash + ':' + symbol);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
const url = this.getPrivateUrl(listenKey);
|
|
607
|
+
const positions = await this.watchMultiple(url, messageHashes, undefined, messageHashes);
|
|
608
|
+
if (this.newUpdates) {
|
|
609
|
+
return positions;
|
|
610
|
+
}
|
|
611
|
+
return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
|
|
612
|
+
}
|
|
613
|
+
handlePosition(client, message) {
|
|
614
|
+
//
|
|
615
|
+
// {
|
|
616
|
+
// "e": "outboundContractPositionInfo",
|
|
617
|
+
// "E": "1723084699801",
|
|
618
|
+
// "A": "1735619524953226496",
|
|
619
|
+
// "s": "ETHUSDT-PERPETUAL",
|
|
620
|
+
// "S": "LONG",
|
|
621
|
+
// "p": "2429.6",
|
|
622
|
+
// "P": "2",
|
|
623
|
+
// "a": "2",
|
|
624
|
+
// "f": "10760.14",
|
|
625
|
+
// "m": "1.0085",
|
|
626
|
+
// "r": "-0.0029",
|
|
627
|
+
// "up": "0.0478",
|
|
628
|
+
// "pr": "0.0492",
|
|
629
|
+
// "pv": "4.8592",
|
|
630
|
+
// "v": "5.00",
|
|
631
|
+
// "mt": "CROSS",
|
|
632
|
+
// "mm": "0.0367"
|
|
633
|
+
// }
|
|
634
|
+
//
|
|
635
|
+
if (this.positions === undefined) {
|
|
636
|
+
this.positions = new Cache.ArrayCacheBySymbolBySide();
|
|
637
|
+
}
|
|
638
|
+
const positions = this.positions;
|
|
639
|
+
const parsed = this.parseWsPosition(message);
|
|
640
|
+
positions.append(parsed);
|
|
641
|
+
const messageHash = 'positions';
|
|
642
|
+
client.resolve(parsed, messageHash);
|
|
643
|
+
const symbol = parsed['symbol'];
|
|
644
|
+
client.resolve(parsed, messageHash + ':' + symbol);
|
|
645
|
+
}
|
|
646
|
+
parseWsPosition(position, market = undefined) {
|
|
647
|
+
const marketId = this.safeString(position, 's');
|
|
648
|
+
market = this.safeMarket(marketId);
|
|
649
|
+
const timestamp = this.safeInteger(position, 'E');
|
|
650
|
+
return this.safePosition({
|
|
651
|
+
'symbol': market['symbol'],
|
|
652
|
+
'id': undefined,
|
|
653
|
+
'timestamp': timestamp,
|
|
654
|
+
'datetime': this.iso8601(timestamp),
|
|
655
|
+
'contracts': this.safeNumber(position, 'P'),
|
|
656
|
+
'contractSize': undefined,
|
|
657
|
+
'side': this.safeStringLower(position, 'S'),
|
|
658
|
+
'notional': this.safeNumber(position, 'pv'),
|
|
659
|
+
'leverage': this.safeInteger(position, 'v'),
|
|
660
|
+
'unrealizedPnl': this.safeNumber(position, 'up'),
|
|
661
|
+
'realizedPnl': this.safeNumber(position, 'r'),
|
|
662
|
+
'collateral': undefined,
|
|
663
|
+
'entryPrice': this.safeNumber(position, 'p'),
|
|
664
|
+
'markPrice': undefined,
|
|
665
|
+
'liquidationPrice': this.safeNumber(position, 'f'),
|
|
666
|
+
'marginMode': this.safeStringLower(position, 'mt'),
|
|
667
|
+
'hedged': true,
|
|
668
|
+
'maintenanceMargin': this.safeNumber(position, 'mm'),
|
|
669
|
+
'maintenanceMarginPercentage': undefined,
|
|
670
|
+
'initialMargin': this.safeNumber(position, 'm'),
|
|
671
|
+
'initialMarginPercentage': undefined,
|
|
672
|
+
'marginRatio': undefined,
|
|
673
|
+
'lastUpdateTimestamp': undefined,
|
|
674
|
+
'lastPrice': undefined,
|
|
675
|
+
'stopLossPrice': undefined,
|
|
676
|
+
'takeProfitPrice': undefined,
|
|
677
|
+
'percentage': undefined,
|
|
678
|
+
'info': position,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
async watchBalance(params = {}) {
|
|
682
|
+
/**
|
|
683
|
+
* @method
|
|
684
|
+
* @name bitmart#watchBalance
|
|
685
|
+
* @description watch balance and get the amount of funds available for trading or funds locked in orders
|
|
686
|
+
* @see https://hashkeyglobal-apidoc.readme.io/reference/websocket-api#private-stream
|
|
687
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
688
|
+
* @param {string} [params.type] 'spot' or 'swap' - the type of the market to watch balance for (default 'spot')
|
|
689
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
690
|
+
*/
|
|
691
|
+
const listenKey = await this.authenticate();
|
|
692
|
+
await this.loadMarkets();
|
|
693
|
+
let type = 'spot';
|
|
694
|
+
[type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params, type);
|
|
695
|
+
const messageHash = 'balance:' + type;
|
|
696
|
+
const url = this.getPrivateUrl(listenKey);
|
|
697
|
+
const client = this.client(url);
|
|
698
|
+
this.setBalanceCache(client, type, messageHash);
|
|
699
|
+
let fetchBalanceSnapshot = undefined;
|
|
700
|
+
let awaitBalanceSnapshot = undefined;
|
|
701
|
+
[fetchBalanceSnapshot, params] = this.handleOptionAndParams(this.options, 'watchBalance', 'fetchBalanceSnapshot', true);
|
|
702
|
+
[awaitBalanceSnapshot, params] = this.handleOptionAndParams(this.options, 'watchBalance', 'awaitBalanceSnapshot', false);
|
|
703
|
+
if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
|
|
704
|
+
await client.future(type + ':fetchBalanceSnapshot');
|
|
705
|
+
}
|
|
706
|
+
return await this.watch(url, messageHash, undefined, messageHash);
|
|
707
|
+
}
|
|
708
|
+
setBalanceCache(client, type, subscribeHash) {
|
|
709
|
+
if (subscribeHash in client.subscriptions) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const options = this.safeDict(this.options, 'watchBalance');
|
|
713
|
+
const snapshot = this.safeBool(options, 'fetchBalanceSnapshot', true);
|
|
714
|
+
if (snapshot) {
|
|
715
|
+
const messageHash = type + ':' + 'fetchBalanceSnapshot';
|
|
716
|
+
if (!(messageHash in client.futures)) {
|
|
717
|
+
client.future(messageHash);
|
|
718
|
+
this.spawn(this.loadBalanceSnapshot, client, messageHash, type);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
this.balance[type] = {};
|
|
722
|
+
// without this comment, transpilation breaks for some reason...
|
|
723
|
+
}
|
|
724
|
+
async loadBalanceSnapshot(client, messageHash, type) {
|
|
725
|
+
const response = await this.fetchBalance({ 'type': type });
|
|
726
|
+
this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
|
|
727
|
+
// don't remove the future from the .futures cache
|
|
728
|
+
const future = client.futures[messageHash];
|
|
729
|
+
future.resolve();
|
|
730
|
+
client.resolve(this.balance[type], 'balance:' + type);
|
|
731
|
+
}
|
|
732
|
+
handleBalance(client, message) {
|
|
733
|
+
//
|
|
734
|
+
// {
|
|
735
|
+
// "e": "outboundContractAccountInfo", // event type
|
|
736
|
+
// // outboundContractAccountInfo
|
|
737
|
+
// "E": "1714717314118", // event time
|
|
738
|
+
// "T": true, // can trade
|
|
739
|
+
// "W": true, // can withdraw
|
|
740
|
+
// "D": true, // can deposit
|
|
741
|
+
// "B": [ // balances changed
|
|
742
|
+
// {
|
|
743
|
+
// "a": "USDT", // asset
|
|
744
|
+
// "f": "474960.65", // free amount
|
|
745
|
+
// "l": "24835.178056020383226869", // locked amount
|
|
746
|
+
// "r": "" // to be released
|
|
747
|
+
// }
|
|
748
|
+
// ]
|
|
749
|
+
// }
|
|
750
|
+
//
|
|
751
|
+
const event = this.safeString(message, 'e');
|
|
752
|
+
const data = this.safeList(message, 'B', []);
|
|
753
|
+
const balanceUpdate = this.safeDict(data, 0);
|
|
754
|
+
const isSpot = event === 'outboundAccountInfo';
|
|
755
|
+
const type = isSpot ? 'spot' : 'swap';
|
|
756
|
+
if (!(type in this.balance)) {
|
|
757
|
+
this.balance[type] = {};
|
|
758
|
+
}
|
|
759
|
+
this.balance[type]['info'] = message;
|
|
760
|
+
const currencyId = this.safeString(balanceUpdate, 'a');
|
|
761
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
762
|
+
const account = this.account();
|
|
763
|
+
account['free'] = this.safeString(balanceUpdate, 'f');
|
|
764
|
+
account['used'] = this.safeString(balanceUpdate, 'l');
|
|
765
|
+
this.balance[type][code] = account;
|
|
766
|
+
this.balance[type] = this.safeBalance(this.balance[type]);
|
|
767
|
+
const messageHash = 'balance:' + type;
|
|
768
|
+
client.resolve(this.balance[type], messageHash);
|
|
769
|
+
}
|
|
770
|
+
async authenticate(params = {}) {
|
|
771
|
+
let listenKey = this.safeString(this.options, 'listenKey');
|
|
772
|
+
if (listenKey !== undefined) {
|
|
773
|
+
return listenKey;
|
|
774
|
+
}
|
|
775
|
+
const response = await this.privatePostApiV1UserDataStream(params);
|
|
776
|
+
//
|
|
777
|
+
// {
|
|
778
|
+
// "listenKey": "atbNEcWnBqnmgkfmYQeTuxKTpTStlZzgoPLJsZhzAOZTbAlxbHqGNWiYaUQzMtDz"
|
|
779
|
+
// }
|
|
780
|
+
//
|
|
781
|
+
listenKey = this.safeString(response, 'listenKey');
|
|
782
|
+
this.options['listenKey'] = listenKey;
|
|
783
|
+
const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 3600000);
|
|
784
|
+
this.delay(listenKeyRefreshRate, this.keepAliveListenKey, listenKey, params);
|
|
785
|
+
return listenKey;
|
|
786
|
+
}
|
|
787
|
+
async keepAliveListenKey(listenKey, params = {}) {
|
|
788
|
+
if (listenKey === undefined) {
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
const request = {
|
|
792
|
+
'listenKey': listenKey,
|
|
793
|
+
};
|
|
794
|
+
try {
|
|
795
|
+
await this.privatePutApiV1UserDataStream(this.extend(request, params));
|
|
796
|
+
const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 1200000);
|
|
797
|
+
this.delay(listenKeyRefreshRate, this.keepAliveListenKey, listenKey, params);
|
|
798
|
+
}
|
|
799
|
+
catch (error) {
|
|
800
|
+
const url = this.getPrivateUrl(listenKey);
|
|
801
|
+
const client = this.client(url);
|
|
802
|
+
this.options['listenKey'] = undefined;
|
|
803
|
+
client.reject(error);
|
|
804
|
+
delete this.clients[url];
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
handleMessage(client, message) {
|
|
808
|
+
if (Array.isArray(message)) {
|
|
809
|
+
message = this.safeDict(message, 0, {});
|
|
810
|
+
}
|
|
811
|
+
const topic = this.safeString2(message, 'topic', 'e');
|
|
812
|
+
if (topic === 'kline') {
|
|
813
|
+
this.handleOHLCV(client, message);
|
|
814
|
+
}
|
|
815
|
+
else if (topic === 'realtimes') {
|
|
816
|
+
this.handleTicker(client, message);
|
|
817
|
+
}
|
|
818
|
+
else if (topic === 'trade') {
|
|
819
|
+
this.handleTrades(client, message);
|
|
820
|
+
}
|
|
821
|
+
else if (topic === 'depth') {
|
|
822
|
+
this.handleOrderBook(client, message);
|
|
823
|
+
}
|
|
824
|
+
else if ((topic === 'contractExecutionReport') || (topic === 'executionReport')) {
|
|
825
|
+
this.handleOrder(client, message);
|
|
826
|
+
}
|
|
827
|
+
else if (topic === 'ticketInfo') {
|
|
828
|
+
this.handleMyTrade(client, message);
|
|
829
|
+
}
|
|
830
|
+
else if (topic === 'outboundContractPositionInfo') {
|
|
831
|
+
this.handlePosition(client, message);
|
|
832
|
+
}
|
|
833
|
+
else if ((topic === 'outboundAccountInfo') || (topic === 'outboundContractAccountInfo')) {
|
|
834
|
+
this.handleBalance(client, message);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
module.exports = hashkey;
|