ccxt 4.5.48 → 4.5.49

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.
Files changed (43) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +10 -10
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/weex.js +11 -0
  5. package/dist/cjs/src/btcbox.js +1 -1
  6. package/dist/cjs/src/bullish.js +2 -1
  7. package/dist/cjs/src/kraken.js +1 -0
  8. package/dist/cjs/src/krakenfutures.js +10 -1
  9. package/dist/cjs/src/kucoin.js +5 -1
  10. package/dist/cjs/src/lighter.js +6 -3
  11. package/dist/cjs/src/mexc.js +7 -12
  12. package/dist/cjs/src/paradex.js +5 -2
  13. package/dist/cjs/src/pro/binance.js +1 -1
  14. package/dist/cjs/src/pro/cex.js +1 -1
  15. package/dist/cjs/src/pro/coinbase.js +1 -1
  16. package/dist/cjs/src/pro/lighter.js +338 -18
  17. package/dist/cjs/src/pro/weex.js +1906 -0
  18. package/dist/cjs/src/weex.js +3823 -0
  19. package/js/ccxt.d.ts +8 -2
  20. package/js/ccxt.js +6 -2
  21. package/js/src/abstract/weex.d.ts +83 -0
  22. package/js/src/abstract/weex.js +11 -0
  23. package/js/src/btcbox.js +1 -1
  24. package/js/src/bullish.js +2 -1
  25. package/js/src/kraken.js +1 -0
  26. package/js/src/krakenfutures.js +10 -1
  27. package/js/src/kucoin.d.ts +4 -0
  28. package/js/src/kucoin.js +5 -1
  29. package/js/src/lighter.d.ts +1 -0
  30. package/js/src/lighter.js +6 -3
  31. package/js/src/mexc.d.ts +2 -0
  32. package/js/src/mexc.js +7 -12
  33. package/js/src/paradex.js +5 -2
  34. package/js/src/pro/binance.js +1 -1
  35. package/js/src/pro/cex.js +1 -1
  36. package/js/src/pro/coinbase.js +1 -1
  37. package/js/src/pro/lighter.d.ts +37 -2
  38. package/js/src/pro/lighter.js +338 -18
  39. package/js/src/pro/weex.d.ts +330 -0
  40. package/js/src/pro/weex.js +1905 -0
  41. package/js/src/weex.d.ts +675 -0
  42. package/js/src/weex.js +3822 -0
  43. package/package.json +1 -1
