ccxt 4.4.90 → 4.4.91

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 +5 -6
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +1 -4
  4. package/dist/cjs/src/base/Exchange.js +9 -11
  5. package/dist/cjs/src/base/ws/Client.js +4 -34
  6. package/dist/cjs/src/binance.js +1 -1
  7. package/dist/cjs/src/bitmex.js +2 -1
  8. package/dist/cjs/src/cex.js +61 -0
  9. package/dist/cjs/src/cryptocom.js +21 -2
  10. package/dist/cjs/src/cryptomus.js +1 -1
  11. package/dist/cjs/src/exmo.js +14 -7
  12. package/dist/cjs/src/fmfwio.js +1 -1
  13. package/dist/cjs/src/gate.js +2 -2
  14. package/dist/cjs/src/hyperliquid.js +115 -59
  15. package/dist/cjs/src/kraken.js +29 -1
  16. package/dist/cjs/src/mexc.js +1 -0
  17. package/dist/cjs/src/modetrade.js +2 -2
  18. package/dist/cjs/src/paradex.js +1 -1
  19. package/dist/cjs/src/pro/bitstamp.js +1 -1
  20. package/dist/cjs/src/pro/bybit.js +6 -143
  21. package/dist/cjs/src/pro/kraken.js +251 -264
  22. package/dist/cjs/src/pro/mexc.js +0 -1
  23. package/js/ccxt.d.ts +2 -5
  24. package/js/ccxt.js +2 -4
  25. package/js/src/base/Exchange.d.ts +2 -1
  26. package/js/src/base/Exchange.js +10 -12
  27. package/js/src/base/ws/Client.d.ts +0 -2
  28. package/js/src/base/ws/Client.js +4 -34
  29. package/js/src/binance.js +1 -1
  30. package/js/src/bitmex.js +2 -1
  31. package/js/src/cex.js +61 -0
  32. package/js/src/cryptocom.js +21 -2
  33. package/js/src/cryptomus.js +1 -1
  34. package/js/src/exmo.js +14 -7
  35. package/js/src/fmfwio.js +2 -2
  36. package/js/src/gate.js +2 -2
  37. package/js/src/hyperliquid.d.ts +1 -0
  38. package/js/src/hyperliquid.js +115 -59
  39. package/js/src/kraken.js +29 -1
  40. package/js/src/mexc.js +1 -0
  41. package/js/src/modetrade.js +2 -2
  42. package/js/src/p2b.d.ts +1 -2
  43. package/js/src/paradex.js +1 -1
  44. package/js/src/pro/bitstamp.js +1 -1
  45. package/js/src/pro/bybit.d.ts +0 -1
  46. package/js/src/pro/bybit.js +6 -143
  47. package/js/src/pro/kraken.d.ts +17 -17
  48. package/js/src/pro/kraken.js +251 -264
  49. package/js/src/pro/mexc.js +0 -1
  50. package/js/src/tradeogre.d.ts +1 -2
  51. package/package.json +1 -1
  52. package/js/src/abstract/coinlist.d.ts +0 -60
  53. package/js/src/abstract/coinlist.js +0 -11
  54. package/js/src/coinlist.d.ts +0 -384
  55. package/js/src/coinlist.js +0 -2610
@@ -40,6 +40,7 @@ export default class kraken extends krakenRest {
40
40
  'public': 'wss://ws.kraken.com',
41
41
  'private': 'wss://ws-auth.kraken.com',
42
42
  'privateV2': 'wss://ws-auth.kraken.com/v2',
43
+ 'publicV2': 'wss://ws.kraken.com/v2',
43
44
  'beta': 'wss://beta-ws.kraken.com',
44
45
  'beta-private': 'wss://beta-ws-auth.kraken.com',
45
46
  },
@@ -54,9 +55,13 @@ export default class kraken extends krakenRest {
54
55
  'ordersLimit': 1000,
55
56
  'symbolsByOrderId': {},
56
57
  'watchOrderBook': {
57
- 'checksum': true,
58
+ 'checksum': false,
58
59
  },
59
60
  },
