ccxt 4.3.62 → 4.3.64

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 (86) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +2 -1
  4. package/dist/cjs/src/ace.js +34 -15
  5. package/dist/cjs/src/alpaca.js +1 -0
  6. package/dist/cjs/src/base/Exchange.js +11 -4
  7. package/dist/cjs/src/base/errors.js +8 -1
  8. package/dist/cjs/src/binance.js +6 -9
  9. package/dist/cjs/src/bingx.js +554 -151
  10. package/dist/cjs/src/bitfinex.js +1 -1
  11. package/dist/cjs/src/bitfinex2.js +1 -1
  12. package/dist/cjs/src/cryptocom.js +18 -2
  13. package/dist/cjs/src/independentreserve.js +107 -0
  14. package/dist/cjs/src/kucoin.js +2 -0
  15. package/dist/cjs/src/mercado.js +5 -1
  16. package/dist/cjs/src/pro/binance.js +58 -34
  17. package/dist/cjs/src/pro/bitfinex2.js +6 -3
  18. package/dist/cjs/src/pro/bitget.js +4 -1
  19. package/dist/cjs/src/pro/bitmart.js +3 -3
  20. package/dist/cjs/src/pro/bitvavo.js +1 -1
  21. package/dist/cjs/src/pro/bybit.js +44 -18
  22. package/dist/cjs/src/pro/cryptocom.js +7 -1
  23. package/dist/cjs/src/pro/gate.js +7 -3
  24. package/dist/cjs/src/pro/gemini.js +4 -2
  25. package/dist/cjs/src/pro/htx.js +5 -1
  26. package/dist/cjs/src/pro/independentreserve.js +5 -3
  27. package/dist/cjs/src/pro/kraken.js +82 -4
  28. package/dist/cjs/src/pro/okx.js +3 -3
  29. package/dist/cjs/src/pro/onetrading.js +3 -2
  30. package/dist/cjs/src/pro/poloniexfutures.js +5 -1
  31. package/dist/cjs/src/pro/vertex.js +3 -2
  32. package/dist/cjs/src/pro/woo.js +2 -1
  33. package/dist/cjs/src/pro/woofipro.js +3 -2
  34. package/dist/cjs/src/woo.js +344 -81
  35. package/js/ccxt.d.ts +3 -3
  36. package/js/ccxt.js +3 -3
  37. package/js/src/abstract/cryptocom.d.ts +11 -0
  38. package/js/src/abstract/kucoin.d.ts +1 -0
  39. package/js/src/abstract/kucoinfutures.d.ts +1 -0
  40. package/js/src/abstract/woo.d.ts +3 -0
  41. package/js/src/ace.js +34 -15
  42. package/js/src/alpaca.js +1 -0
  43. package/js/src/base/Exchange.d.ts +1 -0
  44. package/js/src/base/Exchange.js +11 -4
  45. package/js/src/base/errorHierarchy.d.ts +3 -1
  46. package/js/src/base/errorHierarchy.js +3 -1
  47. package/js/src/base/errors.d.ts +5 -1
  48. package/js/src/base/errors.js +8 -2
  49. package/js/src/binance.js +6 -9
  50. package/js/src/bingx.d.ts +4 -1
  51. package/js/src/bingx.js +554 -151
  52. package/js/src/bitfinex.js +1 -1
  53. package/js/src/bitfinex2.js +1 -1
  54. package/js/src/coinbaseinternational.d.ts +1 -1
  55. package/js/src/cryptocom.js +18 -2
  56. package/js/src/independentreserve.d.ts +3 -1
  57. package/js/src/independentreserve.js +106 -0
  58. package/js/src/kucoin.js +2 -0
  59. package/js/src/mercado.js +5 -1
  60. package/js/src/pro/binance.d.ts +1 -0
  61. package/js/src/pro/binance.js +59 -35
  62. package/js/src/pro/bitfinex2.js +7 -4
  63. package/js/src/pro/bitget.js +5 -2
  64. package/js/src/pro/bitmart.js +3 -3
  65. package/js/src/pro/bitvavo.js +1 -1
  66. package/js/src/pro/bybit.d.ts +1 -0
  67. package/js/src/pro/bybit.js +44 -18
  68. package/js/src/pro/cryptocom.js +8 -2
  69. package/js/src/pro/gate.js +8 -4
  70. package/js/src/pro/gemini.js +4 -2
  71. package/js/src/pro/htx.js +6 -2
  72. package/js/src/pro/independentreserve.js +6 -4
  73. package/js/src/pro/kraken.d.ts +3 -1
  74. package/js/src/pro/kraken.js +83 -5
  75. package/js/src/pro/okx.js +4 -4
  76. package/js/src/pro/onetrading.js +3 -2
  77. package/js/src/pro/poloniexfutures.js +6 -2
  78. package/js/src/pro/vertex.js +3 -2
  79. package/js/src/pro/woo.js +2 -1
  80. package/js/src/pro/woofipro.js +3 -2
  81. package/js/src/whitebit.d.ts +1 -1
  82. package/js/src/woo.d.ts +6 -2
  83. package/js/src/woo.js +344 -81
  84. package/js/src/xt.d.ts +3 -3
  85. package/js/src/zonda.d.ts +1 -1
  86. package/package.json +1 -1
