ccxt 4.5.2 → 4.5.4

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 (66) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +78 -5
  5. package/dist/cjs/src/base/functions/encode.js +8 -0
  6. package/dist/cjs/src/base/functions/rsa.js +14 -1
  7. package/dist/cjs/src/base/functions.js +1 -0
  8. package/dist/cjs/src/binance.js +12 -15
  9. package/dist/cjs/src/bitget.js +1 -1
  10. package/dist/cjs/src/bitvavo.js +8 -0
  11. package/dist/cjs/src/bybit.js +20 -6
  12. package/dist/cjs/src/coinbase.js +28 -10
  13. package/dist/cjs/src/coincatch.js +34 -21
  14. package/dist/cjs/src/delta.js +1 -0
  15. package/dist/cjs/src/gate.js +27 -12
  16. package/dist/cjs/src/gemini.js +3 -3
  17. package/dist/cjs/src/htx.js +4 -4
  18. package/dist/cjs/src/kucoinfutures.js +11 -10
  19. package/dist/cjs/src/mexc.js +30 -1
  20. package/dist/cjs/src/okx.js +19 -4
  21. package/dist/cjs/src/pro/binance.js +3 -3
  22. package/dist/cjs/src/pro/bitfinex.js +140 -0
  23. package/dist/cjs/src/pro/bitget.js +168 -26
  24. package/dist/cjs/src/pro/bybit.js +67 -11
  25. package/dist/cjs/src/pro/coinex.js +10 -11
  26. package/dist/cjs/src/pro/kucoin.js +64 -0
  27. package/dist/cjs/src/pro/mexc.js +7 -3
  28. package/js/ccxt.d.ts +1 -1
  29. package/js/ccxt.js +1 -1
  30. package/js/src/abstract/myokx.d.ts +1 -0
  31. package/js/src/abstract/okx.d.ts +1 -0
  32. package/js/src/abstract/okxus.d.ts +1 -0
  33. package/js/src/base/Exchange.d.ts +6 -0
  34. package/js/src/base/Exchange.js +78 -5
  35. package/js/src/base/functions/encode.d.ts +2 -1
  36. package/js/src/base/functions/encode.js +8 -1
  37. package/js/src/base/functions/rsa.js +16 -3
  38. package/js/src/binance.js +12 -15
  39. package/js/src/bitget.js +1 -1
  40. package/js/src/bitvavo.js +8 -0
  41. package/js/src/bybit.js +20 -6
  42. package/js/src/coinbase.d.ts +1 -1
  43. package/js/src/coinbase.js +28 -10
  44. package/js/src/coincatch.d.ts +2 -0
  45. package/js/src/coincatch.js +34 -21
  46. package/js/src/delta.js +1 -0
  47. package/js/src/gate.js +27 -12
  48. package/js/src/gemini.js +3 -3
  49. package/js/src/htx.js +4 -4
  50. package/js/src/kucoinfutures.js +11 -10
  51. package/js/src/mexc.d.ts +3 -0
  52. package/js/src/mexc.js +30 -1
  53. package/js/src/okx.d.ts +4 -2
  54. package/js/src/okx.js +19 -4
  55. package/js/src/pro/binance.js +3 -3
  56. package/js/src/pro/bitfinex.d.ts +30 -0
  57. package/js/src/pro/bitfinex.js +140 -0
  58. package/js/src/pro/bitget.d.ts +9 -1
  59. package/js/src/pro/bitget.js +168 -26
  60. package/js/src/pro/bybit.d.ts +6 -2
  61. package/js/src/pro/bybit.js +67 -11
  62. package/js/src/pro/coinex.js +11 -12
  63. package/js/src/pro/kucoin.d.ts +22 -0
  64. package/js/src/pro/kucoin.js +64 -0
  65. package/js/src/pro/mexc.js +7 -3
  66. package/package.json +3 -3
@@ -31,6 +31,11 @@ class kucoin extends kucoin$1["default"] {
31
31
  'watchOrderBookForSymbols': true,
32
32
  'watchBalance': true,
33
33
  'watchOHLCV': true,
34
+ 'unWatchTicker': true,
35
+ 'unWatchOHLCV': true,
36
+ 'unWatchOrderBook': true,
37
+ 'unWatchTrades': true,
38
+ 'unWatchhTradesForSymbols': true,
34
39
  },
35
40
  'options': {
36
41
  'tradesLimit': 1000,
@@ -138,6 +143,9 @@ class kucoin extends kucoin$1["default"] {
138
143
  }
139
144
  return await this.watch(url, messageHash, message, subscriptionHash, subscription);
140
145
  }