61
+ 'streaming': {
62
+ 'ping': this.ping,
63
+ 'keepAlive': 6000,
64
+ },
60
65
  'exceptions': {
61
66
  'ws': {
62
67
  'exact': {
@@ -107,6 +112,7 @@ export default class kraken extends krakenRest {
107
112
  'EService:Market in post_only mode': NotSupported,
108
113
  'EService:Unavailable': ExchangeNotAvailable,
109
114
  'ETrade:Invalid request': BadRequest,
115
+ 'ESession:Invalid session': AuthenticationError,
110
116
  },
111
117
  },
112
118
  },
@@ -374,8 +380,8 @@ export default class kraken extends krakenRest {
374
380
  /**
375
381
  * @method
376
382
  * @name kraken#cancelOrdersWs
377
- * @see https://docs.kraken.com/api/docs/websocket-v1/cancelorder
378
383
  * @description cancel multiple orders
384
+ * @see https://docs.kraken.com/api/docs/websocket-v2/cancel_order
379
385
  * @param {string[]} ids order ids
380
386
  * @param {string} [symbol] unified market symbol, default is undefined
381
387
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -403,8 +409,8 @@ export default class kraken extends krakenRest {
403
409
  /**
404
410
  * @method
405
411
  * @name kraken#cancelOrderWs
406
- * @see https://docs.kraken.com/api/docs/websocket-v1/cancelorder
407
412
  * @description cancels an open order
413
+ * @see https://docs.kraken.com/api/docs/websocket-v2/cancel_order
408
414
  * @param {string} id order id
409
415
  * @param {string} [symbol] unified symbol of the market the order was made in
410
416
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -448,8 +454,8 @@ export default class kraken extends krakenRest {
448
454
  /**
449
455
  * @method
450
456
  * @name kraken#cancelAllOrdersWs
451
- * @see https://docs.kraken.com/api/docs/websocket-v1/cancelall
452
457
  * @description cancel all open orders
458
+ * @see https://docs.kraken.com/api/docs/websocket-v2/cancel_all
453
459
  * @param {string} [symbol] unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
454
460
  * @param {object} [params] extra parameters specific to the exchange API endpoint
455
461
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
@@ -488,54 +494,57 @@ export default class kraken extends krakenRest {
488
494
  const reqId = this.safeValue(message, 'req_id');
489
495
  client.resolve(message, reqId);
490
496
  }
491
- handleTicker(client, message, subscription) {
497
+ handleTicker(client, message) {
492
498
  //
493
- // [
494
- // 0, // channelID
495
- // {
496
- // "a": [ "5525.40000", 1, "1.000" ], // ask, wholeAskVolume, askVolume
497
- // "b": [ "5525.10000", 1, "1.000" ], // bid, wholeBidVolume, bidVolume
498
- // "c": [ "5525.10000", "0.00398963" ], // closing price, volume
499
- // "h": [ "5783.00000", "5783.00000" ], // high price today, high price 24h ago
500
- // "l": [ "5505.00000", "5505.00000" ], // low price today, low price 24h ago
501
- // "o": [ "5760.70000", "5763.40000" ], // open price today, open price 24h ago
502
- // "p": [ "5631.44067", "5653.78939" ], // vwap today, vwap 24h ago
503
- // "t": [ 11493, 16267 ], // number of trades today, 24 hours ago
504
- // "v": [ "2634.11501494", "3591.17907851" ], // volume today, volume 24 hours ago
505
- // },
506
- // "ticker",
507
- // "XBT/USD"
508
- // ]
499
+ // {
500
+ // "channel": "ticker",
501
+ // "type": "snapshot",
502
+ // "data": [
503
+ // {
504
+ // "symbol": "BTC/USD",
505
+ // "bid": 108359.8,
506
+ // "bid_qty": 0.01362603,
507
+ // "ask": 108359.9,
508
+ // "ask_qty": 17.17988863,
509
+ // "last": 108359.8,
510
+ // "volume": 2158.32346723,
511
+ // "vwap": 108894.5,
512
+ // "low": 106824,
513
+ // "high": 111300,
514
+ // "change": -2679.9,
515
+ // "change_pct": -2.41
516
+ // }
517
+ // ]
518
+ // }
509
519
  //
510
- const wsName = message[3];
511
- const market = this.safeValue(this.options['marketsByWsName'], wsName);
512
- const symbol = market['symbol'];
520
+ const data = this.safeList(message, 'data', []);
521
+ const ticker = data[0];
522
+ const symbol = this.safeString(ticker, 'symbol');
513
523
  const messageHash = this.getMessageHash('ticker', undefined, symbol);
514
- const ticker = message[1];
515
- const vwap = this.safeString(ticker['p'], 0);
524
+ const vwap = this.safeString(ticker, 'vwap');
516
525
  let quoteVolume = undefined;
517
- const baseVolume = this.safeString(ticker['v'], 0);
526
+ const baseVolume = this.safeString(ticker, 'volume');
518
527
  if (baseVolume !== undefined && vwap !== undefined) {
519
528
  quoteVolume = Precise.stringMul(baseVolume, vwap);
520
529
  }
521
- const last = this.safeString(ticker['c'], 0);
530
+ const last = this.safeString(ticker, 'last');
522
531
  const result = this.safeTicker({
523
532
  'symbol': symbol,
524
533
  'timestamp': undefined,
525
534
  'datetime': undefined,
526
- 'high': this.safeString(ticker['h'], 0),
527
- 'low': this.safeString(ticker['l'], 0),
528
- 'bid': this.safeString(ticker['b'], 0),
529
- 'bidVolume': this.safeString(ticker['b'], 2),
530
- 'ask': this.safeString(ticker['a'], 0),
531
- 'askVolume': this.safeString(ticker['a'], 2),
535
+ 'high': this.safeString(ticker, 'high'),
536
+ 'low': this.safeString(ticker, 'low'),
537
+ 'bid': this.safeString(ticker, 'bid'),
538
+ 'bidVolume': this.safeString(ticker, 'bid_qty'),
539
+ 'ask': this.safeString(ticker, 'ask'),
540
+ 'askVolume': this.safeString(ticker, 'ask_qty'),
532
541
  'vwap': vwap,
533
- 'open': this.safeString(ticker['o'], 0),
542
+ 'open': undefined,
534
543
  'close': last,
535
544
  'last': last,
536
545
  'previousClose': undefined,
537
- 'change': undefined,
538
- 'percentage': undefined,
546
+ 'change': this.safeString(ticker, 'change'),
547
+ 'percentage': this.safeString(ticker, 'change_pct'),
539
548
  'average': undefined,
540
549
  'baseVolume': baseVolume,
541
550
  'quoteVolume': quoteVolume,
@@ -544,31 +553,36 @@ export default class kraken extends krakenRest {
544
553
  this.tickers[symbol] = result;
545
554
  client.resolve(result, messageHash);
546
555
  }
547
- handleTrades(client, message, subscription) {
556
+ handleTrades(client, message) {
548
557
  //
549
- // [
550
- // 0, // channelID
551
- // [ // price volume time side type misc
552
- // [ "5541.20000", "0.15850568", "1534614057.321596", "s", "l", "" ],
553
- // [ "6060.00000", "0.02455000", "1534614057.324998", "b", "l", "" ],
554
- // ],
555
- // "trade",
556
- // "XBT/USD"
557
- // ]
558
+ // {
559
+ // "channel": "trade",
560
+ // "type": "update",
561
+ // "data": [
562
+ // {
563
+ // "symbol": "MATIC/USD",
564
+ // "side": "sell",
565
+ // "price": 0.5117,
566
+ // "qty": 40.0,
567
+ // "ord_type": "market",
568
+ // "trade_id": 4665906,
569
+ // "timestamp": "2023-09-25T07:49:37.708706Z"
570
+ // }
571
+ // ]
572
+ // }
558
573
  //
559
- const wsName = this.safeString(message, 3);
560
- const name = this.safeString(message, 2);
561
- const market = this.safeValue(this.options['marketsByWsName'], wsName);
562
- const symbol = market['symbol'];
563
- const messageHash = this.getMessageHash(name, undefined, symbol);
574
+ const data = this.safeList(message, 'data', []);
575
+ const trade = data[0];
576
+ const symbol = this.safeString(trade, 'symbol');
577
+ const messageHash = this.getMessageHash('trade', undefined, symbol);
564
578
  let stored = this.safeValue(this.trades, symbol);
565
579
  if (stored === undefined) {
566
580
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
567
581
  stored = new ArrayCache(limit);
568
582
  this.trades[symbol] = stored;
569
583
  }
570
- const trades = this.safeValue(message, 1, []);
571
- const parsed = this.parseTrades(trades, market);
584
+ const market = this.market(symbol);
585
+ const parsed = this.parseTrades(data, market);
572
586
  for (let i = 0; i < parsed.length; i++) {
573
587
  stored.append(parsed[i]);
574
588
  }
@@ -656,7 +670,7 @@ export default class kraken extends krakenRest {
656
670
  * @method
657
671
  * @name kraken#watchTicker
658
672
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
659
- * @see https://docs.kraken.com/api/docs/websocket-v1/ticker
673
+ * @see https://docs.kraken.com/api/docs/websocket-v2/ticker
660
674
  * @param {string} symbol unified symbol of the market to fetch the ticker for
661
675
  * @param {object} [params] extra parameters specific to the exchange API endpoint
662
676
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -671,7 +685,7 @@ export default class kraken extends krakenRest {
671
685
  * @method
672
686
  * @name kraken#watchTickers
673
687
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
674
- * @see https://docs.kraken.com/api/docs/websocket-v1/ticker
688
+ * @see https://docs.kraken.com/api/docs/websocket-v2/ticker
675
689
  * @param {string[]} symbols
676
690
  * @param {object} [params] extra parameters specific to the exchange API endpoint
677
691
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -690,8 +704,8 @@ export default class kraken extends krakenRest {
690
704
  /**
691
705
  * @method
692
706
  * @name kraken#watchBidsAsks
693
- * @see https://docs.kraken.com/api/docs/websocket-v1/spread
694
707
  * @description watches best bid & ask for symbols
708
+ * @see https://docs.kraken.com/api/docs/websocket-v2/ticker
695
709
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
696
710
  * @param {object} [params] extra parameters specific to the exchange API endpoint
697
711
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -699,7 +713,8 @@ export default class kraken extends krakenRest {
699
713
  async watchBidsAsks(symbols = undefined, params = {}) {
700
714
  await this.loadMarkets();
701
715
  symbols = this.marketSymbols(symbols, undefined, false);
702
- const ticker = await this.watchMultiHelper('bidask', 'spread', symbols, undefined, params);
716
+ params['event_trigger'] = 'bbo';
717
+ const ticker = await this.watchMultiHelper('bidask', 'ticker', symbols, undefined, params);
703
718
  if (this.newUpdates) {
704
719
  const result = {};
705
720
  result[ticker['symbol']] = ticker;
@@ -707,49 +722,11 @@ export default class kraken extends krakenRest {
707
722
  }
708
723
  return this.filterByArray(this.bidsasks, 'symbol', symbols);
709
724
  }
710
- handleBidAsk(client, message, subscription) {
711
- //
712
- // [
713
- // 7208974, // channelID
714
- // [
715
- // "63758.60000", // bid
716
- // "63759.10000", // ask
717
- // "1726814731.089778", // timestamp
718
- // "0.00057917", // bid_volume
719
- // "0.15681688" // ask_volume
720
- // ],
721
- // "spread",
722
- // "XBT/USDT"
723
- // ]
724
- //
725
- const parsedTicker = this.parseWsBidAsk(message);
726
- const symbol = parsedTicker['symbol'];
727
- this.bidsasks[symbol] = parsedTicker;
728
- const messageHash = this.getMessageHash('bidask', undefined, symbol);
729
- client.resolve(parsedTicker, messageHash);
730
- }
731
- parseWsBidAsk(ticker, market = undefined) {
732
- const data = this.safeList(ticker, 1, []);
733
- const marketId = this.safeString(ticker, 3);
734
- market = this.safeValue(this.options['marketsByWsName'], marketId);
735
- const symbol = this.safeString(market, 'symbol');
736
- const timestamp = this.parseToInt(this.safeInteger(data, 2)) * 1000;
737
- return this.safeTicker({
738
- 'symbol': symbol,
739
- 'timestamp': timestamp,
740
- 'datetime': this.iso8601(timestamp),
741
- 'ask': this.safeString(data, 1),
742
- 'askVolume': this.safeString(data, 4),
743
- 'bid': this.safeString(data, 0),
744
- 'bidVolume': this.safeString(data, 3),
745
- 'info': ticker,
746
- }, market);
747
- }
748
725
  /**
749
726
  * @method
750
727
  * @name kraken#watchTrades
751
728
  * @description get the list of most recent trades for a particular symbol
752
- * @see https://docs.kraken.com/api/docs/websocket-v1/trade
729
+ * @see https://docs.kraken.com/api/docs/websocket-v2/trade
753
730
  * @param {string} symbol unified symbol of the market to fetch trades for
754
731
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
755
732
  * @param {int} [limit] the maximum amount of trades to fetch
@@ -762,8 +739,8 @@ export default class kraken extends krakenRest {
762
739
  /**
763
740
  * @method
764
741
  * @name kraken#watchTradesForSymbols
765
- * @see https://docs.kraken.com/api/docs/websocket-v1/trade
766
742
  * @description get the list of most recent trades for a list of symbols
743
+ * @see https://docs.kraken.com/api/docs/websocket-v2/trade
767
744
  * @param {string[]} symbols unified symbol of the market to fetch trades for
768
745
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
769
746
  * @param {int} [limit] the maximum amount of trades to fetch
@@ -783,7 +760,7 @@ export default class kraken extends krakenRest {
783
760
  * @method
784
761
  * @name kraken#watchOrderBook
785
762
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
786
- * @see https://docs.kraken.com/api/docs/websocket-v1/book
763
+ * @see https://docs.kraken.com/api/docs/websocket-v2/book
787
764
  * @param {string} symbol unified symbol of the market to fetch the order book for
788
765
  * @param {int} [limit] the maximum amount of order book entries to return
789
766
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -796,7 +773,7 @@ export default class kraken extends krakenRest {
796
773
  * @method
797
774
  * @name kraken#watchOrderBookForSymbols
798
775
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
799
- * @see https://docs.kraken.com/api/docs/websocket-v1/book
776
+ * @see https://docs.kraken.com/api/docs/websocket-v2/book
800
777
  * @param {string[]} symbols unified array of symbols
801
778
  * @param {int} [limit] the maximum amount of order book entries to return
802
779
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -806,7 +783,7 @@ export default class kraken extends krakenRest {
806
783
  const request = {};
807
784
  if (limit !== undefined) {
808
785
  if (this.inArray(limit, [10, 25, 100, 500, 1000])) {
809
- request['subscription'] = {
786
+ request['params'] = {
810
787
  'depth': limit, // default 10, valid options 10, 25, 100, 500, 1000
811
788
  };
812
789
  }
@@ -872,6 +849,21 @@ export default class kraken extends krakenRest {
872
849
  }
873
850
  return markets;
874
851
  }
852
+ ping(client) {
853
+ const url = client.url;
854
+ const request = {};
855
+ if (url.indexOf('v2') >= 0) {
856
+ request['method'] = 'ping';
857
+ }
858
+ else {
859
+ request['event'] = 'ping';
860
+ }
861
+ return request;
862
+ }
863
+ handlePong(client, message) {
864
+ client.lastPong = this.milliseconds();
865
+ return message;
866
+ }
875
867
  async watchHeartbeat(params = {}) {
876
868
  await this.loadMarkets();
877
869
  const event = 'heartbeat';
@@ -887,175 +879,165 @@ export default class kraken extends krakenRest {
887
879
  const event = this.safeString(message, 'event');
888
880
  client.resolve(message, event);
889
881
  }
890
- handleOrderBook(client, message, subscription) {
882
+ handleOrderBook(client, message) {
891
883
  //
892
884
  // first message (snapshot)
893
885
  //
894
- // [
895
- // 1234, // channelID
896
- // {
897
- // "as": [
898
- // [ "5541.30000", "2.50700000", "1534614248.123678" ],
899
- // [ "5541.80000", "0.33000000", "1534614098.345543" ],
900
- // [ "5542.70000", "0.64700000", "1534614244.654432" ]
901
- // ],
902
- // "bs": [
903
- // [ "5541.20000", "1.52900000", "1534614248.765567" ],
904
- // [ "5539.90000", "0.30000000", "1534614241.769870" ],
905
- // [ "5539.50000", "5.00000000", "1534613831.243486" ]
906
- // ]
907
- // },
908
- // "book-10",
909
- // "XBT/USD"
910
- // ]
886
+ // {
887
+ // "channel": "book",
888
+ // "type": "snapshot",
889
+ // "data": [
890
+ // {
891
+ // "symbol": "MATIC/USD",
892
+ // "bids": [
893
+ // {
894
+ // "price": 0.5666,
895
+ // "qty": 4831.75496356
896
+ // },
897
+ // {
898
+ // "price": 0.5665,
899
+ // "qty": 6658.22734739
900
+ // }
901
+ // ],
902
+ // "asks": [
903
+ // {
904
+ // "price": 0.5668,
905
+ // "qty": 4410.79769741
906
+ // },
907
+ // {
908
+ // "price": 0.5669,
909
+ // "qty": 4655.40412487
910
+ // }
911
+ // ],
912
+ // "checksum": 2439117997
913
+ // }
914
+ // ]
915
+ // }
911
916
  //
912
917
  // subsequent updates
913
918
  //
914
- // [
915
- // 1234,
916
- // { // optional
917
- // "a": [
918
- // [ "5541.30000", "2.50700000", "1534614248.456738" ],
919
- // [ "5542.50000", "0.40100000", "1534614248.456738" ]
920
- // ]
921
- // },
922
- // { // optional
923
- // "b": [
924
- // [ "5541.30000", "0.00000000", "1534614335.345903" ]
925
- // ]
926
- // },
927
- // "book-10",
928
- // "XBT/USD"
929
- // ]
919
+ // {
920
+ // "channel": "book",
921
+ // "type": "update",
922
+ // "data": [
923
+ // {
924
+ // "symbol": "MATIC/USD",
925
+ // "bids": [
926
+ // {
927
+ // "price": 0.5657,
928
+ // "qty": 1098.3947558
929
+ // }
930
+ // ],
931
+ // "asks": [],
932
+ // "checksum": 2114181697,
933
+ // "timestamp": "2023-10-06T17:35:55.440295Z"
934
+ // }
935
+ // ]
936
+ // }
930
937
  //
931
- const messageLength = message.length;
932
- const wsName = message[messageLength - 1];
933
- const bookDepthString = message[messageLength - 2];
934
- const parts = bookDepthString.split('-');
935
- const depth = this.safeInteger(parts, 1, 10);
936
- const market = this.safeValue(this.options['marketsByWsName'], wsName);
937
- const symbol = market['symbol'];
938
- let timestamp = undefined;
938
+ const type = this.safeString(message, 'type');
939
+ const data = this.safeList(message, 'data', []);
940
+ const first = this.safeDict(data, 0, {});
941
+ const symbol = this.safeString(first, 'symbol');
942
+ const a = this.safeValue(first, 'asks', []);
943
+ const b = this.safeValue(first, 'bids', []);
944
+ const c = this.safeInteger(first, 'checksum');
939
945
  const messageHash = this.getMessageHash('orderbook', undefined, symbol);
940
- // if this is a snapshot
941
- if ('as' in message[1]) {
942
- // todo get depth from marketsByWsName
946
+ let orderbook = undefined;
947
+ if (type === 'update') {
948
+ orderbook = this.orderbooks[symbol];
949
+ const storedAsks = orderbook['asks'];
950
+ const storedBids = orderbook['bids'];
951
+ if (a !== undefined) {
952
+ this.customHandleDeltas(storedAsks, a);
953
+ }
954
+ if (b !== undefined) {
955
+ this.customHandleDeltas(storedBids, b);
956
+ }
957
+ const datetime = this.safeString(first, 'timestamp');
958
+ orderbook['symbol'] = symbol;
959
+ orderbook['timestamp'] = this.parse8601(datetime);
960
+ orderbook['datetime'] = datetime;
961
+ }
962
+ else {
963
+ // snapshot
964
+ const depth = a.length;
943
965
  this.orderbooks[symbol] = this.orderBook({}, depth);
944
- const orderbook = this.orderbooks[symbol];
945
- const sides = {
946
- 'as': 'asks',
947
- 'bs': 'bids',
948
- };
949
- const keys = Object.keys(sides);
966
+ orderbook = this.orderbooks[symbol];
967
+ const keys = ['asks', 'bids'];
950
968
  for (let i = 0; i < keys.length; i++) {
951
969
  const key = keys[i];
952
- const side = sides[key];
953
- const bookside = orderbook[side];
954
- const deltas = this.safeValue(message[1], key, []);
955
- timestamp = this.customHandleDeltas(bookside, deltas, timestamp);
970
+ const bookside = orderbook[key];
971
+ const deltas = this.safeValue(first, key, []);
972
+ if (deltas.length > 0) {
973
+ this.customHandleDeltas(bookside, deltas);
974
+ }
956
975
  }
957
976
  orderbook['symbol'] = symbol;
958
- orderbook['timestamp'] = timestamp;
959
- orderbook['datetime'] = this.iso8601(timestamp);
960
- client.resolve(orderbook, messageHash);
961
977
  }
962
- else {
963
- const orderbook = this.orderbooks[symbol];
964
- // else, if this is an orderbook update
965
- let a = undefined;
966
- let b = undefined;
967
- let c = undefined;
968
- if (messageLength === 5) {
969
- a = this.safeValue(message[1], 'a', []);
970
- b = this.safeValue(message[2], 'b', []);
971
- c = this.safeInteger(message[1], 'c');
972
- c = this.safeInteger(message[2], 'c', c);
973
- }
974
- else {
975
- c = this.safeInteger(message[1], 'c');
976
- if ('a' in message[1]) {
977
- a = this.safeValue(message[1], 'a', []);
978
+ orderbook.limit();
979
+ // checksum temporarily disabled because the exchange checksum was not reliable
980
+ const checksum = this.handleOption('watchOrderBook', 'checksum', false);
981
+ if (checksum) {
982
+ const payloadArray = [];
983
+ if (c !== undefined) {
984
+ const checkAsks = orderbook['asks'];
985
+ const checkBids = orderbook['bids'];
986
+ // const checkAsks = asks.map ((elem) => [ elem['price'], elem['qty'] ]);
987
+ // const checkBids = bids.map ((elem) => [ elem['price'], elem['qty'] ]);
988
+ for (let i = 0; i < 10; i++) {
989
+ const currentAsk = this.safeValue(checkAsks, i, {});
990
+ const formattedAsk = this.formatNumber(currentAsk[0]) + this.formatNumber(currentAsk[1]);
991
+ payloadArray.push(formattedAsk);
978
992
  }
979
- else {
980
- b = this.safeValue(message[1], 'b', []);
993
+ for (let i = 0; i < 10; i++) {
994
+ const currentBid = this.safeValue(checkBids, i, {});
995
+ const formattedBid = this.formatNumber(currentBid[0]) + this.formatNumber(currentBid[1]);
996
+ payloadArray.push(formattedBid);
981
997
  }
982
998
  }
983
- const storedAsks = orderbook['asks'];
984
- const storedBids = orderbook['bids'];
985
- let example = undefined;
986
- if (a !== undefined) {
987
- timestamp = this.customHandleDeltas(storedAsks, a, timestamp);
988
- example = this.safeValue(a, 0);
989
- }
990
- if (b !== undefined) {
991
- timestamp = this.customHandleDeltas(storedBids, b, timestamp);
992
- example = this.safeValue(b, 0);
993
- }
994
- // don't remove this line or I will poop on your face
995
- orderbook.limit();
996
- const checksum = this.handleOption('watchOrderBook', 'checksum', true);
997
- if (checksum) {
998
- const priceString = this.safeString(example, 0);
999
- const amountString = this.safeString(example, 1);
1000
- const priceParts = priceString.split('.');
1001
- const amountParts = amountString.split('.');
1002
- const priceLength = priceParts[1].length - 0;
1003
- const amountLength = amountParts[1].length - 0;
1004
- const payloadArray = [];
1005
- if (c !== undefined) {
1006
- for (let i = 0; i < 10; i++) {
1007
- const formatted = this.formatNumber(storedAsks[i][0], priceLength) + this.formatNumber(storedAsks[i][1], amountLength);
1008
- payloadArray.push(formatted);
1009
- }
1010
- for (let i = 0; i < 10; i++) {
1011
- const formatted = this.formatNumber(storedBids[i][0], priceLength) + this.formatNumber(storedBids[i][1], amountLength);
1012
- payloadArray.push(formatted);
1013
- }
1014
- }
1015
- const payload = payloadArray.join('');
1016
- const localChecksum = this.crc32(payload, false);
1017
- if (localChecksum !== c) {
1018
- const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
1019
- delete client.subscriptions[messageHash];
1020
- delete this.orderbooks[symbol];
1021
- client.reject(error, messageHash);
1022
- return;
1023
- }
999
+ const payload = payloadArray.join('');
1000
+ const localChecksum = this.crc32(payload, false);
1001
+ if (localChecksum !== c) {
1002
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
1003
+ delete client.subscriptions[messageHash];
1004
+ delete this.orderbooks[symbol];
1005
+ client.reject(error, messageHash);
1006
+ return;
1024
1007
  }
1025
- orderbook['symbol'] = symbol;
1026
- orderbook['timestamp'] = timestamp;
1027
- orderbook['datetime'] = this.iso8601(timestamp);
1028
- client.resolve(orderbook, messageHash);
1008
+ }
1009
+ client.resolve(orderbook, messageHash);
1010
+ }
1011
+ customHandleDeltas(bookside, deltas) {
1012
+ // const sortOrder = (key === 'bids') ? true : false;
1013
+ for (let j = 0; j < deltas.length; j++) {
1014
+ const delta = deltas[j];
1015
+ const price = this.safeNumber(delta, 'price');
1016
+ const amount = this.safeNumber(delta, 'qty');
1017
+ bookside.store(price, amount);
1018
+ // if (amount === 0) {
1019
+ // const index = bookside.findIndex ((x: Int) => x[0] === price);
1020
+ // bookside.splice (index, 1);
1021
+ // } else {
1022
+ // bookside.store (price, amount);
1023
+ // }
1024
+ // bookside = this.sortBy (bookside, 0, sortOrder);
1025
+ // bookside.slice (0, 9);
1029
1026
  }
1030
1027
  }
1031
- formatNumber(n, length) {
1032
- const stringNumber = this.numberToString(n);
1033
- const parts = stringNumber.split('.');
1028
+ formatNumber(data) {
1029
+ const parts = data.split('.');
1034
1030
  const integer = this.safeString(parts, 0);
1035
1031
  const decimals = this.safeString(parts, 1, '');
1036
- const paddedDecimals = decimals.padEnd(length, '0');
1037
- const joined = integer + paddedDecimals;
1032
+ let joinedResult = integer + decimals;
1038
1033
  let i = 0;
1039
- while (joined[i] === '0') {
1034
+ while (joinedResult[i] === '0') {
1040
1035
  i += 1;
1041
1036
  }
1042
1037
  if (i > 0) {
1043
- return joined.slice(i);
1038
+ joinedResult = joinedResult.slice(i);
1044
1039
  }
1045
- else {
1046
- return joined;
1047
- }
1048
- }
1049
- customHandleDeltas(bookside, deltas, timestamp = undefined) {
1050
- for (let j = 0; j < deltas.length; j++) {
1051
- const delta = deltas[j];
1052
- const price = this.parseNumber(delta[0]);
1053
- const amount = this.parseNumber(delta[1]);
1054
- const oldTimestamp = timestamp ? timestamp : 0;
1055
- timestamp = Math.max(oldTimestamp, this.parseToInt(parseFloat(delta[2]) * 1000));
1056
- bookside.store(price, amount);
1057
- }
1058
- return timestamp;
1040
+ return joinedResult;
1059
1041
  }
1060
1042
  handleSystemStatus(client, message) {
1061
1043
  //
@@ -1091,7 +1073,11 @@ export default class kraken extends krakenRest {
1091
1073
  const client = this.client(url);
1092
1074
  const authenticated = 'authenticated';
1093
1075
  let subscription = this.safeValue(client.subscriptions, authenticated);
1094
- if (subscription === undefined) {
1076
+ const now = this.seconds();
1077
+ const start = this.safeInteger(subscription, 'start');
1078
+ const expires = this.safeInteger(subscription, 'expires');
1079
+ if ((subscription === undefined) || ((subscription !== undefined) && (start + expires) <= now)) {
1080
+ // https://docs.kraken.com/api/docs/rest-api/get-websockets-token
1095
1081
  const response = await this.privatePostGetWebSocketsToken(params);
1096
1082
  //
1097
1083
  // {
@@ -1102,7 +1088,8 @@ export default class kraken extends krakenRest {
1102
1088
  // }
1103
1089
  // }
1104
1090
  //
1105
- subscription = this.safeValue(response, 'result');
1091
+ subscription = this.safeDict(response, 'result');
1092
+ subscription['start'] = now;
1106
1093
  client.subscriptions[authenticated] = subscription;
1107
1094
  }
1108
1095
  return this.safeString(subscription, 'token');
@@ -1568,25 +1555,25 @@ export default class kraken extends krakenRest {
1568
1555
  symbols = this.marketSymbols(symbols, undefined, false, true, false);
1569
1556
  const messageHashes = [];
1570
1557
  for (let i = 0; i < symbols.length; i++) {
1571
- messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
1572
- }
1573
- // for WS subscriptions, we can't use .marketIds (symbols), instead a custom is field needed
1574
- const markets = this.marketsForSymbols(symbols);
1575
- const wsMarketIds = [];
1576
- for (let i = 0; i < markets.length; i++) {
1577
- const wsMarketId = this.safeString(markets[i]['info'], 'wsname');
1578
- wsMarketIds.push(wsMarketId);
1558
+ const eventTrigger = this.safeString(params, 'event_trigger');
1559
+ if (eventTrigger !== undefined) {
1560
+ messageHashes.push(this.getMessageHash(channelName, undefined, this.symbol(symbols[i])));
1561
+ }
1562
+ else {
1563
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
1564
+ }
1579
1565
  }
1580
1566
  const request = {
1581
- 'event': 'subscribe',
1582
- 'reqid': this.requestId(),
1583
- 'pair': wsMarketIds,
1584
- 'subscription': {
1585
- 'name': channelName,
1567
+ 'method': 'subscribe',
1568
+ 'params': {
1569
+ 'channel': channelName,
1570
+ 'symbol': symbols,
1586
1571
  },
1572
+ 'req_id': this.requestId(),
1587
1573
  };
1588
- const url = this.urls['api']['ws']['public'];
1589
- return await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), messageHashes, subscriptionArgs);
1574
+ request['params'] = this.deepExtend(request['params'], params);
1575
+ const url = this.urls['api']['ws']['publicV2'];
1576
+ return await this.watchMultiple(url, messageHashes, request, messageHashes, subscriptionArgs);
1590
1577
  }
1591
1578
  /**
1592
1579
  * @method
@@ -1751,11 +1738,7 @@ export default class kraken extends krakenRest {
1751
1738
  const name = this.safeString(info, 'name');
1752
1739
  const methods = {
1753
1740
  // public
1754
- 'book': this.handleOrderBook,
1755
1741
  'ohlc': this.handleOHLCV,
1756
- 'ticker': this.handleTicker,
1757
- 'spread': this.handleBidAsk,
1758
- 'trade': this.handleTrades,
1759
1742
  // private
1760
1743
  'openOrders': this.handleOrders,
1761
1744
  'ownTrades': this.handleMyTrades,
@@ -1770,6 +1753,9 @@ export default class kraken extends krakenRest {
1770
1753
  if (channel !== undefined) {
1771
1754
  const methods = {
1772
1755
  'balances': this.handleBalance,
1756
+ 'book': this.handleOrderBook,
1757
+ 'ticker': this.handleTicker,
1758
+ 'trade': this.handleTrades,
1773
1759
  };
1774
1760
  const method = this.safeValue(methods, channel);
1775
1761
  if (method !== undefined) {
@@ -1786,6 +1772,7 @@ export default class kraken extends krakenRest {
1786
1772
  'amend_order': this.handleCreateEditOrder,
1787
1773
  'cancel_order': this.handleCancelOrder,
1788
1774
  'cancel_all': this.handleCancelAllOrders,
1775
+ 'pong': this.handlePong,
1789
1776
  };
1790
1777
  const method = this.safeValue(methods, event);
1791
1778
  if (method !== undefined) {