@@ -31,7 +31,7 @@ export default class bybit extends bybitRest {
31
31
  'watchMyLiquidationsForSymbols': false,
32
32
  'watchMyTrades': true,
33
33
  'watchOHLCV': true,
34
- 'watchOHLCVForSymbols': false,
34
+ 'watchOHLCVForSymbols': true,
35
35
  'watchOrderBook': true,
36
36
  'watchOrderBookForSymbols': true,
37
37
  'watchOrders': true,
@@ -533,20 +533,46 @@ export default class bybit extends bybitRest {
533
533
  * @param {object} [params] extra parameters specific to the exchange API endpoint
534
534
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
535
535
  */
536
+ params['callerMethodName'] = 'watchOHLCV';
537
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
538
+ return result[symbol][timeframe];
539
+ }
540
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
541
+ /**
542
+ * @method
543
+ * @name bybit#watchOHLCVForSymbols
544
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
545
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
546
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
547
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
548
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
549
+ * @param {int} [limit] the maximum amount of candles to fetch
550
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
551
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
552
+ */
536
553
  await this.loadMarkets();
537
- const market = this.market(symbol);
538
- symbol = market['symbol'];
539
- const url = await this.getUrlByMarketType(symbol, false, 'watchOHLCV', params);
540
- params = this.cleanParams(params);
541
- let ohlcv = undefined;
542
- const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
543
- const topics = ['kline.' + timeframeId + '.' + market['id']];
544
- const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
545
- ohlcv = await this.watchTopics(url, [messageHash], topics, params);
554
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
555
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
556
+ const firstSymbol = marketSymbols[0];
557
+ const url = await this.getUrlByMarketType(firstSymbol, false, 'watchOHLCVForSymbols', params);
558
+ const rawHashes = [];
559
+ const messageHashes = [];
560
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
561
+ const data = symbolsAndTimeframes[i];
562
+ let symbolString = this.safeString(data, 0);
563
+ const market = this.market(symbolString);
564
+ symbolString = market['symbol'];
565
+ const unfiedTimeframe = this.safeString(data, 1);
566
+ const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
567
+ rawHashes.push('kline.' + timeframeId + '.' + market['id']);
568
+ messageHashes.push('ohlcv::' + symbolString + '::' + unfiedTimeframe);
569
+ }
570
+ const [symbol, timeframe, stored] = await this.watchTopics(url, messageHashes, rawHashes, params);
546
571
  if (this.newUpdates) {
547
- limit = ohlcv.getLimit(symbol, limit);
572
+ limit = stored.getLimit(symbol, limit);
548
573
  }
549
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
574
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
575
+ return this.createOHLCVObject(symbol, timeframe, filtered);
550
576
  }
