ccxt 4.2.16 → 4.2.18

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 (53) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.js +546 -276
  3. package/dist/ccxt.browser.min.js +3 -3
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/js/ccxt.js +3 -1
  6. package/dist/cjs/js/src/base/Exchange.js +5 -2
  7. package/dist/cjs/js/src/binance.js +7 -0
  8. package/dist/cjs/js/src/bingx.js +26 -0
  9. package/dist/cjs/js/src/bybit.js +21 -47
  10. package/dist/cjs/js/src/coincheck.js +1 -0
  11. package/dist/cjs/js/src/coinlist.js +10 -2
  12. package/dist/cjs/js/src/coinsph.js +2 -2
  13. package/dist/cjs/js/src/deribit.js +5 -1
  14. package/dist/cjs/js/src/kraken.js +1 -1
  15. package/dist/cjs/js/src/pro/binance.js +3 -3
  16. package/dist/cjs/js/src/pro/bitget.js +1 -1
  17. package/dist/cjs/js/src/pro/coincheck.js +208 -0
  18. package/dist/cjs/js/src/pro/hitbtc.js +5 -4
  19. package/dist/cjs/js/src/pro/kucoin.js +46 -36
  20. package/dist/cjs/js/src/pro/kucoinfutures.js +45 -37
  21. package/dist/cjs/js/src/pro/poloniex.js +2 -2
  22. package/dist/cjs/js/src/pro/poloniexfutures.js +43 -35
  23. package/dist/cjs/js/src/whitebit.js +1 -0
  24. package/js/ccxt.d.ts +4 -1
  25. package/js/ccxt.js +3 -1
  26. package/js/src/abstract/binance.d.ts +1 -0
  27. package/js/src/abstract/binancecoinm.d.ts +1 -0
  28. package/js/src/abstract/binanceus.d.ts +1 -0
  29. package/js/src/abstract/binanceusdm.d.ts +1 -0
  30. package/js/src/abstract/coinlist.d.ts +8 -0
  31. package/js/src/base/Exchange.d.ts +2 -3
  32. package/js/src/base/Exchange.js +5 -2
  33. package/js/src/binance.js +7 -0
  34. package/js/src/bingx.d.ts +1 -0
  35. package/js/src/bingx.js +26 -0
  36. package/js/src/bybit.js +21 -47
  37. package/js/src/coincheck.js +1 -0
  38. package/js/src/coinlist.js +10 -2
  39. package/js/src/coinsph.js +2 -2
  40. package/js/src/deribit.js +5 -1
  41. package/js/src/kraken.js +1 -1
  42. package/js/src/pro/binance.js +3 -3
  43. package/js/src/pro/bitget.js +1 -1
  44. package/js/src/pro/coincheck.d.ts +12 -0
  45. package/js/src/pro/coincheck.js +209 -0
  46. package/js/src/pro/hitbtc.js +5 -4
  47. package/js/src/pro/kucoin.js +46 -36
  48. package/js/src/pro/kucoinfutures.js +45 -37
  49. package/js/src/pro/poloniex.js +2 -2
  50. package/js/src/pro/poloniexfutures.js +43 -35
  51. package/js/src/whitebit.js +1 -0
  52. package/package.json +1 -1
  53. package/skip-tests.json +12 -1
package/js/src/bybit.js CHANGED
@@ -3966,7 +3966,7 @@ export default class bybit extends Exchange {
3966
3966
  response = await this.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(this.extend(request, params));
3967
3967
  }
