ccxt 4.2.9 → 4.2.10

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 (47) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +267 -143
  3. package/dist/ccxt.browser.min.js +7 -7
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/base/Exchange.js +37 -8
  6. package/dist/cjs/src/binance.js +6 -1
  7. package/dist/cjs/src/bl3p.js +1 -1
  8. package/dist/cjs/src/btcalpha.js +1 -1
  9. package/dist/cjs/src/cryptocom.js +3 -1
  10. package/dist/cjs/src/deribit.js +39 -22
  11. package/dist/cjs/src/kraken.js +1 -1
  12. package/dist/cjs/src/kucoin.js +1 -1
  13. package/dist/cjs/src/lykke.js +1 -1
  14. package/dist/cjs/src/ndax.js +1 -1
  15. package/dist/cjs/src/pro/bitmart.js +49 -27
  16. package/dist/cjs/src/pro/blockchaincom.js +2 -28
  17. package/dist/cjs/src/pro/coinbasepro.js +9 -16
  18. package/dist/cjs/src/pro/cryptocom.js +110 -28
  19. package/dist/cjs/src/pro/luno.js +5 -5
  20. package/js/ccxt.d.ts +1 -1
  21. package/js/ccxt.js +1 -1
  22. package/js/src/base/Exchange.d.ts +4 -3
  23. package/js/src/base/Exchange.js +37 -8
  24. package/js/src/binance.js +6 -1
  25. package/js/src/bl3p.d.ts +2 -2
  26. package/js/src/bl3p.js +1 -1
  27. package/js/src/btcalpha.d.ts +2 -2
  28. package/js/src/btcalpha.js +1 -1
  29. package/js/src/cryptocom.js +3 -1
  30. package/js/src/deribit.js +39 -22
  31. package/js/src/kraken.d.ts +2 -2
  32. package/js/src/kraken.js +1 -1
  33. package/js/src/kucoin.js +1 -1
  34. package/js/src/lykke.d.ts +2 -2
  35. package/js/src/lykke.js +1 -1
  36. package/js/src/ndax.d.ts +2 -2
  37. package/js/src/ndax.js +1 -1
  38. package/js/src/pro/bitmart.d.ts +1 -0
  39. package/js/src/pro/bitmart.js +49 -27
  40. package/js/src/pro/blockchaincom.d.ts +1 -11
  41. package/js/src/pro/blockchaincom.js +2 -28
  42. package/js/src/pro/coinbasepro.js +9 -16
  43. package/js/src/pro/cryptocom.d.ts +3 -1
  44. package/js/src/pro/cryptocom.js +111 -29
  45. package/js/src/pro/luno.d.ts +4 -4
  46. package/js/src/pro/luno.js +5 -5
  47. package/package.json +1 -1
package/js/src/lykke.js CHANGED
@@ -1081,7 +1081,7 @@ export default class lykke extends Exchange {
1081
1081
  //
1082
1082
  return this.parseTrades(payload, market, since, limit);
1083
1083
  }
1084
- parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
1084
+ parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
1085
1085
  const price = this.safeString(bidask, priceKey);
1086
1086
  const amount = Precise.stringAbs(this.safeString(bidask, amountKey));
1087
1087
  return [this.parseNumber(price), this.parseNumber(amount)];