551
577
  handleOHLCV(client, message) {
552
578
  //
@@ -586,18 +612,18 @@ export default class bybit extends bybitRest {
586
612
  if (ohlcvsByTimeframe === undefined) {
587
613
  this.ohlcvs[symbol] = {};
588
614
  }
589
- let stored = this.safeValue(ohlcvsByTimeframe, timeframe);
590
- if (stored === undefined) {
615
+ if (this.safeValue(ohlcvsByTimeframe, timeframe) === undefined) {
591
616
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
592
- stored = new ArrayCacheByTimestamp(limit);
593
- this.ohlcvs[symbol][timeframe] = stored;
617
+ this.ohlcvs[symbol][timeframe] = new ArrayCacheByTimestamp(limit);
594
618
  }
619
+ const stored = this.ohlcvs[symbol][timeframe];
595
620
  for (let i = 0; i < data.length; i++) {
596
621
  const parsed = this.parseWsOHLCV(data[i]);
597
622
  stored.append(parsed);
598
623
  }
599
- const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
600
- client.resolve(stored, messageHash);
624
+ const messageHash = 'ohlcv::' + symbol + '::' + timeframe;
625
+ const resolveData = [symbol, timeframe, stored];
626
+ client.resolve(resolveData, messageHash);
601
627
  }
602
628
  parseWsOHLCV(ohlcv, market = undefined) {
603
629
  //
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import cryptocomRest from '../cryptocom.js';
9
- import { AuthenticationError, InvalidNonce, NetworkError } from '../base/errors.js';
9
+ import { AuthenticationError, ChecksumError, NetworkError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -47,6 +47,9 @@ export default class cryptocom extends cryptocomRest {
47
47
  'fetchPositionsSnapshot': true,
48
48
  'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
49
49
  },
50
+ 'watchOrderBook': {
51
+ 'checksum': true,
52
+ },
50
53
  },
51
54
  'streaming': {},
52
55
  });
@@ -220,7 +223,10 @@ export default class cryptocom extends cryptocomRest {
220
223
  const previousNonce = this.safeInteger(data, 'pu');
221
224
  const currentNonce = orderbook['nonce'];
222
225
  if (currentNonce !== previousNonce) {
223
- throw new InvalidNonce(this.id + ' watchOrderBook() ' + symbol + ' ' + previousNonce + ' != ' + nonce);
226
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
227
+ if (checksum) {
228
+ throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
229
+ }
224
230
  }
225
231
  }
226
232
  this.handleDeltas(orderbook['asks'], this.safeValue(books, 'asks', []));
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import gateRest from '../gate.js';
9
- import { AuthenticationError, BadRequest, ArgumentsRequired, InvalidNonce, ExchangeError, NotSupported } from '../base/errors.js';
9
+ import { AuthenticationError, BadRequest, ArgumentsRequired, ChecksumError, ExchangeError, NotSupported } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha512 } from '../static_dependencies/noble-hashes/sha512.js';
12
12
  import Precise from '../base/Precise.js';
@@ -97,6 +97,7 @@ export default class gate extends gateRest {
97
97
  'interval': '100ms',
98
98
  'snapshotDelay': 10,
99
99
  'snapshotMaxRetries': 3,
100
+ 'checksum': true,
100
101
  },
101
102
  'watchBalance': {
102
103
  'settle': 'usdt',
@@ -482,10 +483,13 @@ export default class gate extends gateRest {
482
483
  this.handleDelta(storedOrderBook, delta);
483
484
  }
484
485
  else {
485
- const error = new InvalidNonce(this.id + ' orderbook update has a nonce bigger than u');
486
486
  delete client.subscriptions[messageHash];
487
487
  delete this.orderbooks[symbol];
488
- client.reject(error, messageHash);
488
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
489
+ if (checksum) {
490
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
491
+ client.reject(error, messageHash);
492
+ }
489
493
  }
490
494
  client.resolve(storedOrderBook, messageHash);
491
495
  }
