ccxt 4.4.6 → 4.4.8

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 (55) 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/base/Exchange.js +21 -2
  5. package/dist/cjs/src/binance.js +51 -12
  6. package/dist/cjs/src/bingx.js +3 -0
  7. package/dist/cjs/src/bitget.js +10 -6
  8. package/dist/cjs/src/bitmart.js +124 -1
  9. package/dist/cjs/src/bybit.js +377 -10
  10. package/dist/cjs/src/gate.js +3 -0
  11. package/dist/cjs/src/htx.js +22 -0
  12. package/dist/cjs/src/kucoin.js +2 -2
  13. package/dist/cjs/src/mexc.js +97 -13
  14. package/dist/cjs/src/okx.js +4 -0
  15. package/dist/cjs/src/pro/bitget.js +66 -0
  16. package/dist/cjs/src/pro/bitmart.js +81 -0
  17. package/dist/cjs/src/pro/bitvavo.js +92 -1
  18. package/dist/cjs/src/pro/blofin.js +64 -0
  19. package/dist/cjs/src/pro/okx.js +11 -5
  20. package/examples/js/cli.js +2 -0
  21. package/js/ccxt.d.ts +1 -1
  22. package/js/ccxt.js +1 -1
  23. package/js/src/abstract/binance.d.ts +1 -0
  24. package/js/src/abstract/binancecoinm.d.ts +1 -0
  25. package/js/src/abstract/binanceus.d.ts +1 -0
  26. package/js/src/abstract/binanceusdm.d.ts +1 -0
  27. package/js/src/abstract/bybit.d.ts +5 -0
  28. package/js/src/abstract/okx.d.ts +2 -0
  29. package/js/src/base/Exchange.d.ts +4 -0
  30. package/js/src/base/Exchange.js +21 -2
  31. package/js/src/binance.d.ts +15 -15
  32. package/js/src/binance.js +51 -12
  33. package/js/src/bingx.js +3 -0
  34. package/js/src/bitget.js +10 -6
  35. package/js/src/bitmart.d.ts +1 -0
  36. package/js/src/bitmart.js +124 -1
  37. package/js/src/bybit.d.ts +7 -1
  38. package/js/src/bybit.js +377 -10
  39. package/js/src/gate.js +3 -0
  40. package/js/src/htx.js +22 -0
  41. package/js/src/kucoin.js +2 -2
  42. package/js/src/mexc.d.ts +2 -0
  43. package/js/src/mexc.js +97 -13
  44. package/js/src/okx.js +4 -0
  45. package/js/src/pro/bitget.d.ts +3 -0
  46. package/js/src/pro/bitget.js +66 -0
  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/okx.d.ts +1 -0
  54. package/js/src/pro/okx.js +11 -5
  55. package/package.json +1 -1
