ccxt 4.4.7 → 4.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/bigone.js +35 -86
  5. package/dist/cjs/src/binance.js +51 -12
  6. package/dist/cjs/src/bingx.js +7 -2
  7. package/dist/cjs/src/bitget.js +3 -0
  8. package/dist/cjs/src/bybit.js +368 -1
  9. package/dist/cjs/src/gate.js +35 -1
  10. package/dist/cjs/src/htx.js +24 -0
  11. package/dist/cjs/src/kucoin.js +2 -1
  12. package/dist/cjs/src/kucoinfutures.js +162 -2
  13. package/dist/cjs/src/okx.js +4 -0
  14. package/dist/cjs/src/pro/binance.js +4 -4
  15. package/dist/cjs/src/pro/bitmart.js +81 -0
  16. package/dist/cjs/src/pro/bitvavo.js +92 -1
  17. package/dist/cjs/src/pro/blofin.js +64 -0
  18. package/dist/cjs/src/pro/hitbtc.js +122 -48
  19. package/dist/cjs/src/pro/hollaex.js +5 -0
  20. package/dist/cjs/src/pro/okx.js +19 -3
  21. package/dist/cjs/src/pro/p2b.js +35 -1
  22. package/dist/cjs/src/pro/whitebit.js +31 -0
  23. package/js/ccxt.d.ts +1 -1
  24. package/js/ccxt.js +1 -1
  25. package/js/src/abstract/bigone.d.ts +1 -1
  26. package/js/src/abstract/binance.d.ts +1 -0
  27. package/js/src/abstract/binancecoinm.d.ts +1 -0
  28. package/js/src/abstract/binanceus.d.ts +1 -0
  29. package/js/src/abstract/binanceusdm.d.ts +1 -0
  30. package/js/src/abstract/bybit.d.ts +5 -0
  31. package/js/src/abstract/kucoinfutures.d.ts +5 -0
  32. package/js/src/abstract/okx.d.ts +2 -0
  33. package/js/src/bigone.js +35 -86
  34. package/js/src/binance.d.ts +15 -15
  35. package/js/src/binance.js +51 -12
  36. package/js/src/bingx.js +7 -2
  37. package/js/src/bitget.js +3 -0
  38. package/js/src/bybit.d.ts +7 -1
  39. package/js/src/bybit.js +368 -1
  40. package/js/src/gate.js +35 -1
  41. package/js/src/htx.js +24 -0
  42. package/js/src/kucoin.js +2 -1
  43. package/js/src/kucoinfutures.d.ts +7 -1
  44. package/js/src/kucoinfutures.js +162 -2
  45. package/js/src/okx.js +4 -0
  46. package/js/src/pro/binance.js +4 -4
  47. package/js/src/pro/bitmart.d.ts +3 -0
  48. package/js/src/pro/bitmart.js +81 -0
  49. package/js/src/pro/bitvavo.d.ts +7 -2
  50. package/js/src/pro/bitvavo.js +92 -1
  51. package/js/src/pro/blofin.d.ts +3 -0
  52. package/js/src/pro/blofin.js +64 -0
  53. package/js/src/pro/hitbtc.d.ts +4 -1
  54. package/js/src/pro/hitbtc.js +122 -48
  55. package/js/src/pro/hollaex.js +5 -0
  56. package/js/src/pro/okx.js +19 -3
  57. package/js/src/pro/p2b.d.ts +2 -1
  58. package/js/src/pro/p2b.js +35 -1
  59. package/js/src/pro/whitebit.d.ts +2 -1
  60. package/js/src/pro/whitebit.js +31 -0
  61. package/package.json +1 -1