@@ -1285,7 +1289,7 @@ export default class gate extends gateRest {
1285
1289
  else if (event === 'finish') {
1286
1290
  const status = this.safeString(parsed, 'status');
1287
1291
  if (status === undefined) {
1288
- const left = this.safeNumber(info, 'left');
1292
+ const left = this.safeInteger(info, 'left');
1289
1293
  parsed['status'] = (left === 0) ? 'closed' : 'canceled';
1290
1294
  }
1291
1295
  }
@@ -9,6 +9,7 @@ import geminiRest from '../gemini.js';
9
9
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
10
10
  import { ExchangeError, NotSupported } from '../base/errors.js';
11
11
  import { sha384 } from '../static_dependencies/noble-hashes/sha512.js';
12
+ import Precise from '../base/Precise.js';
12
13
  // ---------------------------------------------------------------------------
13
14
  export default class gemini extends geminiRest {
14
15
  describe() {
@@ -473,10 +474,11 @@ export default class gemini extends geminiRest {
473
474
  const entry = rawBidAskChanges[i];
474
475
  const rawSide = this.safeString(entry, 'side');
475
476
  const price = this.safeNumber(entry, 'price');
476
- const size = this.safeNumber(entry, 'remaining');
477
- if (size === 0) {
477
+ const sizeString = this.safeString(entry, 'remaining');
478
+ if (Precise.stringEq(sizeString, '0')) {
478
479
  continue;
479
480
  }
481
+ const size = this.parseNumber(sizeString);
480
482
  if (rawSide === 'bid') {
481
483
  currentBidAsk['bid'] = price;
482
484
  currentBidAsk['bidVolume'] = size;
package/js/src/pro/htx.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import htxRest from '../htx.js';
9
- import { ExchangeError, InvalidNonce, ArgumentsRequired, BadRequest, BadSymbol, AuthenticationError, NetworkError } from '../base/errors.js';
9
+ import { ExchangeError, InvalidNonce, ChecksumError, ArgumentsRequired, BadRequest, BadSymbol, AuthenticationError, NetworkError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -100,6 +100,7 @@ export default class htx extends htxRest {
100
100
  'api': 'api',
101
101
  'watchOrderBook': {
102
102
  'maxRetries': 3,
103
+ 'checksum': true,
103
104
  },
104
105
  'ws': {
105
106
  'gunzip': true,
@@ -571,7 +572,10 @@ export default class htx extends htxRest {
571
572
  orderbook['nonce'] = version;
572
573
  }
573
574
  if ((prevSeqNum !== undefined) && prevSeqNum > orderbook['nonce']) {
574
- throw new InvalidNonce(this.id + ' watchOrderBook() received a mesage out of order');
575
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
576
+ if (checksum) {
577
+ throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
578
+ }
575
579
  }
576
580
  const spotConditon = market['spot'] && (prevSeqNum === orderbook['nonce']);
577
581
  const nonSpotCondition = market['contract'] && (version - 1 === orderbook['nonce']);
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import independentreserveRest from '../independentreserve.js';
9
- import { NotSupported, InvalidNonce } from '../base/errors.js';
9
+ import { NotSupported, ChecksumError } from '../base/errors.js';
10
10
  import { ArrayCache } from '../base/ws/Cache.js';
11
11
  // ---------------------------------------------------------------------------
12
12
  export default class independentreserve extends independentreserveRest {
@@ -29,7 +29,9 @@ export default class independentreserve extends independentreserveRest {
29
29
  },
30
30
  },
31
31
  'options': {
32
- 'checksum': false, // TODO: currently only working for snapshot
32
+ 'watchOrderBook': {
33
+ 'checksum': true, // TODO: currently only working for snapshot
34
+ },
33
35
  },
34
36
  'streaming': {},
35
37
  'exceptions': {},
@@ -199,7 +201,7 @@ export default class independentreserve extends independentreserveRest {
199
201
  orderbook['timestamp'] = timestamp;
200
202
  orderbook['datetime'] = this.iso8601(timestamp);
201
203
  }
202
- const checksum = this.safeBool(this.options, 'checksum', true);
204
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
203
205
  if (checksum && receivedSnapshot) {
204
206
  const storedAsks = orderbook['asks'];
205
207
  const storedBids = orderbook['bids'];
@@ -219,7 +221,7 @@ export default class independentreserve extends independentreserveRest {
219
221
  const calculatedChecksum = this.crc32(payload, true);
220
222
  const responseChecksum = this.safeInteger(orderBook, 'Crc32');
221
223
  if (calculatedChecksum !== responseChecksum) {
222
- const error = new InvalidNonce(this.id + ' invalid checksum');
224
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
223
225
  delete client.subscriptions[messageHash];
224
226
  delete this.orderbooks[symbol];
225
227
  client.reject(error, messageHash);
@@ -1,5 +1,5 @@
1
1
  import krakenRest from '../kraken.js';
2
- import type { Int, Strings, OrderSide, OrderType, Str, OrderBook, Order, Trade, Ticker, Tickers, OHLCV, Num } from '../base/types.js';
2
+ import type { Int, Strings, OrderSide, OrderType, Str, OrderBook, Order, Trade, Ticker, Tickers, OHLCV, Num, Balances } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class kraken extends krakenRest {
5
5
  describe(): any;
@@ -53,6 +53,8 @@ export default class kraken extends krakenRest {
53
53
  handleOrders(client: Client, message: any, subscription?: any): void;
54
54
  parseWsOrder(order: any, market?: any): Order;
55
55
  watchMultiHelper(unifiedName: string, channelName: string, symbols?: Strings, subscriptionArgs?: any, params?: {}): Promise<any>;
56
+ watchBalance(params?: {}): Promise<Balances>;
57
+ handleBalance(client: Client, message: any): void;
56
58
  getMessageHash(unifiedElementName: string, subChannelName?: Str, symbol?: Str): string;
57
59
  handleSubscriptionStatus(client: Client, message: any): void;
58
60
  handleErrorMessage(client: Client, message: any): boolean;
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import krakenRest from '../kraken.js';
9
- import { ExchangeError, BadSymbol, PermissionDenied, AccountSuspended, BadRequest, InsufficientFunds, InvalidOrder, OrderNotFound, NotSupported, RateLimitExceeded, ExchangeNotAvailable, InvalidNonce, AuthenticationError } from '../base/errors.js';
9
+ import { ExchangeError, BadSymbol, PermissionDenied, AccountSuspended, BadRequest, InsufficientFunds, InvalidOrder, OrderNotFound, NotSupported, RateLimitExceeded, ExchangeNotAvailable, ChecksumError, AuthenticationError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
11
11
  import { Precise } from '../base/Precise.js';
12
12
  // ---------------------------------------------------------------------------
@@ -15,7 +15,7 @@ export default class kraken extends krakenRest {
15
15
  return this.deepExtend(super.describe(), {
16
16
  'has': {
17
17
  'ws': true,
18
- 'watchBalance': false,
18
+ 'watchBalance': true,
19
19
  'watchMyTrades': true,
20
20
  'watchOHLCV': true,
21
21
  'watchOrderBook': true,
@@ -38,6 +38,7 @@ export default class kraken extends krakenRest {
38
38
  'ws': {
39
39
  'public': 'wss://ws.kraken.com',
40
40
  'private': 'wss://ws-auth.kraken.com',
41
+ 'privateV2': 'wss://ws-auth.kraken.com/v2',
41
42
  'beta': 'wss://beta-ws.kraken.com',
42
43
  'beta-private': 'wss://beta-ws-auth.kraken.com',
43
44
  },
@@ -51,7 +52,9 @@ export default class kraken extends krakenRest {
51
52
  'OHLCVLimit': 1000,
52
53
  'ordersLimit': 1000,
53
54
  'symbolsByOrderId': {},
54
- 'checksum': true,
55
+ 'watchOrderBook': {
56
+ 'checksum': true,
57
+ },
55
58
  },
56
59
  'exceptions': {
57
60
  'ws': {
@@ -749,7 +752,7 @@ export default class kraken extends krakenRest {
749
752
  }
750
753
  // don't remove this line or I will poop on your face
751
754
  orderbook.limit();
752
- const checksum = this.safeBool(this.options, 'checksum', true);
755
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
753
756
  if (checksum) {
754
757
  const priceString = this.safeString(example, 0);
755
758
  const amountString = this.safeString(example, 1);
@@ -771,7 +774,7 @@ export default class kraken extends krakenRest {
771
774
  const payload = payloadArray.join('');
772
775
  const localChecksum = this.crc32(payload, false);
773
776
  if (localChecksum !== c) {
774
- const error = new InvalidNonce(this.id + ' invalid checksum');
777
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
775
778
  delete client.subscriptions[messageHash];
776
779
  delete this.orderbooks[symbol];
777
780
  client.reject(error, messageHash);
@@ -1329,6 +1332,71 @@ export default class kraken extends krakenRest {
1329
1332
  const url = this.urls['api']['ws']['public'];
1330
1333
  return await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), messageHashes, subscriptionArgs);
1331
1334
  }
1335
+ async watchBalance(params = {}) {
1336
+ /**
1337
+ * @method
1338
+ * @name kraken#watchBalance
1339
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
1340
+ * @see https://docs.kraken.com/api/docs/websocket-v2/balances
1341
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1342
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1343
+ */
1344
+ await this.loadMarkets();
1345
+ const token = await this.authenticate();
1346
+ const messageHash = 'balances';
1347
+ const url = this.urls['api']['ws']['privateV2'];
1348
+ const requestId = this.requestId();
1349
+ const subscribe = {
1350
+ 'method': 'subscribe',
1351
+ 'req_id': requestId,
1352
+ 'params': {
1353
+ 'channel': 'balances',
1354
+ 'token': token,
1355
+ },
1356
+ };
1357
+ const request = this.deepExtend(subscribe, params);
1358
+ return await this.watch(url, messageHash, request, messageHash);
1359
+ }
1360
+ handleBalance(client, message) {
1361
+ //
1362
+ // {
1363
+ // "channel": "balances",
1364
+ // "data": [
1365
+ // {
1366
+ // "asset": "BTC",
1367
+ // "asset_class": "currency",
1368
+ // "balance": 1.2,
1369
+ // "wallets": [
1370
+ // {
1371
+ // "type": "spot",
1372
+ // "id": "main",
1373
+ // "balance": 1.2
1374
+ // }
1375
+ // ]
1376
+ // }
1377
+ // ],
1378
+ // "type": "snapshot",
1379
+ // "sequence": 1
1380
+ // }
1381
+ //
1382
+ const data = this.safeList(message, 'data', []);
1383
+ const result = { 'info': message };
1384
+ for (let i = 0; i < data.length; i++) {
1385
+ const currencyId = this.safeString(data[i], 'asset');
1386
+ const code = this.safeCurrencyCode(currencyId);
1387
+ const account = this.account();
1388
+ const eq = this.safeString(data[i], 'balance');
1389
+ account['total'] = eq;
1390
+ result[code] = account;
1391
+ }
1392
+ const type = 'spot';
1393
+ const balance = this.safeBalance(result);
1394
+ const oldBalance = this.safeValue(this.balance, type, {});
1395
+ const newBalance = this.deepExtend(oldBalance, balance);
1396
+ this.balance[type] = this.safeBalance(newBalance);
1397
+ const channel = this.safeString(message, 'channel');
1398
+ client.resolve(this.balance[type], channel);
1399
+ }
1332
1400
  getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
1333
1401
  // unifiedElementName can be : orderbook, trade, ticker, bidask ...
1334
1402
  // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
@@ -1432,6 +1500,16 @@ export default class kraken extends krakenRest {
1432
1500
  }
1433
1501
  }
1434
1502
  else {
1503
+ const channel = this.safeString(message, 'channel');
1504
+ if (channel !== undefined) {
1505
+ const methods = {
1506
+ 'balances': this.handleBalance,
1507
+ };
1508
+ const method = this.safeValue(methods, channel);
1509
+ if (method !== undefined) {
1510
+ method.call(this, client, message);
1511
+ }
1512
+ }
1435
1513
  if (this.handleErrorMessage(client, message)) {
1436
1514
  const event = this.safeString(message, 'event');
1437
1515
  const methods = {
package/js/src/pro/okx.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import okxRest from '../okx.js';
9
- import { ArgumentsRequired, BadRequest, ExchangeError, InvalidNonce, AuthenticationError } from '../base/errors.js';
9
+ import { ArgumentsRequired, BadRequest, ExchangeError, ChecksumError, AuthenticationError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -49,6 +49,7 @@ export default class okx extends okxRest {
49
49
  },
50
50
  'options': {
51
51
  'watchOrderBook': {
52
+ 'checksum': true,
52
53
  //
53
54
  // bbo-tbt
54
55
  // 1. Newly added channel that sends tick-by-tick Level 1 data
@@ -96,7 +97,6 @@ export default class okx extends okxRest {
96
97
  'ws': {
97
98
  // 'inflate': true,
98
99
  },
99
- 'checksum': true,
100
100
  },
101
101
  'streaming': {
102
102
  // okex does not support built-in ws protocol-level ping-pong
@@ -922,7 +922,7 @@ export default class okx extends okxRest {
922
922
  this.handleDeltas(storedBids, bids);
923
923
  const marketId = this.safeString(message, 'instId');
924
924
  const symbol = this.safeSymbol(marketId);
925
- const checksum = this.safeBool(this.options, 'checksum', true);
925
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
926
926
  if (checksum) {
927
927
  const asksLength = storedAsks.length;
928
928
  const bidsLength = storedBids.length;
@@ -941,7 +941,7 @@ export default class okx extends okxRest {
941
941
  const responseChecksum = this.safeInteger(message, 'checksum');
942
942
  const localChecksum = this.crc32(payload, true);
943
943
  if (responseChecksum !== localChecksum) {
944
- const error = new InvalidNonce(this.id + ' invalid checksum');
944
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
945
945
  delete client.subscriptions[messageHash];
946
946
  delete this.orderbooks[symbol];
947
947
  client.reject(error, messageHash);
@@ -8,6 +8,7 @@
8
8
  import onetradingRest from '../onetrading.js';
9
9
  import { NotSupported, ExchangeError } from '../base/errors.js';
10
10
  import { ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
+ import Precise from '../base/Precise.js';
11
12
  // ---------------------------------------------------------------------------
12
13
  export default class onetrading extends onetradingRest {
13
14
  describe() {
@@ -965,9 +966,9 @@ export default class onetrading extends onetradingRest {
965
966
  const previousOrderArray = this.filterByArray(this.orders, 'id', orderId, false);
966
967
  const previousOrder = this.safeValue(previousOrderArray, 0, {});
967
968
  symbol = previousOrder['symbol'];
968
- const filled = this.safeNumber(update, 'filled_amount');
969
+ const filled = this.safeString(update, 'filled_amount');
969
970
  let status = this.parseWsOrderStatus(updateType);
970
- if (updateType === 'ORDER_CLOSED' && filled === 0) {
971
+ if (updateType === 'ORDER_CLOSED' && Precise.stringEq(filled, '0')) {
971
972
  status = 'canceled';
972
973
  }
973
974
  const orderObject = {
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import poloniexfuturesRest from '../poloniexfutures.js';
9
- import { AuthenticationError, BadRequest, InvalidNonce } from '../base/errors.js';
9
+ import { AuthenticationError, BadRequest, ChecksumError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
11
11
  // ---------------------------------------------------------------------------
12
12
  export default class poloniexfutures extends poloniexfuturesRest {
@@ -52,6 +52,7 @@ export default class poloniexfutures extends poloniexfuturesRest {
52
52
  'method': '/contractMarket/level2',
53
53
  'snapshotDelay': 5,
54
54
  'snapshotMaxRetries': 3,
55
+ 'checksum': true,
55
56
  },
56
57
  'streamLimit': 5,
57
58
  'streamBySubscriptionsHash': {},
@@ -860,7 +861,10 @@ export default class poloniexfutures extends poloniexfuturesRest {
860
861
  return;
861
862
  }
862
863
  if (nonce !== lastSequence) {
863
- throw new InvalidNonce(this.id + ' watchOrderBook received an out-of-order nonce');
864
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
865
+ if (checksum) {
866
+ throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(''));
867
+ }
864
868
  }
865
869
  const changes = this.safeList(delta, 'changes');
866
870
  for (let i = 0; i < changes.length; i++) {
@@ -845,9 +845,10 @@ export default class vertex extends vertexRest {
845
845
  //
846
846
  const marketId = this.safeString(order, 'product_id');
847
847
  const timestamp = this.parseToInt(Precise.stringDiv(this.safeString(order, 'timestamp'), '1000000'));
848
- const remaining = this.parseToNumeric(this.convertFromX18(this.safeString(order, 'amount')));
848
+ const remainingString = this.convertFromX18(this.safeString(order, 'amount'));
849
+ const remaining = this.parseToNumeric(remainingString);
849
850
  let status = this.parseWsOrderStatus(this.safeString(order, 'reason'));
850
- if (remaining === 0 && status === 'open') {
851
+ if (Precise.stringEq(remainingString, '0') && status === 'open') {
851
852
  status = 'closed';
852
853
  }
853
854
  market = this.safeMarket(marketId, market);
package/js/src/pro/woo.js CHANGED
@@ -665,9 +665,10 @@ export default class woo extends wooRest {
665
665
  'cost': this.safeString(order, 'totalFee'),
666
666
  'currency': this.safeString(order, 'feeAsset'),
667
667
  };
668
+ const priceString = this.safeString(order, 'price');
668
669
  let price = this.safeNumber(order, 'price');
669
670
  const avgPrice = this.safeNumber(order, 'avgPrice');
670
- if ((price === 0) && (avgPrice !== undefined)) {
671
+ if (Precise.stringEq(priceString, '0') && (avgPrice !== undefined)) {
671
672
  price = avgPrice;
672
673
  }
673
674
  const amount = this.safeFloat(order, 'quantity');
@@ -377,7 +377,7 @@ export default class woofipro extends woofiproRest {
377
377
  * @param {int} [since] the earliest time in ms to fetch trades for
378
378
  * @param {int} [limit] the maximum number of trade structures to retrieve
379
379
  * @param {object} [params] extra parameters specific to the exchange API endpoint
380
- * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
380
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
381
381
  */
382
382
  await this.loadMarkets();
383
383
  const market = this.market(symbol);
@@ -717,9 +717,10 @@ export default class woofipro extends woofiproRest {
717
717
  'cost': this.safeString(order, 'totalFee'),
718
718
  'currency': this.safeString(order, 'feeAsset'),
719
719
  };
720
+ const priceString = this.safeString(order, 'price');
720
721
  let price = this.safeNumber(order, 'price');
721
722
  const avgPrice = this.safeNumber(order, 'avgPrice');
722
- if ((price === 0) && (avgPrice !== undefined)) {
723
+ if (Precise.stringEq(priceString, '0') && (avgPrice !== undefined)) {
723
724
  price = avgPrice;
724
725
  }
725
726
  const amount = this.safeString(order, 'quantity');
@@ -96,7 +96,7 @@ export default class whitebit extends Exchange {
96
96
  previousFundingDatetime: any;
97
97
  };
98
98
  fetchDepositsWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
99
- isFiat(currency: any): boolean;
99
+ isFiat(currency: string): boolean;
100
100
  nonce(): number;
101
101
  sign(path: any, api?: string, method?: string, params?: {}, headers?: any, body?: any): {
102
102
  url: string;
package/js/src/woo.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/woo.js';
2
- import type { TransferEntry, Balances, Conversion, Currency, FundingRateHistory, Int, Market, Num, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Dict, Strings, Trade, Transaction, Leverage, Account, Currencies, TradingFees, TransferEntries, int } from './base/types.js';
2
+ import type { TransferEntry, Balances, Conversion, Currency, FundingRateHistory, Int, Market, MarginModification, Num, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Dict, Strings, Trade, Transaction, Leverage, Account, Currencies, TradingFees, TransferEntries, int, FundingHistory } from './base/types.js';
3
3
  /**
4
4
  * @class woo
5
5
  * @augments Exchange
@@ -26,6 +26,7 @@ export default class woo extends Exchange {
26
26
  createTrailingAmountOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, trailingAmount?: any, trailingTriggerPrice?: any, params?: {}): Promise<Order>;
27
27
  createTrailingPercentOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, trailingPercent?: any, trailingTriggerPrice?: any, params?: {}): Promise<Order>;
28
28
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, params?: {}): Promise<Order>;
29
+ encodeMarginMode(mode: any): string;
29
30
  editOrder(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: Num, price?: Num, params?: {}): Promise<Order>;
30
31
  cancelOrder(id: string, symbol?: Str, params?: {}): Promise<any>;
31
32
  cancelAllOrders(symbol?: Str, params?: {}): Promise<any>;
@@ -118,7 +119,7 @@ export default class woo extends Exchange {
118
119
  amount: number;
119
120
  rate: number;
120
121
  };
121
- fetchFundingHistory(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<import("./base/types.js").FundingHistory[]>;
122
+ fetchFundingHistory(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<FundingHistory[]>;
122
123
  parseFundingRate(fundingRate: any, market?: Market): {
123
124
  info: any;
124
125
  symbol: string;
@@ -163,6 +164,9 @@ export default class woo extends Exchange {
163
164
  fetchLeverage(symbol: string, params?: {}): Promise<Leverage>;
164
165
  parseLeverage(leverage: Dict, market?: Market): Leverage;
165
166
  setLeverage(leverage: Int, symbol?: Str, params?: {}): Promise<any>;
167
+ addMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
168
+ reduceMargin(symbol: string, amount: number, params?: {}): Promise<MarginModification>;
169
+ modifyMarginHelper(symbol: string, amount: any, type: any, params?: {}): Promise<MarginModification>;
166
170
  fetchPosition(symbol?: Str, params?: {}): Promise<import("./base/types.js").Position>;
167
171
  fetchPositions(symbols?: Strings, params?: {}): Promise<import("./base/types.js").Position[]>;
168
172
  parsePosition(position: Dict, market?: Market): import("./base/types.js").Position;