@@ -40,8 +40,8 @@ class mexc extends mexc$1 {
40
40
  'closePosition': false,
41
41
  'createDepositAddress': true,
42
42
  'createMarketBuyOrderWithCost': true,
43
- 'createMarketOrderWithCost': false,
44
- 'createMarketSellOrderWithCost': false,
43
+ 'createMarketOrderWithCost': true,
44
+ 'createMarketSellOrderWithCost': true,
45
45
  'createOrder': true,
46
46
  'createOrders': true,
47
47
  'createPostOnlyOrder': true,
@@ -130,7 +130,7 @@ class mexc extends mexc$1 {
130
130
  'repayCrossMargin': false,
131
131
  'repayIsolatedMargin': false,
132
132
  'setLeverage': true,
133
- 'setMarginMode': undefined,
133
+ 'setMarginMode': true,
134
134
  'setPositionMode': true,
135
135
  'signIn': undefined,
136
136
  'transfer': undefined,
@@ -416,7 +416,6 @@ class mexc extends mexc$1 {
416
416
  'options': {
417
417
  'adjustForTimeDifference': false,
418
418
  'timeDifference': 0,
419
- 'createMarketBuyOrderRequiresPrice': true,
420
419
  'unavailableContracts': {
421
420
  'BTC/USDT:USDT': true,
422
421
  'LTC/USDT:USDT': true,
@@ -465,12 +464,14 @@ class mexc extends mexc$1 {
465
464
  'LTC': 'LTC',
466
465
  },
467
466
  'networks': {
467
+ 'ZKSYNC': 'ZKSYNCERA',
468
468
  'TRC20': 'TRX',
469
469
  'TON': 'TONCOIN',
470
470
  'AVAXC': 'AVAX_CCHAIN',
471
471
  'ERC20': 'ETH',
472
472
  'ACA': 'ACALA',
473
473
  'BEP20': 'BSC',
474
+ 'OPTIMISM': 'OP',
474
475
  // 'ADA': 'Cardano(ADA)',
475
476
  // 'AE': 'AE',
476
477
  // 'ALGO': 'Algorand(ALGO)',
@@ -2106,8 +2107,27 @@ class mexc extends mexc$1 {
2106
2107
  if (!market['spot']) {
2107
2108
  throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2108
2109
  }
2109
- params['createMarketBuyOrderRequiresPrice'] = false;
2110
- return await this.createOrder(symbol, 'market', 'buy', cost, undefined, params);
2110
+ params['cost'] = cost;
2111
+ return await this.createOrder(symbol, 'market', 'buy', 0, undefined, params);
2112
+ }
2113
+ async createMarketSellOrderWithCost(symbol, cost, params = {}) {
2114
+ /**
2115
+ * @method
2116
+ * @name mexc#createMarketSellOrderWithCost
2117
+ * @description create a market sell order by providing the symbol and cost
2118
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
2119
+ * @param {string} symbol unified symbol of the market to create an order in
2120
+ * @param {float} cost how much you want to trade in units of the quote currency
2121
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2122
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2123
+ */
2124
+ await this.loadMarkets();
2125
+ const market = this.market(symbol);
2126
+ if (!market['spot']) {
2127
+ throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2128
+ }
2129
+ params['cost'] = cost;
2130
+ return await this.createOrder(symbol, 'market', 'sell', 0, undefined, params);
2111
2131
  }
2112
2132
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2113
2133
  /**
@@ -2133,6 +2153,7 @@ class mexc extends mexc$1 {
2133
2153
  * @param {long} [params.positionId] *contract only* it is recommended to fill in this parameter when closing a position
2134
2154
  * @param {string} [params.externalOid] *contract only* external order ID
2135
2155
  * @param {int} [params.positionMode] *contract only* 1:hedge, 2:one-way, default: the user's current config
2156
+ * @param {boolean} [params.test] *spot only* whether to use the test endpoint or not, default is false
2136
2157
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2137
2158
  */
2138
2159
  await this.loadMarkets();
@@ -2153,26 +2174,25 @@ class mexc extends mexc$1 {
2153
2174
  'side': orderSide,
2154
2175
  'type': type.toUpperCase(),
2155
2176
  };
2156
- if (orderSide === 'BUY' && type === 'market') {
2157
- let createMarketBuyOrderRequiresPrice = true;
2158
- [createMarketBuyOrderRequiresPrice, params] = this.handleOptionAndParams(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
2177
+ if (type === 'market') {
2159
2178
  const cost = this.safeNumber2(params, 'cost', 'quoteOrderQty');
2160
2179
  params = this.omit(params, 'cost');
2161
2180
  if (cost !== undefined) {
2162
2181
  amount = cost;
2182
+ request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2163
2183
  }
2164
- else if (createMarketBuyOrderRequiresPrice) {
2184
+ else {
2165
2185
  if (price === undefined) {
2166
- throw new errors.InvalidOrder(this.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to false and pass the cost to spend in the amount argument');
2186
+ request['quantity'] = this.amountToPrecision(symbol, amount);
2167
2187
  }
2168
2188
  else {
2169
2189
  const amountString = this.numberToString(amount);
2170
2190
  const priceString = this.numberToString(price);
2171
2191
  const quoteAmount = Precise["default"].stringMul(amountString, priceString);
2172
2192
  amount = quoteAmount;
2193
+ request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2173
2194
  }
2174
2195
  }
2175
- request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2176
2196
  }
2177
2197
  else {
2178
2198
  request['quantity'] = this.amountToPrecision(symbol, amount);
@@ -2216,8 +2236,16 @@ class mexc extends mexc$1 {
2216
2236
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2217
2237
  */
2218
2238
  await this.loadMarkets();
2239
+ const test = this.safeBool(params, 'test', false);
2240
+ params = this.omit(params, 'test');
2219
2241
  const request = this.createSpotOrderRequest(market, type, side, amount, price, marginMode, params);
2220
- const response = await this.spotPrivatePostOrder(this.extend(request, params));
2242
+ let response = undefined;
2243
+ if (test) {
2244
+ response = await this.spotPrivatePostOrderTest(request);
2245
+ }
2246
+ else {
2247
+ response = await this.spotPrivatePostOrder(request);
2248
+ }
2221
2249
  //
2222
2250
  // spot
2223
2251
  //
@@ -2570,6 +2598,9 @@ class mexc extends mexc$1 {
2570
2598
  * @method
2571
2599
  * @name mexc#fetchOrders
2572
2600
  * @description fetches information on multiple orders made by the user
2601
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2602
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2603
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2573
2604
  * @param {string} symbol unified market symbol of the market orders were made in
2574
2605
  * @param {int} [since] the earliest time in ms to fetch orders for
2575
2606
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -2802,6 +2833,9 @@ class mexc extends mexc$1 {
2802
2833
  * @method
2803
2834
  * @name mexc#fetchOpenOrders
2804
2835
  * @description fetch all unfilled currently open orders
2836
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#current-open-orders
2837
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2838
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2805
2839
  * @param {string} symbol unified market symbol
2806
2840
  * @param {int} [since] the earliest time in ms to fetch open orders for
2807
2841
  * @param {int} [limit] the maximum number of open orders structures to retrieve
@@ -2893,6 +2927,9 @@ class mexc extends mexc$1 {
2893
2927
  * @method
2894
2928
  * @name mexc#fetchClosedOrders
2895
2929
  * @description fetches information on multiple closed orders made by the user
2930
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2931
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2932
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2896
2933
  * @param {string} symbol unified market symbol of the market orders were made in
2897
2934
  * @param {int} [since] the earliest time in ms to fetch orders for
2898
2935
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -2906,6 +2943,9 @@ class mexc extends mexc$1 {
2906
2943
  * @method
2907
2944
  * @name mexc#fetchCanceledOrders
2908
2945
  * @description fetches information on multiple canceled orders made by the user
2946
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2947
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2948
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2909
2949
  * @param {string} symbol unified market symbol of the market orders were made in
2910
2950
  * @param {int} [since] timestamp in ms of the earliest order, default is undefined
2911
2951
  * @param {int} [limit] max number of orders to return, default is undefined
@@ -5649,6 +5689,50 @@ class mexc extends mexc$1 {
5649
5689
  const positions = this.parsePositions(data, symbols, params);
5650
5690
  return this.filterBySinceLimit(positions, since, limit);
5651
5691
  }
5692
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
5693
+ /**
5694
+ * @method
5695
+ * @name mexc#setMarginMode
5696
+ * @description set margin mode to 'cross' or 'isolated'
5697
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#switch-leverage
5698
+ * @param {string} marginMode 'cross' or 'isolated'
5699
+ * @param {string} [symbol] required when there is no position, else provide params["positionId"]
5700
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5701
+ * @param {string} [params.positionId] required when a position is set
5702
+ * @param {string} [params.direction] "long" or "short" required when there is no position
5703
+ * @returns {object} response from the exchange
5704
+ */
5705
+ await this.loadMarkets();
5706
+ const market = this.market(symbol);
5707
+ if (market['spot']) {
5708
+ throw new errors.BadSymbol(this.id + ' setMarginMode() supports contract markets only');
5709
+ }
5710
+ marginMode = marginMode.toLowerCase();
5711
+ if (marginMode !== 'isolated' && marginMode !== 'cross') {
5712
+ throw new errors.BadRequest(this.id + ' setMarginMode() marginMode argument should be isolated or cross');
5713
+ }
5714
+ const leverage = this.safeInteger(params, 'leverage');
5715
+ if (leverage === undefined) {
5716
+ throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a leverage parameter');
5717
+ }
5718
+ const direction = this.safeStringLower2(params, 'direction', 'positionId');
5719
+ const request = {
5720
+ 'leverage': leverage,
5721
+ 'openType': (marginMode === 'isolated') ? 1 : 2,
5722
+ };
5723
+ if (symbol !== undefined) {
5724
+ request['symbol'] = market['id'];
5725
+ }
5726
+ if (direction !== undefined) {
5727
+ request['positionType'] = (direction === 'short') ? 2 : 1;
5728
+ }
5729
+ params = this.omit(params, 'direction');
5730
+ const response = await this.contractPrivatePostPositionChangeLeverage(this.extend(request, params));
5731
+ //
5732
+ // { success: true, code: '0' }
5733
+ //
5734
+ return this.parseLeverage(response, market);
5735
+ }
5652
5736
  nonce() {
5653
5737
  return this.milliseconds() - this.safeInteger(this.options, 'timeDifference', 0);
5654
5738
  }
@@ -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,
@@ -34,6 +34,7 @@ class bitget extends bitget$1 {
34
34
  'watchOrders': true,
35
35
  'watchTicker': true,
36
36
  'watchTickers': true,
37
+ 'watchBidsAsks': true,
37
38
  'watchTrades': true,
38
39
  'watchTradesForSymbols': true,
39
40
  'watchPositions': true,
@@ -212,6 +213,7 @@ class bitget extends bitget$1 {
212
213
  // "ts": 1701842994341
213
214
  // }
214
215
  //
216
+ this.handleBidAsk(client, message);
215
217
  const ticker = this.parseWsTicker(message);
216
218
  const symbol = ticker['symbol'];
217
219
  this.tickers[symbol] = ticker;
@@ -323,6 +325,70 @@ class bitget extends bitget$1 {
323
325
  'info': ticker,
324
326
  }, market);
325
327
  }
328
+ async watchBidsAsks(symbols = undefined, params = {}) {
329
+ /**
330
+ * @method
331
+ * @name bitget#watchBidsAsks
332
+ * @see https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
333
+ * @see https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
334
+ * @description watches best bid & ask for symbols
335
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
336
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
337
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
338
+ */
339
+ await this.loadMarkets();
340
+ symbols = this.marketSymbols(symbols, undefined, false);
341
+ const market = this.market(symbols[0]);
342
+ let instType = undefined;
343
+ [instType, params] = this.getInstType(market, params);
344
+ const topics = [];
345
+ const messageHashes = [];
346
+ for (let i = 0; i < symbols.length; i++) {
347
+ const symbol = symbols[i];
348
+ const marketInner = this.market(symbol);
349
+ const args = {
350
+ 'instType': instType,
351
+ 'channel': 'ticker',
352
+ 'instId': marketInner['id'],
353
+ };
354
+ topics.push(args);
355
+ messageHashes.push('bidask:' + symbol);
356
+ }
357
+ const tickers = await this.watchPublicMultiple(messageHashes, topics, params);
358
+ if (this.newUpdates) {
359
+ const result = {};
360
+ result[tickers['symbol']] = tickers;
361
+ return result;
362
+ }
363
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
364
+ }
365
+ handleBidAsk(client, message) {
366
+ const ticker = this.parseWsBidAsk(message);
367
+ const symbol = ticker['symbol'];
368
+ this.bidsasks[symbol] = ticker;
369
+ const messageHash = 'bidask:' + symbol;
370
+ client.resolve(ticker, messageHash);
371
+ }
372
+ parseWsBidAsk(message, market = undefined) {
373
+ const arg = this.safeValue(message, 'arg', {});
374
+ const data = this.safeValue(message, 'data', []);
375
+ const ticker = this.safeValue(data, 0, {});
376
+ const timestamp = this.safeInteger(ticker, 'ts');
377
+ const instType = this.safeString(arg, 'instType');
378
+ const marketType = (instType === 'SPOT') ? 'spot' : 'contract';
379
+ const marketId = this.safeString(ticker, 'instId');
380
+ market = this.safeMarket(marketId, market, undefined, marketType);
381
+ return this.safeTicker({
382
+ 'symbol': market['symbol'],
383
+ 'timestamp': timestamp,
384
+ 'datetime': this.iso8601(timestamp),
385
+ 'ask': this.safeString(ticker, 'askPr'),
386
+ 'askVolume': this.safeString(ticker, 'askSz'),
387
+ 'bid': this.safeString(ticker, 'bidPr'),
388
+ 'bidVolume': this.safeString(ticker, 'bidSz'),
389
+ 'info': ticker,
390
+ }, market);
391
+ }
326
392
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
327
393
  /**
328
394
  * @method
@@ -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