@@ -0,0 +1,1906 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var weex$1 = require('../weex.js');
6
+ var errors = require('../base/errors.js');
7
+ var sha256 = require('../static_dependencies/noble-hashes/sha256.js');
8
+ var Cache = require('../base/ws/Cache.js');
9
+
10
+ // ----------------------------------------------------------------------------
11
+ // ---------------------------------------------------------------------------
12
+ class weex extends weex$1["default"] {
13
+ describe() {
14
+ return this.deepExtend(super.describe(), {
15
+ 'has': {
16
+ 'watchBalance': true,
17
+ 'watchBidsAsks': true,
18
+ 'watchMyTrades': true,
19
+ 'watchOHLCV': true,
20
+ 'watchOHLCVForSymbols': true,
21
+ 'watchOrderBook': false,
22
+ 'watchOrderBookForSymbols': false,
23
+ 'watchOrders': true,
24
+ 'watchPositions': true,
25
+ 'watchTicker': true,
26
+ 'watchTickers': true,
27
+ 'watchTrades': true,
28
+ 'watchTradesForSymbols': true,
29
+ 'unWatchBidsAsks': true,
30
+ 'unWatchMyTrades': true,
31
+ 'unWatchOHLCV': true,
32
+ 'unWatchOHLCVForSymbols': true,
33
+ 'unWatchOrderBook': false,
34
+ 'unWatchOrderBookForSymbols': false,
35
+ 'unWatchOrders': true,
36
+ 'unWatchPositions': true,
37
+ 'unWatchTicker': true,
38
+ 'unWatchTickers': true,
39
+ 'unWatchTrades': true,
40
+ 'unWatchTradesForSymbols': true,
41
+ },
42
+ 'urls': {
43
+ 'api': {
44
+ 'ws': {
45
+ 'spot': 'wss://ws-spot.weex.com/v3/ws',
46
+ 'contract': 'wss://ws-contract.weex.com/v3/ws',
47
+ },
48
+ },
49
+ },
50
+ 'options': {
51
+ 'ws': {
52
+ 'options': {
53
+ 'headers': {
54
+ 'User-Agent': 'ccxt', // the exchange requires headers
55
+ },
56
+ },
57
+ },
58
+ 'watchOHLCV': {
59
+ 'priceType': 'LAST_PRICE', // or 'MARK_PRICE' for swap markets
60
+ },
61
+ 'watchOHLCVForSymbols': {
62
+ 'priceType': 'LAST_PRICE', // or 'MARK_PRICE' for swap markets
63
+ },
64
+ 'watchOrderBook': {
65
+ 'depth': '200', // or '15'
66
+ },
67
+ 'watchOrderBookForSymbols': {
68
+ 'depth': '200', // or '15'
69
+ },
70
+ 'watchBalance': {
71
+ 'fetchBalanceSnapshot': true,
72
+ 'awaitBalanceSnapshot': true,
73
+ },
74
+ 'watchPositions': {
75
+ 'fetchPositionsSnapshot': true,
76
+ 'awaitPositionsSnapshot': true,
77
+ },
78
+ },
79
+ 'streaming': {},
80
+ });
81
+ }
82
+ requestId() {
83
+ this.lockId();
84
+ const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
85
+ this.options['requestId'] = requestId;
86
+ this.unlockId();
87
+ return this.numberToString(requestId);
88
+ }
89
+ async subscribePublic(messageHashes, channels, isContract = false, params = {}, subscription = {}) {
90
+ const id = this.requestId();
91
+ let method = 'SUBSCRIBE';
92
+ const unsubscribe = this.safeBool(subscription, 'unsubscribe', false);
93
+ if (unsubscribe) {
94
+ method = 'UNSUBSCRIBE';
95
+ }
96
+ const message = {
97
+ 'id': id,
98
+ 'method': method,
99
+ 'params': channels,
100
+ };
101
+ subscription = this.extend(subscription, { 'id': id });
102
+ const type = isContract ? 'contract' : 'spot';
103
+ const url = this.urls['api']['ws'][type] + '/public';
104
+ return await this.watchMultiple(url, messageHashes, this.deepExtend(message, params), messageHashes, subscription);
105
+ }
106
+ async subscribePrivate(messageHash, subscribeHash, channel, isContract = false, params = {}, subscription = {}) {
107
+ const type = isContract ? 'contract' : 'spot';
108
+ const url = this.urls['api']['ws'][type] + '/private';
109
+ this.authenticate(url);
110
+ let method = 'SUBSCRIBE';
111
+ const unsubscribe = this.safeBool(subscription, 'unsubscribe', false);
112
+ if (unsubscribe) {
113
+ method = 'UNSUBSCRIBE';
114
+ }
115
+ const id = this.requestId();
116
+ const message = {
117
+ 'id': id,
118
+ 'method': method,
119
+ 'params': [channel],
120
+ };
121
+ subscription = this.extend(subscription, { 'id': id });
122
+ return await this.watch(url, messageHash, this.deepExtend(message, params), subscribeHash, subscription);
123
+ }
124
+ authenticate(url) {
125
+ this.checkRequiredCredentials();
126
+ if ((this.clients !== undefined) && (url in this.clients)) {
127
+ return;
128
+ }
129
+ const timestamp = this.nonce();
130
+ const payload = timestamp.toString() + '/v3/ws/private';
131
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256.sha256, 'base64');
132
+ const originalHeaders = this.options['ws']['options']['headers'];
133
+ const userAgent = this.safeString(originalHeaders, 'User-Agent', 'ccxt');
134
+ const extendedOptions = {
135
+ 'ws': {
136
+ 'options': {
137
+ 'headers': {
138
+ 'User-Agent': userAgent,
139
+ 'ACCESS-KEY': this.apiKey,
140
+ 'ACCESS-SIGN': signature,
141
+ 'ACCESS-PASSPHRASE': this.password,
142
+ 'ACCESS-TIMESTAMP': this.numberToString(timestamp),
143
+ },
144
+ },
145
+ },
146
+ };
147
+ this.extendExchangeOptions(extendedOptions);
148
+ // instantiate client
149
+ this.client(url);
150
+ // return headers to original state
151
+ const defaultOptions = {
152
+ 'ws': {
153
+ 'options': {
154
+ 'headers': {
155
+ 'User-Agent': userAgent,
156
+ },
157
+ },
158
+ },
159
+ };
160
+ this.extendExchangeOptions(defaultOptions);
161
+ }
162
+ /**
163
+ * @method
164
+ * @name weex#watchTicker
165
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
166
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Tickers-Channel
167
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Tickers-Channel
168
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
169
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
170
+ * @param {string} [params.name] stream to use can be ticker or miniTicker
171
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
172
+ */
173
+ async watchTicker(symbol, params = {}) {
174
+ await this.loadMarkets();
175
+ symbol = this.symbol(symbol);
176
+ const tickers = await this.watchTickers([symbol], params);
177
+ return tickers[symbol];
178
+ }
179
+ /**
180
+ * @method
181
+ * @name weex#watchTickers
182
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
183
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Tickers-Channel
184
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Tickers-Channel
185
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
186
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
187
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
188
+ */
189
+ async watchTickers(symbols = undefined, params = {}) {
190
+ await this.loadMarkets();
191
+ symbols = this.marketSymbols(symbols, undefined, false, true);
192
+ const firstMarket = this.getMarketFromSymbols(symbols);
193
+ const isContract = firstMarket['contract'];
194
+ const topic = 'ticker';
195
+ const messageHashes = [];
196
+ const channels = [];
197
+ for (let i = 0; i < symbols.length; i++) {
198
+ const symbol = symbols[i];
199
+ const market = this.market(symbol);
200
+ const channelName = market['id'] + '@' + topic;
201
+ const messageHash = topic + '::' + symbol;
202
+ messageHashes.push(messageHash);
203
+ channels.push(channelName);
204
+ }
205
+ const newTicker = await this.subscribePublic(messageHashes, channels, isContract, params);
206
+ if (this.newUpdates) {
207
+ const result = {};
208
+ result[newTicker['symbol']] = newTicker;
209
+ return result;
210
+ }
211
+ return this.filterByArray(this.tickers, 'symbol', symbols);
212
+ }
213
+ /**
214
+ * @method
215
+ * @name weex#unWatchTicker
216
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
217
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Tickers-Channel
218
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Tickers-Channel
219
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
220
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
221
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
222
+ */
223
+ async unWatchTicker(symbol, params = {}) {
224
+ return await this.unWatchTickers([symbol], params);
225
+ }
226
+ /**
227
+ * @method
228
+ * @name weex#unWatchTickers
229
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
230
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Tickers-Channel
231
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Tickers-Channel
232
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
233
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
234
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
235
+ */
236
+ async unWatchTickers(symbols = undefined, params = {}) {
237
+ await this.loadMarkets();
238
+ symbols = this.marketSymbols(symbols, undefined, false, true);
239
+ const firstMarket = this.getMarketFromSymbols(symbols);
240
+ const isContract = firstMarket['contract'];
241
+ const topic = 'ticker';
242
+ const subHashes = [];
243
+ const channels = [];
244
+ const unSubHashes = [];
245
+ for (let i = 0; i < symbols.length; i++) {
246
+ const symbol = symbols[i];
247
+ const market = this.market(symbol);
248
+ const channelName = market['id'] + '@' + topic;
249
+ const messageHash = topic + '::' + symbol;
250
+ const unSubMessageHash = 'unsubscribe::' + messageHash;
251
+ subHashes.push(messageHash);
252
+ channels.push(channelName);
253
+ unSubHashes.push(unSubMessageHash);
254
+ }
255
+ const subscription = {
256
+ 'unsubscribe': true,
257
+ 'symbols': symbols,
258
+ 'messageHashes': unSubHashes,
259
+ 'subMessageHashes': subHashes,
260
+ 'topic': topic,
261
+ };
262
+ return await this.subscribePublic(unSubHashes, channels, isContract, params, subscription);
263
+ }
264
+ handleTicker(client, message) {
265
+ //
266
+ // {
267
+ // "e": "ticker",
268
+ // "E": 1776081628845,
269
+ // "s": "ETHUSDT",
270
+ // "d": [
271
+ // {
272
+ // "p": "-18.93",
273
+ // "P": "-0.008592",
274
+ // "w": "2192.40298388",
275
+ // "c": "2184.20",
276
+ // "o": "2203.13",
277
+ // "h": "2217.34",
278
+ // "l": "2173.32",
279
+ // "v": "359395.800",
280
+ // "q": "787940424.31399",
281
+ // "O": 1775995200000,
282
+ // "C": 1776081600000,
283
+ // "n": 485169,
284
+ // "m": "2184.28",
285
+ // "i": "2185.2025"
286
+ // }
287
+ // ]
288
+ // }
289
+ //
290
+ const market = this.getMarketFromClientAndMessage(client, message);
291
+ const tickers = this.safeList(message, 'd', []);
292
+ const data = this.safeDict(tickers, 0, {});
293
+ const ticker = this.parseWsTicker(data, market);
294
+ const symbol = market['symbol'];
295
+ const messageHash = 'ticker::' + symbol;
296
+ this.tickers[symbol] = ticker;
297
+ client.resolve(this.tickers[symbol], messageHash);
298
+ }
299
+ parseWsTicker(ticker, market = undefined) {
300
+ //
301
+ // {
302
+ // "p": "-18.93",
303
+ // "P": "-0.008592",
304
+ // "w": "2192.40298388",
305
+ // "c": "2184.20",
306
+ // "o": "2203.13",
307
+ // "h": "2217.34",
308
+ // "l": "2173.32",
309
+ // "v": "359395.800",
310
+ // "q": "787940424.31399",
311
+ // "O": 1775995200000,
312
+ // "C": 1776081600000,
313
+ // "n": 485169,
314
+ // "m": "2184.28",
315
+ // "i": "2185.2025"
316
+ // }
317
+ //
318
+ const timestamp = this.safeInteger(ticker, 'C');
319
+ const close = this.safeString(ticker, 'c');
320
+ return this.safeTicker({
321
+ 'symbol': market['symbol'],
322
+ 'timestamp': timestamp,
323
+ 'datetime': this.iso8601(timestamp),
324
+ 'high': this.safeString(ticker, 'h'),
325
+ 'low': this.safeString(ticker, 'l'),
326
+ 'bid': this.safeString(ticker, 'b'),
327
+ 'bidVolume': this.safeString(ticker, 'B'),
328
+ 'ask': this.safeString(ticker, 'a'),
329
+ 'askVolume': this.safeString(ticker, 'A'),
330
+ 'vwap': this.safeString(ticker, 'w'),
331
+ 'open': this.safeString(ticker, 'o'),
332
+ 'close': close,
333
+ 'last': close,
334
+ 'previousClose': this.safeString(ticker, 'x'),
335
+ 'change': this.safeString(ticker, 'p'),
336
+ 'percentage': this.safeString(ticker, 'P'),
337
+ 'average': this.safeString(ticker, 'w'),
338
+ 'baseVolume': this.safeString(ticker, 'v'),
339
+ 'quoteVolume': this.safeString(ticker, 'q'),
340
+ 'markPrice': this.safeString(ticker, 'm'),
341
+ 'indexPrice': this.safeString(ticker, 'i'),
342
+ 'info': ticker,
343
+ }, market);
344
+ }
345
+ /**
346
+ * @method
347
+ * @name weex#watchTrades
348
+ * @description get the list of most recent trades for a particular symbol
349
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Trades-Channel
350
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Trades-Channel
351
+ * @param {string} symbol unified symbol of the market to fetch trades for
352
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
353
+ * @param {int} [limit] the maximum amount of trades to fetch
354
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
355
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
356
+ */
357
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
358
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
359
+ }
360
+ /**
361
+ * @method
362
+ * @name weex#watchTradesForSymbols
363
+ * @description get the list of most recent trades for a list of symbols
364
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Trades-Channel
365
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Trades-Channel
366
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
367
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
368
+ * @param {int} [limit] the maximum amount of trades to fetch
369
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
370
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
371
+ */
372
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
373
+ await this.loadMarkets();
374
+ symbols = this.marketSymbols(symbols, undefined, false, true);
375
+ const firstMarket = this.getMarketFromSymbols(symbols);
376
+ const isContract = firstMarket['contract'];
377
+ const topic = 'trade';
378
+ const messageHashes = [];
379
+ const channels = [];
380
+ for (let i = 0; i < symbols.length; i++) {
381
+ const symbol = symbols[i];
382
+ const market = this.market(symbol);
383
+ const channelName = market['id'] + '@' + topic;
384
+ const messageHash = topic + '::' + symbol;
385
+ messageHashes.push(messageHash);
386
+ channels.push(channelName);
387
+ }
388
+ const trades = await this.subscribePublic(messageHashes, channels, isContract, params);
389
+ if (this.newUpdates) {
390
+ const first = this.safeValue(trades, 0);
391
+ const tradeSymbol = this.safeString(first, 'symbol');
392
+ limit = trades.getLimit(tradeSymbol, limit);
393
+ }
394
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
395
+ }
396
+ /**
397
+ * @method
398
+ * @name weex#unWatchTrades
399
+ * @description unsubscribes from the trades channel
400
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Trades-Channel
401
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Trades-Channel
402
+ * @param {string} symbol unified symbol of the market to fetch trades for
403
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
404
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
405
+ */
406
+ async unWatchTrades(symbol, params = {}) {
407
+ await this.loadMarkets();
408
+ return await this.unWatchTradesForSymbols([symbol], params);
409
+ }
410
+ /**
411
+ * @method
412
+ * @name weex#unWatchTradesForSymbols
413
+ * @description unsubscribes from the trades channel
414
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Trades-Channel
415
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Trades-Channel
416
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
417
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
418
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
419
+ */
420
+ async unWatchTradesForSymbols(symbols, params = {}) {
421
+ await this.loadMarkets();
422
+ symbols = this.marketSymbols(symbols, undefined, false, true);
423
+ const firstMarket = this.getMarketFromSymbols(symbols);
424
+ const isContract = firstMarket['contract'];
425
+ const topic = 'trade';
426
+ const subHashes = [];
427
+ const channels = [];
428
+ const unSubHashes = [];
429
+ for (let i = 0; i < symbols.length; i++) {
430
+ const symbol = symbols[i];
431
+ const market = this.market(symbol);
432
+ const channelName = market['id'] + '@' + topic;
433
+ const messageHash = topic + '::' + symbol;
434
+ const unSubMessageHash = 'unsubscribe::' + messageHash;
435
+ subHashes.push(messageHash);
436
+ channels.push(channelName);
437
+ unSubHashes.push(unSubMessageHash);
438
+ }
439
+ const subscription = {
440
+ 'unsubscribe': true,
441
+ 'symbols': symbols,
442
+ 'messageHashes': unSubHashes,
443
+ 'subMessageHashes': subHashes,
444
+ 'topic': 'trades',
445
+ };
446
+ return await this.subscribePublic(unSubHashes, channels, isContract, params, subscription);
447
+ }
448
+ handleTrade(client, message) {
449
+ //
450
+ // {
451
+ // "e": "trade",
452
+ // "E": 1776104608321,
453
+ // "s": "ETHUSDT",
454
+ // "d": [
455
+ // {
456
+ // "T": 1776104608298,
457
+ // "t": "41099265-7985-4f4c-af93-2cc3bc1cf13b",
458
+ // "p": "2225.15",
459
+ // "q": "0.02525",
460
+ // "v": "56.1850375",
461
+ // "m": false
462
+ // }
463
+ // ]
464
+ // }
465
+ //
466
+ const market = this.getMarketFromClientAndMessage(client, message);
467
+ const symbol = market['symbol'];
468
+ const messageHash = 'trade::' + symbol;
469
+ if (!(symbol in this.trades)) {
470
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
471
+ this.trades[symbol] = new Cache.ArrayCache(limit);
472
+ }
473
+ const tradesArray = this.trades[symbol];
474
+ const data = this.safeList(message, 'd', []);
475
+ const newTrades = [];
476
+ for (let i = 0; i < data.length; i++) {
477
+ const rawTrade = this.safeDict(data, i, {});
478
+ const trade = this.parseWsTrade(rawTrade, market);
479
+ newTrades.push(trade);
480
+ }
481
+ const sorted = this.sortBy(newTrades, 'timestamp');
482
+ for (let j = 0; j < sorted.length; j++) {
483
+ const sortedTrade = sorted[j];
484
+ tradesArray.append(sortedTrade);
485
+ }
486
+ this.trades[symbol] = tradesArray;
487
+ client.resolve(tradesArray, messageHash);
488
+ }
489
+ parseWsTrade(trade, market = undefined) {
490
+ //
491
+ // {
492
+ // "T": 1776089287762,
493
+ // "t": "df4d1af1-71e8-400d-9571-f2cee2e6bea8",
494
+ // "p": "2203.73",
495
+ // "q": "7.214",
496
+ // "v": "15897.70822",
497
+ // "m": false
498
+ // }
499
+ //
500
+ const timestamp = this.safeInteger(trade, 'T');
501
+ return this.safeTrade({
502
+ 'info': trade,
503
+ 'id': this.safeString(trade, 't'),
504
+ 'timestamp': timestamp,
505
+ 'datetime': this.iso8601(timestamp),
506
+ 'symbol': market['symbol'],
507
+ 'order': undefined,
508
+ 'type': undefined,
509
+ 'side': undefined,
510
+ 'takerOrMaker': undefined,
511
+ 'price': this.safeString(trade, 'p'),
512
+ 'amount': this.safeString(trade, 'q'),
513
+ 'cost': this.safeString(trade, 'v'),
514
+ 'fee': undefined,
515
+ }, market);
516
+ }
517
+ /**
518
+ * @method
519
+ * @name weex#watchOHLCV
520
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
521
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Candlesticks-Channel
522
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Candlesticks-Channel
523
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
524
+ * @param {string} timeframe the length of time each candle represents
525
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
526
+ * @param {int} [limit] the maximum amount of candles to fetch
527
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
528
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
529
+ */
530
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
531
+ const extendedParams = this.extend(params, {
532
+ 'callerMethodName': 'watchOHLCV',
533
+ });
534
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, extendedParams);
535
+ return result[symbol][timeframe];
536
+ }
537
+ /**
538
+ * @method
539
+ * @name weex#watchOHLCVForSymbols
540
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
541
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Candlesticks-Channel
542
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Candlesticks-Channel
543
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
544
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
545
+ * @param {int} [limit] the maximum amount of candles to fetch
546
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
547
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
548
+ */
549
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
550
+ await this.loadMarkets();
551
+ const callerMethodName = this.safeString(params, 'callerMethodName', 'watchOHLCVForSymbols');
552
+ params = this.omit(params, 'callerMethodName');
553
+ const channels = [];
554
+ const messageHashes = [];
555
+ const firstEntry = this.safeList(symbolsAndTimeframes, 0, []);
556
+ const firstSymbol = this.safeString(firstEntry, 0);
557
+ const firstMarket = this.market(firstSymbol);
558
+ const isContract = firstMarket['contract'];
559
+ let priceType = 'LAST_PRICE';
560
+ if (isContract) {
561
+ [priceType, params] = this.handleOptionAndParams2(params, callerMethodName, 'price', 'priceType', priceType);
562
+ }
563
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
564
+ const data = this.safeList(symbolsAndTimeframes, i);
565
+ let symbolString = this.safeString(data, 0);
566
+ const market = this.market(symbolString);
567
+ if (market['type'] !== firstMarket['type']) {
568
+ throw new errors.BadRequest(this.id + ' ' + callerMethodName + ' market symbols must be of the same type');
569
+ }
570
+ symbolString = market['symbol'];
571
+ const unifiedTimeframe = this.safeString(data, 1, '1');
572
+ const interval = this.safeString(this.timeframes, unifiedTimeframe, unifiedTimeframe);
573
+ const channel = market['id'] + '@kline_' + interval + '_' + priceType;
574
+ const messageHash = 'ohlcv::' + symbolString + '::' + unifiedTimeframe;
575
+ channels.push(channel);
576
+ messageHashes.push(messageHash);
577
+ }
578
+ const [symbol, timeframe, stored] = await this.subscribePublic(messageHashes, channels, isContract, params);
579
+ if (this.newUpdates) {
580
+ limit = stored.getLimit(symbol, limit);
581
+ }
582
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
583
+ return this.createOHLCVObject(symbol, timeframe, filtered);
584
+ }
585
+ /**
586
+ * @method
587
+ * @name weex#unWatchOHLCV
588
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
589
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Candlesticks-Channel
590
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Candlesticks-Channel
591
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
592
+ * @param {string} timeframe the length of time each candle represents
593
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
594
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
595
+ */
596
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
597
+ params['callerMethodName'] = 'unWatchOHLCV';
598
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
599
+ }
600
+ /**
601
+ * @method
602
+ * @name weex#unWatchOHLCVForSymbols
603
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
604
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Candlesticks-Channel
605
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Candlesticks-Channel
606
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
607
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
608
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
609
+ */
610
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
611
+ await this.loadMarkets();
612
+ const callerMethodName = this.safeString(params, 'callerMethodName', 'unWatchOHLCVForSymbols');
613
+ params = this.omit(params, 'callerMethodName');
614
+ const channels = [];
615
+ const subHashes = [];
616
+ const unSubHashes = [];
617
+ const firstEntry = this.safeList(symbolsAndTimeframes, 0, []);
618
+ const firstSymbol = this.safeString(firstEntry, 0);
619
+ const firstMarket = this.market(firstSymbol);
620
+ const isContract = firstMarket['contract'];
621
+ let priceType = 'LAST_PRICE';
622
+ if (isContract) {
623
+ [priceType, params] = this.handleOptionAndParams2(params, callerMethodName, 'price', 'priceType', priceType);
624
+ }
625
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
626
+ const data = this.safeList(symbolsAndTimeframes, i);
627
+ let symbolString = this.safeString(data, 0);
628
+ const market = this.market(symbolString);
629
+ if (market['type'] !== firstMarket['type']) {
630
+ throw new errors.BadRequest(this.id + ' ' + callerMethodName + ' market symbols must be of the same type');
631
+ }
632
+ symbolString = market['symbol'];
633
+ const unifiedTimeframe = this.safeString(data, 1, '1');
634
+ const interval = this.safeString(this.timeframes, unifiedTimeframe, unifiedTimeframe);
635
+ const channel = market['id'] + '@kline_' + interval + '_' + priceType;
636
+ const messageHash = 'ohlcv::' + symbolString + '::' + unifiedTimeframe;
637
+ const unSubMessageHash = 'unsubscribe::' + messageHash;
638
+ channels.push(channel);
639
+ subHashes.push(messageHash);
640
+ unSubHashes.push(unSubMessageHash);
641
+ }
642
+ const subscription = {
643
+ 'unsubscribe': true,
644
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
645
+ 'messageHashes': unSubHashes,
646
+ 'subMessageHashes': subHashes,
647
+ 'topic': 'ohlcv',
648
+ };
649
+ return await this.subscribePublic(unSubHashes, channels, isContract, params, subscription);
650
+ }
651
+ handleOHLCV(client, message) {
652
+ //
653
+ // {
654
+ // e: 'kline',
655
+ // E: 1776095535012,
656
+ // s: 'ETHUSDT',
657
+ // p: 'LAST_PRICE',
658
+ // d: [
659
+ // {
660
+ // t: 1776092400000,
661
+ // T: 1776096000000,
662
+ // s: 'ETHUSDT',
663
+ // i: '1h',
664
+ // o: '2234.18',
665
+ // c: '2205.15',
666
+ // h: '2236.43',
667
+ // l: '2199.53',
668
+ // v: '12505.60574',
669
+ // n: 3381,
670
+ // q: '27682528.6655305',
671
+ // V: '6420.47929',
672
+ // Q: '14213680.1906424'
673
+ // }
674
+ // ]
675
+ // }
676
+ //
677
+ const market = this.getMarketFromClientAndMessage(client, message);
678
+ const symbol = market['symbol'];
679
+ if (!(symbol in this.ohlcvs)) {
680
+ this.ohlcvs[symbol] = {};
681
+ }
682
+ const data = this.safeList(message, 'd', []);
683
+ const firstEntry = this.safeDict(data, 0, {});
684
+ const interval = this.safeString(firstEntry, 'i');
685
+ const timeframe = this.findTimeframe(interval);
686
+ if (!(timeframe in this.ohlcvs[symbol])) {
687
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
688
+ this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit);
689
+ }
690
+ const stored = this.ohlcvs[symbol][timeframe];
691
+ for (let i = 0; i < data.length; i++) {
692
+ const entry = this.safeDict(data, i, {});
693
+ const parsed = this.parseWsOHLCV(entry);
694
+ stored.append(parsed);
695
+ }
696
+ const messageHash = 'ohlcv::' + symbol + '::' + timeframe;
697
+ const resolveData = [symbol, timeframe, stored];
698
+ client.resolve(resolveData, messageHash);
699
+ }
700
+ parseWsOHLCV(ohlcv, market = undefined) {
701
+ //
702
+ // {
703
+ // t: 1776092400000,
704
+ // T: 1776096000000,
705
+ // s: 'ETHUSDT',
706
+ // i: '1h',
707
+ // o: '2234.18',
708
+ // c: '2205.15',
709
+ // h: '2236.43',
710
+ // l: '2199.53',
711
+ // v: '12505.60574',
712
+ // n: 3381,
713
+ // q: '27682528.6655305',
714
+ // V: '6420.47929',
715
+ // Q: '14213680.1906424'
716
+ // }
717
+ //
718
+ return [
719
+ this.safeInteger(ohlcv, 't'),
720
+ this.safeNumber(ohlcv, 'o'),
721
+ this.safeNumber(ohlcv, 'h'),
722
+ this.safeNumber(ohlcv, 'l'),
723
+ this.safeNumber(ohlcv, 'c'),
724
+ this.safeNumber(ohlcv, 'v'),
725
+ ];
726
+ }
727
+ /**
728
+ * @method
729
+ * @name weex#watchOrderBook
730
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
731
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Depth-Channel
732
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Depth-Channel
733
+ * @param {string} symbol unified symbol of the market to fetch the order book for
734
+ * @param {int} [limit] the maximum amount of order book entries to return
735
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
736
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
737
+ */
738
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
739
+ params = this.extend(params, {
740
+ 'callerMethodName': 'watchOrderBook',
741
+ });
742
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
743
+ }
744
+ /**
745
+ * @method
746
+ * @name weex#watchOrderBookForSymbols
747
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
748
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Depth-Channel
749
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Depth-Channel
750
+ * @param {string[]} symbols unified array of symbols
751
+ * @param {int} [limit] the maximum amount of order book entries to return
752
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
753
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
754
+ */
755
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
756
+ await this.loadMarkets();
757
+ symbols = this.marketSymbols(symbols, undefined, false, true);
758
+ const firstMarket = this.getMarketFromSymbols(symbols);
759
+ const isContract = firstMarket['contract'];
760
+ const callerMethodName = this.safeString(params, 'callerMethodName', 'watchOrderBookForSymbols');
761
+ params = this.omit(params, 'callerMethodName');
762
+ let depth = '200';
763
+ [depth, params] = this.handleOptionAndParams(params, callerMethodName, 'depth', depth);
764
+ const messageHashes = [];
765
+ const channels = [];
766
+ for (let i = 0; i < symbols.length; i++) {
767
+ const symbol = symbols[i];
768
+ const market = this.market(symbol);
769
+ const messageHash = 'orderbook::' + symbol;
770
+ const channel = market['id'] + '@depth' + depth;
771
+ messageHashes.push(messageHash);
772
+ channels.push(channel);
773
+ }
774
+ const subscription = {
775
+ 'limit': limit,
776
+ };
777
+ const orderbook = await this.subscribePublic(messageHashes, channels, isContract, params, subscription);
778
+ return orderbook.limit();
779
+ }
780
+ /**
781
+ * @method
782
+ * @name weex#unWatchOrderBook
783
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
784
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Depth-Channel
785
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Depth-Channel
786
+ * @param {string} symbol unified array of symbols
787
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
788
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
789
+ */
790
+ async unWatchOrderBook(symbol, params = {}) {
791
+ params = this.extend(params, {
792
+ 'callerMethodName': 'unWatchOrderBook',
793
+ });
794
+ return await this.unWatchOrderBookForSymbols([symbol], params);
795
+ }
796
+ /**
797
+ * @method
798
+ * @name weex#unWatchOrderBookForSymbols
799
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
800
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/Depth-Channel
801
+ * @see https://www.weex.com/api-doc/contract/Websocket/public/Depth-Channel
802
+ * @param {string[]} symbols unified array of symbols
803
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
804
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
805
+ */
806
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
807
+ await this.loadMarkets();
808
+ symbols = this.marketSymbols(symbols, undefined, false, true);
809
+ const firstMarket = this.getMarketFromSymbols(symbols);
810
+ const isContract = firstMarket['contract'];
811
+ const callerMethodName = this.safeString(params, 'callerMethodName', 'unWatchOrderBookForSymbols');
812
+ params = this.omit(params, 'callerMethodName');
813
+ let depth = '200';
814
+ [depth, params] = this.handleOptionAndParams(params, callerMethodName, 'depth', depth);
815
+ const subHashes = [];
816
+ const channels = [];
817
+ const unSubHashes = [];
818
+ for (let i = 0; i < symbols.length; i++) {
819
+ const symbol = symbols[i];
820
+ const market = this.market(symbol);
821
+ const messageHash = 'orderbook::' + symbol;
822
+ const channel = market['id'] + '@depth' + depth;
823
+ const unSubMessageHash = 'unsubscribe::' + messageHash;
824
+ subHashes.push(messageHash);
825
+ channels.push(channel);
826
+ unSubHashes.push(unSubMessageHash);
827
+ }
828
+ const subscription = {
829
+ 'unsubscribe': true,
830
+ 'symbols': symbols,
831
+ 'messageHashes': unSubHashes,
832
+ 'subMessageHashes': subHashes,
833
+ 'topic': 'orderbook',
834
+ };
835
+ return await this.subscribePublic(unSubHashes, channels, isContract, params, subscription);
836
+ }
837
+ handleOrderBook(client, message) {
838
+ //
839
+ // {
840
+ // "e": "depth",
841
+ // "E": 1776098967972,
842
+ // "s": "ETHUSDT",
843
+ // "U": 14181847790,
844
+ // "u": 14181847802,
845
+ // "l": 200,
846
+ // "d": "CHANGED",
847
+ // "b": [ [ "2227.21", "0" ], [ "2227.20", "46.519" ] ],
848
+ // "a": [ [ "2227.21", "44.092" ], [ "2227.26", "0" ] ]
849
+ // }
850
+ //
851
+ const market = this.getMarketFromClientAndMessage(client, message);
852
+ const symbol = market['symbol'];
853
+ const messageHash = 'orderbook::' + symbol;
854
+ if (!(symbol in this.orderbooks)) {
855
+ const subscription = this.safeDict(client.subscriptions, messageHash, {});
856
+ const limit = this.safeInteger(subscription, 'limit');
857
+ if (limit !== undefined) {
858
+ this.orderbooks[symbol] = this.orderBook({}, limit);
859
+ }
860
+ else {
861
+ this.orderbooks[symbol] = this.orderBook({});
862
+ }
863
+ }
864
+ const orderbook = this.orderbooks[symbol];
865
+ const timestamp = this.safeInteger(message, 'E');
866
+ const event = this.safeString(message, 'e');
867
+ const nonce = this.safeInteger(message, 'u');
868
+ if (event === 'depthSnapshot') {
869
+ const parsed = this.parseOrderBook(message, symbol, timestamp, 'b', 'a');
870
+ parsed['nonce'] = nonce;
871
+ orderbook.reset(parsed);
872
+ }
873
+ else {
874
+ const asks = this.safeList(message, 'a', []);
875
+ const bids = this.safeList(message, 'b', []);
876
+ this.handleDeltas(orderbook['asks'], asks);
877
+ this.handleDeltas(orderbook['bids'], bids);
878
+ orderbook['timestamp'] = timestamp;
879
+ orderbook['datetime'] = this.iso8601(timestamp);
880
+ orderbook['nonce'] = nonce;
881
+ }
882
+ client.resolve(orderbook, messageHash);
883
+ }
884
+ handleDelta(bookside, delta) {
885
+ const bidAsk = this.parseBidAsk(delta);
886
+ bookside.storeArray(bidAsk);
887
+ }
888
+ /**
889
+ * @method
890
+ * @name weex#watchBidsAsks
891
+ * @description watches best bid & ask for spot symbols
892
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/BookTicker-Channel
893
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
894
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
895
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
896
+ */
897
+ async watchBidsAsks(symbols = undefined, params = {}) {
898
+ await this.loadMarkets();
899
+ symbols = this.marketSymbols(symbols, undefined, false, true);
900
+ const firstMarket = this.getMarketFromSymbols(symbols);
901
+ if (firstMarket['contract']) {
902
+ throw new errors.NotSupported(this.id + ' watchBidsAsks is supported for spot markets only');
903
+ }
904
+ const messageHashes = [];
905
+ const channels = [];
906
+ for (let i = 0; i < symbols.length; i++) {
907
+ const symbol = symbols[i];
908
+ const market = this.market(symbol);
909
+ const channelName = market['id'] + '@' + 'bookTicker';
910
+ const messageHash = 'bidask::' + symbol;
911
+ messageHashes.push(messageHash);
912
+ channels.push(channelName);
913
+ }
914
+ const newTicker = await this.subscribePublic(messageHashes, channels, false, params);
915
+ if (this.newUpdates) {
916
+ const result = {};
917
+ result[newTicker['symbol']] = newTicker;
918
+ return result;
919
+ }
920
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
921
+ }
922
+ /**
923
+ * @method
924
+ * @name weex#unWatchBidsAsks
925
+ * @description unWatches best bid & ask for spot symbols
926
+ * @see https://www.weex.com/api-doc/spot/Websocket/public/BookTicker-Channel
927
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
928
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
929
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
930
+ */
931
+ async unWatchBidsAsks(symbols = undefined, params = {}) {
932
+ await this.loadMarkets();
933
+ symbols = this.marketSymbols(symbols, undefined, false, true);
934
+ const firstMarket = this.getMarketFromSymbols(symbols);
935
+ if (firstMarket['contract']) {
936
+ throw new errors.NotSupported(this.id + ' unWatchBidsAsks is supported for spot markets only');
937
+ }
938
+ const subHashes = [];
939
+ const channels = [];
940
+ const unSubHashes = [];
941
+ for (let i = 0; i < symbols.length; i++) {
942
+ const symbol = symbols[i];
943
+ const market = this.market(symbol);
944
+ const channelName = market['id'] + '@' + 'bookTicker';
945
+ const messageHash = 'bidask::' + symbol;
946
+ const unSubMessageHash = 'unsubscribe::' + messageHash;
947
+ subHashes.push(messageHash);
948
+ channels.push(channelName);
949
+ unSubHashes.push(unSubMessageHash);
950
+ }
951
+ const subscription = {
952
+ 'unsubscribe': true,
953
+ 'symbols': symbols,
954
+ 'messageHashes': unSubHashes,
955
+ 'subMessageHashes': subHashes,
956
+ 'topic': 'bidsasks',
957
+ };
958
+ return await this.subscribePublic(unSubHashes, channels, false, params, subscription);
959
+ }
960
+ handleBidAsk(client, message) {
961
+ //
962
+ // {
963
+ // "e": "bookTicker",
964
+ // "E": 1776103547551,
965
+ // "s": "ETHUSDT",
966
+ // "u": 1776103547547,
967
+ // "b": "2227.39",
968
+ // "B": "1.05512",
969
+ // "a": "2227.40",
970
+ // "A": "6.30889"
971
+ // }
972
+ //
973
+ const market = this.getMarketFromClientAndMessage(client, message);
974
+ const ticker = this.parseWsBidAsk(message, market);
975
+ const symbol = ticker['symbol'];
976
+ this.bidsasks[symbol] = ticker;
977
+ const messageHash = 'bidask::' + symbol;
978
+ client.resolve(ticker, messageHash);
979
+ }
980
+ parseWsBidAsk(message, market = undefined) {
981
+ const timestamp = this.safeInteger(message, 'E');
982
+ return this.safeTicker({
983
+ 'symbol': market['symbol'],
984
+ 'timestamp': timestamp,
985
+ 'datetime': this.iso8601(timestamp),
986
+ 'ask': this.safeString(message, 'a'),
987
+ 'askVolume': this.safeString(message, 'A'),
988
+ 'bid': this.safeString(message, 'b'),
989
+ 'bidVolume': this.safeString(message, 'B'),
990
+ 'info': message,
991
+ }, market);
992
+ }
993
+ /**
994
+ * @method
995
+ * @name weex#watchMyTrades
996
+ * @description watches information on multiple trades made by the user
997
+ * @see https://www.weex.com/api-doc/spot/Websocket/private/Fill-Channel
998
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Fill-Channel
999
+ * @param {string} symbol unified market symbol of the market trades were made in
1000
+ * @param {int} [since] the earliest time in ms to fetch trades for
1001
+ * @param {int} [limit] the maximum number of trade structures to retrieve
1002
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1003
+ * @param {string} [params.type] spot or swap, default is spot if symbol is not provided
1004
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
1005
+ */
1006
+ async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1007
+ await this.loadMarkets();
1008
+ let marketType = undefined;
1009
+ let market = undefined;
1010
+ if (symbol !== undefined) {
1011
+ market = this.market(symbol);
1012
+ symbol = market['symbol'];
1013
+ }
1014
+ [marketType, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
1015
+ const isContract = (marketType !== 'spot');
1016
+ let messageHash = isContract ? 'myContractTrades' : 'myTrades';
1017
+ const subscriptionHash = messageHash;
1018
+ if (symbol !== undefined) {
1019
+ messageHash += '::' + symbol;
1020
+ }
1021
+ const channel = 'fill';
1022
+ const trades = await this.subscribePrivate(messageHash, subscriptionHash, channel, isContract, params);
1023
+ if (this.newUpdates) {
1024
+ limit = trades.getLimit(symbol, limit);
1025
+ }
1026
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
1027
+ }
1028
+ /**
1029
+ * @method
1030
+ * @name weex#unWatchMyTrades
1031
+ * @description unWatches information on multiple trades made by the user
1032
+ * @see https://www.weex.com/api-doc/spot/Websocket/private/Fill-Channel
1033
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Fill-Channel
1034
+ * @param {string} [symbol] not used by the exchange
1035
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1036
+ * @param {string} [params.type] spot or swap, default is spot
1037
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1038
+ */
1039
+ async unWatchMyTrades(symbol = undefined, params = {}) {
1040
+ if (symbol !== undefined) {
1041
+ throw new errors.NotSupported(this.id + ' unWatchMyTrades does not support a symbol argument. Unsubscribing from myTrades is global for all symbols.');
1042
+ }
1043
+ let marketType = undefined;
1044
+ [marketType, params] = this.handleMarketTypeAndParams('unWatchMyTrades', undefined, params);
1045
+ const isContract = (marketType !== 'spot');
1046
+ const subHash = isContract ? 'myContractTrades' : 'myTrades';
1047
+ const unSubHash = 'unsubscribe::' + subHash;
1048
+ const channel = 'fill';
1049
+ const subscription = {
1050
+ 'unsubscribe': true,
1051
+ 'messageHashes': [unSubHash],
1052
+ 'subMessageHashes': [subHash],
1053
+ 'topic': 'myTrades',
1054
+ 'subHashIsPrefix': true,
1055
+ };
1056
+ return await this.subscribePrivate(unSubHash, unSubHash, channel, isContract, params, subscription);
1057
+ }
1058
+ handleMyTrades(client, message) {
1059
+ //
1060
+ // spot
1061
+ // {
1062
+ // e: 'fill',
1063
+ // E: 1776174283564,
1064
+ // v: 83,
1065
+ // msgEvent: 'OrderUpdate',
1066
+ // d: [
1067
+ // {
1068
+ // id: '738928502249620072',
1069
+ // symbol: 'DOGEUSDT',
1070
+ // baseCoin: 'DOGE',
1071
+ // quoteCoin: 'USDT',
1072
+ // orderId: '738928502174122600',
1073
+ // orderSide: 'SELL',
1074
+ // fillSize: '200.0',
1075
+ // fillValue: '19.098000',
1076
+ // fillFee: '0.01909800',
1077
+ // direction: 'TAKER',
1078
+ // createdTime: '1776174283564',
1079
+ // updatedTime: '1776174283564'
1080
+ // }
1081
+ // ]
1082
+ // }
1083
+ //
1084
+ // swap
1085
+ // {
1086
+ // "id": "738957755401896296",
1087
+ // "coin": "USDT",
1088
+ // "symbol": "DOGEUSDT",
1089
+ // "orderId": "738957755376730472",
1090
+ // "marginMode": "CROSSED",
1091
+ // "separatedMode": "COMBINED",
1092
+ // "separatedOpenOrderId": "0",
1093
+ // "positionSide": "LONG",
1094
+ // "orderSide": "BUY",
1095
+ // "fillSize": "100",
1096
+ // "fillValue": "9.59500",
1097
+ // "fillFee": "0.00767600",
1098
+ // "liquidateFee": "0",
1099
+ // "realizePnl": "0",
1100
+ // "direction": "TAKER",
1101
+ // "createdTime": "1776181258059",
1102
+ // "updatedTime": "1776181258059"
1103
+ // }
1104
+ //
1105
+ if (this.myTrades === undefined) {
1106
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
1107
+ this.myTrades = new Cache.ArrayCacheBySymbolById(limit);
1108
+ }
1109
+ const trades = this.myTrades;
1110
+ const data = this.safeList(message, 'd', []);
1111
+ const symbols = {};
1112
+ for (let i = 0; i < data.length; i++) {
1113
+ const trade = this.safeDict(data, i, {});
1114
+ const parsed = this.parseWsMyTrade(trade);
1115
+ const symbol = parsed['symbol'];
1116
+ symbols[symbol] = true;
1117
+ trades.append(parsed);
1118
+ }
1119
+ let messageHash = 'myTrades';
1120
+ const symbolKeys = Object.keys(symbols);
1121
+ const market = this.getMarketFromSymbols(symbolKeys);
1122
+ if (market['contract']) {
1123
+ messageHash = 'myContractTrades';
1124
+ }
1125
+ for (let j = 0; j < symbolKeys.length; j++) {
1126
+ const symbol = symbolKeys[j];
1127
+ const symbolMessageHash = messageHash + '::' + symbol;
1128
+ client.resolve(trades, symbolMessageHash);
1129
+ }
1130
+ client.resolve(trades, messageHash);
1131
+ }
1132
+ parseWsMyTrade(trade, market = undefined) {
1133
+ //
1134
+ // spot
1135
+ // {
1136
+ // id: '738928502249620072',
1137
+ // symbol: 'DOGEUSDT',
1138
+ // baseCoin: 'DOGE',
1139
+ // quoteCoin: 'USDT',
1140
+ // orderId: '738928502174122600',
1141
+ // orderSide: 'SELL',
1142
+ // fillSize: '200.0',
1143
+ // fillValue: '19.098000',
1144
+ // fillFee: '0.01909800',
1145
+ // direction: 'TAKER',
1146
+ // createdTime: '1776174283564',
1147
+ // updatedTime: '1776174283564'
1148
+ // }
1149
+ //
1150
+ const timestamp = this.safeInteger(trade, 'createdTime');
1151
+ const marketId = this.safeString(trade, 'symbol');
1152
+ let marketType = 'spot';
1153
+ const positionSide = this.safeString(trade, 'positionSide');
1154
+ if (positionSide !== undefined) {
1155
+ marketType = 'swap';
1156
+ }
1157
+ market = this.safeMarket(marketId, undefined, undefined, marketType);
1158
+ const side = this.safeStringLower(trade, 'orderSide');
1159
+ let fee = undefined;
1160
+ const commission = this.safeString(trade, 'fillFee');
1161
+ if (commission !== undefined) {
1162
+ const commissionAsset = this.safeString(trade, 'coin');
1163
+ let feeCurrency = this.safeCurrencyCode(commissionAsset);
1164
+ if (marketType === 'spot') {
1165
+ if (side === 'buy') {
1166
+ feeCurrency = market['base'];
1167
+ }
1168
+ else {
1169
+ feeCurrency = market['quote'];
1170
+ }
1171
+ }
1172
+ fee = {
1173
+ 'cost': commission,
1174
+ 'currency': feeCurrency,
1175
+ };
1176
+ }
1177
+ return this.safeTrade({
1178
+ 'info': trade,
1179
+ 'id': this.safeString(trade, 'id'),
1180
+ 'timestamp': timestamp,
1181
+ 'datetime': this.iso8601(timestamp),
1182
+ 'symbol': market['symbol'],
1183
+ 'order': this.safeString(trade, 'orderId'),
1184
+ 'type': this.safeString(trade, 'type'),
1185
+ 'side': side,
1186
+ 'takerOrMaker': this.safeStringLower(trade, 'direction'),
1187
+ 'price': undefined,
1188
+ 'amount': this.safeString(trade, 'fillSize'),
1189
+ 'cost': this.safeString(trade, 'fillValue'),
1190
+ 'fee': fee,
1191
+ });
1192
+ }
1193
+ /**
1194
+ * @method
1195
+ * @name weex#watchOrders
1196
+ * @description watches information on multiple orders made by the user
1197
+ * @see https://www.weex.com/api-doc/spot/Websocket/private/Order-Channel
1198
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Order-Channel
1199
+ * @param {string} symbol unified market symbol of the market orders were made in
1200
+ * @param {int} [since] the earliest time in ms to fetch orders for
1201
+ * @param {int} [limit] the maximum number of order structures to retrieve
1202
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1203
+ * @param {string} [params.type] spot or swap, default is spot if symbol is not provided
1204
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1205
+ */
1206
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1207
+ await this.loadMarkets();
1208
+ let market = undefined;
1209
+ if (symbol !== undefined) {
1210
+ market = this.market(symbol);
1211
+ symbol = market['symbol'];
1212
+ }
1213
+ let marketType = undefined;
1214
+ [marketType, params] = this.handleMarketTypeAndParams('watchOrders', market, params);
1215
+ const isContract = (marketType !== 'spot');
1216
+ let messageHash = isContract ? 'contractOrders' : 'orders';
1217
+ const subscriptionHash = messageHash;
1218
+ if (symbol !== undefined) {
1219
+ messageHash += '::' + symbol;
1220
+ }
1221
+ const channel = 'orders';
1222
+ const orders = await this.subscribePrivate(messageHash, subscriptionHash, channel, isContract, params);
1223
+ if (this.newUpdates) {
1224
+ limit = orders.getLimit(symbol, limit);
1225
+ }
1226
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
1227
+ }
1228
+ /**
1229
+ * @method
1230
+ * @name weex#unWatchOrders
1231
+ * @description unWatches information on multiple orders made by the user
1232
+ * @see https://www.weex.com/api-doc/spot/Websocket/private/Order-Channel
1233
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Order-Channel
1234
+ * @param {string} [symbol] not used by the exchange
1235
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1236
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1237
+ */
1238
+ async unWatchOrders(symbol = undefined, params = {}) {
1239
+ if (symbol !== undefined) {
1240
+ throw new errors.NotSupported(this.id + ' unWatchOrders does not support a symbol argument. Unsubscribing from orders is global for all symbols.');
1241
+ }
1242
+ let marketType = undefined;
1243
+ [marketType, params] = this.handleMarketTypeAndParams('unWatchOrders', undefined, params);
1244
+ const isContract = (marketType !== 'spot');
1245
+ const subHash = isContract ? 'contractOrders' : 'orders';
1246
+ const unSubHash = 'unsubscribe::' + subHash;
1247
+ const channel = 'orders';
1248
+ const subscription = {
1249
+ 'unsubscribe': true,
1250
+ 'messageHashes': [unSubHash],
1251
+ 'subMessageHashes': [subHash],
1252
+ 'topic': 'orders',
1253
+ 'subHashIsPrefix': true,
1254
+ };
1255
+ return await this.subscribePrivate(unSubHash, unSubHash, channel, isContract, params, subscription);
1256
+ }
1257
+ handleOrders(client, message) {
1258
+ //
1259
+ // {
1260
+ // "e": "orders",
1261
+ // "E": 1776184415058,
1262
+ // "v": 153,
1263
+ // "msgEvent": "OrderUpdate",
1264
+ // "d": [
1265
+ // {
1266
+ // "id": "738970996765098600",
1267
+ // "symbol": "DOGEUSDT",
1268
+ // "baseCoin": "DOGE",
1269
+ // "quoteCoin": "USDT",
1270
+ // "orderSide": "SELL",
1271
+ // "price": "0",
1272
+ // "size": "200.0",
1273
+ // "value": "0",
1274
+ // "clientOrderId": "b-WEEX111125-bf78d975ca38422bb6ea65",
1275
+ // "type": "MARKET",
1276
+ // "timeInForce": "IOC",
1277
+ // "reduceOnly": false,
1278
+ // "triggerPrice": "0",
1279
+ // "orderSource": "API",
1280
+ // "openTpslParentOrderId": "0",
1281
+ // "setOpenTp": false,
1282
+ // "setOpenSl": false,
1283
+ // "takerFeeRate": "0.001",
1284
+ // "makerFeeRate": "0.001",
1285
+ // "feeDiscount": "1",
1286
+ // "takerFeeDiscount": "1",
1287
+ // "makerFeeDiscount": "1",
1288
+ // "status": "FILLED",
1289
+ // "triggerTime": "0",
1290
+ // "triggerPriceTime": "0",
1291
+ // "triggerPriceValue": "0",
1292
+ // "cancelReason": "UNKNOWN_ORDER_CANCEL_REASON",
1293
+ // "latestFillPrice": "0.09571",
1294
+ // "maxFillPrice": "0.09571",
1295
+ // "minFillPrice": "0.09571",
1296
+ // "cumFillSize": "200.0",
1297
+ // "cumFillValue": "19.142000",
1298
+ // "cumFillFee": "0.01914200",
1299
+ // "createdTime": "1776184415046",
1300
+ // "updatedTime": "1776184415058"
1301
+ // }
1302
+ // ]
1303
+ // }
1304
+ //
1305
+ const data = this.safeList(message, 'd', []);
1306
+ const symbols = {};
1307
+ if (this.orders === undefined) {
1308
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
1309
+ this.orders = new Cache.ArrayCacheBySymbolById(limit);
1310
+ }
1311
+ const orders = this.orders;
1312
+ const newOrders = [];
1313
+ for (let i = 0; i < data.length; i++) {
1314
+ const rawOrder = this.safeDict(data, i, {});
1315
+ const parsed = this.parseWsOrder(rawOrder);
1316
+ orders.append(parsed);
1317
+ newOrders.push(parsed);
1318
+ const symbol = parsed['symbol'];
1319
+ symbols[symbol] = true;
1320
+ }
1321
+ let messageHash = 'orders';
1322
+ const symbolKeys = Object.keys(symbols);
1323
+ const market = this.getMarketFromSymbols(symbolKeys);
1324
+ if (market['contract']) {
1325
+ messageHash = 'contractOrders';
1326
+ }
1327
+ for (let i = 0; i < symbolKeys.length; i++) {
1328
+ const symbol = symbolKeys[i];
1329
+ const symbolMessageHash = messageHash + '::' + symbol;
1330
+ client.resolve(newOrders, symbolMessageHash);
1331
+ }
1332
+ client.resolve(newOrders, messageHash);
1333
+ }
1334
+ parseWsOrder(order, market = undefined) {
1335
+ //
1336
+ // spot
1337
+ // {
1338
+ // "id": "738970996765098600",
1339
+ // "symbol": "DOGEUSDT",
1340
+ // "baseCoin": "DOGE",
1341
+ // "quoteCoin": "USDT",
1342
+ // "orderSide": "SELL",
1343
+ // "price": "0",
1344
+ // "size": "200.0",
1345
+ // "value": "0",
1346
+ // "clientOrderId": "b-WEEX111125-bf78d975ca38422bb6ea65",
1347
+ // "type": "MARKET",
1348
+ // "timeInForce": "IOC",
1349
+ // "reduceOnly": false,
1350
+ // "triggerPrice": "0",
1351
+ // "orderSource": "API",
1352
+ // "openTpslParentOrderId": "0",
1353
+ // "setOpenTp": false,
1354
+ // "setOpenSl": false,
1355
+ // "takerFeeRate": "0.001",
1356
+ // "makerFeeRate": "0.001",
1357
+ // "feeDiscount": "1",
1358
+ // "takerFeeDiscount": "1",
1359
+ // "makerFeeDiscount": "1",
1360
+ // "status": "FILLED",
1361
+ // "triggerTime": "0",
1362
+ // "triggerPriceTime": "0",
1363
+ // "triggerPriceValue": "0",
1364
+ // "cancelReason": "UNKNOWN_ORDER_CANCEL_REASON",
1365
+ // "latestFillPrice": "0.09571",
1366
+ // "maxFillPrice": "0.09571",
1367
+ // "minFillPrice": "0.09571",
1368
+ // "cumFillSize": "200.0",
1369
+ // "cumFillValue": "19.142000",
1370
+ // "cumFillFee": "0.01914200",
1371
+ // "createdTime": "1776184415046",
1372
+ // "updatedTime": "1776184415058"
1373
+ // }
1374
+ //
1375
+ // swap
1376
+ // {
1377
+ // "id": "617414920861909658",
1378
+ // "coin": "USDT",
1379
+ // "symbol": "BTCUSDT",
1380
+ // "marginMode": "CROSSED",
1381
+ // "separatedMode": "COMBINED",
1382
+ // "separatedOpenOrderId": "0",
1383
+ // "positionSide": "LONG",
1384
+ // "orderSide": "BUY",
1385
+ // "price": "0.0",
1386
+ // "size": "0.10000",
1387
+ // "clientOrderId": "1747203186927FPIZRP",
1388
+ // "type": "MARKET",
1389
+ // "timeInForce": "IOC",
1390
+ // "reduceOnly": false,
1391
+ // "triggerPrice": "0",
1392
+ // "triggerPriceType": "CONTRACT_PRICE",
1393
+ // "orderSource": "WEB",
1394
+ // "openTpslParentOrderId": "0",
1395
+ // "positionTpsl": false,
1396
+ // "setOpenTp": false,
1397
+ // "setOpenSl": false,
1398
+ // "leverage": "20",
1399
+ // "takerFeeRate": "0.0006",
1400
+ // "makerFeeRate": "0.0002",
1401
+ // "feeDiscount": "1",
1402
+ // "liquidateFeeRate": "0.01",
1403
+ // "status": "PENDING",
1404
+ // "triggerTime": "0",
1405
+ // "triggerPriceTime": "0",
1406
+ // "triggerPriceValue": "0",
1407
+ // "cancelReason": "UNKNOWN_ORDER_CANCEL_REASON",
1408
+ // "latestFillPrice": "0",
1409
+ // "maxFillPrice": "0",
1410
+ // "minFillPrice": "0",
1411
+ // "cumFillSize": "0",
1412
+ // "cumFillValue": "0",
1413
+ // "cumFillFee": "0",
1414
+ // "cumLiquidateFee": "0",
1415
+ // "cumRealizePnl": "0",
1416
+ // "createdTime": "1747203188148",
1417
+ // "updatedTime": "1747203188148"
1418
+ // }
1419
+ //
1420
+ const timestamp = this.safeInteger(order, 'createdTime');
1421
+ const marketId = this.safeString(order, 'symbol');
1422
+ let marketType = 'spot';
1423
+ const positionSide = this.safeString(order, 'positionSide');
1424
+ if (positionSide !== undefined) {
1425
+ marketType = 'swap';
1426
+ }
1427
+ market = this.safeMarket(marketId, undefined, undefined, marketType);
1428
+ const side = this.safeStringLower(order, 'orderSide');
1429
+ let fee = undefined;
1430
+ const commission = this.safeString(order, 'cumFillFee');
1431
+ if (commission !== undefined) {
1432
+ const commissionAsset = this.safeString(order, 'coin');
1433
+ let feeCurrency = this.safeCurrencyCode(commissionAsset);
1434
+ if (marketType === 'spot') {
1435
+ if (side === 'buy') {
1436
+ feeCurrency = market['base'];
1437
+ }
1438
+ else {
1439
+ feeCurrency = market['quote'];
1440
+ }
1441
+ }
1442
+ fee = {
1443
+ 'cost': commission,
1444
+ 'currency': feeCurrency,
1445
+ };
1446
+ }
1447
+ const rawStatus = this.safeStringLower(order, 'status');
1448
+ const rawType = this.safeString(order, 'type');
1449
+ const triggerPrice = this.omitZero(this.safeString(order, 'triggerPrice'));
1450
+ let stopLossPrice = undefined;
1451
+ let takeProfitPrice = undefined;
1452
+ if (rawType === 'TAKE_PROFIT_MARKET' || rawType === 'TAKE_PROFIT') {
1453
+ takeProfitPrice = triggerPrice;
1454
+ }
1455
+ else if (rawType === 'STOP_LOSS' || rawType === 'STOP' || rawType === 'STOP_MARKET') {
1456
+ stopLossPrice = triggerPrice;
1457
+ }
1458
+ return this.safeOrder({
1459
+ 'id': this.safeString(order, 'id'),
1460
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
1461
+ 'symbol': market['symbol'],
1462
+ 'type': this.parseOrderType(rawType),
1463
+ 'timeInForce': this.safeString(order, 'timeInForce'),
1464
+ 'postOnly': undefined,
1465
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
1466
+ 'side': side,
1467
+ 'amount': this.safeString(order, 'size'),
1468
+ 'price': this.safeString(order, 'price'),
1469
+ 'triggerPrice': triggerPrice,
1470
+ 'cost': this.safeString(order, 'cumFillValue'),
1471
+ 'filled': this.safeString(order, 'cumFillSize'),
1472
+ 'remaining': undefined,
1473
+ 'timestamp': timestamp,
1474
+ 'datetime': this.iso8601(timestamp),
1475
+ 'fee': fee,
1476
+ 'status': this.parseOrderStatus(rawStatus),
1477
+ 'lastTradeTimestamp': undefined,
1478
+ 'lastUpdateTimestamp': this.safeInteger(order, 'updatedTime'),
1479
+ 'average': undefined,
1480
+ 'trades': undefined,
1481
+ 'stopLossPrice': stopLossPrice,
1482
+ 'takeProfitPrice': takeProfitPrice,
1483
+ 'info': order,
1484
+ }, market);
1485
+ }
1486
+ /**
1487
+ * @method
1488
+ * @name weex#watchBalance
1489
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1490
+ * @see https://www.weex.com/api-doc/spot/Websocket/private/Account-Channel
1491
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Account-Channel
1492
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1493
+ * @param {string} [params.type] 'spot' or 'swap', default is 'spot'
1494
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
1495
+ */
1496
+ async watchBalance(params = {}) {
1497
+ await this.loadMarkets();
1498
+ let type = undefined;
1499
+ [type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
1500
+ const isContract = (type !== 'spot');
1501
+ const urlType = isContract ? 'contract' : 'spot';
1502
+ const url = this.urls['api']['ws'][urlType] + '/private';
1503
+ this.authenticate(url);
1504
+ const client = this.client(url);
1505
+ this.setBalanceCache(client, type);
1506
+ const options = this.safeDict(this.options, 'watchBalance');
1507
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
1508
+ const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
1509
+ if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
1510
+ await client.future(type + ':fetchBalanceSnapshot');
1511
+ }
1512
+ const messageHash = type + ':' + 'balance';
1513
+ return await this.subscribePrivate(messageHash, type, 'account', isContract, params);
1514
+ }
1515
+ setBalanceCache(client, type) {
1516
+ if ((type in client.subscriptions) && (type in this.balance)) {
1517
+ return;
1518
+ }
1519
+ const options = this.safeDict(this.options, 'watchBalance');
1520
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
1521
+ if (fetchBalanceSnapshot) {
1522
+ const messageHash = type + ':fetchBalanceSnapshot';
1523
+ if (!(messageHash in client.futures)) {
1524
+ client.future(messageHash);
1525
+ this.spawn(this.loadBalanceSnapshot, client, messageHash, type);
1526
+ }
1527
+ }
1528
+ else {
1529
+ this.balance[type] = {};
1530
+ }
1531
+ }
1532
+ async loadBalanceSnapshot(client, messageHash, type) {
1533
+ const params = {
1534
+ 'type': type,
1535
+ };
1536
+ const response = await this.fetchBalance(params);
1537
+ this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
1538
+ // don't remove the future from the .futures cache
1539
+ if (messageHash in client.futures) {
1540
+ const future = client.futures[messageHash];
1541
+ future.resolve();
1542
+ client.resolve(this.balance[type], type + ':balance');
1543
+ }
1544
+ }
1545
+ handleBalance(client, message) {
1546
+ //
1547
+ // spot
1548
+ // {
1549
+ // "e": "account",
1550
+ // "E": 1776187844633,
1551
+ // "v": 178,
1552
+ // "msgEvent": "DepositUpdate",
1553
+ // "d": [
1554
+ // {
1555
+ // "coin": "USDT",
1556
+ // "equity": "47.98428060",
1557
+ // "available": "47.98428060",
1558
+ // "frozen": "0"
1559
+ // }
1560
+ // ]
1561
+ // }
1562
+ //
1563
+ // coontract
1564
+ // {
1565
+ // "e": "account",
1566
+ // "E": 1776189629849,
1567
+ // "v": 281,
1568
+ // "msgEvent": "DepositUpdate",
1569
+ // "d": [
1570
+ // {
1571
+ // "coin": "USDT",
1572
+ // "marginMode": "CROSSED",
1573
+ // "crossSymbol": "0",
1574
+ // "isolatedPositionId": "0",
1575
+ // "amount": "0.00000000",
1576
+ // "pendingDepositAmount": "20.00000000",
1577
+ // "pendingWithdrawAmount": "0.00000000",
1578
+ // "pendingTransferInAmount": "0",
1579
+ // "pendingTransferOutAmount": "0",
1580
+ // "liquidating": false,
1581
+ // "legacyAmount": "0.00000000",
1582
+ // "cumDepositAmount": "167.50000925",
1583
+ // "cumWithdrawAmount": "166.94609514",
1584
+ // "cumTransferInAmount": "0",
1585
+ // "cumTransferOutAmount": "0",
1586
+ // "cumMarginMoveInAmount": "10.86162763",
1587
+ // "cumMarginMoveOutAmount": "10.83205378",
1588
+ // "cumPositionOpenLongAmount": "305.59400",
1589
+ // "cumPositionOpenShortAmount": "238.95700",
1590
+ // "cumPositionCloseLongAmount": "305.86600000",
1591
+ // "cumPositionCloseShortAmount": "238.94700000",
1592
+ // "cumPositionFillFeeAmount": "0.00761040",
1593
+ // "cumPositionLiquidateFeeAmount": "0",
1594
+ // "cumPositionFundingAmount": "0.00049824",
1595
+ // "cumOrderFillFeeIncomeAmount": "0",
1596
+ // "cumOrderLiquidateFeeIncomeAmount": "0",
1597
+ // "createdTime": "1775605824300",
1598
+ // "updatedTime": "1776189629849"
1599
+ // }
1600
+ // ]
1601
+ // }
1602
+ //
1603
+ const url = client.url;
1604
+ let accountType = 'spot';
1605
+ if (url.indexOf('contract') >= 0) {
1606
+ accountType = 'swap';
1607
+ }
1608
+ const messageHash = accountType + ':balance';
1609
+ if (this.balance[accountType] === undefined) {
1610
+ this.balance[accountType] = {};
1611
+ }
1612
+ this.balance[accountType]['info'] = message;
1613
+ const balanceUpdates = this.safeList(message, 'd', []);
1614
+ for (let i = 0; i < balanceUpdates.length; i++) {
1615
+ const entry = this.safeDict(balanceUpdates, i);
1616
+ const currencyId = this.safeString(entry, 'coin');
1617
+ const code = this.safeCurrencyCode(currencyId);
1618
+ const account = this.account();
1619
+ account['free'] = this.safeString2(entry, 'available', 'amount');
1620
+ account['used'] = this.safeString(entry, 'frozen');
1621
+ account['total'] = this.safeString2(entry, 'equity', 'legacyAmount');
1622
+ this.balance[accountType][code] = account;
1623
+ }
1624
+ const timestamp = this.safeInteger(message, 'E');
1625
+ this.balance[accountType]['timestamp'] = timestamp;
1626
+ this.balance[accountType]['datetime'] = this.iso8601(timestamp);
1627
+ this.balance[accountType] = this.safeBalance(this.balance[accountType]);
1628
+ client.resolve(this.balance[accountType], messageHash);
1629
+ }
1630
+ /**
1631
+ * @method
1632
+ * @name weex#watchPositions
1633
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Positions-Channel
1634
+ * @description watch all open positions
1635
+ * @param {string[]|undefined} symbols list of unified market symbols
1636
+ * @param {int} [since] the earliest time in ms to fetch positions for
1637
+ * @param {int} [limit] the maximum number of position structures to retrieve
1638
+ * @param {object} params extra parameters specific to the exchange API endpoint
1639
+ * @param {int} [params.accountNumber] account number to query orders for, required
1640
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
1641
+ */
1642
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
1643
+ await this.loadMarkets();
1644
+ const url = this.urls['api']['ws']['contract'] + '/private';
1645
+ this.authenticate(url);
1646
+ const client = this.client(url);
1647
+ symbols = this.marketSymbols(symbols, 'swap', true);
1648
+ let messageHash = 'positions';
1649
+ const subscriptionHash = messageHash;
1650
+ if (symbols !== undefined) {
1651
+ messageHash += '::' + symbols.join(',');
1652
+ }
1653
+ const channel = 'positions';
1654
+ this.setPositionsCache(client, params);
1655
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
1656
+ const awaitPositionsSnapshot = this.handleOption('watchPositions', 'awaitPositionsSnapshot', true);
1657
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
1658
+ const snapshot = await client.future('fetchPositionsSnapshot');
1659
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
1660
+ }
1661
+ const newPositions = await this.subscribePrivate(messageHash, subscriptionHash, channel, true, params);
1662
+ if (this.newUpdates) {
1663
+ return newPositions;
1664
+ }
1665
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
1666
+ }
1667
+ setPositionsCache(client, params = {}) {
1668
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
1669
+ if (fetchPositionsSnapshot) {
1670
+ const messageHash = 'fetchPositionsSnapshot';
1671
+ if (!(messageHash in client.futures)) {
1672
+ client.future(messageHash);
1673
+ this.spawn(this.loadPositionsSnapshot, client, messageHash, params);
1674
+ }
1675
+ }
1676
+ else {
1677
+ this.positions = new Cache.ArrayCacheBySymbolById();
1678
+ }
1679
+ }
1680
+ async loadPositionsSnapshot(client, messageHash, params) {
1681
+ const positions = await this.fetchPositions(undefined, params);
1682
+ this.positions = new Cache.ArrayCacheBySymbolById();
1683
+ const cache = this.positions;
1684
+ for (let i = 0; i < positions.length; i++) {
1685
+ const position = positions[i];
1686
+ cache.append(position);
1687
+ }
1688
+ // don't remove the future from the .futures cache
1689
+ const future = client.futures[messageHash];
1690
+ future.resolve(cache);
1691
+ client.resolve(cache, 'positions');
1692
+ }
1693
+ /**
1694
+ * @method
1695
+ * @name weex#unWatchPositions
1696
+ * @description unWatches all open positions
1697
+ * @see https://www.weex.com/api-doc/contract/Websocket/private/Positions-Channel
1698
+ * @param {string[]} [symbols] not used by the exchange, unsubscription from positions is global for all symbols
1699
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1700
+ * @returns {object} status of the unwatch request
1701
+ */
1702
+ async unWatchPositions(symbols = undefined, params = {}) {
1703
+ if (symbols !== undefined) {
1704
+ throw new errors.NotSupported(this.id + ' unWatchPositions does not support a symbols argument. Unsubscribing from positions is global for all symbols.');
1705
+ }
1706
+ const subHash = 'positions';
1707
+ const unSubHash = 'unsubscribe::' + subHash;
1708
+ const channel = 'positions';
1709
+ const subscription = {
1710
+ 'unsubscribe': true,
1711
+ 'messageHashes': [unSubHash],
1712
+ 'subMessageHashes': [subHash],
1713
+ 'topic': 'positions',
1714
+ 'subHashIsPrefix': true,
1715
+ };
1716
+ return await this.subscribePrivate(unSubHash, unSubHash, channel, true, params, subscription);
1717
+ }
1718
+ handlePositions(client, message) {
1719
+ //
1720
+ // {
1721
+ // "e": "positions",
1722
+ // "E": 1776192398399,
1723
+ // "v": 319,
1724
+ // "msgEvent": "OrderUpdate",
1725
+ // "d": [
1726
+ // {
1727
+ // "id": "739004481374519656",
1728
+ // "coin": "USDT",
1729
+ // "symbol": "DOGEUSDT",
1730
+ // "side": "LONG",
1731
+ // "marginMode": "CROSSED",
1732
+ // "separatedMode": "COMBINED",
1733
+ // "separatedOpenOrderId": "0",
1734
+ // "leverage": "11",
1735
+ // "size": "100",
1736
+ // "openValue": "9.31100",
1737
+ // "openFee": "0.00744880",
1738
+ // "fundingFee": "0",
1739
+ // "isolatedMargin": "0",
1740
+ // "autoAppendIsolatedMargin": false,
1741
+ // "cumOpenSize": "100",
1742
+ // "cumOpenValue": "9.31100",
1743
+ // "cumOpenFee": "0.00744880",
1744
+ // "cumCloseSize": "0",
1745
+ // "cumCloseValue": "0",
1746
+ // "cumCloseFee": "0",
1747
+ // "cumFundingFee": "0",
1748
+ // "cumLiquidateFee": "0",
1749
+ // "createdMatchSequenceId": "5792711540",
1750
+ // "updatedMatchSequenceId": "5792711540",
1751
+ // "createdTime": "1776192398399",
1752
+ // "updatedTime": "1776192398399"
1753
+ // }
1754
+ // ]
1755
+ // }
1756
+ //
1757
+ if (this.positions === undefined) {
1758
+ this.positions = new Cache.ArrayCacheBySymbolById();
1759
+ }
1760
+ const cache = this.positions;
1761
+ const newPositions = [];
1762
+ const data = this.safeList(message, 'd', []);
1763
+ for (let i = 0; i < data.length; i++) {
1764
+ const rawPosition = this.safeDict(data, i, {});
1765
+ const position = this.parsePosition(rawPosition);
1766
+ cache.append(position);
1767
+ newPositions.push(position);
1768
+ }
1769
+ const messageHashes = this.findMessageHashes(client, 'positions::');
1770
+ for (let i = 0; i < messageHashes.length; i++) {
1771
+ const messageHash = messageHashes[i];
1772
+ const parts = messageHash.split('::');
1773
+ const symbolsString = parts[1];
1774
+ const symbols = symbolsString.split(',');
1775
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
1776
+ if (!this.isEmpty(positions)) {
1777
+ client.resolve(positions, messageHash);
1778
+ }
1779
+ }
1780
+ client.resolve(newPositions, 'positions');
1781
+ }
1782
+ getMarketFromClientAndMessage(client, message) {
1783
+ const url = client.url;
1784
+ let marketType = 'spot';
1785
+ if (url.indexOf('contract') >= 0) {
1786
+ marketType = 'swap';
1787
+ }
1788
+ const marketId = this.safeString(message, 's');
1789
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
1790
+ return market;
1791
+ }
1792
+ async pong(client, message) {
1793
+ //
1794
+ // { "event": "ping", "time": "1776078750000" } - public
1795
+ //
1796
+ // { "type": "ping", "time": "1776172740000" } - private
1797
+ //
1798
+ const response = {
1799
+ 'id': this.requestId(),
1800
+ 'method': 'PONG',
1801
+ };
1802
+ await client.send(response);
1803
+ }
1804
+ handlePing(client, message) {
1805
+ this.spawn(this.pong, client, message);
1806
+ }
1807
+ handleSubscriptionStatus(client, message) {
1808
+ //
1809
+ // { "result": true, "id": 2 }
1810
+ //
1811
+ const id = this.safeString(message, 'id');
1812
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
1813
+ const subscription = this.safeDict(subscriptionsById, id, {});
1814
+ const unsubscribe = this.safeBool(subscription, 'unsubscribe', false);
1815
+ if (unsubscribe) {
1816
+ const subHashIsPrefix = this.safeBool(subscription, 'subHashIsPrefix', false);
1817
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1818
+ const subHashes = this.safeList(subscription, 'subMessageHashes', []);
1819
+ for (let i = 0; i < messageHashes.length; i++) {
1820
+ const unSubHash = this.safeString(messageHashes, i);
1821
+ const subHash = this.safeString(subHashes, i);
1822
+ this.cleanUnsubscription(client, subHash, unSubHash, subHashIsPrefix);
1823
+ }
1824
+ this.cleanCache(subscription);
1825
+ }
1826
+ return message;
1827
+ }
1828
+ handleErrorMessage(client, message) {
1829
+ //
1830
+ // {
1831
+ // "result": false,
1832
+ // "id": 1,
1833
+ // "msg": "INVALID_ARGUMENT: invalid symbol : ASDFS_SPBL"
1834
+ // }
1835
+ //
1836
+ const result = this.safeBool(message, 'result', true);
1837
+ if (!result) {
1838
+ const msg = this.safeString(message, 'msg', '');
1839
+ const feedback = this.id + ' ' + this.json(message);
1840
+ try {
1841
+ this.throwExactlyMatchedException(this.exceptions['exact'], msg, feedback);
1842
+ this.throwBroadlyMatchedException(this.exceptions['broad'], msg, feedback);
1843
+ throw new errors.ExchangeError(feedback);
1844
+ }
1845
+ catch (error) {
1846
+ client.reject(error);
1847
+ return true;
1848
+ }
1849
+ }
1850
+ return false;
1851
+ }
1852
+ handleMessage(client, message) {
1853
+ //
1854
+ // { "id": "5", "method": "PONG" }
1855
+ //
1856
+ // { "result": true, "id": 2 }
1857
+ //
1858
+ // {
1859
+ // "result": false,
1860
+ // "id": 1,
1861
+ // "msg": "INVALID_ARGUMENT: invalid symbol : ASDFS_SPBL"
1862
+ // }
1863
+ //
1864
+ if (this.handleErrorMessage(client, message)) {
1865
+ return;
1866
+ }
1867
+ const id = this.safeString(message, 'id');
1868
+ if (id !== undefined) {
1869
+ this.handleSubscriptionStatus(client, message);
1870
+ return;
1871
+ }
1872
+ const event = this.safeStringN(message, ['e', 'event', 'type']);
1873
+ if (event === 'ping') {
1874
+ this.handlePing(client, message);
1875
+ }
1876
+ else if (event === 'ticker') {
1877
+ this.handleTicker(client, message);
1878
+ }
1879
+ else if ((event === 'trade') || (event === 'tradeSnapshot')) {
1880
+ this.handleTrade(client, message);
1881
+ }
1882
+ else if ((event === 'kline') || (event === 'klineSnapshot')) {
1883
+ this.handleOHLCV(client, message);
1884
+ }
1885
+ else if ((event === 'depth') || (event === 'depthSnapshot')) {
1886
+ this.handleOrderBook(client, message);
1887
+ }
1888
+ else if (event === 'bookTicker') {
1889
+ this.handleBidAsk(client, message);
1890
+ }
1891
+ else if (event === 'fill') {
1892
+ this.handleMyTrades(client, message);
1893
+ }
1894
+ else if (event === 'orders') {
1895
+ this.handleOrders(client, message);
1896
+ }
1897
+ else if (event === 'account') {
1898
+ this.handleBalance(client, message);
1899
+ }
1900
+ else if (event === 'positions') {
1901
+ this.handlePositions(client, message);
1902
+ }
1903
+ }
1904
+ }
1905
+
1906
+ exports["default"] = weex;