ccxt 4.2.37 → 4.2.39

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 (113) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.js +3015 -509
  3. package/dist/ccxt.browser.min.js +7 -7
  4. package/dist/cjs/ccxt.js +4 -1
  5. package/dist/cjs/src/abstract/blofin.js +9 -0
  6. package/dist/cjs/src/base/Exchange.js +14 -2
  7. package/dist/cjs/src/binance.js +156 -35
  8. package/dist/cjs/src/bitget.js +1 -1
  9. package/dist/cjs/src/bitso.js +18 -2
  10. package/dist/cjs/src/bitstamp.js +24 -2
  11. package/dist/cjs/src/bl3p.js +6 -0
  12. package/dist/cjs/src/blockchaincom.js +21 -0
  13. package/dist/cjs/src/blofin.js +2103 -0
  14. package/dist/cjs/src/btcalpha.js +9 -0
  15. package/dist/cjs/src/btcbox.js +9 -0
  16. package/dist/cjs/src/btcmarkets.js +19 -0
  17. package/dist/cjs/src/coinbase.js +13 -2
  18. package/dist/cjs/src/krakenfutures.js +7 -14
  19. package/dist/cjs/src/luno.js +1 -1
  20. package/dist/cjs/src/okx.js +2 -2
  21. package/dist/cjs/src/poloniexfutures.js +11 -5
  22. package/dist/cjs/src/pro/bitmart.js +110 -35
  23. package/dist/cjs/src/pro/kucoin.js +93 -40
  24. package/dist/cjs/src/pro/mexc.js +1 -1
  25. package/dist/cjs/src/wavesexchange.js +1 -1
  26. package/dist/cjs/src/woo.js +1 -1
  27. package/js/ccxt.d.ts +5 -2
  28. package/js/ccxt.js +4 -2
  29. package/js/src/abstract/blofin.d.ts +36 -0
  30. package/js/src/abstract/blofin.js +11 -0
  31. package/js/src/abstract/coinbase.d.ts +1 -0
  32. package/js/src/abstract/okx.d.ts +1 -0
  33. package/js/src/ascendex.d.ts +2 -2
  34. package/js/src/base/Exchange.d.ts +4 -0
  35. package/js/src/base/Exchange.js +14 -2
  36. package/js/src/base/types.d.ts +2 -0
  37. package/js/src/bigone.d.ts +2 -2
  38. package/js/src/binance.d.ts +8 -8
  39. package/js/src/binance.js +156 -35
  40. package/js/src/bingx.d.ts +5 -5
  41. package/js/src/bitfinex.d.ts +3 -3
  42. package/js/src/bitfinex2.d.ts +2 -2
  43. package/js/src/bitget.d.ts +5 -5
  44. package/js/src/bitget.js +1 -1
  45. package/js/src/bitmart.d.ts +2 -2
  46. package/js/src/bitmex.d.ts +2 -2
  47. package/js/src/bitrue.d.ts +2 -2
  48. package/js/src/bitso.d.ts +1 -1
  49. package/js/src/bitso.js +18 -2
  50. package/js/src/bitstamp.d.ts +1 -1
  51. package/js/src/bitstamp.js +24 -2
  52. package/js/src/bitvavo.d.ts +1 -1
  53. package/js/src/bl3p.js +6 -0
  54. package/js/src/blockchaincom.js +21 -0
  55. package/js/src/blofin.d.ts +124 -0
  56. package/js/src/blofin.js +2104 -0
  57. package/js/src/btcalpha.js +9 -0
  58. package/js/src/btcbox.js +9 -0
  59. package/js/src/btcmarkets.js +19 -0
  60. package/js/src/bybit.d.ts +7 -7
  61. package/js/src/cex.d.ts +1 -1
  62. package/js/src/coinbase.d.ts +2 -2
  63. package/js/src/coinbase.js +13 -2
  64. package/js/src/coinex.d.ts +4 -4
  65. package/js/src/coinlist.d.ts +2 -2
  66. package/js/src/coinone.d.ts +1 -1
  67. package/js/src/delta.d.ts +2 -2
  68. package/js/src/deribit.d.ts +3 -3
  69. package/js/src/digifinex.d.ts +3 -3
  70. package/js/src/exmo.d.ts +2 -2
  71. package/js/src/gate.d.ts +6 -6
  72. package/js/src/hitbtc.d.ts +2 -2
  73. package/js/src/hollaex.d.ts +1 -1
  74. package/js/src/htx.d.ts +3 -3
  75. package/js/src/huobijp.d.ts +1 -1
  76. package/js/src/kraken.d.ts +2 -2
  77. package/js/src/krakenfutures.d.ts +2 -2
  78. package/js/src/krakenfutures.js +7 -14
  79. package/js/src/kucoin.d.ts +5 -5
  80. package/js/src/kucoinfutures.d.ts +2 -2
  81. package/js/src/latoken.d.ts +1 -1
  82. package/js/src/lbank.d.ts +2 -2
  83. package/js/src/luno.d.ts +1 -1
  84. package/js/src/luno.js +1 -1
  85. package/js/src/mexc.d.ts +4 -4
  86. package/js/src/ndax.d.ts +1 -1
  87. package/js/src/novadax.d.ts +1 -1
  88. package/js/src/okcoin.d.ts +2 -2
  89. package/js/src/okx.d.ts +7 -7
  90. package/js/src/okx.js +2 -2
  91. package/js/src/paymium.d.ts +2 -2
  92. package/js/src/phemex.d.ts +4 -4
  93. package/js/src/poloniex.d.ts +2 -2
  94. package/js/src/poloniexfutures.d.ts +2 -2
  95. package/js/src/poloniexfutures.js +11 -5
  96. package/js/src/pro/bitmart.d.ts +2 -0
  97. package/js/src/pro/bitmart.js +110 -35
  98. package/js/src/pro/bitvavo.d.ts +1 -1
  99. package/js/src/pro/cex.d.ts +2 -2
  100. package/js/src/pro/coinbase.d.ts +2 -2
  101. package/js/src/pro/coinex.d.ts +1 -1
  102. package/js/src/pro/kucoin.js +93 -40
  103. package/js/src/pro/lbank.d.ts +1 -1
  104. package/js/src/pro/mexc.js +1 -1
  105. package/js/src/probit.d.ts +1 -1
  106. package/js/src/timex.d.ts +1 -1
  107. package/js/src/upbit.d.ts +1 -1
  108. package/js/src/wavesexchange.js +1 -1
  109. package/js/src/whitebit.d.ts +2 -2
  110. package/js/src/woo.d.ts +3 -3
  111. package/js/src/woo.js +1 -1
  112. package/js/src/zonda.d.ts +3 -3
  113. package/package.json +2 -2