146
+ async unSubscribe(url, messageHash, topic, subscriptionHash, params = {}, subscription = undefined) {
147
+ return await this.unSubscribeMultiple(url, [messageHash], topic, [subscriptionHash], params, subscription);
148
+ }
141
149
  async subscribeMultiple(url, messageHashes, topic, subscriptionHashes, params = {}, subscription = undefined) {
142
150
  const requestId = this.requestId().toString();
143
151
  const request = {
@@ -196,6 +204,34 @@ class kucoin extends kucoin$1["default"] {
196
204
  const messageHash = 'ticker:' + symbol;
197
205
  return await this.subscribe(url, messageHash, topic, query);
198
206
  }
207
+ /**
208
+ * @method
209
+ * @name kucoin#unWatchTicker
210
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
211
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/market-snapshot
212
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
213
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
214
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
215
+ */
216
+ async unWatchTicker(symbol, params = {}) {
217
+ await this.loadMarkets();
218
+ const market = this.market(symbol);
219
+ symbol = market['symbol'];
220
+ const url = await this.negotiate(false);
221
+ let method = undefined;
222
+ [method, params] = this.handleOptionAndParams(params, 'watchTicker', 'method', '/market/snapshot');
223
+ const topic = method + ':' + market['id'];
224
+ const messageHash = 'unsubscribe:ticker:' + symbol;
225
+ const subMessageHash = 'ticker:' + symbol;
226
+ const subscription = {
227
+ 'messageHashes': [messageHash],
228
+ 'subMessageHashes': [subMessageHash],
229
+ 'topic': 'trades',
230
+ 'unsubscribe': true,
231
+ 'symbols': [symbol],
232
+ };
233
+ return await this.unSubscribe(url, messageHash, topic, subMessageHash, params, subscription);
234
+ }
199
235
  /**
200
236
  * @method
201
237
  * @name kucoin#watchTickers
@@ -436,6 +472,34 @@ class kucoin extends kucoin$1["default"] {
436
472
  }
437
473
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
438
474
  }
475
+ /**
476
+ * @method
477
+ * @name kucoin#unWatchOHLCV
478
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
479
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/klines
480
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
481
+ * @param {string} timeframe the length of time each candle represents
482
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
483
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
484
+ */
485
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
486
+ await this.loadMarkets();
487
+ const url = await this.negotiate(false);
488
+ const market = this.market(symbol);
489
+ symbol = market['symbol'];
490
+ const period = this.safeString(this.timeframes, timeframe, timeframe);
491
+ const topic = '/market/candles:' + market['id'] + '_' + period;
492
+ const messageHash = 'unsubscribe:candles:' + symbol + ':' + timeframe;
493
+ const subMessageHash = 'candles:' + symbol + ':' + timeframe;
494
+ const subscription = {
495
+ 'messageHashes': [messageHash],
496
+ 'subMessageHashes': [subMessageHash],
497
+ 'topic': 'ohlcv',
498
+ 'unsubscribe': true,
499
+ 'symbols': [symbol],
500
+ };
501
+ return await this.unSubscribe(url, messageHash, topic, messageHash, params, subscription);
502
+ }
439
503
  handleOHLCV(client, message) {
440
504
  //
441
505
  // {
@@ -176,7 +176,7 @@ class mexc extends mexc$1["default"] {
176
176
  this.handleBidAsk(client, message);
177
177
  const rawTicker = this.safeDictN(message, ['d', 'data', 'publicAggreBookTicker']);
178
178
  const marketId = this.safeString2(message, 's', 'symbol');
179
- const timestamp = this.safeInteger2(message, 't', 'sendtime');
179
+ const timestamp = this.safeInteger2(message, 't', 'sendTime');
180
180
  const market = this.safeMarket(marketId);
181
181
  const symbol = market['symbol'];
182
182
  let ticker = undefined;
@@ -1532,7 +1532,7 @@ class mexc extends mexc$1["default"] {
1532
1532
  // "ts": 1680059188190
1533
1533
  // }
1534
1534
  //
1535
- const c = this.safeString2(message, 'c', 'channel');
1535
+ const c = this.safeString(message, 'c'); // do not add 'channel' here, this is especially for spot
1536
1536
  const type = (c === undefined) ? 'swap' : 'spot';
1537
1537
  const messageHash = 'balance:' + type;
1538
1538
  const data = this.safeDictN(message, ['d', 'data', 'privateAccount']);
@@ -1547,7 +1547,11 @@ class mexc extends mexc$1["default"] {
1547
1547
  const currencyId = this.safeStringN(data, ['a', 'currency', 'vcoinName']);
1548
1548
  const code = this.safeCurrencyCode(currencyId);
1549
1549
  const account = this.account();
1550
- account['total'] = this.safeStringN(data, ['f', 'availableBalance', 'balanceAmount']);
1550
+ const balanceAmount = this.safeString(data, 'balanceAmount');
1551
+ if (balanceAmount !== undefined) {
1552
+ account['free'] = balanceAmount;
1553
+ }
1554
+ account['total'] = this.safeStringN(data, ['f', 'availableBalance']);
1551
1555
  account['used'] = this.safeStringN(data, ['l', 'frozenBalance', 'frozenAmount']);
1552
1556
  this.balance[type][code] = account;
1553
1557
  this.balance[type] = this.safeBalance(this.balance[type]);
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Int, int, Str, Strings, Num, Bool, IndexType, OrderSide, OrderType, MarketType, SubType, Dict, NullableDict, List, NullableList, Fee, OHLCV, OHLCVC, implicitReturnType, Market, Currency, Dictionary, MinMax, FeeInterface, TradingFeeInterface, MarketInterface, Trade, Order, OrderBook, Ticker, Transaction, Tickers, CurrencyInterface, Balance, BalanceAccount, Account, PartialBalances, Balances, DepositAddress, WithdrawalResponse, FundingRate, FundingRates, Position, BorrowInterest, LeverageTier, LedgerEntry, DepositWithdrawFeeNetwork, DepositWithdrawFee, TransferEntry, CrossBorrowRate, IsolatedBorrowRate, FundingRateHistory, OpenInterest, Liquidation, OrderRequest, CancellationRequest, FundingHistory, MarketMarginModes, MarginMode, Greeks, Conversion, Option, LastPrice, Leverage, MarginModification, Leverages, LastPrices, Currencies, TradingFees, MarginModes, OptionChain, IsolatedBorrowRates, CrossBorrowRates, LeverageTiers, LongShortRatio, OrderBooks, OpenInterests, ConstructorArgs } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, RestrictedLocation, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
7
- declare const version = "4.5.1";
7
+ declare const version = "4.5.3";
8
8
  import alpaca from './src/alpaca.js';
9
9
  import apex from './src/apex.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, RestrictedLocation, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.5.1';
41
+ const version = '4.5.3';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import alpaca from './src/alpaca.js';
@@ -20,6 +20,7 @@ interface okx {
20
20
  publicGetMarketOpenOracle(params?: {}): Promise<implicitReturnType>;
21
21
  publicGetMarketExchangeRate(params?: {}): Promise<implicitReturnType>;
22
22
  publicGetMarketIndexComponents(params?: {}): Promise<implicitReturnType>;
23
+ publicGetPublicMarketDataHistory(params?: {}): Promise<implicitReturnType>;
23
24
  publicGetPublicEconomicCalendar(params?: {}): Promise<implicitReturnType>;
24
25
  publicGetMarketBlockTickers(params?: {}): Promise<implicitReturnType>;
25
26
  publicGetMarketBlockTicker(params?: {}): Promise<implicitReturnType>;
@@ -20,6 +20,7 @@ interface Exchange {
20
20
  publicGetMarketOpenOracle(params?: {}): Promise<implicitReturnType>;
21
21
  publicGetMarketExchangeRate(params?: {}): Promise<implicitReturnType>;
22
22
  publicGetMarketIndexComponents(params?: {}): Promise<implicitReturnType>;
23
+ publicGetPublicMarketDataHistory(params?: {}): Promise<implicitReturnType>;
23
24
  publicGetPublicEconomicCalendar(params?: {}): Promise<implicitReturnType>;
24
25
  publicGetMarketBlockTickers(params?: {}): Promise<implicitReturnType>;
25
26
  publicGetMarketBlockTicker(params?: {}): Promise<implicitReturnType>;
@@ -20,6 +20,7 @@ interface okx {
20
20
  publicGetMarketOpenOracle(params?: {}): Promise<implicitReturnType>;
21
21
  publicGetMarketExchangeRate(params?: {}): Promise<implicitReturnType>;
22
22
  publicGetMarketIndexComponents(params?: {}): Promise<implicitReturnType>;
23
+ publicGetPublicMarketDataHistory(params?: {}): Promise<implicitReturnType>;
23
24
  publicGetPublicEconomicCalendar(params?: {}): Promise<implicitReturnType>;
24
25
  publicGetMarketBlockTickers(params?: {}): Promise<implicitReturnType>;
25
26
  publicGetMarketBlockTicker(params?: {}): Promise<implicitReturnType>;
@@ -461,6 +461,7 @@ export default class Exchange {
461
461
  watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
462
462
  unWatchOrderBookForSymbols(symbols: string[], params?: {}): Promise<any>;
463
463
  unWatchPositions(symbols?: Strings, params?: {}): Promise<any>;
464
+ unWatchTicker(symbol: string, params?: {}): Promise<any>;
464
465
  fetchDepositAddresses(codes?: Strings, params?: {}): Promise<DepositAddress[]>;
465
466
  fetchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
466
467
  fetchOrderBookWs(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
@@ -567,6 +568,7 @@ export default class Exchange {
567
568
  safeCurrencyStructure(currency: object): CurrencyInterface;
568
569
  safeMarketStructure(market?: Dict): MarketInterface;
569
570
  setMarkets(markets: any, currencies?: any): Dictionary<any>;
571
+ setMarketsFromExchange(sourceExchange: any): this;
570
572
  getDescribeForExtendedWsExchange(currentRestInstance: any, parentRestInstance: any, wsBaseDescribe: Dictionary<any>): any;
571
573
  safeBalance(balance: Dict): Balances;
572
574
  safeOrder(order: Dict, market?: Market): Order;
@@ -629,7 +631,9 @@ export default class Exchange {
629
631
  safePosition(position: Dict): Position;
630
632
  parsePositions(positions: any[], symbols?: string[], params?: {}): Position[];
631
633
  parseAccounts(accounts: any[], params?: {}): Account[];
634
+ parseTradesHelper(isWs: boolean, trades: any[], market?: Market, since?: Int, limit?: Int, params?: {}): Trade[];
632
635
  parseTrades(trades: any[], market?: Market, since?: Int, limit?: Int, params?: {}): Trade[];
636
+ parseWsTrades(trades: any[], market?: Market, since?: Int, limit?: Int, params?: {}): Trade[];
633
637
  parseTransactions(transactions: any[], currency?: Currency, since?: Int, limit?: Int, params?: {}): Transaction[];
634
638
  parseTransfers(transfers: any[], currency?: Currency, since?: Int, limit?: Int, params?: {}): TransferEntry[];
635
639
  parseLedger(data: any, currency?: Currency, since?: Int, limit?: Int, params?: {}): LedgerEntry[];
@@ -684,6 +688,7 @@ export default class Exchange {
684
688
  parseBidAsk(bidask: any, priceKey?: IndexType, amountKey?: IndexType, countOrIdKey?: IndexType): number[];
685
689
  safeCurrency(currencyId: Str, currency?: Currency): CurrencyInterface;
686
690
  safeMarket(marketId?: Str, market?: Market, delimiter?: Str, marketType?: Str): MarketInterface;
691
+ marketOrNull(symbol: string): MarketInterface;
687
692
  checkRequiredCredentials(error?: boolean): boolean;
688
693
  oath(): string;
689
694
  fetchBalance(params?: {}): Promise<Balances>;
@@ -854,6 +859,7 @@ export default class Exchange {
854
859
  parseFundingRates(response: any, symbols?: Strings): FundingRates;
855
860
  parseLongShortRatio(info: Dict, market?: Market): LongShortRatio;
856
861
  parseLongShortRatioHistory(response: any, market?: any, since?: Int, limit?: Int): LongShortRatio[];
862
+ handleTriggerPricesAndParams(symbol: any, params: any, omitParams?: boolean): any[];
857
863
  handleTriggerDirectionAndParams(params: any, exchangeSpecificKey?: Str, allowEmpty?: Bool): any[];
858
864
  handleTriggerAndParams(params: any): any[];
859
865
  isTriggerOrder(params: any): any[];
@@ -1145,6 +1145,7 @@ export default class Exchange {
1145
1145
  }
1146
1146
  async close() {
1147
1147
  // test by running ts/src/pro/test/base/test.close.ts
1148
+ await this.sleep(0); // allow other futures to run
1148
1149
  const clients = Object.values(this.clients || {});
1149
1150
  const closedClients = [];
1150
1151
  for (let i = 0; i < clients.length; i++) {
@@ -1183,6 +1184,7 @@ export default class Exchange {
1183
1184
  }
1184
1185
  client.reject(new ExchangeError(this.id + ' nonce is behind the cache after ' + maxRetries.toString() + ' tries.'), messageHash);
1185
1186
  delete this.clients[client.url];
1187
+ this.orderbooks[symbol] = this.orderBook(); // clear the orderbook and its cache - issue https://github.com/ccxt/ccxt/issues/26753
1186
1188
  }
1187
1189
  catch (e) {
1188
1190
  client.reject(e, messageHash);
@@ -2194,6 +2196,9 @@ export default class Exchange {
2194
2196
  async unWatchPositions(symbols = undefined, params = {}) {
2195
2197
  throw new NotSupported(this.id + ' unWatchPositions() is not supported yet');
2196
2198
  }
2199
+ async unWatchTicker(symbol, params = {}) {
2200
+ throw new NotSupported(this.id + ' unWatchTicker() is not supported yet');
2201
+ }
2197
2202
  async fetchDepositAddresses(codes = undefined, params = {}) {
2198
2203
  throw new NotSupported(this.id + ' fetchDepositAddresses() is not supported yet');
2199
2204
  }
@@ -2427,9 +2432,9 @@ export default class Exchange {
2427
2432
  parseToNumeric(number) {
2428
2433
  const stringVersion = this.numberToString(number); // this will convert 1.0 and 1 to "1" and 1.1 to "1.1"
2429
2434
  // keep this in mind:
2430
- // in JS: 1 == 1.0 is true; 1 === 1.0 is true
2435
+ // in JS: 1 === 1.0 is true
2431
2436
  // in Python: 1 == 1.0 is true
2432
- // in PHP 1 == 1.0 is true, but 1 === 1.0 is false.
2437
+ // in PHP: 1 == 1.0 is true, but 1 === 1.0 is false.
2433
2438
  if (stringVersion.indexOf('.') >= 0) {
2434
2439
  return parseFloat(stringVersion);
2435
2440
  }
@@ -2944,6 +2949,26 @@ export default class Exchange {
2944
2949
  this.codes = Object.keys(currenciesSortedByCode);
2945
2950
  return this.markets;
2946
2951
  }
2952
+ setMarketsFromExchange(sourceExchange) {
2953
+ // Validate that both exchanges are of the same type
2954
+ if (this.id !== sourceExchange.id) {
2955
+ throw new ArgumentsRequired(this.id + ' shareMarkets() can only share markets with exchanges of the same type (got ' + sourceExchange['id'] + ')');
2956
+ }
2957
+ // Validate that source exchange has loaded markets
2958
+ if (!sourceExchange.markets) {
2959
+ throw new ExchangeError('setMarketsFromExchange() source exchange must have loaded markets first. Can call by using loadMarkets function');
2960
+ }
2961
+ // Set all market-related data
2962
+ this.markets = sourceExchange.markets;
2963
+ this.markets_by_id = sourceExchange.markets_by_id;
2964
+ this.symbols = sourceExchange.symbols;
2965
+ this.ids = sourceExchange.ids;
2966
+ this.currencies = sourceExchange.currencies;
2967
+ this.baseCurrencies = sourceExchange.baseCurrencies;
2968
+ this.quoteCurrencies = sourceExchange.quoteCurrencies;
2969
+ this.codes = sourceExchange.codes;
2970
+ return this;
2971
+ }
2947
2972
  getDescribeForExtendedWsExchange(currentRestInstance, parentRestInstance, wsBaseDescribe) {
2948
2973
  const extendedRestDescribe = this.deepExtend(parentRestInstance.describe(), currentRestInstance.describe());
2949
2974
  const superWithRestDescribe = this.deepExtend(extendedRestDescribe, wsBaseDescribe);
@@ -4222,17 +4247,30 @@ export default class Exchange {
4222
4247
  }
4223
4248
  return result;
4224
4249
  }
4225
- parseTrades(trades, market = undefined, since = undefined, limit = undefined, params = {}) {
4250
+ parseTradesHelper(isWs, trades, market = undefined, since = undefined, limit = undefined, params = {}) {
4226
4251
  trades = this.toArray(trades);
4227
4252
  let result = [];
4228
4253
  for (let i = 0; i < trades.length; i++) {
4229
- const trade = this.extend(this.parseTrade(trades[i], market), params);
4254
+ let parsed = undefined;
4255
+ if (isWs) {
4256
+ parsed = this.parseWsTrade(trades[i], market);
4257
+ }
4258
+ else {
4259
+ parsed = this.parseTrade(trades[i], market);
4260
+ }
4261
+ const trade = this.extend(parsed, params);
4230
4262
  result.push(trade);
4231
4263
  }
4232
4264
  result = this.sortBy2(result, 'timestamp', 'id');
4233
4265
  const symbol = (market !== undefined) ? market['symbol'] : undefined;
4234
4266
  return this.filterBySymbolSinceLimit(result, symbol, since, limit);
4235
4267
  }
4268
+ parseTrades(trades, market = undefined, since = undefined, limit = undefined, params = {}) {
4269
+ return this.parseTradesHelper(false, trades, market, since, limit, params);
4270
+ }
4271
+ parseWsTrades(trades, market = undefined, since = undefined, limit = undefined, params = {}) {
4272
+ return this.parseTradesHelper(true, trades, market, since, limit, params);
4273
+ }
4236
4274
  parseTransactions(transactions, currency = undefined, since = undefined, limit = undefined, params = {}) {
4237
4275
  transactions = this.toArray(transactions);
4238
4276
  let result = [];
@@ -4683,6 +4721,12 @@ export default class Exchange {
4683
4721
  }
4684
4722
  return result;
4685
4723
  }
4724
+ marketOrNull(symbol) {
4725
+ if (symbol === undefined) {
4726
+ return undefined;
4727
+ }
4728
+ return this.market(symbol);
4729
+ }
4686
4730
  checkRequiredCredentials(error = true) {
4687
4731
  /**
4688
4732
  * @ignore
@@ -6182,6 +6226,35 @@ export default class Exchange {
6182
6226
  const symbol = (market === undefined) ? undefined : market['symbol'];
6183
6227
  return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
6184
6228
  }
6229
+ handleTriggerPricesAndParams(symbol, params, omitParams = true) {
6230
+ //
6231
+ const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
6232
+ let triggerPriceStr = undefined;
6233
+ const stopLossPrice = this.safeString(params, 'stopLossPrice');
6234
+ let stopLossPriceStr = undefined;
6235
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
6236
+ let takeProfitPriceStr = undefined;
6237
+ //
6238
+ if (triggerPrice !== undefined) {
6239
+ if (omitParams) {
6240
+ params = this.omit(params, ['triggerPrice', 'stopPrice']);
6241
+ }
6242
+ triggerPriceStr = this.priceToPrecision(symbol, parseFloat(triggerPrice));
6243
+ }
6244
+ if (stopLossPrice !== undefined) {
6245
+ if (omitParams) {
6246
+ params = this.omit(params, 'stopLossPrice');
6247
+ }
6248
+ stopLossPriceStr = this.priceToPrecision(symbol, parseFloat(stopLossPrice));
6249
+ }
6250
+ if (takeProfitPrice !== undefined) {
6251
+ if (omitParams) {
6252
+ params = this.omit(params, 'takeProfitPrice');
6253
+ }
6254
+ takeProfitPriceStr = this.priceToPrecision(symbol, parseFloat(takeProfitPrice));
6255
+ }
6256
+ return [triggerPriceStr, stopLossPriceStr, takeProfitPriceStr, params];
6257
+ }
6185
6258
  handleTriggerDirectionAndParams(params, exchangeSpecificKey = undefined, allowEmpty = false) {
6186
6259
  /**
6187
6260
  * @ignore
@@ -7378,7 +7451,7 @@ export default class Exchange {
7378
7451
  const clients = Object.values(this.clients);
7379
7452
  for (let i = 0; i < clients.length; i++) {
7380
7453
  const client = clients[i];
7381
- const futures = this.safeDict(client, 'futures');
7454
+ const futures = client.futures;
7382
7455
  if ((futures !== undefined) && ('fetchPositionsSnapshot' in futures)) {
7383
7456
  delete futures['fetchPositionsSnapshot'];
7384
7457
  }
@@ -1,4 +1,5 @@
1
1
  import { concatBytes } from '../../static_dependencies/noble-curves/abstract/utils.js';
2
2
  declare const json: (data: any, params?: any) => string, isJsonEncodedObject: (object: any) => boolean, binaryToString: (data: Uint8Array) => string, stringToBinary: (str: string) => Uint8Array, stringToBase64: (string: string) => string, base64ToString: (string: string) => string, base64ToBinary: (str: string) => Uint8Array, binaryToBase64: (data: Uint8Array) => string, base16ToBinary: (str: string) => Uint8Array, binaryToBase16: (data: Uint8Array) => string, base58ToBinary: (str: string) => Uint8Array, binaryToBase58: (data: Uint8Array) => string, binaryConcat: typeof concatBytes, binaryConcatArray: (arr: any[]) => Uint8Array, urlencode: (object: object, sort?: boolean) => string, urlencodeNested: (object: object) => string, urlencodeWithArrayRepeat: (object: object) => string, rawencode: (object: object, sort?: boolean) => string, encode: (str: string) => Uint8Array, decode: (data: Uint8Array) => string, urlencodeBase64: (payload: string | Uint8Array) => string, numberToLE: (n: number, padding: number) => Uint8Array, numberToBE: (n: number, padding: number) => Uint8Array;
3
3
  declare function packb(req: any): Uint8Array;
4
- export { json, isJsonEncodedObject, binaryToString, stringToBinary, stringToBase64, base64ToBinary, base64ToString, binaryToBase64, base16ToBinary, binaryToBase16, binaryConcat, binaryConcatArray, urlencode, urlencodeWithArrayRepeat, rawencode, encode, decode, urlencodeBase64, numberToLE, numberToBE, base58ToBinary, binaryToBase58, urlencodeNested, packb };
4
+ declare function base64ToBase64Url(base64: string, stripPadding?: boolean): string;
5
+ export { json, isJsonEncodedObject, binaryToString, stringToBinary, stringToBase64, base64ToBinary, base64ToString, binaryToBase64, base16ToBinary, binaryToBase16, binaryConcat, binaryConcatArray, base64ToBase64Url, urlencode, urlencodeWithArrayRepeat, rawencode, encode, decode, urlencodeBase64, numberToLE, numberToBE, base58ToBinary, binaryToBase58, urlencodeNested, packb };
@@ -26,7 +26,14 @@ const json = (data, params = undefined) => JSON.stringify(data), isJsonEncodedOb
26
26
  function packb(req) {
27
27
  return serialize(req);
28
28
  }
29
- export { json, isJsonEncodedObject, binaryToString, stringToBinary, stringToBase64, base64ToBinary, base64ToString, binaryToBase64, base16ToBinary, binaryToBase16, binaryConcat, binaryConcatArray, urlencode, urlencodeWithArrayRepeat, rawencode, encode, decode
29
+ function base64ToBase64Url(base64, stripPadding = true) {
30
+ let base64url = base64.replace(/\+/g, "-").replace(/\//g, "_");
31
+ if (stripPadding) {
32
+ base64url = base64url.replace(/=+$/, "");
33
+ }
34
+ return base64url;
35
+ }
36
+ export { json, isJsonEncodedObject, binaryToString, stringToBinary, stringToBase64, base64ToBinary, base64ToString, binaryToBase64, base16ToBinary, binaryToBase16, binaryConcat, binaryConcatArray, base64ToBase64Url, urlencode, urlencodeWithArrayRepeat, rawencode, encode, decode
30
37
  // Url-safe-base64 without equals signs, with + replaced by - and slashes replaced by underscores
31
38
  , urlencodeBase64, numberToLE, numberToBE, base58ToBinary, binaryToBase58, urlencodeNested, packb };
32
39
  /* ------------------------------------------------------------------------ */
@@ -6,10 +6,11 @@
6
6
 
7
7
  import { JSEncrypt } from "../../static_dependencies/jsencrypt/JSEncrypt.js";
8
8
  import { base16, utf8 } from '../../static_dependencies/scure-base/index.js';
9
- import { urlencodeBase64, base16ToBinary, base64ToBinary } from './encode.js';
10
- import { hmac } from './crypto.js';
9
+ import { urlencodeBase64, base16ToBinary, base64ToBinary, base64ToBase64Url } from './encode.js';
10
+ import { eddsa, hmac } from './crypto.js';
11
11
  import { P256 } from '../../static_dependencies/noble-curves/p256.js';
12
12
  import { ecdsa } from '../../base/functions/crypto.js';
13
+ import { ed25519 } from "../../static_dependencies/noble-curves/ed25519.js";
13
14
  function rsa(request, secret, hash) {
14
15
  const RSA = new JSEncrypt();
15
16
  const digester = (input) => base16.encode(hash(input));
@@ -29,7 +30,7 @@ function jwt(request, secret, hash, isRSA = false, opts = {}) {
29
30
  }
30
31
  const encodedHeader = urlencodeBase64(JSON.stringify(header));
31
32
  const encodedData = urlencodeBase64(JSON.stringify(request));
32
- const token = [encodedHeader, encodedData].join('.');
33
+ let token = [encodedHeader, encodedData].join('.');
33
34
  const algoType = alg.slice(0, 2);
34
35
  let signature = undefined;
35
36
  if (algoType === 'HS') {
@@ -44,6 +45,18 @@ function jwt(request, secret, hash, isRSA = false, opts = {}) {
44
45
  const s = signedHash.s.padStart(64, '0');
45
46
  signature = urlencodeBase64(base16ToBinary(r + s));
46
47
  }
48
+ else if (algoType === 'ED') {
49
+ const base64str = eddsa(toHex(token), secret, ed25519);
50
+ // we need urlencoded64 not base64
51
+ signature = base64ToBase64Url(base64str);
52
+ }
47
53
  return [token, signature].join('.');
48
54
  }
55
+ function toHex(str) {
56
+ var result = '';
57
+ for (var i = 0; i < str.length; i++) {
58
+ result += str.charCodeAt(i).toString(16);
59
+ }
60
+ return result;
61
+ }
49
62
  export { rsa, jwt };
package/js/src/binance.js CHANGED
@@ -6612,19 +6612,13 @@ export default class binance extends Exchange {
6612
6612
  }
6613
6613
  }
6614
6614
  if (quantityIsRequired) {
6615
- // portfolio margin has a different amount precision
6616
- if (isPortfolioMargin) {
6617
- request['quantity'] = this.parseToNumeric(amount);
6615
+ const marketAmountPrecision = this.safeString(market['precision'], 'amount');
6616
+ const isPrecisionAvailable = (marketAmountPrecision !== undefined);
6617
+ if (isPrecisionAvailable) {
6618
+ request['quantity'] = this.amountToPrecision(symbol, amount);
6618
6619
  }
6619
6620
  else {
6620
- const marketAmountPrecision = this.safeString(market['precision'], 'amount');
6621
- const isPrecisionAvailable = (marketAmountPrecision !== undefined);
6622
- if (isPrecisionAvailable) {
6623
- request['quantity'] = this.amountToPrecision(symbol, amount);
6624
- }
6625
- else {
6626
- request['quantity'] = this.parseToNumeric(amount); // some options don't have the precision available
6627
- }
6621
+ request['quantity'] = this.parseToNumeric(amount); // some options don't have the precision available
6628
6622
  }
6629
6623
  }
6630
6624
  if (priceIsRequired && !isPriceMatch) {
@@ -11410,11 +11404,14 @@ export default class binance extends Exchange {
11410
11404
  * @returns {object} response from the exchange
11411
11405
  */
11412
11406
  async setPositionMode(hedged, symbol = undefined, params = {}) {
11413
- const defaultType = this.safeString(this.options, 'defaultType', 'future');
11414
- const type = this.safeString(params, 'type', defaultType);
11415
- params = this.omit(params, ['type']);
11407
+ let market = undefined;
11408
+ if (symbol !== undefined) {
11409
+ market = this.market(symbol);
11410
+ }
11411
+ let type = undefined;
11412
+ [type, params] = this.handleMarketTypeAndParams('setPositionMode', market, params);
11416
11413
  let subType = undefined;
11417
- [subType, params] = this.handleSubTypeAndParams('setPositionMode', undefined, params);
11414
+ [subType, params] = this.handleSubTypeAndParams('setPositionMode', market, params);
11418
11415
  let isPortfolioMargin = undefined;
11419
11416
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'setPositionMode', 'papi', 'portfolioMargin', false);
11420
11417
  let dualSidePosition = undefined;
package/js/src/bitget.js CHANGED
@@ -7709,7 +7709,7 @@ export default class bitget extends Exchange {
7709
7709
  // "requestTime": 1700802995406,
7710
7710
  // "data": [
7711
7711
  // {
7712
- // "userId": "7264631750",
7712
+ // "userId": "7264631751",
7713
7713
  // "symbol": "BTCUSDT",
7714
7714
  // "orderId": "1098394344925597696",
7715
7715
  // "tradeId": "1098394344974925824",
package/js/src/bitvavo.js CHANGED
@@ -1424,6 +1424,14 @@ export default class bitvavo extends Exchange {
1424
1424
  market = this.market(symbol);
1425
1425
  request['market'] = market['id'];
1426
1426
  }
1427
+ let operatorId = undefined;
1428
+ [operatorId, params] = this.handleOptionAndParams(params, 'cancelAllOrders', 'operatorId');
1429
+ if (operatorId !== undefined) {
1430
+ request['operatorId'] = this.parseToInt(operatorId);
1431
+ }
1432
+ else {
1433
+ throw new ArgumentsRequired(this.id + ' canceAllOrders() requires an operatorId in params or options, eg: exchange.options[\'operatorId\'] = 1234567890');
1434
+ }
1427
1435
  const response = await this.privateDeleteOrders(this.extend(request, params));
1428
1436
  //
1429
1437
  // [
package/js/src/bybit.js CHANGED
@@ -2997,17 +2997,31 @@ export default class bybit extends Exchange {
2997
2997
  // "tradeId": "0e94eaf5-b08e-5505-b43f-7f1f30b1ca80"
2998
2998
  // }
2999
2999
  //
3000
+ // watchMyTrades execution.fast
3001
+ //
3002
+ // {
3003
+ // "category": "linear",
3004
+ // "symbol": "ICPUSDT",
3005
+ // "execId": "3510f361-0add-5c7b-a2e7-9679810944fc",
3006
+ // "execPrice": "12.015",
3007
+ // "execQty": "3000",
3008
+ // "orderId": "443d63fa-b4c3-4297-b7b1-23bca88b04dc",
3009
+ // "isMaker": false,
3010
+ // "orderLinkId": "test-00001",
3011
+ // "side": "Sell",
3012
+ // "execTime": "1716800399334",
3013
+ // "seq": 34771365464
3014
+ // }
3015
+ //
3000
3016
  const id = this.safeStringN(trade, ['execId', 'id', 'tradeId']);
3001
3017
  const marketId = this.safeString(trade, 'symbol');
3002
3018
  let marketType = ('createType' in trade) ? 'contract' : 'spot';
3003
- if (market !== undefined) {
3004
- marketType = market['type'];
3005
- }
3006
3019
  const category = this.safeString(trade, 'category');
3007
3020
  if (category !== undefined) {
3008
- if (category === 'spot') {
3009
- marketType = 'spot';
3010
- }
3021
+ marketType = (category === 'spot') ? 'spot' : 'contract';
3022
+ }
3023
+ if (market !== undefined) {
3024
+ marketType = market['type'];
3011
3025
  }
3012
3026
  market = this.safeMarket(marketId, market, undefined, marketType);
3013
3027
  const symbol = market['symbol'];
@@ -611,7 +611,7 @@ export default class coinbase extends Exchange {
611
611
  */
612
612
  fetchPortfolioDetails(portfolioUuid: string, params?: {}): Promise<any[]>;
613
613
  parsePortfolioDetails(portfolioData: Dict): any[];
614
- createAuthToken(seconds: Int, method?: Str, url?: Str): string;
614
+ createAuthToken(seconds: Int, method?: Str, url?: Str, useEddsa?: boolean): string;
615
615
  nonce(): number;
616
616
  sign(path: any, api?: any[], method?: string, params?: {}, headers?: any, body?: any): {
617
617
  url: string;
@@ -5015,8 +5015,9 @@ export default class coinbase extends Exchange {
5015
5015
  }
5016
5016
  return parsedPositions;
5017
5017
  }
5018
- createAuthToken(seconds, method = undefined, url = undefined) {
5019
- // it may not work for v2
5018
+ createAuthToken(seconds, method = undefined, url = undefined, useEddsa = false) {
5019
+ // v1 https://docs.cdp.coinbase.com/api-reference/authentication#php-2
5020
+ // v2 https://docs.cdp.coinbase.com/api-reference/v2/authentication
5020
5021
  let uri = undefined;
5021
5022
  if (url !== undefined) {
5022
5023
  uri = method + ' ' + url.replace('https://', '');
@@ -5027,20 +5028,35 @@ export default class coinbase extends Exchange {
5027
5028
  uri = uri.slice(0, quesPos);
5028
5029
  }
5029
5030
  }
5031
+ // eddsa {"sub":"d2efa49a-369c-43d7-a60e-ae26e28853c2","iss":"cdp","aud":["cdp_service"],"uris":["GET api.coinbase.com/api/v3/brokerage/transaction_summary"]}
5030
5032
  const nonce = this.randomBytes(16);
5033
+ const aud = useEddsa ? 'cdp_service' : 'retail_rest_api_proxy';
5034
+ const iss = useEddsa ? 'cdp' : 'coinbase-cloud';
5031
5035
  const request = {
5032
- 'aud': ['retail_rest_api_proxy'],
5033
- 'iss': 'coinbase-cloud',
5036
+ 'aud': [aud],
5037
+ 'iss': iss,
5034
5038
  'nbf': seconds,
5035
5039
  'exp': seconds + 120,
5036
5040
  'sub': this.apiKey,
5037
5041
  'iat': seconds,
5038
5042
  };
5039
5043
  if (uri !== undefined) {
5040
- request['uri'] = uri;
5044
+ if (!useEddsa) {
5045
+ request['uri'] = uri;
5046
+ }
5047
+ else {
5048
+ request['uris'] = [uri];
5049
+ }
5050
+ }
5051
+ if (useEddsa) {
5052
+ const byteArray = this.base64ToBinary(this.secret);
5053
+ const seed = this.arraySlice(byteArray, 0, 32);
5054
+ return jwt(request, seed, sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'EdDSA' });
5055
+ }
5056
+ else {
5057
+ // ecdsa with p256
5058
+ return jwt(request, this.encode(this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
5041
5059
  }
5042
- const token = jwt(request, this.encode(this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
5043
- return token;
5044
5060
  }
5045
5061
  nonce() {
5046
5062
  return this.milliseconds() - this.options['timeDifference'];
@@ -5090,8 +5106,10 @@ export default class coinbase extends Exchange {
5090
5106
  // v2: 'GET' require payload in the signature
5091
5107
  // https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
5092
5108
  const isCloudAPiKey = (this.apiKey.indexOf('organizations/') >= 0) || (this.secret.startsWith('-----BEGIN'));
5093
- if (isCloudAPiKey) {
5094
- if (this.apiKey.startsWith('-----BEGIN')) {
5109
+ // using the size might be fragile, so we add an option to force v2 cloud api key if needed
5110
+ const isV2CloudAPiKey = this.secret.length === 88 || this.safeBool(this.options, 'v2CloudAPiKey', false) || this.secret.endsWith('=');
5111
+ if (isCloudAPiKey || isV2CloudAPiKey) {
5112
+ if (isCloudAPiKey && this.apiKey.startsWith('-----BEGIN')) {
5095
5113
  throw new ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
5096
5114
  }
5097
5115
  // // it may not work for v2
@@ -5112,7 +5130,7 @@ export default class coinbase extends Exchange {
5112
5130
  // 'uri': uri,
5113
5131
  // 'iat': seconds,
5114
5132
  // };
5115
- const token = this.createAuthToken(seconds, method, url);
5133
+ const token = this.createAuthToken(seconds, method, url, isV2CloudAPiKey);
5116
5134
  // const token = jwt (request, this.encode (this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
5117
5135
  authorizationString = 'Bearer ' + token;
5118
5136
  }