package/js/src/ndax.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/ndax.js';
2
- import type { Balances, Currency, Int, Market, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, Transaction } from './base/types.js';
2
+ import type { IndexType, Balances, Currency, Int, Market, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, Transaction } from './base/types.js';
3
3
  /**
4
4
  * @class ndax
5
5
  * @augments Exchange
@@ -10,7 +10,7 @@ export default class ndax extends Exchange {
10
10
  fetchCurrencies(params?: {}): Promise<{}>;
11
11
  fetchMarkets(params?: {}): Promise<import("./base/types.js").MarketInterface[]>;
12
12
  parseMarket(market: any): Market;
13
- parseOrderBook(orderbook: any, symbol: any, timestamp?: any, bidsKey?: string, asksKey?: string, priceKey?: number, amountKey?: number): OrderBook;
13
+ parseOrderBook(orderbook: any, symbol: any, timestamp?: any, bidsKey?: string, asksKey?: string, priceKey?: IndexType, amountKey?: IndexType, countOrIdKey?: IndexType): OrderBook;
14
14
  fetchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
15
15
  parseTicker(ticker: any, market?: Market): Ticker;
16
16
  fetchTicker(symbol: string, params?: {}): Promise<Ticker>;
package/js/src/ndax.js CHANGED
@@ -521,7 +521,7 @@ export default class ndax extends Exchange {
521
521
  'info': market,
522
522
  };
523
523
  }
524
- parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 6, amountKey = 8) {
524
+ parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 6, amountKey = 8, countOrIdKey = 2) {
525
525
  let nonce = undefined;
526
526
  const result = {
527
527
  'symbol': symbol,
@@ -22,6 +22,7 @@ export default class bitmart extends bitmartRest {
22
22
  handleTrade(client: Client, message: any): any;
23
23
  parseWsTrade(trade: any, market?: Market): Trade;
24
24
  handleTicker(client: Client, message: any): any;
25
+ resolveMessageHashesForSymbol(client: any, symbol: any, result: any, prexif: any): void;
25
26
  parseWsSwapTicker(ticker: any, market?: Market): Ticker;
26
27
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
27
28
  handleOHLCV(client: Client, message: any): void;
@@ -293,25 +293,39 @@ export default class bitmart extends bitmartRest {
293
293
  const market = this.getMarketFromSymbols(symbols);
294
294
  let type = 'spot';
295
295
  [type, params] = this.handleMarketTypeAndParams('watchTickers', market, params);
296
- symbols = this.marketSymbols(symbols);
297
- if (type === 'spot') {
298
- throw new NotSupported(this.id + ' watchTickers() does not support ' + type + ' markets. Use watchTicker() instead');
299
- }
300
296
  const url = this.implodeHostname(this.urls['api']['ws'][type]['public']);
301
- if (type === 'swap') {
302
- type = 'futures';
303
- }
304
- let messageHash = 'tickers';
297
+ symbols = this.marketSymbols(symbols);
298
+ let messageHash = 'tickers::' + type;
305
299
  if (symbols !== undefined) {
306
300
  messageHash += '::' + symbols.join(',');
307
301
  }
308
- const request = {
309
- 'action': 'subscribe',
310
- 'args': ['futures/ticker'],
311
- };
312
- const newTickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
302
+ let request = undefined;
303
+ let tickers = undefined;
304
+ const isSpot = (type === 'spot');
305
+ if (isSpot) {
306
+ if (symbols === undefined) {
307
+ throw new ArgumentsRequired(this.id + ' watchTickers() for ' + type + ' market type requires symbols argument to be provided');
308
+ }
309
+ const marketIds = this.marketIds(symbols);
310
+ const finalArray = [];
311
+ for (let i = 0; i < marketIds.length; i++) {
312
+ finalArray.push('spot/ticker:' + marketIds[i]);
313
+ }
314
+ request = {
315
+ 'op': 'subscribe',
316
+ 'args': finalArray,
317
+ };
318
+ tickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
319
+ }
320
+ else {
321
+ request = {
322
+ 'action': 'subscribe',
323
+ 'args': ['futures/ticker'],
324
+ };
325
+ tickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
326
+ }
313
327
  if (this.newUpdates) {
314
- return newTickers;
328
+ return tickers;
315
329
  }
316
330
  return this.filterByArray(this.tickers, 'symbol', symbols);
317
331
  }
@@ -896,28 +910,36 @@ export default class bitmart extends bitmartRest {
896
910
  const messageHash = table + ':' + marketId;
897
911
  this.tickers[symbol] = ticker;
898
912
  client.resolve(ticker, messageHash);
913
+ this.resolveMessageHashesForSymbol(client, symbol, ticker, 'tickers::');
899
914
  }
900
915
  }
901
916
  else {
917
+ // on each update for contract markets, single ticker is provided
902
918
  const ticker = this.parseWsSwapTicker(data);
903
919
  const symbol = this.safeString(ticker, 'symbol');
904
920
  this.tickers[symbol] = ticker;
905
- client.resolve(ticker, 'tickers');
906
- const messageHashes = this.findMessageHashes(client, 'tickers::');
907
- for (let i = 0; i < messageHashes.length; i++) {
908
- const messageHash = messageHashes[i];
909
- const parts = messageHash.split('::');
910
- const symbolsString = parts[1];
911
- const symbols = symbolsString.split(',');
912
- if (this.inArray(symbol, symbols)) {
913
- const response = {};
914
- response[symbol] = ticker;
915
- client.resolve(response, messageHash);
916
- }
917
- }
921
+ client.resolve(ticker, 'tickers::swap');
922
+ this.resolveMessageHashesForSymbol(client, symbol, ticker, 'tickers::');
918
923
  }
919
924
  return message;
920
925
  }
926
+ resolveMessageHashesForSymbol(client, symbol, result, prexif) {
927
+ const prefixSeparator = '::';
928
+ const symbolsSeparator = ',';
929
+ const messageHashes = this.findMessageHashes(client, prexif);
930
+ for (let i = 0; i < messageHashes.length; i++) {
931
+ const messageHash = messageHashes[i];
932
+ const parts = messageHash.split(prefixSeparator);
933
+ const length = parts.length;
934
+ const symbolsString = parts[length - 1];
935
+ const symbols = symbolsString.split(symbolsSeparator);
936
+ if (this.inArray(symbol, symbols)) {
937
+ const response = {};
938
+ response[symbol] = result;
939
+ client.resolve(response, messageHash);
940
+ }
941
+ }
942
+ }
921
943
  parseWsSwapTicker(ticker, market = undefined) {
922
944
  //
923
945
  // {
@@ -1,5 +1,5 @@
1
1
  import blockchaincomRest from '../blockchaincom.js';
2
- import type { IndexType, Int, Str, OrderBook, Order, Trade, Ticker, OHLCV, Balances } from '../base/types.js';
2
+ import type { Int, Str, OrderBook, Order, Trade, Ticker, OHLCV, Balances } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class blockchaincom extends blockchaincomRest {
5
5
  describe(): any;
@@ -19,16 +19,6 @@ export default class blockchaincom extends blockchaincomRest {
19
19
  parseWsOrderStatus(status: any): string;
20
20
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
21
21
  handleOrderBook(client: Client, message: any): any;
22
- parseCountedBidAsk(bidAsk: any, priceKey?: IndexType, amountKey?: IndexType, countKey?: IndexType): number[];
23
- parseCountedBidsAsks(bidasks: any, priceKey?: IndexType, amountKey?: IndexType, countKey?: IndexType): any[];
24
- parseCountedOrderBook(orderbook: any, symbol: string, timestamp?: Int, bidsKey?: IndexType, asksKey?: IndexType, priceKey?: IndexType, amountKey?: IndexType, countKey?: IndexType): {
25
- symbol: string;
26
- bids: any;
27
- asks: any;
28
- timestamp: number;
29
- datetime: string;
30
- nonce: any;
31
- };
32
22
  handleDelta(bookside: any, delta: any): void;
33
23
  handleDeltas(bookside: any, deltas: any): void;
34
24
  checkSequenceNumber(client: Client, message: any): void;
@@ -698,7 +698,7 @@ export default class blockchaincom extends blockchaincomRest {
698
698
  return message;
699
699
  }
700
700
  else if (event === 'snapshot') {
701
- const snapshot = this.parseCountedOrderBook(message, symbol, timestamp, 'bids', 'asks', 'px', 'qty', 'num');
701
+ const snapshot = this.parseOrderBook(message, symbol, timestamp, 'bids', 'asks', 'px', 'qty', 'num');
702
702
  storedOrderBook.reset(snapshot);
703
703
  }
704
704
  else if (event === 'updated') {
@@ -714,34 +714,8 @@ export default class blockchaincom extends blockchaincomRest {
714
714
  }
715
715
  client.resolve(storedOrderBook, messageHash);
716
716
  }
717
- parseCountedBidAsk(bidAsk, priceKey = 0, amountKey = 1, countKey = 2) {
718
- const price = this.safeNumber(bidAsk, priceKey);
719
- const amount = this.safeNumber(bidAsk, amountKey);
720
- const count = this.safeNumber(bidAsk, countKey);
721
- return [price, amount, count];
722
- }
723
- parseCountedBidsAsks(bidasks, priceKey = 0, amountKey = 1, countKey = 2) {
724
- bidasks = this.toArray(bidasks);
725
- const result = [];
726
- for (let i = 0; i < bidasks.length; i++) {
727
- result.push(this.parseCountedBidAsk(bidasks[i], priceKey, amountKey, countKey));
728
- }
729
- return result;
730
- }
731
- parseCountedOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1, countKey = 2) {
732
- const bids = this.parseCountedBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey, countKey);
733
- const asks = this.parseCountedBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey, countKey);
734
- return {
735
- 'symbol': symbol,
736
- 'bids': this.sortBy(bids, 0, true),
737
- 'asks': this.sortBy(asks, 0),
738
- 'timestamp': timestamp,
739
- 'datetime': this.iso8601(timestamp),
740
- 'nonce': undefined,
741
- };
742
- }
743
717
  handleDelta(bookside, delta) {
744
- const bookArray = this.parseCountedBidAsk(delta, 'px', 'qty', 'num');
718
+ const bookArray = this.parseBidAsk(delta, 'px', 'qty', 'num');
745
719
  bookside.storeArray(bookArray);
746
720
  }
747
721
  handleDeltas(bookside, deltas) {
@@ -92,7 +92,7 @@ export default class coinbasepro extends coinbaseproRest {
92
92
  const symbol = symbols[i];
93
93
  market = this.market(symbol);
94
94
  productIds.push(market['id']);
95
- messageHashes.push(messageHashStart + ':' + market['id']);
95
+ messageHashes.push(messageHashStart + ':' + market['symbol']);
96
96
  }
97
97
  let url = this.urls['api']['ws'];
98
98
  if ('signature' in params) {
@@ -137,10 +137,12 @@ export default class coinbasepro extends coinbaseproRest {
137
137
  throw new BadSymbol(this.id + ' watchTickers requires a non-empty symbols array');
138
138
  }
139
139
  const channel = 'ticker';
140
- const messageHash = 'tickers::';
141
- const newTickers = await this.subscribeMultiple(channel, symbols, messageHash, params);
140
+ const messageHash = 'ticker';
141
+ const ticker = await this.subscribeMultiple(channel, symbols, messageHash, params);
142
142
  if (this.newUpdates) {
143
- return newTickers;
143
+ const result = {};
144
+ result[ticker['symbol']] = ticker;
145
+ return result;
144
146
  }
145
147
  return this.filterByArray(this.tickers, 'symbol', symbols);
146
148
  }
@@ -752,19 +754,10 @@ export default class coinbasepro extends coinbaseproRest {
752
754
  const ticker = this.parseTicker(message);
753
755
  const symbol = ticker['symbol'];
754
756
  this.tickers[symbol] = ticker;
755
- const type = this.safeString(message, 'type');
756
- const messageHash = type + ':' + marketId;
757
+ const messageHash = 'ticker:' + symbol;
758
+ const idMessageHash = 'ticker:' + marketId;
757
759
  client.resolve(ticker, messageHash);
758
- const messageHashes = this.findMessageHashes(client, 'tickers::');
759
- for (let i = 0; i < messageHashes.length; i++) {
760
- const currentMessageHash = messageHashes[i];
761
- const parts = currentMessageHash.split('::');
762
- const symbolsString = parts[1];
763
- const symbols = symbolsString.split(',');
764
- if (this.inArray(symbol, symbols)) {
765
- client.resolve(ticker, currentMessageHash);
766
- }
767
- }
760
+ client.resolve(ticker, idMessageHash);
768
761
  }
769
762
  return message;
770
763
  }
@@ -6,7 +6,9 @@ export default class cryptocom extends cryptocomRest {
6
6
  pong(client: any, message: any): Promise<void>;
7
7
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
8
8
  watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
9
- handleOrderBookSnapshot(client: Client, message: any): void;
9
+ handleDelta(bookside: any, delta: any): void;
10
+ handleDeltas(bookside: any, deltas: any): void;
11
+ handleOrderBook(client: Client, message: any): void;
10
12
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
11
13
  watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
12
14
  handleTrades(client: Client, message: any): void;
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import cryptocomRest from '../cryptocom.js';
9
- import { AuthenticationError, NetworkError } from '../base/errors.js';
9
+ import { AuthenticationError, InvalidNonce, 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
  // ---------------------------------------------------------------------------
@@ -74,6 +74,8 @@ export default class cryptocom extends cryptocomRest {
74
74
  * @param {string} symbol unified symbol of the market to fetch the order book for
75
75
  * @param {int} [limit] the maximum amount of order book entries to return
76
76
  * @param {object} [params] extra parameters specific to the exchange API endpoint
77
+ * @param {string} [params.bookSubscriptionType] The subscription type. Allowed values: SNAPSHOT full snapshot. This is the default if not specified. SNAPSHOT_AND_UPDATE delta updates
78
+ * @param {int} [params.bookUpdateFrequency] Book update interval in ms. Allowed values: 100 for snapshot subscription 10 for delta subscription
77
79
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
78
80
  */