3968
3968
  else {
3969
- const isStop = this.safeValue(params, 'stop', false);
3969
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
3970
3970
  const triggerPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
3971
3971
  const stopLossPrice = this.safeValue(params, 'stopLossPrice');
3972
3972
  const isStopLossOrder = stopLossPrice !== undefined;
@@ -4145,8 +4145,8 @@ export default class bybit extends Exchange {
4145
4145
  // 'orderLinkId': 'string', // one of order_id, stop_order_id or order_link_id is required
4146
4146
  // 'orderId': id,
4147
4147
  };
4148
- const isStop = this.safeValue(params, 'stop', false);
4149
- params = this.omit(params, ['stop']);
4148
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4149
+ params = this.omit(params, ['stop', 'trigger']);
4150
4150
  if (id !== undefined) { // The user can also use argument params["order_link_id"]
4151
4151
  request['orderId'] = id;
4152
4152
  }
@@ -4207,9 +4207,9 @@ export default class bybit extends Exchange {
4207
4207
  };
4208
4208
  if (market['spot']) {
4209
4209
  // only works for spot market
4210
- const isStop = this.safeValue(params, 'stop', false);
4211
- params = this.omit(params, ['stop']);
4212
- request['orderFilter'] = isStop ? 'tpslOrder' : 'Order';
4210
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4211
+ params = this.omit(params, ['stop', 'trigger']);
4212
+ request['orderFilter'] = isStop ? 'StopOrder' : 'Order';
4213
4213
  }
4214
4214
  if (id !== undefined) { // The user can also use argument params["orderLinkId"]
4215
4215
  request['orderId'] = id;
@@ -4256,14 +4256,14 @@ export default class bybit extends Exchange {
4256
4256
  response = await this.privatePostOptionUsdcOpenapiPrivateV1CancelAll(this.extend(request, params));
4257
4257
  }
4258
4258
  else {
4259
- const isStop = this.safeValue(params, 'stop', false);
4259
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4260
4260
  if (isStop) {
4261
4261
  request['orderFilter'] = 'StopOrder';
4262
4262
  }
4263
4263
  else {
4264
4264
  request['orderFilter'] = 'Order';
4265
4265
  }
4266
- params = this.omit(params, ['stop']);
4266
+ params = this.omit(params, ['stop', 'trigger']);
4267
4267
  response = await this.privatePostPerpetualUsdcOpenapiPrivateV1CancelAll(this.extend(request, params));
4268
4268
  }
4269
4269
  //
@@ -4330,10 +4330,10 @@ export default class bybit extends Exchange {
4330
4330
  request['settleCoin'] = this.safeString(params, 'settleCoin', defaultSettle);
4331
4331
  }
4332
4332
  }
4333
- const isStop = this.safeValue(params, 'stop', false);
4334
- params = this.omit(params, ['stop']);
4333
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4334
+ params = this.omit(params, ['stop', 'trigger']);
4335
4335
  if (isStop) {
4336
- request['orderFilter'] = 'tpslOrder';
4336
+ request['orderFilter'] = 'StopOrder';
4337
4337
  }
4338
4338
  const response = await this.privatePostV5OrderCancelAll(this.extend(request, params));
4339
4339
  //
@@ -4398,8 +4398,8 @@ export default class bybit extends Exchange {
4398
4398
  else {
4399
4399
  request['category'] = 'OPTION';
4400
4400
  }
4401
- const isStop = this.safeValue(params, 'stop', false);
4402
- params = this.omit(params, ['stop']);
4401
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4402
+ params = this.omit(params, ['stop', 'trigger']);
4403
4403
  if (isStop) {
4404
4404
  request['orderFilter'] = 'StopOrder';
4405
4405
  }
@@ -4501,12 +4501,7 @@ export default class bybit extends Exchange {
4501
4501
  const isStop = this.safeValueN(params, ['trigger', 'stop'], false);
4502
4502
  params = this.omit(params, ['trigger', 'stop']);
4503
4503
  if (isStop) {
4504
- if (type === 'spot') {
4505
- request['orderFilter'] = 'tpslOrder';
4506
- }
4507
- else {
4508
- request['orderFilter'] = 'StopOrder';
4509
- }
4504
+ request['orderFilter'] = 'StopOrder';
4510
4505
  }
4511
4506
  if (limit !== undefined) {
4512
4507
  request['limit'] = limit;
@@ -4665,7 +4660,7 @@ export default class bybit extends Exchange {
4665
4660
  * @param {int} [since] the earliest time in ms to fetch open orders for
4666
4661
  * @param {int} [limit] the maximum number of open orders structures to retrieve
4667
4662
  * @param {object} [params] extra parameters specific to the exchange API endpoint
4668
- * @param {boolean} [params.stop] true if stop order
4663
+ * @param {boolean} [params.stop] set to true for fetching open stop orders
4669
4664
  * @param {string} [params.type] market type, ['swap', 'option', 'spot']
4670
4665
  * @param {string} [params.subType] market subType, ['linear', 'inverse']
4671
4666
  * @param {string} [params.baseCoin] Base coin. Supports linear, inverse & option
@@ -4699,15 +4694,10 @@ export default class bybit extends Exchange {
4699
4694
  return await this.fetchUsdcOpenOrders(symbol, since, limit, params);
4700
4695
  }
4701
4696
  request['category'] = type;
4702
- const isStop = this.safeValue(params, 'stop', false);
4703
- params = this.omit(params, ['stop']);
4697
+ const isStop = this.safeValue2(params, 'stop', 'trigger', false);
4698
+ params = this.omit(params, ['stop', 'trigger']);
4704
4699
  if (isStop) {
4705
- if (type === 'spot') {
4706
- request['orderFilter'] = 'tpslOrder';
4707
- }
4708
- else {
4709
- request['orderFilter'] = 'StopOrder';
4710
- }
4700
+ request['orderFilter'] = 'StopOrder';
4711
4701
  }
4712
4702
  if (limit !== undefined) {
4713
4703
  request['limit'] = limit;
@@ -4839,12 +4829,11 @@ export default class bybit extends Exchange {
4839
4829
  * @method
4840
4830
  * @name bybit#fetchMyTrades
4841
4831
  * @description fetch all trades made by the user
4842
- * @see https://bybit-exchange.github.io/docs/v5/position/execution
4832
+ * @see https://bybit-exchange.github.io/docs/api-explorer/v5/position/execution
4843
4833
  * @param {string} symbol unified market symbol
4844
4834
  * @param {int} [since] the earliest time in ms to fetch trades for
4845
4835
  * @param {int} [limit] the maximum number of trades structures to retrieve
4846
4836
  * @param {object} [params] extra parameters specific to the exchange API endpoint
4847
- * @param {boolean} [params.stop] true if stop order
4848
4837
  * @param {string} [params.type] market type, ['swap', 'option', 'spot']
4849
4838
  * @param {string} [params.subType] market subType, ['linear', 'inverse']
4850
4839
  * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
@@ -4858,7 +4847,7 @@ export default class bybit extends Exchange {
4858
4847
  }
4859
4848
  const [enableUnifiedMargin, enableUnifiedAccount] = await this.isUnifiedEnabled();
4860
4849
  const isUnifiedAccount = (enableUnifiedMargin || enableUnifiedAccount);
4861
- const request = {};
4850
+ let request = {};
4862
4851
  let market = undefined;
4863
4852
  let isUsdcSettled = false;
4864
4853
  if (symbol !== undefined) {
@@ -4872,28 +4861,13 @@ export default class bybit extends Exchange {
4872
4861
  return await this.fetchMyUsdcTrades(symbol, since, limit, params);
4873
4862
  }
4874
4863
  request['category'] = type;
4875
- const isStop = this.safeValue(params, 'stop', false);
4876
- params = this.omit(params, ['stop', 'type']);
4877
- if (isStop) {
4878
- if (type === 'spot') {
4879
- request['orderFilter'] = 'tpslOrder';
4880
- }
4881
- else {
4882
- request['orderFilter'] = 'StopOrder';
4883
- }
4884
- }
4885
4864
  if (limit !== undefined) {
4886
4865
  request['limit'] = limit;
4887
4866
  }
4888
4867
  if (since !== undefined) {
4889
4868
  request['startTime'] = since;
4890
4869
  }
4891
- const until = this.safeInteger2(params, 'until', 'till'); // unified in milliseconds
4892
- const endTime = this.safeInteger(params, 'endTime', until); // exchange-specific in milliseconds
4893
- params = this.omit(params, ['endTime', 'till', 'until']);
4894
- if (endTime !== undefined) {
4895
- request['endTime'] = endTime;
4896
- }
4870
+ [request, params] = this.handleUntilOption('endTime', request, params);
4897
4871
  const response = await this.privateGetV5ExecutionList(this.extend(request, params));
4898
4872
  //
4899
4873
  // {
@@ -68,6 +68,7 @@ export default class coincheck extends Exchange {
68
68
  'setLeverage': false,
69
69
  'setMarginMode': false,
70
70
  'setPositionMode': false,
71
+ 'ws': true,
71
72
  },
72
73
  'urls': {
73
74
  'logo': 'https://user-images.githubusercontent.com/51840849/87182088-1d6d6380-c2ec-11ea-9c64-8ab9f9b289f5.jpg',
@@ -151,6 +151,9 @@ export default class coinlist extends Exchange {
151
151
  'v1/symbols/{symbol}/auctions/{auction_code}': 1,
152
152
  'v1/time': 1,
153
153
  'v1/assets': 1,
154
+ 'v1/leaderboard': 1,
155
+ 'v1/affiliate/{competition_code}': 1,
156
+ 'v1/competition/{competition_id}': 1,
154
157
  },
155
158
  },
156
159
  'private': {
@@ -158,6 +161,7 @@ export default class coinlist extends Exchange {
158
161
  'v1/fees': 1,
159
162
  'v1/accounts': 1,
160
163
  'v1/accounts/{trader_id}': 1,
164
+ 'v1/accounts/{trader_id}/alias': 1,
161
165
  'v1/accounts/{trader_id}/ledger': 1,
162
166
  'v1/accounts/{trader_id}/wallets': 1,
163
167
  'v1/accounts/{trader_id}/wallet-ledger': 1,
@@ -170,7 +174,9 @@ export default class coinlist extends Exchange {
170
174
  'v1/balances': 1,
171
175
  'v1/transfers': 1,
172
176
  'v1/user': 1,
173
- 'v1/credits': 1, // not unified
177
+ 'v1/credits': 1,
178
+ 'v1/positions': 1,
179
+ 'v1/accounts/{trader_id}/competitions': 1,
174
180
  },
175
181
  'post': {
176
182
  'v1/keys': 1,
@@ -181,7 +187,9 @@ export default class coinlist extends Exchange {
181
187
  'v1/transfers/from-wallet': 1,
182
188
  'v1/transfers/internal-transfer': 1,
183
189
  'v1/transfers/withdrawal-request': 1,
184
- 'v1/orders/bulk': 1, // not unified
190
+ 'v1/orders/bulk': 1,
191
+ 'v1/accounts/{trader_id}/competitions': 1,
192
+ 'v1/accounts/{trader_id}/create-competition': 1,
185
193
  },
186
194
  'patch': {
187
195
  'v1/orders/{order_id}': 1,
package/js/src/coinsph.js CHANGED
@@ -999,10 +999,10 @@ export default class coinsph extends Exchange {
999
999
  'currency': this.safeCurrencyCode(feeCurrencyId),
1000
1000
  };
1001
1001
  }
1002
- const isBuyer = this.safeString2(trade, 'isBuyer', 'isBuyerMaker', undefined);
1002
+ const isBuyer = this.safeValue2(trade, 'isBuyer', 'isBuyerMaker', undefined);
1003
1003
  let side = undefined;
1004
1004
  if (isBuyer !== undefined) {
1005
- side = (isBuyer === 'true') ? 'buy' : 'sell';
1005
+ side = (isBuyer === true) ? 'buy' : 'sell';
1006
1006
  }
1007
1007
  const isMaker = this.safeString2(trade, 'isMaker', undefined);
1008
1008
  let takerOrMaker = undefined;
package/js/src/deribit.js CHANGED
@@ -1686,6 +1686,10 @@ export default class deribit extends Exchange {
1686
1686
  const request = {
1687
1687
  'order_id': id,
1688
1688
  };
1689
+ let market = undefined;
1690
+ if (symbol !== undefined) {
1691
+ market = this.market(symbol);
1692
+ }
1689
1693
  const response = await this.privateGetGetOrderState(this.extend(request, params));
1690
1694
  //
1691
1695
  // {
@@ -1716,7 +1720,7 @@ export default class deribit extends Exchange {
1716
1720
  // }
1717
1721
  //
1718
1722
  const result = this.safeValue(response, 'result');
1719
- return this.parseOrder(result);
1723
+ return this.parseOrder(result, market);
1720
1724
  }
1721
1725
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1722
1726
  /**
package/js/src/kraken.js CHANGED
@@ -106,7 +106,7 @@ export default class kraken extends Exchange {
106
106
  'zendesk': 'https://kraken.zendesk.com/api/v2/help_center/en-us/articles', // use the public zendesk api to receive article bodies and bypass new anti-spam protections
107
107
  },
108
108
  'www': 'https://www.kraken.com',
109
- 'doc': 'https://www.kraken.com/features/api',
109
+ 'doc': 'https://docs.kraken.com/rest/',
110
110
  'fees': 'https://www.kraken.com/en-us/features/fee-schedule',
111
111
  },
112
112
  'fees': {
@@ -145,7 +145,7 @@ export default class binance extends binanceRest {
145
145
  }
146
146
  const subscriptionsByStream = this.safeInteger(this.options['numSubscriptionsByStream'], stream, 0);
147
147
  const newNumSubscriptions = subscriptionsByStream + numSubscriptions;
148
- const subscriptionLimitByStream = this.safeInteger(this.options, 'subscriptionLimitByStream', 200);
148
+ const subscriptionLimitByStream = this.safeInteger(this.options['subscriptionLimitByStream'], type, 200);
149
149
  if (newNumSubscriptions > subscriptionLimitByStream) {
150
150
  throw new BadRequest(this.id + ' reached the limit of subscriptions by stream. Increase the number of streams, or increase the stream limit or subscription limit by stream if the exchange allows.');
151
151
  }
@@ -1084,7 +1084,7 @@ export default class binance extends binanceRest {
1084
1084
  const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
1085
1085
  const marketType = (isSpot) ? 'spot' : 'contract';
1086
1086
  let rawTickers = [];
1087
- const newTickers = [];
1087
+ const newTickers = {};
1088
1088
  if (Array.isArray(message)) {
1089
1089
  rawTickers = message;
1090
1090
  }
@@ -1096,7 +1096,7 @@ export default class binance extends binanceRest {
1096
1096
  const result = this.parseWsTicker(ticker, marketType);
1097
1097
  const symbol = result['symbol'];
1098
1098
  this.tickers[symbol] = result;
1099
- newTickers.push(result);
1099
+ newTickers[symbol] = result;
1100
1100
  }
1101
1101
  const messageHashes = this.findMessageHashes(client, 'tickers::');
1102
1102
  for (let i = 0; i < messageHashes.length; i++) {
@@ -449,7 +449,7 @@ export default class bitget extends bitgetRest {
449
449
  symbols = this.marketSymbols(symbols);
450
450
  let channel = 'books';
451
451
  let incrementalFeed = true;
452
- if ((limit === 5) || (limit === 15)) {
452
+ if ((limit === 1) || (limit === 5) || (limit === 15)) {
453
453
  channel += limit.toString();
454
454
  incrementalFeed = false;
455
455
  }
@@ -0,0 +1,12 @@
1
+ import coincheckRest from '../coincheck.js';
2
+ import type { Int, Market, OrderBook, Trade } from '../base/types.js';
3
+ import Client from '../base/ws/Client.js';
4
+ export default class coincheck extends coincheckRest {
5
+ describe(): any;
6
+ watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
7
+ handleOrderBook(client: any, message: any): void;
8
+ watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
9
+ handleTrades(client: Client, message: any): void;
10
+ parseWsTrade(trade: any, market?: Market): Trade;
11
+ handleMessage(client: Client, message: any): void;
12
+ }
@@ -0,0 +1,209 @@
1
+ // ----------------------------------------------------------------------------
2
+
3
+ // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
7
+ // ---------------------------------------------------------------------------
8
+ import coincheckRest from '../coincheck.js';
9
+ import { AuthenticationError } from '../base/errors.js';
10
+ import { ArrayCache } from '../base/ws/Cache.js';
11
+ // ---------------------------------------------------------------------------
12
+ export default class coincheck extends coincheckRest {
13
+ describe() {
14
+ return this.deepExtend(super.describe(), {
15
+ 'has': {
16
+ 'ws': true,
17
+ 'watchOrderBook': true,
18
+ 'watchOrders': false,
19
+ 'watchTrades': true,
20
+ 'watchOHLCV': false,
21
+ 'watchTicker': false,
22
+ 'watchTickers': false,
23
+ },
24
+ 'urls': {
25
+ 'api': {
26
+ 'ws': 'wss://ws-api.coincheck.com/',
27
+ },
28
+ },
29
+ 'options': {
30
+ 'expiresIn': '',
31
+ 'userId': '',
32
+ 'wsSessionToken': '',
33
+ 'watchOrderBook': {
34
+ 'snapshotDelay': 6,
35
+ 'snapshotMaxRetries': 3,
36
+ },
37
+ 'tradesLimit': 1000,
38
+ 'OHLCVLimit': 1000,
39
+ },
40
+ 'exceptions': {
41
+ 'exact': {
42
+ '4009': AuthenticationError,
43
+ },
44
+ },
45
+ });
46
+ }
47
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
48
+ /**
49
+ * @method
50
+ * @name coincheck#watchOrderBook
51
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
52
+ * @see https://coincheck.com/documents/exchange/api#websocket-order-book
53
+ * @param {string} symbol unified symbol of the market to fetch the order book for
54
+ * @param {int} [limit] the maximum amount of order book entries to return
55
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
56
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
57
+ */
58
+ await this.loadMarkets();
59
+ const market = this.market(symbol);
60
+ const messageHash = 'orderbook:' + market['symbol'];
61
+ const url = this.urls['api']['ws'];
62
+ const request = {
63
+ 'type': 'subscribe',
64
+ 'channel': market['id'] + '-orderbook',
65
+ };
66
+ const message = this.extend(request, params);
67
+ const orderbook = await this.watch(url, messageHash, message, messageHash);
68
+ return orderbook.limit();
69
+ }
70
+ handleOrderBook(client, message) {
71
+ //
72
+ // [
73
+ // "btc_jpy",
74
+ // {
75
+ // "bids": [
76
+ // [
77
+ // "6288279.0",
78
+ // "0"
79
+ // ]
80
+ // ],
81
+ // "asks": [
82
+ // [
83
+ // "6290314.0",
84
+ // "0"
85
+ // ]
86
+ // ],
87
+ // "last_update_at": "1705396097"
88
+ // }
89
+ // ]
90
+ //
91
+ const symbol = this.symbol(this.safeString(message, 0));
92
+ const data = this.safeValue(message, 1, {});
93
+ const timestamp = this.safeTimestamp(data, 'last_update_at');
94
+ const snapshot = this.parseOrderBook(data, symbol, timestamp);
95
+ let orderbook = this.safeValue(this.orderbooks, symbol);
96
+ if (orderbook === undefined) {
97
+ orderbook = this.orderBook(snapshot);
98
+ this.orderbooks[symbol] = orderbook;
99
+ }
100
+ else {
101
+ orderbook = this.orderbooks[symbol];
102
+ orderbook.reset(snapshot);
103
+ }
104
+ const messageHash = 'orderbook:' + symbol;
105
+ client.resolve(orderbook, messageHash);
106
+ }
107
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
108
+ /**
109
+ * @method
110
+ * @name coincheck#watchTrades
111
+ * @description watches information on multiple trades made in a market
112
+ * @see https://coincheck.com/documents/exchange/api#websocket-trades
113
+ * @param {string} symbol unified market symbol of the market trades were made in
114
+ * @param {int} [since] the earliest time in ms to fetch trades for
115
+ * @param {int} [limit] the maximum number of trade structures to retrieve
116
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
117
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
118
+ */
119
+ await this.loadMarkets();
120
+ const market = this.market(symbol);
121
+ symbol = market['symbol'];
122
+ const messageHash = 'trade:' + market['symbol'];
123
+ const url = this.urls['api']['ws'];
124
+ const request = {
125
+ 'type': 'subscribe',
126
+ 'channel': market['id'] + '-trades',
127
+ };
128
+ const message = this.extend(request, params);
129
+ const trades = await this.watch(url, messageHash, message, messageHash);
130
+ if (this.newUpdates) {
131
+ limit = trades.getLimit(symbol, limit);
132
+ }
133
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
134
+ }
135
+ handleTrades(client, message) {
136
+ //
137
+ // [
138
+ // [
139
+ // "1663318663", // transaction timestamp (unix time)
140
+ // "2357062", // transaction ID
141
+ // "btc_jpy", // pair
142
+ // "2820896.0", // transaction rate
143
+ // "5.0", // transaction amount
144
+ // "sell", // order side
145
+ // "1193401", // ID of the Taker
146
+ // "2078767" // ID of the Maker
147
+ // ]
148
+ // ]
149
+ //
150
+ const first = this.safeValue(message, 0, []);
151
+ const symbol = this.symbol(this.safeString(first, 2));
152
+ let stored = this.safeValue(this.trades, symbol);
153
+ if (stored === undefined) {
154
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
155
+ stored = new ArrayCache(limit);
156
+ this.trades[symbol] = stored;
157
+ }
158
+ for (let i = 0; i < message.length; i++) {
159
+ const data = this.safeValue(message, i);
160
+ const trade = this.parseWsTrade(data);
161
+ stored.append(trade);
162
+ }
163
+ const messageHash = 'trade:' + symbol;
164
+ client.resolve(stored, messageHash);
165
+ }
166
+ parseWsTrade(trade, market = undefined) {
167
+ //
168
+ // [
169
+ // "1663318663", // transaction timestamp (unix time)
170
+ // "2357062", // transaction ID
171
+ // "btc_jpy", // pair
172
+ // "2820896.0", // transaction rate
173
+ // "5.0", // transaction amount
174
+ // "sell", // order side
175
+ // "1193401", // ID of the Taker
176
+ // "2078767" // ID of the Maker
177
+ // ]
178
+ //
179
+ const symbol = this.symbol(this.safeString(trade, 2));
180
+ const timestamp = this.safeTimestamp(trade, 0);
181
+ const side = this.safeString(trade, 5);
182
+ const priceString = this.safeString(trade, 3);
183
+ const amountString = this.safeString(trade, 4);
184
+ return this.safeTrade({
185
+ 'id': this.safeString(trade, 1),
186
+ 'info': trade,
187
+ 'timestamp': timestamp,
188
+ 'datetime': this.iso8601(timestamp),
189
+ 'order': undefined,
190
+ 'symbol': symbol,
191
+ 'type': undefined,
192
+ 'side': side,
193
+ 'takerOrMaker': undefined,
194
+ 'price': priceString,
195
+ 'amount': amountString,
196
+ 'cost': undefined,
197
+ 'fee': undefined,
198
+ }, market);
199
+ }
200
+ handleMessage(client, message) {
201
+ const data = this.safeValue(message, 0);
202
+ if (!Array.isArray(data)) {
203
+ this.handleOrderBook(client, message);
204
+ }
205
+ else {
206
+ this.handleTrades(client, message);
207
+ }
208
+ }
209
+ }
@@ -310,7 +310,8 @@ export default class hitbtc extends hitbtcRest {
310
310
  'symbols': [market['id']],
311
311
  },
312
312
  };
313
- return await this.subscribePublic(name, [symbol], this.deepExtend(request, params));
313
+ const result = await this.subscribePublic(name, [symbol], this.deepExtend(request, params));
314
+ return this.safeValue(result, symbol);
314
315
  }
315
316
  async watchTickers(symbols = undefined, params = {}) {
316
317
  /**
@@ -393,16 +394,16 @@ export default class hitbtc extends hitbtcRest {
393
394
  const data = this.safeValue(message, 'data', {});
394
395
  const marketIds = Object.keys(data);
395
396
  const channel = this.safeString(message, 'ch');
396
- const newTickers = [];
397
+ const newTickers = {};
397
398
  for (let i = 0; i < marketIds.length; i++) {
398
399
  const marketId = marketIds[i];
399
400
  const market = this.safeMarket(marketId);
400
401
  const symbol = market['symbol'];
401
402
  const ticker = this.parseWsTicker(data[marketId], market);
402
403
  this.tickers[symbol] = ticker;
403
- newTickers.push(ticker);
404
+ newTickers[symbol] = ticker;
404
405
  const messageHash = channel + '::' + symbol;
405
- client.resolve(this.tickers[symbol], messageHash);
406
+ client.resolve(newTickers, messageHash);
406
407
  }
407
408
  const messageHashes = this.findMessageHashes(client, channel + '::');
408
409
  for (let i = 0; i < messageHashes.length; i++) {
@@ -67,43 +67,51 @@ export default class kucoin extends kucoinRest {
67
67
  async negotiateHelper(privateChannel, params = {}) {
68
68
  let response = undefined;
69
69
  const connectId = privateChannel ? 'private' : 'public';
70
- if (privateChannel) {
71
- response = await this.privatePostBulletPrivate(params);
72
- //
73
- // {
74
- // "code": "200000",
75
- // "data": {
76
- // "instanceServers": [
77
- // {
78
- // "pingInterval": 50000,
79
- // "endpoint": "wss://push-private.kucoin.com/endpoint",
80
- // "protocol": "websocket",
81
- // "encrypt": true,
82
- // "pingTimeout": 10000
83
- // }
84
- // ],
85
- // "token": "2neAiuYvAU61ZDXANAGAsiL4-iAExhsBXZxftpOeh_55i3Ysy2q2LEsEWU64mdzUOPusi34M_wGoSf7iNyEWJ1UQy47YbpY4zVdzilNP-Bj3iXzrjjGlWtiYB9J6i9GjsxUuhPw3BlrzazF6ghq4Lzf7scStOz3KkxjwpsOBCH4=.WNQmhZQeUKIkh97KYgU0Lg=="
86
- // }
87
- // }
88
- //
70
+ try {
71
+ if (privateChannel) {
72
+ response = await this.privatePostBulletPrivate(params);
73
+ //
74
+ // {
75
+ // "code": "200000",
76
+ // "data": {
77
+ // "instanceServers": [
78
+ // {
79
+ // "pingInterval": 50000,
80
+ // "endpoint": "wss://push-private.kucoin.com/endpoint",
81
+ // "protocol": "websocket",
82
+ // "encrypt": true,
83
+ // "pingTimeout": 10000
84
+ // }
85
+ // ],
86
+ // "token": "2neAiuYvAU61ZDXANAGAsiL4-iAExhsBXZxftpOeh_55i3Ysy2q2LEsEWU64mdzUOPusi34M_wGoSf7iNyEWJ1UQy47YbpY4zVdzilNP-Bj3iXzrjjGlWtiYB9J6i9GjsxUuhPw3BlrzazF6ghq4Lzf7scStOz3KkxjwpsOBCH4=.WNQmhZQeUKIkh97KYgU0Lg=="
87
+ // }
88
+ // }
89
+ //
90
+ }
91
+ else {
92
+ response = await this.publicPostBulletPublic(params);
93
+ }
94
+ const data = this.safeValue(response, 'data', {});
95
+ const instanceServers = this.safeValue(data, 'instanceServers', []);
96
+ const firstInstanceServer = this.safeValue(instanceServers, 0);
97
+ const pingInterval = this.safeInteger(firstInstanceServer, 'pingInterval');
98
+ const endpoint = this.safeString(firstInstanceServer, 'endpoint');
99
+ const token = this.safeString(data, 'token');
100
+ const result = endpoint + '?' + this.urlencode({
101
+ 'token': token,
102
+ 'privateChannel': privateChannel,
103
+ 'connectId': connectId,
104
+ });
105
+ const client = this.client(result);
106
+ client.keepAlive = pingInterval;
107
+ return result;
89
108
  }
90
- else {
91
- response = await this.publicPostBulletPublic(params);
109
+ catch (e) {
110
+ const future = this.safeValue(this.options['urls'], connectId);
111
+ future.reject(e);
112
+ delete this.options['urls'][connectId];
92
113
  }
93
- const data = this.safeValue(response, 'data', {});
94
- const instanceServers = this.safeValue(data, 'instanceServers', []);
95
- const firstInstanceServer = this.safeValue(instanceServers, 0);
96
- const pingInterval = this.safeInteger(firstInstanceServer, 'pingInterval');
97
- const endpoint = this.safeString(firstInstanceServer, 'endpoint');
98
- const token = this.safeString(data, 'token');
99
- const result = endpoint + '?' + this.urlencode({
100
- 'token': token,
101
- 'privateChannel': privateChannel,
102
- 'connectId': connectId,
103
- });
104
- const client = this.client(result);
105
- client.keepAlive = pingInterval;
106
- return result;
114
+ return undefined;
107
115
  }
108
116
  requestId() {
109
117
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
@@ -261,7 +269,9 @@ export default class kucoin extends kucoinRest {
261
269
  const messageHash = 'ticker:' + symbol;
262
270
  client.resolve(ticker, messageHash);
263
271
  // watchTickers
264
- client.resolve(ticker, 'tickers');
272
+ const allTickers = {};
273
+ allTickers[symbol] = ticker;
274
+ client.resolve(allTickers, 'tickers');
265
275
  const messageHashes = this.findMessageHashes(client, 'tickers::');
266
276
  for (let i = 0; i < messageHashes.length; i++) {
267
277
  const currentMessageHash = messageHashes[i];