@@ -67,9 +67,10 @@ class kucoinfutures extends kucoinfutures$1 {
67
67
  'fetchIsolatedBorrowRates': false,
68
68
  'fetchL3OrderBook': true,
69
69
  'fetchLedger': true,
70
+ 'fetchLeverage': true,
70
71
  'fetchLeverageTiers': false,
71
72
  'fetchMarginAdjustmentHistory': false,
72
- 'fetchMarginMode': false,
73
+ 'fetchMarginMode': true,
73
74
  'fetchMarketLeverageTiers': true,
74
75
  'fetchMarkets': true,
75
76
  'fetchMarkOHLCV': false,
@@ -93,7 +94,7 @@ class kucoinfutures extends kucoinfutures$1 {
93
94
  'fetchTransactionFee': false,
94
95
  'fetchWithdrawals': true,
95
96
  'setLeverage': false,
96
- 'setMarginMode': false,
97
+ 'setMarginMode': true,
97
98
  'transfer': true,
98
99
  'withdraw': undefined,
99
100
  },
@@ -170,12 +171,15 @@ class kucoinfutures extends kucoinfutures$1 {
170
171
  'trade-fees': 1,
171
172
  'history-positions': 1,
172
173
  'getMaxOpenSize': 1,
174
+ 'getCrossUserLeverage': 1,
175
+ 'position/getMarginMode': 1,
173
176
  },
174
177
  'post': {
175
178
  'withdrawals': 1,
176
179
  'transfer-out': 1,
177
180
  'transfer-in': 1,
178
181
  'orders': 1.33,
182
+ 'st-orders': 1.33,
179
183
  'orders/test': 1.33,
180
184
  'position/margin/auto-deposit-status': 1,
181
185
  'position/margin/deposit-margin': 1,
@@ -183,6 +187,8 @@ class kucoinfutures extends kucoinfutures$1 {
183
187
  'bullet-private': 1,
184
188
  'sub/api-key': 1,
185
189
  'sub/api-key/update': 1,
190
+ 'changeCrossUserLeverage': 1,
191
+ 'position/changeMarginMode': 1,
186
192
  },
187
193
  'delete': {
188
194
  'withdrawals/{withdrawalId}': 1,
@@ -317,9 +323,13 @@ class kucoinfutures extends kucoinfutures$1 {
317
323
  'futuresPrivate': {
318
324
  'GET': {
319
325
  'getMaxOpenSize': 'v2',
326
+ 'getCrossUserLeverage': 'v2',
327
+ 'position/getMarginMode': 'v2',
320
328
  },
321
329
  'POST': {
322
330
  'transfer-out': 'v2',
331
+ 'changeCrossUserLeverage': 'v2',
332
+ 'position/changeMarginMode': 'v2',
323
333
  },
324
334
  },
325
335
  'futuresPublic': {
@@ -2878,6 +2888,156 @@ class kucoinfutures extends kucoinfutures$1 {
2878
2888
  'tierBased': true,
2879
2889
  };
2880
2890
  }
2891
+ async fetchMarginMode(symbol, params = {}) {
2892
+ /**
2893
+ * @method
2894
+ * @name kucoinfutures#fetchMarginMode
2895
+ * @description fetches the margin mode of a trading pair
2896
+ * @see https://www.kucoin.com/docs/rest/futures-trading/positions/get-margin-mode
2897
+ * @param {string} symbol unified symbol of the market to fetch the margin mode for
2898
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2899
+ * @returns {object} a [margin mode structure]{@link https://docs.ccxt.com/#/?id=margin-mode-structure}
2900
+ */
2901
+ await this.loadMarkets();
2902
+ const market = this.market(symbol);
2903
+ const request = {
2904
+ 'symbol': market['id'],
2905
+ };
2906
+ const response = await this.futuresPrivateGetPositionGetMarginMode(this.extend(request, params));
2907
+ //
2908
+ // {
2909
+ // "code": "200000",
2910
+ // "data": {
2911
+ // "symbol": "XBTUSDTM",
2912
+ // "marginMode": "ISOLATED"
2913
+ // }
2914
+ // }
2915
+ //
2916
+ const data = this.safeDict(response, 'data', {});
2917
+ return this.parseMarginMode(data, market);
2918
+ }
2919
+ parseMarginMode(marginMode, market = undefined) {
2920
+ let marginType = this.safeString(marginMode, 'marginMode');
2921
+ marginType = (marginType === 'ISOLATED') ? 'isolated' : 'cross';
2922
+ return {
2923
+ 'info': marginMode,
2924
+ 'symbol': market['symbol'],
2925
+ 'marginMode': marginType,
2926
+ };
2927
+ }
2928
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
2929
+ /**
2930
+ * @method
2931
+ * @name kucoinfutures#setMarginMode
2932
+ * @description set margin mode to 'cross' or 'isolated'
2933
+ * @see https://www.kucoin.com/docs/rest/futures-trading/positions/modify-margin-mode
2934
+ * @param {string} marginMode 'cross' or 'isolated'
2935
+ * @param {string} symbol unified market symbol
2936
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2937
+ * @returns {object} response from the exchange
2938
+ */
2939
+ if (symbol === undefined) {
2940
+ throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
2941
+ }
2942
+ this.checkRequiredArgument('setMarginMode', marginMode, 'marginMode', ['cross', 'isolated']);
2943
+ await this.loadMarkets();
2944
+ const market = this.market(symbol);
2945
+ const request = {
2946
+ 'symbol': market['id'],
2947
+ 'marginMode': marginMode.toUpperCase(),
2948
+ };
2949
+ const response = await this.futuresPrivatePostPositionChangeMarginMode(this.extend(request, params));
2950
+ //
2951
+ // {
2952
+ // "code": "200000",
2953
+ // "data": {
2954
+ // "symbol": "XBTUSDTM",
2955
+ // "marginMode": "ISOLATED"
2956
+ // }
2957
+ // }
2958
+ //
2959
+ const data = this.safeDict(response, 'data', {});
2960
+ return this.parseMarginMode(data, market);
2961
+ }
2962
+ async fetchLeverage(symbol, params = {}) {
2963
+ /**
2964
+ * @method
2965
+ * @name kucoin#fetchLeverage
2966
+ * @description fetch the set leverage for a market
2967
+ * @see https://www.kucoin.com/docs/rest/futures-trading/positions/get-cross-margin-leverage
2968
+ * @param {string} symbol unified market symbol
2969
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2970
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
2971
+ */
2972
+ let marginMode = undefined;
2973
+ [marginMode, params] = this.handleMarginModeAndParams(symbol, params);
2974
+ if (marginMode !== 'cross') {
2975
+ throw new errors.NotSupported(this.id + ' fetchLeverage() currently supports only params["marginMode"] = "cross"');
2976
+ }
2977
+ await this.loadMarkets();
2978
+ const market = this.market(symbol);
2979
+ const request = {
2980
+ 'symbol': market['id'],
2981
+ };
2982
+ const response = await this.futuresPrivateGetGetCrossUserLeverage(this.extend(request, params));
2983
+ //
2984
+ // {
2985
+ // "code": "200000",
2986
+ // "data": {
2987
+ // "symbol": "XBTUSDTM",
2988
+ // "leverage": "3"
2989
+ // }
2990
+ // }
2991
+ //
2992
+ const data = this.safeDict(response, 'data', {});
2993
+ const parsed = this.parseLeverage(data, market);
2994
+ return this.extend(parsed, {
2995
+ 'marginMode': marginMode,
2996
+ });
2997
+ }
2998
+ async setLeverage(leverage, symbol = undefined, params = {}) {
2999
+ /**
3000
+ * @method
3001
+ * @name kucoinfutures#setLeverage
3002
+ * @description set the level of leverage for a market
3003
+ * @see https://www.kucoin.com/docs/rest/futures-trading/positions/modify-cross-margin-leverage
3004
+ * @param {float} leverage the rate of leverage
3005
+ * @param {string} symbol unified market symbol
3006
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3007
+ * @returns {object} response from the exchange
3008
+ */
3009
+ let marginMode = undefined;
3010
+ [marginMode, params] = this.handleMarginModeAndParams(symbol, params);
3011
+ if (marginMode !== 'cross') {
3012
+ throw new errors.NotSupported(this.id + ' setLeverage() currently supports only params["marginMode"] = "cross"');
3013
+ }
3014
+ await this.loadMarkets();
3015
+ const market = this.market(symbol);
3016
+ const request = {
3017
+ 'symbol': market['id'],
3018
+ 'leverage': leverage.toString(),
3019
+ };
3020
+ const response = await this.futuresPrivatePostChangeCrossUserLeverage(this.extend(request, params));
3021
+ //
3022
+ // {
3023
+ // "code": "200000",
3024
+ // "data": true
3025
+ // }
3026
+ //
3027
+ return this.parseLeverage(response, market);
3028
+ }
3029
+ parseLeverage(leverage, market = undefined) {
3030
+ const marketId = this.safeString(leverage, 'symbol');
3031
+ market = this.safeMarket(marketId, market);
3032
+ const leverageNum = this.safeInteger(leverage, 'leverage');
3033
+ return {
3034
+ 'info': leverage,
3035
+ 'symbol': market['symbol'],
3036
+ 'marginMode': undefined,
3037
+ 'longLeverage': leverageNum,
3038
+ 'shortLeverage': leverageNum,
3039
+ };
3040
+ }
2881
3041
  }
2882
3042
 
2883
3043
  module.exports = kucoinfutures;
@@ -266,6 +266,7 @@ class okx extends okx$1 {
266
266
  'copytrading/public-preference-currency': 4,
267
267
  'copytrading/public-current-subpositions': 4,
268
268
  'copytrading/public-subpositions-history': 4,
269
+ 'support/announcements-types': 20,
269
270
  },
270
271
  },
271
272
  'private': {
@@ -411,6 +412,7 @@ class okx extends okx$1 {
411
412
  // affiliate
412
413
  'affiliate/invitee/detail': 1,
413
414
  'users/partner/if-rebate': 1,
415
+ 'support/announcements': 4,
414
416
  },
415
417
  'post': {
416
418
  // rfq
@@ -790,6 +792,8 @@ class okx extends okx$1 {
790
792
  // SPOT/MARGIN error codes 54000-54999
791
793
  '54000': errors.ExchangeError,
792
794
  '54001': errors.ExchangeError,
795
+ '54008': errors.InvalidOrder,
796
+ '54009': errors.InvalidOrder,
793
797
  '54011': errors.InvalidOrder,
794
798
  // Trading bot Error Code from 55100 to 55999
795
799
  '55100': errors.InvalidOrder,
@@ -2643,16 +2643,16 @@ class binance extends binance$1 {
2643
2643
  [subType, params] = this.handleSubTypeAndParams('watchBalance', undefined, params);
2644
2644
  let isPortfolioMargin = undefined;
2645
2645
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'watchBalance', 'papi', 'portfolioMargin', false);
2646
- let urlType = type;
2647
- if (isPortfolioMargin) {
2648
- urlType = 'papi';
2649
- }
2650
2646
  if (this.isLinear(type, subType)) {
2651
2647
  type = 'future';
2652
2648
  }
2653
2649
  else if (this.isInverse(type, subType)) {
2654
2650
  type = 'delivery';
2655
2651
  }
2652
+ let urlType = type;
2653
+ if (isPortfolioMargin) {
2654
+ urlType = 'papi';
2655
+ }
2656
2656
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2657
2657
  const client = this.client(url);
2658
2658
  this.setBalanceCache(client, type, isPortfolioMargin);
@@ -23,6 +23,7 @@ class bitmart extends bitmart$1 {
23
23
  'watchBalance': true,
24
24
  'watchTicker': true,
25
25
  'watchTickers': true,
26
+ 'watchBidsAsks': true,
26
27
  'watchOrderBook': true,
27
28
  'watchOrderBookForSymbols': true,
28
29
  'watchOrders': true,
@@ -334,6 +335,7 @@ class bitmart extends bitmart$1 {
334
335
  /**
335
336
  * @method
336
337
  * @name bitmart#watchTickers
338
+ * @see https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
337
339
  * @see https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
338
340
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
339
341
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
@@ -352,6 +354,84 @@ class bitmart extends bitmart$1 {
352
354
  }
353
355
  return this.filterByArray(this.tickers, 'symbol', symbols);
354
356
  }
357
+ async watchBidsAsks(symbols = undefined, params = {}) {
358
+ /**
359
+ * @method
360
+ * @name bitmart#watchBidsAsks
361
+ * @see https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
362
+ * @see https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
363
+ * @description watches best bid & ask for symbols
364
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
365
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
366
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
367
+ */
368
+ await this.loadMarkets();
369
+ symbols = this.marketSymbols(symbols, undefined, false);
370
+ const firstMarket = this.getMarketFromSymbols(symbols);
371
+ let marketType = undefined;
372
+ [marketType, params] = this.handleMarketTypeAndParams('watchBidsAsks', firstMarket, params);
373
+ const url = this.implodeHostname(this.urls['api']['ws'][marketType]['public']);
374
+ const channelType = (marketType === 'spot') ? 'spot' : 'futures';
375
+ const actionType = (marketType === 'spot') ? 'op' : 'action';
376
+ let rawSubscriptions = [];
377
+ const messageHashes = [];
378
+ for (let i = 0; i < symbols.length; i++) {
379
+ const market = this.market(symbols[i]);
380
+ rawSubscriptions.push(channelType + '/ticker:' + market['id']);
381
+ messageHashes.push('bidask:' + symbols[i]);
382
+ }
383
+ if (marketType !== 'spot') {
384
+ rawSubscriptions = [channelType + '/ticker'];
385
+ }
386
+ const request = {
387
+ 'args': rawSubscriptions,
388
+ };
389
+ request[actionType] = 'subscribe';
390
+ const newTickers = await this.watchMultiple(url, messageHashes, request, rawSubscriptions);
391
+ if (this.newUpdates) {
392
+ const tickers = {};
393
+ tickers[newTickers['symbol']] = newTickers;
394
+ return tickers;
395
+ }
396
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
397
+ }
398
+ handleBidAsk(client, message) {
399
+ const table = this.safeString(message, 'table');
400
+ const isSpot = (table !== undefined);
401
+ let rawTickers = [];
402
+ if (isSpot) {
403
+ rawTickers = this.safeList(message, 'data', []);
404
+ }
405
+ else {
406
+ rawTickers = [this.safeValue(message, 'data', {})];
407
+ }
408
+ if (!rawTickers.length) {
409
+ return;
410
+ }
411
+ for (let i = 0; i < rawTickers.length; i++) {
412
+ const ticker = this.parseWsBidAsk(rawTickers[i]);
413
+ const symbol = ticker['symbol'];
414
+ this.bidsasks[symbol] = ticker;
415
+ const messageHash = 'bidask:' + symbol;
416
+ client.resolve(ticker, messageHash);
417
+ }
418
+ }
419
+ parseWsBidAsk(ticker, market = undefined) {
420
+ const marketId = this.safeString(ticker, 'symbol');
421
+ market = this.safeMarket(marketId, market);
422
+ const symbol = this.safeString(market, 'symbol');
423
+ const timestamp = this.safeInteger(ticker, 'ms_t');
424
+ return this.safeTicker({
425
+ 'symbol': symbol,
426
+ 'timestamp': timestamp,
427
+ 'datetime': this.iso8601(timestamp),
428
+ 'ask': this.safeString2(ticker, 'ask_px', 'ask_price'),
429
+ 'askVolume': this.safeString2(ticker, 'ask_sz', 'ask_vol'),
430
+ 'bid': this.safeString2(ticker, 'bid_px', 'bid_price'),
431
+ 'bidVolume': this.safeString2(ticker, 'bid_sz', 'bid_vol'),
432
+ 'info': ticker,
433
+ }, market);
434
+ }
355
435
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
356
436
  /**
357
437
  * @method
@@ -931,6 +1011,7 @@ class bitmart extends bitmart$1 {
931
1011
  // }
932
1012
  // }
933
1013
  //
1014
+ this.handleBidAsk(client, message);
934
1015
  const table = this.safeString(message, 'table');
935
1016
  const isSpot = (table !== undefined);
936
1017
  let rawTickers = [];
@@ -17,6 +17,8 @@ class bitvavo extends bitvavo$1 {
17
17
  'watchOrderBook': true,
18
18
  'watchTrades': true,
19
19
  'watchTicker': true,
20
+ 'watchTickers': true,
21
+ 'watchBidsAsks': true,
20
22
  'watchOHLCV': true,
21
23
  'watchOrders': true,
22
24
  'watchMyTrades': true,
@@ -77,17 +79,56 @@ class bitvavo extends bitvavo$1 {
77
79
  const message = this.extend(request, params);
78
80
  return await this.watch(url, messageHash, message, messageHash);
79
81
  }
82
+ async watchPublicMultiple(methodName, channelName, symbols, params = {}) {
83
+ await this.loadMarkets();
84
+ symbols = this.marketSymbols(symbols);
85
+ const messageHashes = [methodName];
86
+ const args = [];
87
+ for (let i = 0; i < symbols.length; i++) {
88
+ const market = this.market(symbols[i]);
89
+ args.push(market['id']);
90
+ }
91
+ const url = this.urls['api']['ws'];
92
+ const request = {
93
+ 'action': 'subscribe',
94
+ 'channels': [
95
+ {
96
+ 'name': channelName,
97
+ 'markets': args,
98
+ },
99
+ ],
100
+ };
101
+ const message = this.extend(request, params);
102
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
103
+ }
80
104
  async watchTicker(symbol, params = {}) {
81
105
  /**
82
106
  * @method
83
107
  * @name bitvavo#watchTicker
84
108
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
109
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
85
110
  * @param {string} symbol unified symbol of the market to fetch the ticker for
86
111
  * @param {object} [params] extra parameters specific to the exchange API endpoint
87
112
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
88
113
  */
89
114
  return await this.watchPublic('ticker24h', symbol, params);
90
115
  }
116
+ async watchTickers(symbols = undefined, params = {}) {
117
+ /**
118
+ * @method
119
+ * @name bitvavo#watchTickers
120
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
121
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
122
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
123
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
124
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
125
+ */
126
+ await this.loadMarkets();
127
+ symbols = this.marketSymbols(symbols, undefined, false);
128
+ const channel = 'ticker24h';
129
+ const tickers = await this.watchPublicMultiple(channel, channel, symbols, params);
130
+ return this.filterByArray(tickers, 'symbol', symbols);
131
+ }
91
132
  handleTicker(client, message) {
92
133
  //
93
134
  // {
@@ -110,8 +151,10 @@ class bitvavo extends bitvavo$1 {
110
151
  // ]
111
152
  // }
112
153
  //
154
+ this.handleBidAsk(client, message);
113
155
  const event = this.safeString(message, 'event');
114
156
  const tickers = this.safeValue(message, 'data', []);
157
+ const result = [];
115
158
  for (let i = 0; i < tickers.length; i++) {
116
159
  const data = tickers[i];
117
160
  const marketId = this.safeString(data, 'market');
@@ -120,9 +163,57 @@ class bitvavo extends bitvavo$1 {
120
163
  const ticker = this.parseTicker(data, market);
121
164
  const symbol = ticker['symbol'];
122
165
  this.tickers[symbol] = ticker;
166
+ result.push(ticker);
123
167
  client.resolve(ticker, messageHash);
124
168
  }
125
- return message;
169
+ client.resolve(result, event);
170
+ }
171
+ async watchBidsAsks(symbols = undefined, params = {}) {
172
+ /**
173
+ * @method
174
+ * @name mexc#watchBidsAsks
175
+ * @description watches best bid & ask for symbols
176
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
177
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
178
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
179
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
180
+ */
181
+ await this.loadMarkets();
182
+ symbols = this.marketSymbols(symbols, undefined, false);
183
+ const channel = 'ticker24h';
184
+ const tickers = await this.watchPublicMultiple('bidask', channel, symbols, params);
185
+ return this.filterByArray(tickers, 'symbol', symbols);
186
+ }
187
+ handleBidAsk(client, message) {
188
+ const event = 'bidask';
189
+ const tickers = this.safeValue(message, 'data', []);
190
+ const result = [];
191
+ for (let i = 0; i < tickers.length; i++) {
192
+ const data = tickers[i];
193
+ const ticker = this.parseWsBidAsk(data);
194
+ const symbol = ticker['symbol'];
195
+ this.bidsasks[symbol] = ticker;
196
+ result.push(ticker);
197
+ const messageHash = event + ':' + symbol;
198
+ client.resolve(ticker, messageHash);
199
+ }
200
+ client.resolve(result, event);
201
+ }
202
+ parseWsBidAsk(ticker, market = undefined) {
203
+ const marketId = this.safeString(ticker, 'market');
204
+ market = this.safeMarket(marketId, undefined, '-');
205
+ const symbol = this.safeString(market, 'symbol');
206
+ const timestamp = this.safeInteger(ticker, 'timestamp');
207
+ return this.safeTicker({
208
+ 'symbol': symbol,
209
+ 'timestamp': timestamp,
210
+ 'datetime': this.iso8601(timestamp),
211
+ 'ask': this.safeNumber(ticker, 'ask'),
212
+ 'askVolume': this.safeNumber(ticker, 'askSize'),
213
+ 'bid': this.safeNumber(ticker, 'bid'),
214
+ 'bidVolume': this.safeNumber(ticker, 'bidSize'),
215
+ 'info': ticker,
216
+ }, market);
126
217
  }
127
218
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
128
219
  /**
@@ -18,6 +18,7 @@ class blofin extends blofin$1 {
18
18
  'watchOrderBookForSymbols': true,
19
19
  'watchTicker': true,
20
20
  'watchTickers': true,
21
+ 'watchBidsAsks': true,
21
22
  'watchOHLCV': true,
22
23
  'watchOHLCVForSymbols': true,
23
24
  'watchOrders': true,
@@ -270,6 +271,7 @@ class blofin extends blofin$1 {
270
271
  // ],
271
272
  // }
272
273
  //
274
+ this.handleBidAsk(client, message);
273
275
  const arg = this.safeDict(message, 'arg');
274
276
  const channelName = this.safeString(arg, 'channel');
275
277
  const data = this.safeList(message, 'data');
@@ -284,6 +286,68 @@ class blofin extends blofin$1 {
284
286
  parseWsTicker(ticker, market = undefined) {
285
287
  return this.parseTicker(ticker, market);
286
288
  }
289
+ async watchBidsAsks(symbols = undefined, params = {}) {
290
+ /**
291
+ * @method
292
+ * @name blofin#watchBidsAsks
293
+ * @description watches best bid & ask for symbols
294
+ * @see https://docs.blofin.com/index.html#ws-tickers-channel
295
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
296
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
297
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
298
+ */
299
+ await this.loadMarkets();
300
+ symbols = this.marketSymbols(symbols, undefined, false);
301
+ const firstMarket = this.market(symbols[0]);
302
+ const channel = 'tickers';
303
+ let marketType = undefined;
304
+ [marketType, params] = this.handleMarketTypeAndParams('watchBidsAsks', firstMarket, params);
305
+ const url = this.implodeHostname(this.urls['api']['ws'][marketType]['public']);
306
+ const messageHashes = [];
307
+ const args = [];
308
+ for (let i = 0; i < symbols.length; i++) {
309
+ const market = this.market(symbols[i]);
310
+ messageHashes.push('bidask:' + market['symbol']);
311
+ args.push({
312
+ 'channel': channel,
313
+ 'instId': market['id'],
314
+ });
315
+ }
316
+ const request = this.getSubscriptionRequest(args);
317
+ const ticker = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), messageHashes);
318
+ if (this.newUpdates) {
319
+ const tickers = {};
320
+ tickers[ticker['symbol']] = ticker;
321
+ return tickers;
322
+ }
323
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
324
+ }
325
+ handleBidAsk(client, message) {
326
+ const data = this.safeList(message, 'data');
327
+ for (let i = 0; i < data.length; i++) {
328
+ const ticker = this.parseWsBidAsk(data[i]);
329
+ const symbol = ticker['symbol'];
330
+ const messageHash = 'bidask:' + symbol;
331
+ this.bidsasks[symbol] = ticker;
332
+ client.resolve(ticker, messageHash);
333
+ }
334
+ }
335
+ parseWsBidAsk(ticker, market = undefined) {
336
+ const marketId = this.safeString(ticker, 'instId');
337
+ market = this.safeMarket(marketId, market, '-');
338
+ const symbol = this.safeString(market, 'symbol');
339
+ const timestamp = this.safeInteger(ticker, 'ts');
340
+ return this.safeTicker({
341
+ 'symbol': symbol,
342
+ 'timestamp': timestamp,
343
+ 'datetime': this.iso8601(timestamp),
344
+ 'ask': this.safeString(ticker, 'askPrice'),
345
+ 'askVolume': this.safeString(ticker, 'askSize'),
346
+ 'bid': this.safeString(ticker, 'bidPrice'),
347
+ 'bidVolume': this.safeString(ticker, 'bidSize'),
348
+ 'info': ticker,
349
+ }, market);
350
+ }
287
351
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
288
352
  /**
289
353
  * @method