79
81
  return await this.watchOrderBookForSymbols([symbol], limit, params);
@@ -87,6 +89,8 @@ export default class cryptocom extends cryptocomRest {
87
89
  * @param {string[]} symbols unified array of symbols
88
90
  * @param {int} [limit] the maximum amount of order book entries to return
89
91
  * @param {object} [params] extra parameters specific to the exchange API endpoint
92
+ * @param {string} [params.bookSubscriptionType] The subscription type. Allowed values: SNAPSHOT full snapshot. This is the default if not specified. SNAPSHOT_AND_UPDATE delta updates
93
+ * @param {int} [params.bookUpdateFrequency] Book update interval in ms. Allowed values: 100 for snapshot subscription 10 for delta subscription
90
94
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
91
95
  */
92
96
  await this.loadMarkets();
@@ -94,12 +98,26 @@ export default class cryptocom extends cryptocomRest {
94
98
  const topics = [];
95
99
  const messageHashes = [];
96
100
  if (!limit) {
97
- limit = 150;
101
+ limit = 50;
102
+ }
103
+ const topicParams = this.safeValue(params, 'params');
104
+ if (topicParams === undefined) {
105
+ params['params'] = {};
106
+ }
107
+ let bookSubscriptionType = undefined;
108
+ [bookSubscriptionType, params] = this.handleOptionAndParams2(params, 'watchOrderBook', 'watchOrderBookForSymbols', 'bookSubscriptionType', 'SNAPSHOT_AND_UPDATE');
109
+ if (bookSubscriptionType !== undefined) {
110
+ params['params']['bookSubscriptionType'] = bookSubscriptionType;
111
+ }
112
+ let bookUpdateFrequency = undefined;
113
+ [bookUpdateFrequency, params] = this.handleOptionAndParams2(params, 'watchOrderBook', 'watchOrderBookForSymbols', 'bookUpdateFrequency');
114
+ if (bookUpdateFrequency !== undefined) {
115
+ params['params']['bookSubscriptionType'] = bookSubscriptionType;
98
116
  }
99
117
  for (let i = 0; i < symbols.length; i++) {
100
118
  const symbol = symbols[i];
101
119
  const market = this.market(symbol);
102
- const currentTopic = 'book' + '.' + market['id'] + '.' + limit;
120
+ const currentTopic = 'book' + '.' + market['id'] + '.' + limit.toString();
103
121
  const messageHash = 'orderbook:' + market['symbol'];
104
122
  messageHashes.push(messageHash);
105
123
  topics.push(currentTopic);
@@ -107,27 +125,72 @@ export default class cryptocom extends cryptocomRest {
107
125
  const orderbook = await this.watchPublicMultiple(messageHashes, topics, params);
108
126
  return orderbook.limit();
109
127
  }
110
- handleOrderBookSnapshot(client, message) {
111
- // full snapshot
128
+ handleDelta(bookside, delta) {
129
+ const price = this.safeFloat(delta, 0);
130
+ const amount = this.safeFloat(delta, 1);
131
+ const count = this.safeInteger(delta, 2);
132
+ bookside.store(price, amount, count);
133
+ }
134
+ handleDeltas(bookside, deltas) {
135
+ for (let i = 0; i < deltas.length; i++) {
136
+ this.handleDelta(bookside, deltas[i]);
137
+ }
138
+ }
139
+ handleOrderBook(client, message) {
112
140
  //
113
- // {
114
- // "instrument_name":"LTC_USDT",
115
- // "subscription":"book.LTC_USDT.150",
116
- // "channel":"book",
117
- // "depth":150,
118
- // "data": [
119
- // {
120
- // "bids": [
121
- // [122.21, 0.74041, 4]
122
- // ],
123
- // "asks": [
124
- // [122.29, 0.00002, 1]
125
- // ]
126
- // "t": 1648123943803,
127
- // "s":754560122
128
- // }
129
- // ]
130
- // }
141
+ // snapshot
142
+ // {
143
+ // "instrument_name":"LTC_USDT",
144
+ // "subscription":"book.LTC_USDT.150",
145
+ // "channel":"book",
146
+ // "depth":150,
147
+ // "data": [
148
+ // {
149
+ // "bids": [
150
+ // [122.21, 0.74041, 4]
151
+ // ],
152
+ // "asks": [
153
+ // [122.29, 0.00002, 1]
154
+ // ]
155
+ // "t": 1648123943803,
156
+ // "s":754560122
157
+ // }
158
+ // ]
159
+ // }
160
+ // update
161
+ // {
162
+ // "instrument_name":"BTC_USDT",
163
+ // "subscription":"book.BTC_USDT.50",
164
+ // "channel":"book.update",
165
+ // "depth":50,
166
+ // "data":[
167
+ // {
168
+ // "update":{
169
+ // "asks":[
170
+ // [
171
+ // "43755.46",
172
+ // "0.10000",
173
+ // "1"
174
+ // ],
175
+ // ...
176
+ // ],
177
+ // "bids":[
178
+ // [
179
+ // "43737.46",
180
+ // "0.14096",
181
+ // "1"
182
+ // ],
183
+ // ...
184
+ // ]
185
+ // },
186
+ // "t":1704484068898,
187
+ // "tt":1704484068892,
188
+ // "u":78795598253024,
189
+ // "pu":78795598162080,
190
+ // "cs":-781431132
191
+ // }
192
+ // ]
193
+ // }
131
194
  //
132
195
  const marketId = this.safeString(message, 'instrument_name');
133
196
  const market = this.safeMarket(marketId);
@@ -135,14 +198,32 @@ export default class cryptocom extends cryptocomRest {
135
198
  let data = this.safeValue(message, 'data');
136
199
  data = this.safeValue(data, 0);
137
200
  const timestamp = this.safeInteger(data, 't');
138
- const snapshot = this.parseOrderBook(data, symbol, timestamp);
139
- snapshot['nonce'] = this.safeInteger(data, 's');
140
201
  let orderbook = this.safeValue(this.orderbooks, symbol);
141
202
  if (orderbook === undefined) {
142
203
  const limit = this.safeInteger(message, 'depth');
143
- orderbook = this.orderBook({}, limit);
204
+ orderbook = this.countedOrderBook({}, limit);
144
205
  }
145
- orderbook.reset(snapshot);
206
+ const channel = this.safeString(message, 'channel');
207
+ const nonce = this.safeInteger2(data, 'u', 's');
208
+ let books = data;
209
+ if (channel === 'book') { // snapshot
210
+ orderbook.reset({});
211
+ orderbook['symbol'] = symbol;
212
+ orderbook['timestamp'] = timestamp;
213
+ orderbook['datetime'] = this.iso8601(timestamp);
214
+ orderbook['nonce'] = nonce;
215
+ }
216
+ else {
217
+ books = this.safeValue(data, 'update', {});
218
+ const previousNonce = this.safeInteger(data, 'pu');
219
+ const currentNonce = orderbook['nonce'];
220
+ if (currentNonce !== previousNonce) {
221
+ throw new InvalidNonce(this.id + ' watchOrderBook() ' + symbol + ' ' + previousNonce + ' != ' + nonce);
222
+ }
223
+ }
224
+ this.handleDeltas(orderbook['asks'], this.safeValue(books, 'asks', []));
225
+ this.handleDeltas(orderbook['bids'], this.safeValue(books, 'bids', []));
226
+ orderbook['nonce'] = nonce;
146
227
  this.orderbooks[symbol] = orderbook;
147
228
  const messageHash = 'orderbook:' + symbol;
148
229
  client.resolve(orderbook, messageHash);
@@ -764,7 +845,7 @@ export default class cryptocom extends cryptocomRest {
764
845
  },
765
846
  'nonce': id,
766
847
  };
767
- const message = this.extend(request, params);
848
+ const message = this.deepExtend(request, params);
768
849
  return await this.watchMultiple(url, messageHashes, message, messageHashes);
769
850
  }
770
851
  async watchPrivateRequest(nonce, params = {}) {
@@ -831,7 +912,8 @@ export default class cryptocom extends cryptocomRest {
831
912
  'candlestick': this.handleOHLCV,
832
913
  'ticker': this.handleTicker,
833
914
  'trade': this.handleTrades,
834
- 'book': this.handleOrderBookSnapshot,
915
+ 'book': this.handleOrderBook,
916
+ 'book.update': this.handleOrderBook,
835
917
  'user.order': this.handleOrders,
836
918
  'user.trade': this.handleTrades,
837
919
  'user.balance': this.handleBalance,
@@ -1,5 +1,5 @@
1
1
  import lunoRest from '../luno.js';
2
- import type { Int, Trade, OrderBook } from '../base/types.js';
2
+ import type { Int, Trade, OrderBook, IndexType } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class luno extends lunoRest {
5
5
  describe(): any;
@@ -8,7 +8,7 @@ export default class luno extends lunoRest {
8
8
  parseTrade(trade: any, market?: any): Trade;
9
9
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
10
10
  handleOrderBook(client: Client, message: any, subscription: any): void;
11
- customParseOrderBook(orderbook: any, symbol: any, timestamp?: any, bidsKey?: string, asksKey?: string, priceKey?: string, amountKey?: string, thirdKey?: any): {
11
+ customParseOrderBook(orderbook: any, symbol: any, timestamp?: any, bidsKey?: string, asksKey?: IndexType, priceKey?: IndexType, amountKey?: IndexType, countOrIdKey?: IndexType): {
12
12
  symbol: any;
13
13
  bids: any;
14
14
  asks: any;
@@ -16,8 +16,8 @@ export default class luno extends lunoRest {
16
16
  datetime: string;
17
17
  nonce: any;
18
18
  };
19
- parseBidsAsks(bidasks: any, priceKey?: string, amountKey?: string, thirdKey?: any): any[];
20
- customParseBidAsk(bidask: any, priceKey?: string, amountKey?: string, thirdKey?: any): number[];
19
+ parseBidsAsks(bidasks: any, priceKey?: IndexType, amountKey?: IndexType, thirdKey?: IndexType): any[];
20
+ customParseBidAsk(bidask: any, priceKey?: IndexType, amountKey?: IndexType, thirdKey?: IndexType): number[];
21
21
  handleDelta(orderbook: any, message: any): any;
22
22
  handleMessage(client: Client, message: any): any;
23
23
  }
@@ -213,9 +213,9 @@ export default class luno extends lunoRest {
213
213
  storedOrderBook['nonce'] = nonce;
214
214
  client.resolve(storedOrderBook, messageHash);
215
215
  }
216
- customParseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 'price', amountKey = 'volume', thirdKey = undefined) {
217
- const bids = this.parseBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey, thirdKey);
218
- const asks = this.parseBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey, thirdKey);
216
+ customParseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 'price', amountKey = 'volume', countOrIdKey = 2) {
217
+ const bids = this.parseBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey, countOrIdKey);
218
+ const asks = this.parseBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey, countOrIdKey);
219
219
  return {
220
220
  'symbol': symbol,
221
221
  'bids': this.sortBy(bids, 0, true),
@@ -225,7 +225,7 @@ export default class luno extends lunoRest {
225
225
  'nonce': undefined,
226
226
  };
227
227
  }
228
- parseBidsAsks(bidasks, priceKey = 'price', amountKey = 'volume', thirdKey = undefined) {
228
+ parseBidsAsks(bidasks, priceKey = 'price', amountKey = 'volume', thirdKey = 2) {
229
229
  bidasks = this.toArray(bidasks);
230
230
  const result = [];
231
231
  for (let i = 0; i < bidasks.length; i++) {
@@ -233,7 +233,7 @@ export default class luno extends lunoRest {
233
233
  }
234
234
  return result;
235
235
  }
236
- customParseBidAsk(bidask, priceKey = 'price', amountKey = 'volume', thirdKey = undefined) {
236
+ customParseBidAsk(bidask, priceKey = 'price', amountKey = 'volume', thirdKey = 2) {
237
237
  const price = this.safeNumber(bidask, priceKey);
238
238
  const amount = this.safeNumber(bidask, amountKey);
239
239
  const result = [price, amount];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.2.9",
3
+ "version": "4.2.10",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",