@@ -27,6 +27,7 @@ export default class bitmart extends bitmartRest {
27
27
  'watchTicker': true,
28
28
  'watchTickers': true,
29
29
  'watchOrderBook': true,
30
+ 'watchOrderBookForSymbols': true,
30
31
  'watchOrders': true,
31
32
  'watchTrades': true,
32
33
  'watchOHLCV': true,
@@ -53,8 +54,15 @@ export default class bitmart extends bitmartRest {
53
54
  'fetchBalanceSnapshot': true,
54
55
  'awaitBalanceSnapshot': false, // whether to wait for the balance snapshot before providing updates
55
56
  },
57
+ //
58
+ // orderbook channels can have:
59
+ // - 'depth5', 'depth20', 'depth50' // these endpoints emit full Orderbooks once in every 500ms
60
+ // - 'depth/increase100' // this endpoint is preferred, because it emits once in 100ms. however, when this value is chosen, it only affects spot-market, but contracts markets automatically `depth50` will be being used
56
61
  'watchOrderBook': {
57
- 'depth': 'depth/increase100', // depth/increase100, depth5, depth20, depth50
62
+ 'depth': 'depth/increase100',
63
+ },
64
+ 'watchOrderBookForSymbols': {
65
+ 'depth': 'depth/increase100',
58
66
  },
59
67
  'ws': {
60
68
  'inflate': true,
@@ -101,6 +109,24 @@ export default class bitmart extends bitmartRest {
101
109
  }
102
110
  return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
103
111
  }
112
+ async subscribeMultiple(channel, type, symbols, params = {}) {
113
+ const url = this.implodeHostname(this.urls['api']['ws'][type]['public']);
114
+ const channelType = (type === 'spot') ? 'spot' : 'futures';
115
+ const actionType = (type === 'spot') ? 'op' : 'action';
116
+ const rawSubscriptions = [];
117
+ const messageHashes = [];
118
+ for (let i = 0; i < symbols.length; i++) {
119
+ const market = this.market(symbols[i]);
120
+ const message = channelType + '/' + channel + ':' + market['id'];
121
+ rawSubscriptions.push(message);
122
+ messageHashes.push(channel + ':' + market['symbol']);
123
+ }
124
+ const request = {
125
+ 'args': rawSubscriptions,
126
+ };
127
+ request[actionType] = 'subscribe';
128
+ return await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), rawSubscriptions);
129
+ }
104
130
  async watchBalance(params = {}) {
105
131
  /**
106
132
  * @method
@@ -1159,8 +1185,8 @@ export default class bitmart extends bitmartRest {
1159
1185
  // "symbol": "BTC_USDT"
1160
1186
  // }
1161
1187
  //
1162
- const asks = this.safeValue(message, 'asks', []);
1163
- const bids = this.safeValue(message, 'bids', []);
1188
+ const asks = this.safeList(message, 'asks', []);
1189
+ const bids = this.safeList(message, 'bids', []);
1164
1190
  this.handleDeltas(orderbook['asks'], asks);
1165
1191
  this.handleDeltas(orderbook['bids'], bids);
1166
1192
  const timestamp = this.safeInteger(message, 'ms_t');
@@ -1174,6 +1200,7 @@ export default class bitmart extends bitmartRest {
1174
1200
  handleOrderBook(client, message) {
1175
1201
  //
1176
1202
  // spot depth-all
1203
+ //
1177
1204
  // {
1178
1205
  // "data": [
1179
1206
  // {
@@ -1193,33 +1220,31 @@ export default class bitmart extends bitmartRest {
1193
1220
  // ],
1194
1221
  // "table": "spot/depth5"
1195
1222
  // }
1223
+ //
1196
1224
  // spot increse depth snapshot
1225
+ //
1197
1226
  // {
1198
1227
  // "data":[
1199
1228
  // {
1200
- // "asks":[
1201
- // [
1202
- // "43652.52",
1203
- // "0.02039"
1204
- // ],
1205
- // ...
1206
- // ],
1207
- // "bids":[
1208
- // [
1209
- // "43652.51",
1210
- // "0.00500"
1229
+ // "asks":[
1230
+ // [ "43652.52", "0.02039" ],
1231
+ // ...
1211
1232
  // ],
1212
- // ...
1213
- // ],
1214
- // "ms_t":1703376836487,
1215
- // "symbol":"BTC_USDT",
1216
- // "type":"snapshot", // or update
1217
- // "version":2141731
1233
+ // "bids":[
1234
+ // [ "43652.51", "0.00500" ],
1235
+ // ...
1236
+ // ],
1237
+ // "ms_t":1703376836487,
1238
+ // "symbol":"BTC_USDT",
1239
+ // "type":"snapshot", // or update
1240
+ // "version":2141731
1218
1241
  // }
1219
1242
  // ],
1220
1243
  // "table":"spot/depth/increase100"
1221
1244
  // }
1245
+ //
1222
1246
  // swap
1247
+ //
1223
1248
  // {
1224
1249
  // "group":"futures/depth50:BTCUSDT",
1225
1250
  // "data":{
@@ -1240,50 +1265,69 @@ export default class bitmart extends bitmartRest {
1240
1265
  // }
1241
1266
  // }
1242
1267
  //
1243
- const data = this.safeValue(message, 'data');
1244
- if (data === undefined) {
1268
+ const isSpot = ('table' in message);
1269
+ let datas = [];
1270
+ if (isSpot) {
1271
+ datas = this.safeList(message, 'data', datas);
1272
+ }
1273
+ else {
1274
+ const orderBookEntry = this.safeDict(message, 'data');
1275
+ if (orderBookEntry !== undefined) {
1276
+ datas.push(orderBookEntry);
1277
+ }
1278
+ }
1279
+ const length = datas.length;
1280
+ if (length <= 0) {
1245
1281
  return;
1246
1282
  }
1247
- const depths = this.safeValue(data, 'depths');
1248
- const isSpot = (depths === undefined);
1249
- const table = this.safeString2(message, 'table', 'group');
1283
+ const channelName = this.safeString2(message, 'table', 'group');
1250
1284
  // find limit subscribed to
1251
1285
  const limitsToCheck = ['100', '50', '20', '10', '5'];
1252
1286
  let limit = 0;
1253
1287
  for (let i = 0; i < limitsToCheck.length; i++) {
1254
1288
  const limitString = limitsToCheck[i];
1255
- if (table.indexOf(limitString) >= 0) {
1289
+ if (channelName.indexOf(limitString) >= 0) {
1256
1290
  limit = this.parseToInt(limitString);
1257
1291
  break;
1258
1292
  }
1259
1293
  }
1260
1294
  if (isSpot) {
1261
- for (let i = 0; i < data.length; i++) {
1262
- const update = data[i];
1295
+ const channel = channelName.replace('spot/', '');
1296
+ for (let i = 0; i < datas.length; i++) {
1297
+ const update = datas[i];
1263
1298
  const marketId = this.safeString(update, 'symbol');
1264
1299
  const symbol = this.safeSymbol(marketId);
1265
- let orderbook = this.safeValue(this.orderbooks, symbol);
1300
+ let orderbook = this.safeDict(this.orderbooks, symbol);
1266
1301
  if (orderbook === undefined) {
1267
1302
  orderbook = this.orderBook({}, limit);
1268
1303
  orderbook['symbol'] = symbol;
1269
1304
  this.orderbooks[symbol] = orderbook;
1270
1305
  }
1271
1306
  const type = this.safeValue(update, 'type');
1272
- if ((type === 'snapshot') || (!(table.indexOf('increase') >= 0))) {
1307
+ if ((type === 'snapshot') || (!(channelName.indexOf('increase') >= 0))) {
1273
1308
  orderbook.reset({});
1274
1309
  }
1275
1310
  this.handleOrderBookMessage(client, update, orderbook);
1276
1311
  const timestamp = this.safeInteger(update, 'ms_t');
1277
- orderbook['timestamp'] = timestamp;
1278
- orderbook['datetime'] = this.iso8601(timestamp);
1279
- const messageHash = table + ':' + marketId;
1312
+ if (orderbook['timestamp'] === undefined) {
1313
+ orderbook['timestamp'] = timestamp;
1314
+ orderbook['datetime'] = this.iso8601(timestamp);
1315
+ }
1316
+ const messageHash = channelName + ':' + marketId;
1280
1317
  client.resolve(orderbook, messageHash);
1318
+ // resolve ForSymbols
1319
+ const messageHashForMulti = channel + ':' + symbol;
1320
+ client.resolve(orderbook, messageHashForMulti);
1281
1321
  }
1282
1322
  }
1283
1323
  else {
1324
+ const tableParts = channelName.split(':');
1325
+ const channel = tableParts[0].replace('futures/', '');
1326
+ const data = datas[0]; // contract markets always contain only one member
1327
+ const depths = data['depths'];
1284
1328
  const marketId = this.safeString(data, 'symbol');
1285
1329
  const symbol = this.safeSymbol(marketId);
1286
- let orderbook = this.safeValue(this.orderbooks, symbol);
1330
+ let orderbook = this.safeDict(this.orderbooks, symbol);
1287
1331
  if (orderbook === undefined) {
1288
1332
  orderbook = this.orderBook({}, limit);
1289
1333
  orderbook['symbol'] = symbol;
@@ -1312,10 +1356,41 @@ export default class bitmart extends bitmartRest {
1312
1356
  const timestamp = this.safeInteger(data, 'ms_t');
1313
1357
  orderbook['timestamp'] = timestamp;
1314
1358
  orderbook['datetime'] = this.iso8601(timestamp);
1315
- const messageHash = table;
1359
+ const messageHash = channelName;
1316
1360
  client.resolve(orderbook, messageHash);
1361
+ // resolve ForSymbols
1362
+ const messageHashForMulti = channel + ':' + symbol;
1363
+ client.resolve(orderbook, messageHashForMulti);
1317
1364
  }
1318
1365
  }
1366
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
1367
+ /**
1368
+ * @method
1369
+ * @name bitmart#watchOrderBookForSymbols
1370
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1371
+ * @see https://developer-pro.bitmart.com/en/spot/#public-depth-increase-channel
1372
+ * @param {string[]} symbols unified array of symbols
1373
+ * @param {int} [limit] the maximum amount of order book entries to return
1374
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1375
+ * @param {string} [params.depth] the type of order book to subscribe to, default is 'depth/increase100', also accepts 'depth5' or 'depth20' or depth50
1376
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1377
+ */
1378
+ await this.loadMarkets();
1379
+ symbols = this.marketSymbols(symbols, undefined, false, true);
1380
+ if (symbols.length > 20) {
1381
+ throw new NotSupported(this.id + ' watchOrderBookForSymbols() accepts a maximum of 20 symbols in one request');
1382
+ }
1383
+ const market = this.market(symbols[0]);
1384
+ let channel = undefined;
1385
+ [channel, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', 'depth/increase100');
1386
+ let type = 'spot';
1387
+ [type, params] = this.handleMarketTypeAndParams('watchOrderBookForSymbols', market, params);
1388
+ if (type === 'swap' && channel === 'depth/increase100') {
1389
+ channel = 'depth50';
1390
+ }
1391
+ const orderbook = await this.subscribeMultiple(channel, type, symbols, params);
1392
+ return orderbook.limit();
1393
+ }
1319
1394
  async authenticate(type, params = {}) {
1320
1395
  this.checkRequiredCredentials();
1321
1396
  const url = this.implodeHostname(this.urls['api']['ws'][type]['private']);
@@ -23,7 +23,7 @@ export default class bitvavo extends bitvavoRest {
23
23
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
24
24
  watchMyTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
25
25
  createOrderWs(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: number, params?: {}): Promise<Order>;
26
- editOrderWs(id: string, symbol: any, type: any, side: any, amount?: any, price?: any, params?: {}): Promise<Order>;
26
+ editOrderWs(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: number, price?: number, params?: {}): Promise<Order>;
27
27
  cancelOrderWs(id: string, symbol?: string, params?: {}): Promise<any>;
28
28
  cancelAllOrdersWs(symbol?: string, params?: {}): Promise<any>;
29
29
  handleMultipleOrders(client: Client, message: any): void;
@@ -40,9 +40,9 @@ export default class cex extends cexRest {
40
40
  fetchOrderWs(id: string, symbol?: string, params?: {}): Promise<Order>;
41
41
  fetchOpenOrdersWs(symbol?: string, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
42
42
  createOrderWs(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: number, params?: {}): Promise<Order>;
43
- editOrderWs(id: string, symbol: any, type: any, side: any, amount?: any, price?: any, params?: {}): Promise<Order>;
43
+ editOrderWs(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: number, price?: number, params?: {}): Promise<Order>;
44
44
  cancelOrderWs(id: string, symbol?: string, params?: {}): Promise<Order>;
45
- cancelOrdersWs(ids: any, symbol?: string, params?: {}): Promise<Order[]>;
45
+ cancelOrdersWs(ids: string[], symbol?: string, params?: {}): Promise<Order[]>;
46
46
  resolveData(client: Client, message: any): void;
47
47
  handleConnected(client: Client, message: any): any;
48
48
  handleErrorMessage(client: Client, message: any): void;
@@ -3,12 +3,12 @@ import { Strings, Tickers, Ticker, Int, Trade, OrderBook, Order } from '../base/
3
3
  export default class coinbase extends coinbaseRest {
4
4
  describe(): any;
5
5
  subscribe(name: any, symbol?: any, params?: {}): Promise<any>;
6
- watchTicker(symbol: any, params?: {}): Promise<Ticker>;
6
+ watchTicker(symbol: string, params?: {}): Promise<Ticker>;
7
7
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
8
8
  handleTickers(client: any, message: any): any;
9
9
  parseWsTicker(ticker: any, market?: any): Ticker;
10
10
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
11
- watchOrders(symbol?: any, since?: any, limit?: any, params?: {}): Promise<Order[]>;
11
+ watchOrders(symbol?: string, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
12
12
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
13
13
  handleTrade(client: any, message: any): any;
14
14
  handleOrder(client: any, message: any): any;
@@ -16,7 +16,7 @@ export default class coinex extends coinexRest {
16
16
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
17
17
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
18
18
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
19
- fetchOHLCVWs(symbol: any, timeframe?: string, since?: any, limit?: any, params?: {}): Promise<OHLCV[]>;
19
+ fetchOHLCVWs(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
20
20
  handleDelta(bookside: any, delta: any): void;
21
21
  handleDeltas(bookside: any, deltas: any): void;
22
22
  handleOrderBook(client: Client, message: any): void;
@@ -40,6 +40,7 @@ export default class kucoin extends kucoinRest {
40
40
  'watchOrderBook': {
41
41
  'snapshotDelay': 5,
42
42
  'snapshotMaxRetries': 3,
43
+ 'method': '/market/level2', // '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50'
43
44
  },
44
45
  },
45
46
  'streaming': {
@@ -441,10 +442,15 @@ export default class kucoin extends kucoinRest {
441
442
  /**
442
443
  * @method
443
444
  * @name kucoin#watchOrderBook
445
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
446
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
447
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
448
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
444
449
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
445
450
  * @param {string} symbol unified symbol of the market to fetch the order book for
446
451
  * @param {int} [limit] the maximum amount of order book entries to return
447
452
  * @param {object} [params] extra parameters specific to the exchange API endpoint
453
+ * @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
448
454
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
449
455
  */
450
456
  //
@@ -468,10 +474,15 @@ export default class kucoin extends kucoinRest {
468
474
  /**
469
475
  * @method
470
476
  * @name kucoin#watchOrderBookForSymbols
477
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
478
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
479
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
480
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
471
481
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
472
482
  * @param {string[]} symbols unified array of symbols
473
483
  * @param {int} [limit] the maximum amount of order book entries to return
474
484
  * @param {object} [params] extra parameters specific to the exchange API endpoint
485
+ * @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
475
486
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
476
487
  */
477
488
  const symbolsLength = symbols.length;
@@ -479,28 +490,36 @@ export default class kucoin extends kucoinRest {
479
490
  throw new ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
480
491
  }
481
492
  if (limit !== undefined) {
482
- if ((limit !== 20) && (limit !== 100)) {
483
- throw new ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
493
+ if ((limit !== 20) && (limit !== 100) && (limit !== 50) && (limit !== 5)) {
494
+ throw new ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 5, 20, 50 or 100");
484
495
  }
485
496
  }
486
497
  await this.loadMarkets();
487
498
  symbols = this.marketSymbols(symbols);
488
499
  const marketIds = this.marketIds(symbols);
489
500
  const url = await this.negotiate(false);
490
- const topic = '/market/level2:' + marketIds.join(',');
501
+ let method = undefined;
502
+ [method, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'method', '/market/level2');
503
+ if ((limit === 5) || (limit === 50)) {
504
+ method = '/spotMarket/level2Depth' + limit.toString();
505
+ }
506
+ const topic = method + ':' + marketIds.join(',');
491
507
  const messageHashes = [];
492
508
  const subscriptionHashes = [];
493
509
  for (let i = 0; i < symbols.length; i++) {
494
510
  const symbol = symbols[i];
495
511
  messageHashes.push('orderbook:' + symbol);
496
512
  const marketId = marketIds[i];
497
- subscriptionHashes.push('/market/level2:' + marketId);
513
+ subscriptionHashes.push(method + ':' + marketId);
514
+ }
515
+ let subscription = {};
516
+ if (method === '/market/level2') { // other streams return the entire orderbook, so we don't need to fetch the snapshot through REST
517
+ subscription = {
518
+ 'method': this.handleOrderBookSubscription,
519
+ 'symbols': symbols,
520
+ 'limit': limit,
521
+ };
498
522
  }
499
- const subscription = {
500
- 'method': this.handleOrderBookSubscription,
501
- 'symbols': symbols,
502
- 'limit': limit,
503
- };
504
523
  const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, params, subscription);
505
524
  return orderbook.limit();
506
525
  }
@@ -524,41 +543,74 @@ export default class kucoin extends kucoinRest {
524
543
  // }
525
544
  // }
526
545
  //
546
+ // {
547
+ // "topic": "/spotMarket/level2Depth5:BTC-USDT",
548
+ // "type": "message",
549
+ // "data": {
550
+ // "asks": [
551
+ // [
552
+ // "42815.6",
553
+ // "1.24016245"
554
+ // ]
555
+ // ],
556
+ // "bids": [
557
+ // [
558
+ // "42815.5",
559
+ // "0.08652716"
560
+ // ]
561
+ // ],
562
+ // "timestamp": 1707204474018
563
+ // },
564
+ // "subject": "level2"
565
+ // }
566
+ //
527
567
  const data = this.safeValue(message, 'data');
528
- const marketId = this.safeString(data, 'symbol');
568
+ const subject = this.safeString(message, 'subject');
569
+ const topic = this.safeString(message, 'topic');
570
+ const topicParts = topic.split(':');
571
+ const topicSymbol = this.safeString(topicParts, 1);
572
+ const topicChannel = this.safeString(topicParts, 0);
573
+ const marketId = this.safeString(data, 'symbol', topicSymbol);
529
574
  const symbol = this.safeSymbol(marketId, undefined, '-');
530
575
  const messageHash = 'orderbook:' + symbol;
531
- const storedOrderBook = this.orderbooks[symbol];
532
- const nonce = this.safeInteger(storedOrderBook, 'nonce');
533
- const deltaEnd = this.safeInteger(data, 'sequenceEnd');
534
- if (nonce === undefined) {
535
- const cacheLength = storedOrderBook.cache.length;
536
- const topic = this.safeString(message, 'topic');
537
- const topicParts = topic.split(':');
538
- const topicSymbol = this.safeString(topicParts, 1);
539
- const topicChannel = this.safeString(topicParts, 0);
540
- const subscriptions = Object.keys(client.subscriptions);
541
- let subscription = undefined;
542
- for (let i = 0; i < subscriptions.length; i++) {
543
- const key = subscriptions[i];
544
- if ((key.indexOf(topicSymbol) >= 0) && (key.indexOf(topicChannel) >= 0)) {
545
- subscription = client.subscriptions[key];
546
- break;
547
- }
576
+ let orderbook = this.safeDict(this.orderbooks, symbol);
577
+ if (subject === 'level2') {
578
+ if (orderbook === undefined) {
579
+ orderbook = this.orderBook();
548
580
  }
549
- const limit = this.safeInteger(subscription, 'limit');
550
- const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 5);
551
- if (cacheLength === snapshotDelay) {
552
- this.spawn(this.loadOrderBook, client, messageHash, symbol, limit, {});
581
+ else {
582
+ orderbook.reset();
553
583
  }
554
- storedOrderBook.cache.push(data);
555
- return;
584
+ orderbook['symbol'] = symbol;
556
585
  }
557
- else if (nonce >= deltaEnd) {
558
- return;
586
+ else {
587
+ const nonce = this.safeInteger(orderbook, 'nonce');
588
+ const deltaEnd = this.safeInteger2(data, 'sequenceEnd', 'timestamp');
589
+ if (nonce === undefined) {
590
+ const cacheLength = orderbook.cache.length;
591
+ const subscriptions = Object.keys(client.subscriptions);
592
+ let subscription = undefined;
593
+ for (let i = 0; i < subscriptions.length; i++) {
594
+ const key = subscriptions[i];
595
+ if ((key.indexOf(topicSymbol) >= 0) && (key.indexOf(topicChannel) >= 0)) {
596
+ subscription = client.subscriptions[key];
597
+ break;
598
+ }
599
+ }
600
+ const limit = this.safeInteger(subscription, 'limit');
601
+ const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 5);
602
+ if (cacheLength === snapshotDelay) {
603
+ this.spawn(this.loadOrderBook, client, messageHash, symbol, limit, {});
604
+ }
605
+ orderbook.cache.push(data);
606
+ return;
607
+ }
608
+ else if (nonce >= deltaEnd) {
609
+ return;
610
+ }
559
611
  }
560
- this.handleDelta(storedOrderBook, data);
561
- client.resolve(storedOrderBook, messageHash);
612
+ this.handleDelta(orderbook, data);
613
+ client.resolve(orderbook, messageHash);
562
614
  }
563
615
  getCacheIndex(orderbook, cache) {
564
616
  const firstDelta = this.safeValue(cache, 0);
@@ -578,11 +630,11 @@ export default class kucoin extends kucoinRest {
578
630
  return cache.length;
579
631
  }
580
632
  handleDelta(orderbook, delta) {
581
- orderbook['nonce'] = this.safeInteger(delta, 'sequenceEnd');
582
- const timestamp = this.safeInteger(delta, 'time');
633
+ const timestamp = this.safeInteger2(delta, 'time', 'timestamp');
634
+ orderbook['nonce'] = this.safeInteger(delta, 'sequenceEnd', timestamp);
583
635
  orderbook['timestamp'] = timestamp;
584
636
  orderbook['datetime'] = this.iso8601(timestamp);
585
- const changes = this.safeValue(delta, 'changes');
637
+ const changes = this.safeValue(delta, 'changes', delta);
586
638
  const bids = this.safeValue(changes, 'bids', []);
587
639
  const asks = this.safeValue(changes, 'asks', []);
588
640
  const storedBids = orderbook['bids'];
@@ -996,6 +1048,7 @@ export default class kucoin extends kucoinRest {
996
1048
  }
997
1049
  const subject = this.safeString(message, 'subject');
998
1050
  const methods = {
1051
+ 'level2': this.handleOrderBook,
999
1052
  'trade.l2update': this.handleOrderBook,
1000
1053
  'trade.ticker': this.handleTicker,
1001
1054
  'trade.snapshot': this.handleTicker,
@@ -8,7 +8,7 @@ export default class lbank extends lbankRest {
8
8
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
9
9
  handleOHLCV(client: any, message: any): void;
10
10
  fetchTickerWs(symbol: any, params?: {}): Promise<Ticker>;
11
- watchTicker(symbol: any, params?: {}): Promise<Ticker>;
11
+ watchTicker(symbol: string, params?: {}): Promise<Ticker>;
12
12
  handleTicker(client: any, message: any): void;
13
13
  parseWsTicker(ticker: any, market?: any): Ticker;
14
14
  fetchTradesWs(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
@@ -472,7 +472,7 @@ export default class mexc extends mexcRest {
472
472
  }
473
473
  try {
474
474
  this.handleDelta(storedOrderBook, data);
475
- const timestamp = this.safeInteger(message, 't');
475
+ const timestamp = this.safeInteger2(message, 't', 'ts');
476
476
  storedOrderBook['timestamp'] = timestamp;
477
477
  storedOrderBook['datetime'] = this.iso8601(timestamp);
478
478
  }
@@ -44,7 +44,7 @@ export default class probit extends Exchange {
44
44
  network: string;
45
45
  info: any;
46
46
  }>;
47
- fetchDepositAddresses(codes?: any, params?: {}): Promise<{}>;
47
+ fetchDepositAddresses(codes?: string[], params?: {}): Promise<{}>;
48
48
  withdraw(code: string, amount: number, address: any, tag?: any, params?: {}): Promise<Transaction>;
49
49
  fetchDeposits(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
50
50
  fetchWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
package/js/src/timex.d.ts CHANGED
@@ -20,7 +20,7 @@ export default class timex extends Exchange {
20
20
  parseBalance(response: any): Balances;
21
21
  fetchBalance(params?: {}): Promise<Balances>;
22
22
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: number, params?: {}): Promise<Order>;
23
- editOrder(id: string, symbol: any, type: any, side: any, amount?: any, price?: any, params?: {}): Promise<Order>;
23
+ editOrder(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: number, price?: number, params?: {}): Promise<Order>;
24
24
  cancelOrder(id: string, symbol?: Str, params?: {}): Promise<any>;
25
25
  cancelOrders(ids: any, symbol?: Str, params?: {}): Promise<any>;
26
26
  fetchOrder(id: string, symbol?: Str, params?: {}): Promise<Order>;
package/js/src/upbit.d.ts CHANGED
@@ -72,7 +72,7 @@ export default class upbit extends Exchange {
72
72
  fetchClosedOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
73
73
  fetchCanceledOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
74
74
  fetchOrder(id: string, symbol?: Str, params?: {}): Promise<Order>;
75
- fetchDepositAddresses(codes?: any, params?: {}): Promise<{}>;
75
+ fetchDepositAddresses(codes?: string[], params?: {}): Promise<{}>;
76
76
  parseDepositAddress(depositAddress: any, currency?: Currency): {
77
77
  currency: string;
78
78
  address: string;
@@ -314,7 +314,7 @@ export default class wavesexchange extends Exchange {
314
314
  },
315
315
  },
316
316
  'currencies': {
317
- 'WX': this.safeCurrencyStructure({ 'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': undefined, 'code': 'WX', 'precision': this.parseNumber('8') }),
317
+ 'WX': this.safeCurrencyStructure({ 'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': undefined, 'code': 'WX', 'precision': this.parseToInt('8') }),
318
318
  },
319
319
  'precisionMode': DECIMAL_PLACES,
320
320
  'options': {
@@ -9,7 +9,7 @@ export default class whitebit extends Exchange {
9
9
  fetchMarkets(params?: {}): Promise<import("./base/types.js").MarketInterface[]>;
10
10
  parseMarket(market: any): Market;
11
11
  fetchCurrencies(params?: {}): Promise<{}>;
12
- fetchTransactionFees(codes?: any, params?: {}): Promise<{
12
+ fetchTransactionFees(codes?: string[], params?: {}): Promise<{
13
13
  withdraw: {};
14
14
  deposit: {};
15
15
  info: any;
@@ -51,7 +51,7 @@ export default class whitebit extends Exchange {
51
51
  info: any;
52
52
  }>;
53
53
  setLeverage(leverage: Int, symbol?: Str, params?: {}): Promise<any>;
54
- transfer(code: string, amount: number, fromAccount: any, toAccount: any, params?: {}): Promise<TransferEntry>;
54
+ transfer(code: string, amount: number, fromAccount: string, toAccount: string, params?: {}): Promise<TransferEntry>;
55
55
  parseTransfer(transfer: any, currency?: Currency): {
56
56
  info: any;
57
57
  id: any;
package/js/src/woo.d.ts CHANGED
@@ -13,11 +13,11 @@ export default class woo extends Exchange {
13
13
  parseTokenAndFeeTemp(item: any, feeTokenKey: any, feeAmountKey: any): any;
14
14
  fetchTradingFees(params?: {}): Promise<{}>;
15
15
  fetchCurrencies(params?: {}): Promise<{}>;
16
- createMarketBuyOrderWithCost(symbol: string, cost: any, params?: {}): Promise<Order>;
16
+ createMarketBuyOrderWithCost(symbol: string, cost: number, params?: {}): Promise<Order>;
17
17
  createTrailingAmountOrder(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, trailingAmount?: any, trailingTriggerPrice?: any, params?: {}): Promise<Order>;
18
18
  createTrailingPercentOrder(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, trailingPercent?: any, trailingTriggerPrice?: any, params?: {}): Promise<Order>;
19
19
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: number, params?: {}): Promise<Order>;
20
- editOrder(id: string, symbol: any, type: any, side: any, amount?: any, price?: any, params?: {}): Promise<Order>;
20
+ editOrder(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: number, price?: number, params?: {}): Promise<Order>;
21
21
  cancelOrder(id: string, symbol?: Str, params?: {}): Promise<any>;
22
22
  cancelAllOrders(symbol?: Str, params?: {}): Promise<any>;
23
23
  fetchOrder(id: string, symbol?: Str, params?: {}): Promise<Order>;
@@ -73,7 +73,7 @@ export default class woo extends Exchange {
73
73
  fetchDepositsWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
74
74
  parseTransaction(transaction: any, currency?: Currency): Transaction;
75
75
  parseTransactionStatus(status: any): string;
76
- transfer(code: string, amount: number, fromAccount: any, toAccount: any, params?: {}): Promise<TransferEntry>;
76
+ transfer(code: string, amount: number, fromAccount: string, toAccount: string, params?: {}): Promise<TransferEntry>;
77
77
  fetchTransfers(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<any>;
78
78
  parseTransfer(transfer: any, currency?: Currency): {
79
79
  id: string;
package/js/src/woo.js CHANGED
@@ -1068,7 +1068,7 @@ export default class woo extends Exchange {
1068
1068
  if (stopPrice !== undefined) {
1069
1069
  request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
1070
1070
  }
1071
- const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activatedPrice', price);
1071
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activatedPrice', this.numberToString(price));
1072
1072
  const trailingAmount = this.safeString2(params, 'trailingAmount', 'callbackValue');
1073
1073
  const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
1074
1074
  const isTrailingAmountOrder = trailingAmount !== undefined;