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
package/js/src/mexc.js CHANGED
@@ -43,8 +43,8 @@ export default class mexc extends Exchange {
43
43
  'closePosition': false,
44
44
  'createDepositAddress': true,
45
45
  'createMarketBuyOrderWithCost': true,
46
- 'createMarketOrderWithCost': false,
47
- 'createMarketSellOrderWithCost': false,
46
+ 'createMarketOrderWithCost': true,
47
+ 'createMarketSellOrderWithCost': true,
48
48
  'createOrder': true,
49
49
  'createOrders': true,
50
50
  'createPostOnlyOrder': true,
@@ -133,7 +133,7 @@ export default class mexc extends Exchange {
133
133
  'repayCrossMargin': false,
134
134
  'repayIsolatedMargin': false,
135
135
  'setLeverage': true,
136
- 'setMarginMode': undefined,
136
+ 'setMarginMode': true,
137
137
  'setPositionMode': true,
138
138
  'signIn': undefined,
139
139
  'transfer': undefined,
@@ -419,7 +419,6 @@ export default class mexc extends Exchange {
419
419
  'options': {
420
420
  'adjustForTimeDifference': false,
421
421
  'timeDifference': 0,
422
- 'createMarketBuyOrderRequiresPrice': true,
423
422
  'unavailableContracts': {
424
423
  'BTC/USDT:USDT': true,
425
424
  'LTC/USDT:USDT': true,
@@ -468,12 +467,14 @@ export default class mexc extends Exchange {
468
467
  'LTC': 'LTC',
469
468
  },
470
469
  'networks': {
470
+ 'ZKSYNC': 'ZKSYNCERA',
471
471
  'TRC20': 'TRX',
472
472
  'TON': 'TONCOIN',
473
473
  'AVAXC': 'AVAX_CCHAIN',
474
474
  'ERC20': 'ETH',
475
475
  'ACA': 'ACALA',
476
476
  'BEP20': 'BSC',
477
+ 'OPTIMISM': 'OP',
477
478
  // 'ADA': 'Cardano(ADA)',
478
479
  // 'AE': 'AE',
479
480
  // 'ALGO': 'Algorand(ALGO)',
@@ -2109,8 +2110,27 @@ export default class mexc extends Exchange {
2109
2110
  if (!market['spot']) {
2110
2111
  throw new NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2111
2112
  }
2112
- params['createMarketBuyOrderRequiresPrice'] = false;
2113
- return await this.createOrder(symbol, 'market', 'buy', cost, undefined, params);
2113
+ params['cost'] = cost;
2114
+ return await this.createOrder(symbol, 'market', 'buy', 0, undefined, params);
2115
+ }
2116
+ async createMarketSellOrderWithCost(symbol, cost, params = {}) {
2117
+ /**
2118
+ * @method
2119
+ * @name mexc#createMarketSellOrderWithCost
2120
+ * @description create a market sell order by providing the symbol and cost
2121
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
2122
+ * @param {string} symbol unified symbol of the market to create an order in
2123
+ * @param {float} cost how much you want to trade in units of the quote currency
2124
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2125
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2126
+ */
2127
+ await this.loadMarkets();
2128
+ const market = this.market(symbol);
2129
+ if (!market['spot']) {
2130
+ throw new NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2131
+ }
2132
+ params['cost'] = cost;
2133
+ return await this.createOrder(symbol, 'market', 'sell', 0, undefined, params);
2114
2134
  }
2115
2135
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2116
2136
  /**
@@ -2136,6 +2156,7 @@ export default class mexc extends Exchange {
2136
2156
  * @param {long} [params.positionId] *contract only* it is recommended to fill in this parameter when closing a position
2137
2157
  * @param {string} [params.externalOid] *contract only* external order ID
2138
2158
  * @param {int} [params.positionMode] *contract only* 1:hedge, 2:one-way, default: the user's current config
2159
+ * @param {boolean} [params.test] *spot only* whether to use the test endpoint or not, default is false
2139
2160
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2140
2161
  */
2141
2162
  await this.loadMarkets();
@@ -2156,26 +2177,25 @@ export default class mexc extends Exchange {
2156
2177
  'side': orderSide,
2157
2178
  'type': type.toUpperCase(),
2158
2179
  };
2159
- if (orderSide === 'BUY' && type === 'market') {
2160
- let createMarketBuyOrderRequiresPrice = true;
2161
- [createMarketBuyOrderRequiresPrice, params] = this.handleOptionAndParams(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
2180
+ if (type === 'market') {
2162
2181
  const cost = this.safeNumber2(params, 'cost', 'quoteOrderQty');
2163
2182
  params = this.omit(params, 'cost');
2164
2183
  if (cost !== undefined) {
2165
2184
  amount = cost;
2185
+ request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2166
2186
  }
2167
- else if (createMarketBuyOrderRequiresPrice) {
2187
+ else {
2168
2188
  if (price === undefined) {
2169
- throw new 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');
2189
+ request['quantity'] = this.amountToPrecision(symbol, amount);
2170
2190
  }
2171
2191
  else {
2172
2192
  const amountString = this.numberToString(amount);
2173
2193
  const priceString = this.numberToString(price);
2174
2194
  const quoteAmount = Precise.stringMul(amountString, priceString);
2175
2195
  amount = quoteAmount;
2196
+ request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2176
2197
  }
2177
2198
  }
2178
- request['quoteOrderQty'] = this.costToPrecision(symbol, amount);
2179
2199
  }
2180
2200
  else {
2181
2201
  request['quantity'] = this.amountToPrecision(symbol, amount);
@@ -2219,8 +2239,16 @@ export default class mexc extends Exchange {
2219
2239
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2220
2240
  */
2221
2241
  await this.loadMarkets();
2242
+ const test = this.safeBool(params, 'test', false);
2243
+ params = this.omit(params, 'test');
2222
2244
  const request = this.createSpotOrderRequest(market, type, side, amount, price, marginMode, params);
2223
- const response = await this.spotPrivatePostOrder(this.extend(request, params));
2245
+ let response = undefined;
2246
+ if (test) {
2247
+ response = await this.spotPrivatePostOrderTest(request);
2248
+ }
2249
+ else {
2250
+ response = await this.spotPrivatePostOrder(request);
2251
+ }
2224
2252
  //
2225
2253
  // spot
2226
2254
  //
@@ -2573,6 +2601,9 @@ export default class mexc extends Exchange {
2573
2601
  * @method
2574
2602
  * @name mexc#fetchOrders
2575
2603
  * @description fetches information on multiple orders made by the user
2604
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2605
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2606
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2576
2607
  * @param {string} symbol unified market symbol of the market orders were made in
2577
2608
  * @param {int} [since] the earliest time in ms to fetch orders for
2578
2609
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -2805,6 +2836,9 @@ export default class mexc extends Exchange {
2805
2836
  * @method
2806
2837
  * @name mexc#fetchOpenOrders
2807
2838
  * @description fetch all unfilled currently open orders
2839
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#current-open-orders
2840
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2841
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2808
2842
  * @param {string} symbol unified market symbol
2809
2843
  * @param {int} [since] the earliest time in ms to fetch open orders for
2810
2844
  * @param {int} [limit] the maximum number of open orders structures to retrieve
@@ -2896,6 +2930,9 @@ export default class mexc extends Exchange {
2896
2930
  * @method
2897
2931
  * @name mexc#fetchClosedOrders
2898
2932
  * @description fetches information on multiple closed orders made by the user
2933
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2934
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2935
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2899
2936
  * @param {string} symbol unified market symbol of the market orders were made in
2900
2937
  * @param {int} [since] the earliest time in ms to fetch orders for
2901
2938
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -2909,6 +2946,9 @@ export default class mexc extends Exchange {
2909
2946
  * @method
2910
2947
  * @name mexc#fetchCanceledOrders
2911
2948
  * @description fetches information on multiple canceled orders made by the user
2949
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
2950
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
2951
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
2912
2952
  * @param {string} symbol unified market symbol of the market orders were made in
2913
2953
  * @param {int} [since] timestamp in ms of the earliest order, default is undefined
2914
2954
  * @param {int} [limit] max number of orders to return, default is undefined
@@ -5653,6 +5693,50 @@ export default class mexc extends Exchange {
5653
5693
  const positions = this.parsePositions(data, symbols, params);
5654
5694
  return this.filterBySinceLimit(positions, since, limit);
5655
5695
  }
5696
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
5697
+ /**
5698
+ * @method
5699
+ * @name mexc#setMarginMode
5700
+ * @description set margin mode to 'cross' or 'isolated'
5701
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#switch-leverage
5702
+ * @param {string} marginMode 'cross' or 'isolated'
5703
+ * @param {string} [symbol] required when there is no position, else provide params["positionId"]
5704
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5705
+ * @param {string} [params.positionId] required when a position is set
5706
+ * @param {string} [params.direction] "long" or "short" required when there is no position
5707
+ * @returns {object} response from the exchange
5708
+ */
5709
+ await this.loadMarkets();
5710
+ const market = this.market(symbol);
5711
+ if (market['spot']) {
5712
+ throw new BadSymbol(this.id + ' setMarginMode() supports contract markets only');
5713
+ }
5714
+ marginMode = marginMode.toLowerCase();
5715
+ if (marginMode !== 'isolated' && marginMode !== 'cross') {
5716
+ throw new BadRequest(this.id + ' setMarginMode() marginMode argument should be isolated or cross');
5717
+ }
5718
+ const leverage = this.safeInteger(params, 'leverage');
5719
+ if (leverage === undefined) {
5720
+ throw new ArgumentsRequired(this.id + ' setMarginMode() requires a leverage parameter');
5721
+ }
5722
+ const direction = this.safeStringLower2(params, 'direction', 'positionId');
5723
+ const request = {
5724
+ 'leverage': leverage,
5725
+ 'openType': (marginMode === 'isolated') ? 1 : 2,
5726
+ };
5727
+ if (symbol !== undefined) {
5728
+ request['symbol'] = market['id'];
5729
+ }
5730
+ if (direction !== undefined) {
5731
+ request['positionType'] = (direction === 'short') ? 2 : 1;
5732
+ }
5733
+ params = this.omit(params, 'direction');
5734
+ const response = await this.contractPrivatePostPositionChangeLeverage(this.extend(request, params));
5735
+ //
5736
+ // { success: true, code: '0' }
5737
+ //
5738
+ return this.parseLeverage(response, market);
5739
+ }
5656
5740
  nonce() {
5657
5741
  return this.milliseconds() - this.safeInteger(this.options, 'timeDifference', 0);
5658
5742
  }
package/js/src/okx.js CHANGED
@@ -269,6 +269,7 @@ export default class okx extends Exchange {
269
269
  'copytrading/public-preference-currency': 4,
270
270
  'copytrading/public-current-subpositions': 4,
271
271
  'copytrading/public-subpositions-history': 4,
272
+ 'support/announcements-types': 20,
272
273
  },
273
274
  },
274
275
  'private': {
@@ -414,6 +415,7 @@ export default class okx extends Exchange {
414
415
  // affiliate
415
416
  'affiliate/invitee/detail': 1,
416
417
  'users/partner/if-rebate': 1,
418
+ 'support/announcements': 4,
417
419
  },
418
420
  'post': {
419
421
  // rfq
@@ -793,6 +795,8 @@ export default class okx extends Exchange {
793
795
  // SPOT/MARGIN error codes 54000-54999
794
796
  '54000': ExchangeError,
795
797
  '54001': ExchangeError,
798
+ '54008': InvalidOrder,
799
+ '54009': InvalidOrder,
796
800
  '54011': InvalidOrder,
797
801
  // Trading bot Error Code from 55100 to 55999
798
802
  '55100': InvalidOrder,
@@ -14,6 +14,9 @@ export default class bitget extends bitgetRest {
14
14
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
15
15
  handleTicker(client: Client, message: any): void;
16
16
  parseWsTicker(message: any, market?: any): Ticker;
17
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
18
+ handleBidAsk(client: Client, message: any): void;
19
+ parseWsBidAsk(message: any, market?: any): Ticker;
17
20
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
18
21
  unWatchOHLCV(symbol: string, timeframe?: string, params?: {}): Promise<any>;
19
22
  handleOHLCV(client: Client, message: any): void;
@@ -37,6 +37,7 @@ export default class bitget extends bitgetRest {
37
37
  'watchOrders': true,
38
38
  'watchTicker': true,
39
39
  'watchTickers': true,
40
+ 'watchBidsAsks': true,
40
41
  'watchTrades': true,
41
42
  'watchTradesForSymbols': true,
42
43
  'watchPositions': true,
@@ -215,6 +216,7 @@ export default class bitget extends bitgetRest {
215
216
  // "ts": 1701842994341
216
217
  // }
217
218
  //
219
+ this.handleBidAsk(client, message);
218
220
  const ticker = this.parseWsTicker(message);
219
221
  const symbol = ticker['symbol'];
220
222
  this.tickers[symbol] = ticker;
@@ -326,6 +328,70 @@ export default class bitget extends bitgetRest {
326
328
  'info': ticker,
327
329
  }, market);
328
330
  }
331
+ async watchBidsAsks(symbols = undefined, params = {}) {
332
+ /**
333
+ * @method
334
+ * @name bitget#watchBidsAsks
335
+ * @see https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
336
+ * @see https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
337
+ * @description watches best bid & ask for symbols
338
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
339
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
340
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
341
+ */
342
+ await this.loadMarkets();
343
+ symbols = this.marketSymbols(symbols, undefined, false);
344
+ const market = this.market(symbols[0]);
345
+ let instType = undefined;
346
+ [instType, params] = this.getInstType(market, params);
347
+ const topics = [];
348
+ const messageHashes = [];
349
+ for (let i = 0; i < symbols.length; i++) {
350
+ const symbol = symbols[i];
351
+ const marketInner = this.market(symbol);
352
+ const args = {
353
+ 'instType': instType,
354
+ 'channel': 'ticker',
355
+ 'instId': marketInner['id'],
356
+ };
357
+ topics.push(args);
358
+ messageHashes.push('bidask:' + symbol);
359
+ }
360
+ const tickers = await this.watchPublicMultiple(messageHashes, topics, params);
361
+ if (this.newUpdates) {
362
+ const result = {};
363
+ result[tickers['symbol']] = tickers;
364
+ return result;
365
+ }
366
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
367
+ }
368
+ handleBidAsk(client, message) {
369
+ const ticker = this.parseWsBidAsk(message);
370
+ const symbol = ticker['symbol'];
371
+ this.bidsasks[symbol] = ticker;
372
+ const messageHash = 'bidask:' + symbol;
373
+ client.resolve(ticker, messageHash);
374
+ }
375
+ parseWsBidAsk(message, market = undefined) {
376
+ const arg = this.safeValue(message, 'arg', {});
377
+ const data = this.safeValue(message, 'data', []);
378
+ const ticker = this.safeValue(data, 0, {});
379
+ const timestamp = this.safeInteger(ticker, 'ts');
380
+ const instType = this.safeString(arg, 'instType');
381
+ const marketType = (instType === 'SPOT') ? 'spot' : 'contract';
382
+ const marketId = this.safeString(ticker, 'instId');
383
+ market = this.safeMarket(marketId, market, undefined, marketType);
384
+ return this.safeTicker({
385
+ 'symbol': market['symbol'],
386
+ 'timestamp': timestamp,
387
+ 'datetime': this.iso8601(timestamp),
388
+ 'ask': this.safeString(ticker, 'askPr'),
389
+ 'askVolume': this.safeString(ticker, 'askSz'),
390
+ 'bid': this.safeString(ticker, 'bidPr'),
391
+ 'bidVolume': this.safeString(ticker, 'bidSz'),
392
+ 'info': ticker,
393
+ }, market);
394
+ }
329
395
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
330
396
  /**
331
397
  * @method
@@ -14,6 +14,9 @@ export default class bitmart extends bitmartRest {
14
14
  getParamsForMultipleSub(methodName: string, symbols: string[], limit?: Int, params?: {}): any[];
15
15
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
16
16
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
17
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
18
+ handleBidAsk(client: Client, message: any): void;
19
+ parseWsBidAsk(ticker: any, market?: any): Ticker;
17
20
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
18
21
  handleOrders(client: Client, message: any): void;
19
22
  parseWsOrder(order: Dict, market?: Market): Order;
@@ -26,6 +26,7 @@ export default class bitmart extends bitmartRest {
26
26
  'watchBalance': true,
27
27
  'watchTicker': true,
28
28
  'watchTickers': true,
29
+ 'watchBidsAsks': true,
29
30
  'watchOrderBook': true,
30
31
  'watchOrderBookForSymbols': true,
31
32
  'watchOrders': true,
@@ -337,6 +338,7 @@ export default class bitmart extends bitmartRest {
337
338
  /**
338
339
  * @method
339
340
  * @name bitmart#watchTickers
341
+ * @see https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
340
342
  * @see https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
341
343
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
342
344
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
@@ -355,6 +357,84 @@ export default class bitmart extends bitmartRest {
355
357
  }
356
358
  return this.filterByArray(this.tickers, 'symbol', symbols);
357
359
  }
360
+ async watchBidsAsks(symbols = undefined, params = {}) {
361
+ /**
362
+ * @method
363
+ * @name bitmart#watchBidsAsks
364
+ * @see https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
365
+ * @see https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
366
+ * @description watches best bid & ask for symbols
367
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
368
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
369
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
370
+ */
371
+ await this.loadMarkets();
372
+ symbols = this.marketSymbols(symbols, undefined, false);
373
+ const firstMarket = this.getMarketFromSymbols(symbols);
374
+ let marketType = undefined;
375
+ [marketType, params] = this.handleMarketTypeAndParams('watchBidsAsks', firstMarket, params);
376
+ const url = this.implodeHostname(this.urls['api']['ws'][marketType]['public']);
377
+ const channelType = (marketType === 'spot') ? 'spot' : 'futures';
378
+ const actionType = (marketType === 'spot') ? 'op' : 'action';
379
+ let rawSubscriptions = [];
380
+ const messageHashes = [];
381
+ for (let i = 0; i < symbols.length; i++) {
382
+ const market = this.market(symbols[i]);
383
+ rawSubscriptions.push(channelType + '/ticker:' + market['id']);
384
+ messageHashes.push('bidask:' + symbols[i]);
385
+ }
386
+ if (marketType !== 'spot') {
387
+ rawSubscriptions = [channelType + '/ticker'];
388
+ }
389
+ const request = {
390
+ 'args': rawSubscriptions,
391
+ };
392
+ request[actionType] = 'subscribe';
393
+ const newTickers = await this.watchMultiple(url, messageHashes, request, rawSubscriptions);
394
+ if (this.newUpdates) {
395
+ const tickers = {};
396
+ tickers[newTickers['symbol']] = newTickers;
397
+ return tickers;
398
+ }
399
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
400
+ }
401
+ handleBidAsk(client, message) {
402
+ const table = this.safeString(message, 'table');
403
+ const isSpot = (table !== undefined);
404
+ let rawTickers = [];
405
+ if (isSpot) {
406
+ rawTickers = this.safeList(message, 'data', []);
407
+ }
408
+ else {
409
+ rawTickers = [this.safeValue(message, 'data', {})];
410
+ }
411
+ if (!rawTickers.length) {
412
+ return;
413
+ }
414
+ for (let i = 0; i < rawTickers.length; i++) {
415
+ const ticker = this.parseWsBidAsk(rawTickers[i]);
416
+ const symbol = ticker['symbol'];
417
+ this.bidsasks[symbol] = ticker;
418
+ const messageHash = 'bidask:' + symbol;
419
+ client.resolve(ticker, messageHash);
420
+ }
421
+ }
422
+ parseWsBidAsk(ticker, market = undefined) {
423
+ const marketId = this.safeString(ticker, 'symbol');
424
+ market = this.safeMarket(marketId, market);
425
+ const symbol = this.safeString(market, 'symbol');
426
+ const timestamp = this.safeInteger(ticker, 'ms_t');
427
+ return this.safeTicker({
428
+ 'symbol': symbol,
429
+ 'timestamp': timestamp,
430
+ 'datetime': this.iso8601(timestamp),
431
+ 'ask': this.safeString2(ticker, 'ask_px', 'ask_price'),
432
+ 'askVolume': this.safeString2(ticker, 'ask_sz', 'ask_vol'),
433
+ 'bid': this.safeString2(ticker, 'bid_px', 'bid_price'),
434
+ 'bidVolume': this.safeString2(ticker, 'bid_sz', 'bid_vol'),
435
+ 'info': ticker,
436
+ }, market);
437
+ }
358
438
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
359
439
  /**
360
440
  * @method
@@ -934,6 +1014,7 @@ export default class bitmart extends bitmartRest {
934
1014
  // }
935
1015
  // }
936
1016
  //
1017
+ this.handleBidAsk(client, message);
937
1018
  const table = this.safeString(message, 'table');
938
1019
  const isSpot = (table !== undefined);
939
1020
  let rawTickers = [];
@@ -1,11 +1,16 @@
1
1
  import bitvavoRest from '../bitvavo.js';
2
- import { Int, Str, OrderSide, OrderType, OrderBook, Ticker, Trade, Order, OHLCV, Balances, Num, TradingFees } from '../base/types.js';
2
+ import { Int, Str, OrderSide, OrderType, OrderBook, Ticker, Trade, Order, OHLCV, Balances, Num, TradingFees, Strings, Tickers } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class bitvavo extends bitvavoRest {
5
5
  describe(): any;
6
6
  watchPublic(name: any, symbol: any, params?: {}): Promise<any>;
7
+ watchPublicMultiple(methodName: any, channelName: string, symbols: any, params?: {}): Promise<any>;
7
8
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
8
- handleTicker(client: Client, message: any): any;
9
+ watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
10
+ handleTicker(client: Client, message: any): void;
11
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
12
+ handleBidAsk(client: Client, message: any): void;
13
+ parseWsBidAsk(ticker: any, market?: any): Ticker;
9
14
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
10
15
  handleTrade(client: Client, message: any): void;
11
16
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
@@ -20,6 +20,8 @@ export default class bitvavo extends bitvavoRest {
20
20
  'watchOrderBook': true,
21
21
  'watchTrades': true,
22
22
  'watchTicker': true,
23
+ 'watchTickers': true,
24
+ 'watchBidsAsks': true,
23
25
  'watchOHLCV': true,
24
26
  'watchOrders': true,
25
27
  'watchMyTrades': true,
@@ -80,17 +82,56 @@ export default class bitvavo extends bitvavoRest {
80
82
  const message = this.extend(request, params);
81
83
  return await this.watch(url, messageHash, message, messageHash);
82
84
  }
85
+ async watchPublicMultiple(methodName, channelName, symbols, params = {}) {
86
+ await this.loadMarkets();
87
+ symbols = this.marketSymbols(symbols);
88
+ const messageHashes = [methodName];
89
+ const args = [];
90
+ for (let i = 0; i < symbols.length; i++) {
91
+ const market = this.market(symbols[i]);
92
+ args.push(market['id']);
93
+ }
94
+ const url = this.urls['api']['ws'];
95
+ const request = {
96
+ 'action': 'subscribe',
97
+ 'channels': [
98
+ {
99
+ 'name': channelName,
100
+ 'markets': args,
101
+ },
102
+ ],
103
+ };
104
+ const message = this.extend(request, params);
105
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
106
+ }
83
107
  async watchTicker(symbol, params = {}) {
84
108
  /**
85
109
  * @method
86
110
  * @name bitvavo#watchTicker
87
111
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
112
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
88
113
  * @param {string} symbol unified symbol of the market to fetch the ticker for
89
114
  * @param {object} [params] extra parameters specific to the exchange API endpoint
90
115
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
91
116
  */
92
117
  return await this.watchPublic('ticker24h', symbol, params);
93
118
  }
119
+ async watchTickers(symbols = undefined, params = {}) {
120
+ /**
121
+ * @method
122
+ * @name bitvavo#watchTickers
123
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
124
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
125
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
126
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
127
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
128
+ */
129
+ await this.loadMarkets();
130
+ symbols = this.marketSymbols(symbols, undefined, false);
131
+ const channel = 'ticker24h';
132
+ const tickers = await this.watchPublicMultiple(channel, channel, symbols, params);
133
+ return this.filterByArray(tickers, 'symbol', symbols);
134
+ }
94
135
  handleTicker(client, message) {
95
136
  //
96
137
  // {
@@ -113,8 +154,10 @@ export default class bitvavo extends bitvavoRest {
113
154
  // ]
114
155
  // }
115
156
  //
157
+ this.handleBidAsk(client, message);
116
158
  const event = this.safeString(message, 'event');
117
159
  const tickers = this.safeValue(message, 'data', []);
160
+ const result = [];
118
161
  for (let i = 0; i < tickers.length; i++) {
119
162
  const data = tickers[i];
120
163
  const marketId = this.safeString(data, 'market');
@@ -123,9 +166,57 @@ export default class bitvavo extends bitvavoRest {
123
166
  const ticker = this.parseTicker(data, market);
124
167
  const symbol = ticker['symbol'];
125
168
  this.tickers[symbol] = ticker;
169
+ result.push(ticker);
126
170
  client.resolve(ticker, messageHash);
127
171
  }
128
- return message;
172
+ client.resolve(result, event);
173
+ }
174
+ async watchBidsAsks(symbols = undefined, params = {}) {
175
+ /**
176
+ * @method
177
+ * @name mexc#watchBidsAsks
178
+ * @description watches best bid & ask for symbols
179
+ * @see https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
180
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
181
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
182
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
183
+ */
184
+ await this.loadMarkets();
185
+ symbols = this.marketSymbols(symbols, undefined, false);
186
+ const channel = 'ticker24h';
187
+ const tickers = await this.watchPublicMultiple('bidask', channel, symbols, params);
188
+ return this.filterByArray(tickers, 'symbol', symbols);
189
+ }
190
+ handleBidAsk(client, message) {
191
+ const event = 'bidask';
192
+ const tickers = this.safeValue(message, 'data', []);
193
+ const result = [];
194
+ for (let i = 0; i < tickers.length; i++) {
195
+ const data = tickers[i];
196
+ const ticker = this.parseWsBidAsk(data);
197
+ const symbol = ticker['symbol'];
198
+ this.bidsasks[symbol] = ticker;
199
+ result.push(ticker);
200
+ const messageHash = event + ':' + symbol;
201
+ client.resolve(ticker, messageHash);
202
+ }
203
+ client.resolve(result, event);
204
+ }
205
+ parseWsBidAsk(ticker, market = undefined) {
206
+ const marketId = this.safeString(ticker, 'market');
207
+ market = this.safeMarket(marketId, undefined, '-');
208
+ const symbol = this.safeString(market, 'symbol');
209
+ const timestamp = this.safeInteger(ticker, 'timestamp');
210
+ return this.safeTicker({
211
+ 'symbol': symbol,
212
+ 'timestamp': timestamp,
213
+ 'datetime': this.iso8601(timestamp),
214
+ 'ask': this.safeNumber(ticker, 'ask'),
215
+ 'askVolume': this.safeNumber(ticker, 'askSize'),
216
+ 'bid': this.safeNumber(ticker, 'bid'),
217
+ 'bidVolume': this.safeNumber(ticker, 'bidSize'),
218
+ 'info': ticker,
219
+ }, market);
129
220
  }
130
221
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
131
222
  /**
@@ -16,6 +16,9 @@ export default class blofin extends blofinRest {
16
16
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
17
17
  handleTicker(client: Client, message: any): void;
18
18
  parseWsTicker(ticker: any, market?: Market): Ticker;
19
+ watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
20
+ handleBidAsk(client: Client, message: any): void;
21
+ parseWsBidAsk(ticker: any, market?: any): Ticker;
19
22
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
20
23
  watchOHLCVForSymbols(symbolsAndTimeframes: string[][], since?: Int, limit?: Int, params?: {}): Promise<import("../base/types.js").Dictionary<import("../base/types.js").Dictionary<OHLCV[]>>>;
21
24
  handleOHLCV(client: Client, message: any): void;