ccxt 4.1.39 → 4.1.41

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.
package/js/src/bingx.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/bingx.js';
2
- import { Int, OrderSide, OHLCV, FundingRateHistory, Order } from './base/types.js';
2
+ import { Int, OrderSide, OHLCV, FundingRateHistory, Order, OrderType, OrderRequest } from './base/types.js';
3
3
  export default class bingx extends Exchange {
4
4
  describe(): any;
5
5
  fetchTime(params?: {}): Promise<number>;
@@ -113,7 +113,9 @@ export default class bingx extends Exchange {
113
113
  parseBalance(response: any): import("./base/types.js").Balances;
114
114
  fetchPositions(symbols?: string[], params?: {}): Promise<import("./base/types.js").Position[]>;
115
115
  parsePosition(position: any, market?: any): import("./base/types.js").Position;
116
- createOrder(symbol: string, type: any, side: OrderSide, amount: any, price?: any, params?: {}): Promise<Order>;
116
+ createOrderRequest(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, params?: {}): any;
117
+ createOrder(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, params?: {}): Promise<Order>;
118
+ createOrders(orders: OrderRequest[], params?: {}): Promise<Order[]>;
117
119
  parseOrderSide(side: any): string;
118
120
  parseOrder(order: any, market?: any): Order;
119
121
  parseOrderStatus(status: any): string;
package/js/src/bingx.js CHANGED
@@ -33,6 +33,7 @@ export default class bingx extends Exchange {
33
33
  'cancelOrder': true,
34
34
  'cancelOrders': true,
35
35
  'createOrder': true,
36
+ 'createOrders': true,
36
37
  'fetchBalance': true,
37
38
  'fetchClosedOrders': true,
38
39
  'fetchCurrencies': true,
@@ -1591,31 +1592,22 @@ export default class bingx extends Exchange {
1591
1592
  'takeProfitPrice': undefined,
1592
1593
  });
1593
1594
  }
1594
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1595
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1595
1596
  /**
1596
1597
  * @method
1597
- * @name bingx#createOrder
1598
- * @description create a trade order
1599
- * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Create%20an%20Order
1600
- * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Trade%20order
1598
+ * @ignore
1599
+ * @name bingx#createOrderRequest
1600
+ * @description helper function to build request
1601
1601
  * @param {string} symbol unified symbol of the market to create an order in
1602
1602
  * @param {string} type 'market' or 'limit'
1603
1603
  * @param {string} side 'buy' or 'sell'
1604
- * @param {float} amount how much of currency you want to trade in units of base currency
1604
+ * @param {float} amount how much you want to trade in units of the base currency
1605
1605
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1606
1606
  * @param {object} [params] extra parameters specific to the bingx api endpoint
1607
- * @param {bool} [params.postOnly] true to place a post only order
1608
- * @param {string} [params.timeInForce] spot supports 'PO' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1609
- * @param {bool} [params.reduceOnly] *swap only* true or false whether the order is reduce only
1610
- * @param {float} [params.triggerPrice] *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1611
- * @param {float} [params.stopLossPrice] *swap only* stop loss trigger price
1612
- * @param {float} [params.takeProfitPrice] *swap only* take profit trigger price
1613
- * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1607
+ * @returns {object} request to be sent to the exchange
1614
1608
  */
1615
- await this.loadMarkets();
1616
1609
  const market = this.market(symbol);
1617
1610
  let postOnly = undefined;
1618
- let response = undefined;
1619
1611
  let marketType = undefined;
1620
1612
  [marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
1621
1613
  type = type.toUpperCase();
@@ -1645,20 +1637,19 @@ export default class bingx extends Exchange {
1645
1637
  const amountString = this.numberToString(amount);
1646
1638
  const priceString = this.numberToString(price);
1647
1639
  const cost = this.parseNumber(Precise.stringMul(amountString, priceString));
1648
- request['quoteOrderQty'] = this.priceToPrecision(symbol, cost);
1640
+ request['quoteOrderQty'] = this.parseToNumeric(this.priceToPrecision(symbol, cost));
1649
1641
  }
1650
1642
  }
1651
1643
  else {
1652
- request['quoteOrderQty'] = this.priceToPrecision(symbol, amount);
1644
+ request['quoteOrderQty'] = this.parseToNumeric(this.priceToPrecision(symbol, amount));
1653
1645
  }
1654
1646
  }
1655
1647
  else {
1656
- request['quantity'] = this.amountToPrecision(symbol, amount);
1648
+ request['quantity'] = this.parseToNumeric(this.amountToPrecision(symbol, amount));
1657
1649
  }
1658
1650
  if (!isMarketOrder) {
1659
- request['price'] = this.priceToPrecision(symbol, price);
1651
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1660
1652
  }
1661
- response = await this.spotV1PrivatePostTradeOrder(this.extend(request, params));
1662
1653
  }
1663
1654
  else {
1664
1655
  [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'PostOnly', params);
@@ -1672,7 +1663,7 @@ export default class bingx extends Exchange {
1672
1663
  request['timeInForce'] = 'FOK';
1673
1664
  }
1674
1665
  if ((type === 'LIMIT') || (type === 'TRIGGER_LIMIT') || (type === 'STOP') || (type === 'TAKE_PROFIT')) {
1675
- request['price'] = this.priceToPrecision(symbol, price);
1666
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1676
1667
  }
1677
1668
  const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
1678
1669
  const stopLossPrice = this.safeNumber(params, 'stopLossPrice');
@@ -1680,8 +1671,9 @@ export default class bingx extends Exchange {
1680
1671
  const isTriggerOrder = triggerPrice !== undefined;
1681
1672
  const isStopLossPriceOrder = stopLossPrice !== undefined;
1682
1673
  const isTakeProfitPriceOrder = takeProfitPrice !== undefined;
1674
+ let reduceOnly = this.safeValue(params, 'reduceOnly', false);
1683
1675
  if (isTriggerOrder) {
1684
- request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
1676
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, triggerPrice));
1685
1677
  if (isMarketOrder || (type === 'TRIGGER_MARKET')) {
1686
1678
  request['type'] = 'TRIGGER_MARKET';
1687
1679
  }
@@ -1691,8 +1683,9 @@ export default class bingx extends Exchange {
1691
1683
  }
1692
1684
  else if (isStopLossPriceOrder || isTakeProfitPriceOrder) {
1693
1685
  // This can be used to set the stop loss and take profit, but the position needs to be opened first
1686
+ reduceOnly = true;
1694
1687
  if (isStopLossPriceOrder) {
1695
- request['stopPrice'] = this.priceToPrecision(symbol, stopLossPrice);
1688
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, stopLossPrice));
1696
1689
  if (isMarketOrder || (type === 'STOP_MARKET')) {
1697
1690
  request['type'] = 'STOP_MARKET';
1698
1691
  }
@@ -1701,7 +1694,7 @@ export default class bingx extends Exchange {
1701
1694
  }
1702
1695
  }
1703
1696
  else if (isTakeProfitPriceOrder) {
1704
- request['stopPrice'] = this.priceToPrecision(symbol, takeProfitPrice);
1697
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, takeProfitPrice));
1705
1698
  if (isMarketOrder || (type === 'TAKE_PROFIT_MARKET')) {
1706
1699
  request['type'] = 'TAKE_PROFIT_MARKET';
1707
1700
  }
@@ -1710,7 +1703,6 @@ export default class bingx extends Exchange {
1710
1703
  }
1711
1704
  }
1712
1705
  }
1713
- const reduceOnly = this.safeValue(params, 'reduceOnly', false);
1714
1706
  let positionSide = undefined;
1715
1707
  if (reduceOnly) {
1716
1708
  positionSide = (side === 'buy') ? 'SHORT' : 'LONG';
@@ -1719,9 +1711,41 @@ export default class bingx extends Exchange {
1719
1711
  positionSide = (side === 'buy') ? 'LONG' : 'SHORT';
1720
1712
  }
1721
1713
  request['positionSide'] = positionSide;
1722
- request['quantity'] = this.amountToPrecision(symbol, amount);
1714
+ request['quantity'] = this.parseToNumeric(this.amountToPrecision(symbol, amount));
1723
1715
  params = this.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
1724
- response = await this.swapV2PrivatePostTradeOrder(this.extend(request, params));
1716
+ }
1717
+ return this.extend(request, params);
1718
+ }
1719
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1720
+ /**
1721
+ * @method
1722
+ * @name bingx#createOrder
1723
+ * @description create a trade order
1724
+ * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Create%20an%20Order
1725
+ * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Trade%20order
1726
+ * @param {string} symbol unified symbol of the market to create an order in
1727
+ * @param {string} type 'market' or 'limit'
1728
+ * @param {string} side 'buy' or 'sell'
1729
+ * @param {float} amount how much you want to trade in units of the base currency
1730
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1731
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
1732
+ * @param {bool} [params.postOnly] true to place a post only order
1733
+ * @param {string} [params.timeInForce] spot supports 'PO' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1734
+ * @param {bool} [params.reduceOnly] *swap only* true or false whether the order is reduce only
1735
+ * @param {float} [params.triggerPrice] *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1736
+ * @param {float} [params.stopLossPrice] *swap only* stop loss trigger price
1737
+ * @param {float} [params.takeProfitPrice] *swap only* take profit trigger price
1738
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1739
+ */
1740
+ await this.loadMarkets();
1741
+ const market = this.market(symbol);
1742
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
1743
+ let response = undefined;
1744
+ if (market['swap']) {
1745
+ response = await this.swapV2PrivatePostTradeOrder(request);
1746
+ }
1747
+ else {
1748
+ response = await this.spotV1PrivatePostTradeOrder(request);
1725
1749
  }
1726
1750
  //
1727
1751
  // spot
@@ -1765,6 +1789,99 @@ export default class bingx extends Exchange {
1765
1789
  const order = this.safeValue(data, 'order', data);
1766
1790
  return this.parseOrder(order, market);
1767
1791
  }
1792
+ async createOrders(orders, params = {}) {
1793
+ /**
1794
+ * @method
1795
+ * @name bingx#createOrders
1796
+ * @description create a list of trade orders
1797
+ * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Batch%20Placing%20Orders
1798
+ * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Bulk%20order
1799
+ * @param {array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1800
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
1801
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1802
+ */
1803
+ await this.loadMarkets();
1804
+ const ordersRequests = [];
1805
+ let symbol = undefined;
1806
+ for (let i = 0; i < orders.length; i++) {
1807
+ const rawOrder = orders[i];
1808
+ const marketId = this.safeString(rawOrder, 'symbol');
1809
+ if (symbol === undefined) {
1810
+ symbol = marketId;
1811
+ }
1812
+ else {
1813
+ if (symbol !== marketId) {
1814
+ throw new BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
1815
+ }
1816
+ }
1817
+ const type = this.safeString(rawOrder, 'type');
1818
+ const side = this.safeString(rawOrder, 'side');
1819
+ const amount = this.safeNumber(rawOrder, 'amount');
1820
+ const price = this.safeNumber(rawOrder, 'price');
1821
+ const orderParams = this.safeValue(rawOrder, 'params', {});
1822
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
1823
+ ordersRequests.push(orderRequest);
1824
+ }
1825
+ const market = this.market(symbol);
1826
+ const request = {};
1827
+ let response = undefined;
1828
+ if (market['swap']) {
1829
+ request['batchOrders'] = this.json(ordersRequests);
1830
+ response = await this.swapV2PrivatePostTradeBatchOrders(request);
1831
+ }
1832
+ else {
1833
+ request['data'] = this.json(ordersRequests);
1834
+ response = await this.spotV1PrivatePostTradeBatchOrders(request);
1835
+ }
1836
+ //
1837
+ // spot
1838
+ //
1839
+ // {
1840
+ // "code": 0,
1841
+ // "msg": "",
1842
+ // "debugMsg": "",
1843
+ // "data": {
1844
+ // "orders": [
1845
+ // {
1846
+ // "symbol": "BTC-USDT",
1847
+ // "orderId": 1720661389564968960,
1848
+ // "transactTime": 1699072618272,
1849
+ // "price": "25000",
1850
+ // "origQty": "0.0002",
1851
+ // "executedQty": "0",
1852
+ // "cummulativeQuoteQty": "0",
1853
+ // "status": "PENDING",
1854
+ // "type": "LIMIT",
1855
+ // "side": "BUY"
1856
+ // },
1857
+ // ]
1858
+ // }
1859
+ // }
1860
+ //
1861
+ // swap
1862
+ //
1863
+ // {
1864
+ // "code": 0,
1865
+ // "msg": "",
1866
+ // "data": {
1867
+ // "orders": [
1868
+ // {
1869
+ // "symbol": "BTC-USDT",
1870
+ // "orderId": 1720657081994006528,
1871
+ // "side": "BUY",
1872
+ // "positionSide": "LONG",
1873
+ // "type": "LIMIT",
1874
+ // "clientOrderID": "",
1875
+ // "workingType": ""
1876
+ // },
1877
+ // ]
1878
+ // }
1879
+ // }
1880
+ //
1881
+ const data = this.safeValue(response, 'data', {});
1882
+ const result = this.safeValue(data, 'orders', []);
1883
+ return this.parseOrders(result, market);
1884
+ }
1768
1885
  parseOrderSide(side) {
1769
1886
  const sides = {
1770
1887
  'BUY': 'buy',
@@ -1777,7 +1894,7 @@ export default class bingx extends Exchange {
1777
1894
  parseOrder(order, market = undefined) {
1778
1895
  //
1779
1896
  // spot
1780
- // createOrder, cancelOrder
1897
+ // createOrder, createOrders, cancelOrder
1781
1898
  //
1782
1899
  // {
1783
1900
  // "symbol": "XRP-USDT",
@@ -1830,7 +1947,7 @@ export default class bingx extends Exchange {
1830
1947
  //
1831
1948
  //
1832
1949
  // swap
1833
- // createOrder
1950
+ // createOrder, createOrders
1834
1951
  //
1835
1952
  // {
1836
1953
  // "symbol": "BTC-USDT",
package/js/src/bittrex.js CHANGED
@@ -511,6 +511,7 @@ export default class bittrex extends Exchange {
511
511
  'max': undefined,
512
512
  },
513
513
  },
514
+ 'networks': {},
514
515
  };
515
516
  }
516
517
  return result;
@@ -7,9 +7,9 @@ import { Int, OrderSide, OrderType, Order, Trade, OHLCV } from './base/types.js'
7
7
  export default class coinbase extends Exchange {
8
8
  describe(): any;
9
9
  fetchTime(params?: {}): Promise<number>;
10
- fetchAccounts(params?: {}): Promise<any[]>;
11
- fetchAccountsV2(params?: {}): Promise<any[]>;
12
- fetchAccountsV3(params?: {}): Promise<any[]>;
10
+ fetchAccounts(params?: {}): Promise<any>;
11
+ fetchAccountsV2(params?: {}): Promise<any>;
12
+ fetchAccountsV3(params?: {}): Promise<any>;
13
13
  parseAccount(account: any): {
14
14
  id: string;
15
15
  type: string;
@@ -322,6 +322,7 @@ export default class coinbase extends Exchange {
322
322
  * @name coinbase#fetchAccounts
323
323
  * @description fetch all the accounts associated with a profile
324
324
  * @param {object} [params] extra parameters specific to the coinbase api endpoint
325
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
325
326
  * @returns {object} a dictionary of [account structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#account-structure} indexed by the account type
326
327
  */
327
328
  const method = this.safeString(this.options, 'fetchAccounts', 'fetchAccountsV3');
@@ -332,6 +333,11 @@ export default class coinbase extends Exchange {
332
333
  }
333
334
  async fetchAccountsV2(params = {}) {
334
335
  await this.loadMarkets();
336
+ let paginate = false;
337
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate');
338
+ if (paginate) {
339
+ return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'next_starting_after', 'starting_after', undefined, 100);
340
+ }
335
341
  const request = {
336
342
  'limit': 100,
337
343
  };
@@ -381,10 +387,24 @@ export default class coinbase extends Exchange {
381
387
  // }
382
388
  //
383
389
  const data = this.safeValue(response, 'data', []);
390
+ const pagination = this.safeValue(response, 'pagination', {});
391
+ const cursor = this.safeString(pagination, 'next_starting_after');
392
+ const accounts = this.safeValue(response, 'data', []);
393
+ const lastIndex = accounts.length - 1;
394
+ const last = this.safeValue(accounts, lastIndex);
395
+ if ((cursor !== undefined) && (cursor !== '')) {
396
+ last['next_starting_after'] = cursor;
397
+ accounts[lastIndex] = last;
398
+ }
384
399
  return this.parseAccounts(data, params);
385
400
  }
386
401
  async fetchAccountsV3(params = {}) {
387
402
  await this.loadMarkets();
403
+ let paginate = false;
404
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate');
405
+ if (paginate) {
406
+ return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'cursor', 'cursor', undefined, 100);
407
+ }
388
408
  const request = {
389
409
  'limit': 100,
390
410
  };
@@ -419,8 +439,15 @@ export default class coinbase extends Exchange {
419
439
  // "size": 9
420
440
  // }
421
441
  //
422
- const data = this.safeValue(response, 'accounts', []);
423
- return this.parseAccounts(data, params);
442
+ const accounts = this.safeValue(response, 'accounts', []);
443
+ const lastIndex = accounts.length - 1;
444
+ const last = this.safeValue(accounts, lastIndex);
445
+ const cursor = this.safeString(response, 'cursor');
446
+ if ((cursor !== undefined) && (cursor !== '')) {
447
+ last['cursor'] = cursor;
448
+ accounts[lastIndex] = last;
449
+ }
450
+ return this.parseAccounts(accounts, params);
424
451
  }
425
452
  parseAccount(account) {
426
453
  //
package/js/src/okx.js CHANGED
@@ -570,9 +570,12 @@ export default class okx extends Exchange {
570
570
  '51028': ContractUnavailable,
571
571
  '51029': ContractUnavailable,
572
572
  '51030': ContractUnavailable,
573
+ '51031': InvalidOrder,
573
574
  '51046': InvalidOrder,
574
575
  '51047': InvalidOrder,
575
- '51031': InvalidOrder,
576
+ '51072': InvalidOrder,
577
+ '51073': InvalidOrder,
578
+ '51074': InvalidOrder,
576
579
  '51100': InvalidOrder,
577
580
  '51101': InvalidOrder,
578
581
  '51102': InvalidOrder,
@@ -617,6 +620,7 @@ export default class okx extends Exchange {
617
620
  '51163': InvalidOrder,
618
621
  '51166': InvalidOrder,
619
622
  '51174': InvalidOrder,
623
+ '51185': InvalidOrder,
620
624
  '51201': InvalidOrder,
621
625
  '51202': InvalidOrder,
622
626
  '51203': InvalidOrder,
@@ -764,6 +768,8 @@ export default class okx extends Exchange {
764
768
  '59200': InsufficientFunds,
765
769
  '59201': InsufficientFunds,
766
770
  '59216': BadRequest,
771
+ '59260': PermissionDenied,
772
+ '59262': PermissionDenied,
767
773
  '59300': ExchangeError,
768
774
  '59301': ExchangeError,
769
775
  '59313': ExchangeError,
@@ -777,6 +783,8 @@ export default class okx extends Exchange {
777
783
  '59506': ExchangeError,
778
784
  '59507': ExchangeError,
779
785
  '59508': AccountSuspended,
786
+ '59642': BadRequest,
787
+ '59643': ExchangeError,
780
788
  // WebSocket error Codes from 60000-63999
781
789
  '60001': AuthenticationError,
782
790
  '60002': AuthenticationError,
@@ -1237,10 +1237,11 @@ export default class binance extends binanceRest {
1237
1237
  }
1238
1238
  async authenticate(params = {}) {
1239
1239
  const time = this.milliseconds();
1240
- let type = this.safeString2(this.options, 'defaultType', 'authenticate', 'spot');
1241
- type = this.safeString(params, 'type', type);
1240
+ let query = undefined;
1241
+ let type = undefined;
1242
+ [type, query] = this.handleMarketTypeAndParams('authenticate', undefined, params);
1242
1243
  let subType = undefined;
1243
- [subType, params] = this.handleSubTypeAndParams('authenticate', undefined, params);
1244
+ [subType, query] = this.handleSubTypeAndParams('authenticate', undefined, query);
1244
1245
  if (this.isLinear(type, subType)) {
1245
1246
  type = 'future';
1246
1247
  }
@@ -1248,11 +1249,11 @@ export default class binance extends binanceRest {
1248
1249
  type = 'delivery';
1249
1250
  }
1250
1251
  let marginMode = undefined;
1251
- [marginMode, params] = this.handleMarginModeAndParams('authenticate', params);
1252
+ [marginMode, query] = this.handleMarginModeAndParams('authenticate', query);
1252
1253
  const isIsolatedMargin = (marginMode === 'isolated');
1253
1254
  const isCrossMargin = (marginMode === 'cross') || (marginMode === undefined);
1254
- const symbol = this.safeString(params, 'symbol');
1255
- params = this.omit(params, 'symbol');
1255
+ const symbol = this.safeString(query, 'symbol');
1256
+ query = this.omit(query, 'symbol');
1256
1257
  const options = this.safeValue(this.options, type, {});
1257
1258
  const lastAuthenticatedTime = this.safeInteger(options, 'lastAuthenticatedTime', 0);
1258
1259
  const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 1200000);
@@ -1274,9 +1275,9 @@ export default class binance extends binanceRest {
1274
1275
  throw new ArgumentsRequired(this.id + ' authenticate() requires a symbol argument for isolated margin mode');
1275
1276
  }
1276
1277
  const marketId = this.marketId(symbol);
1277
- params = this.extend(params, { 'symbol': marketId });
1278
+ query = this.extend(query, { 'symbol': marketId });
1278
1279
  }
1279
- const response = await this[method](params);
1280
+ const response = await this[method](query);
1280
1281
  this.options[type] = this.extend(options, {
1281
1282
  'listenKey': this.safeString(response, 'listenKey'),
1282
1283
  'lastAuthenticatedTime': time,
@@ -1288,8 +1289,8 @@ export default class binance extends binanceRest {
1288
1289
  // https://binance-docs.github.io/apidocs/spot/en/#listen-key-spot
1289
1290
  let type = this.safeString2(this.options, 'defaultType', 'authenticate', 'spot');
1290
1291
  type = this.safeString(params, 'type', type);
1291
- let subType = undefined;
1292
- [subType, params] = this.handleSubTypeAndParams('keepAliveListenKey', undefined, params);
1292
+ const subTypeInfo = this.handleSubTypeAndParams('keepAliveListenKey', undefined, params);
1293
+ const subType = subTypeInfo[0];
1293
1294
  if (this.isLinear(type, subType)) {
1294
1295
  type = 'future';
1295
1296
  }
@@ -2066,7 +2067,7 @@ export default class binance extends binanceRest {
2066
2067
  market = this.market(symbol);
2067
2068
  symbol = market['symbol'];
2068
2069
  messageHash += ':' + symbol;
2069
- params = this.extend(params, { 'symbol': symbol }); // needed inside authenticate for isolated margin
2070
+ params = this.extend(params, { 'type': market['type'], 'symbol': symbol }); // needed inside authenticate for isolated margin
2070
2071
  }
2071
2072
  await this.authenticate(params);
2072
2073
  let type = undefined;
@@ -2079,7 +2080,11 @@ export default class binance extends binanceRest {
2079
2080
  else if (this.isInverse(type, subType)) {
2080
2081
  type = 'delivery';
2081
2082
  }
2082
- const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
2083
+ let urlType = type;
2084
+ if (type === 'margin') {
2085
+ urlType = 'spot'; // spot-margin shares the same stream as regular spot
2086
+ }
2087
+ const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2083
2088
  const client = this.client(url);
2084
2089
  this.setBalanceCache(client, type);
2085
2090
  const message = undefined;
@@ -2419,10 +2424,15 @@ export default class binance extends binanceRest {
2419
2424
  * @returns {object[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure
2420
2425
  */
2421
2426
  await this.loadMarkets();
2422
- const defaultType = this.safeString2(this.options, 'watchMyTrades', 'defaultType', 'spot');
2423
- let type = this.safeString(params, 'type', defaultType);
2427
+ let type = undefined;
2428
+ let market = undefined;
2429
+ if (symbol !== undefined) {
2430
+ market = this.market(symbol);
2431
+ symbol = market['symbol'];
2432
+ }
2433
+ [type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
2424
2434
  let subType = undefined;
2425
- [subType, params] = this.handleSubTypeAndParams('watchMyTrades', undefined, params);
2435
+ [subType, params] = this.handleSubTypeAndParams('watchMyTrades', market, params);
2426
2436
  if (this.isLinear(type, subType)) {
2427
2437
  type = 'future';
2428
2438
  }
@@ -2433,10 +2443,14 @@ export default class binance extends binanceRest {
2433
2443
  if (symbol !== undefined) {
2434
2444
  symbol = this.symbol(symbol);
2435
2445
  messageHash += ':' + symbol;
2436
- params = this.extend(params, { 'symbol': symbol });
2446
+ params = this.extend(params, { 'type': market['type'], 'symbol': symbol });
2437
2447
  }
2438
2448
  await this.authenticate(params);
2439
- const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
2449
+ let urlType = type; // we don't change type because the listening key is different
2450
+ if (type === 'margin') {
2451
+ urlType = 'spot'; // spot-margin shares the same stream as regular spot
2452
+ }
2453
+ const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2440
2454
  const client = this.client(url);
2441
2455
  this.setBalanceCache(client, type);
2442
2456
  const message = undefined;
@@ -1408,13 +1408,13 @@ export default class huobi extends huobiRest {
1408
1408
  // }
1409
1409
  //
1410
1410
  const channel = this.safeString(message, 'ch');
1411
- const timestamp = this.safeInteger(message, 'ts');
1411
+ const data = this.safeValue(message, 'data', []);
1412
+ const timestamp = this.safeInteger(data, 'changeTime', this.safeInteger(message, 'ts'));
1412
1413
  this.balance['timestamp'] = timestamp;
1413
1414
  this.balance['datetime'] = this.iso8601(timestamp);
1414
- this.balance['info'] = this.safeValue(message, 'data');
1415
+ this.balance['info'] = data;
1415
1416
  if (channel !== undefined) {
1416
1417
  // spot balance
1417
- const data = this.safeValue(message, 'data', {});
1418
1418
  const currencyId = this.safeString(data, 'currency');
1419
1419
  const code = this.safeCurrencyCode(currencyId);
1420
1420
  const account = this.account();
@@ -1426,7 +1426,6 @@ export default class huobi extends huobiRest {
1426
1426
  }
1427
1427
  else {
1428
1428
  // contract balance
1429
- const data = this.safeValue(message, 'data', []);
1430
1429
  const dataLength = data.length;
1431
1430
  if (dataLength === 0) {
1432
1431
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.1.39",
3
+ "version": "4.1.41",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",
@@ -40,13 +40,13 @@
40
40
  "fast-test": "npm run commonjs-test && node run-tests --js",
41
41
  "commonjs-test": "node test-commonjs.cjs",
42
42
  "fast-test-ws": "node run-tests-ws --js",
43
- "test-js": "npm run commonjs-test && node js/src/test/static/test.ids && node run-tests --js",
43
+ "test-js": "npm run commonjs-test && node run-tests --js",
44
44
  "test-js-ws": "node run-tests-ws --js",
45
45
  "test-py": "node run-tests --python",
46
46
  "test-py-ws": "node run-tests-ws --python",
47
47
  "test-php": "node run-tests --php",
48
48
  "test-php-ws": "node run-tests-ws --php",
49
- "test-base": "npm run test-js-base && npm run test-python-base && npm run test-php-base",
49
+ "test-base": "npm run test-js-base && npm run test-python-base && npm run test-php-base && npm run id-tests && npm run static-tests",
50
50
  "test-base-ws": "npm run test-js-base-ws && npm run test-python-base-ws && npm run test-php-base-ws",
51
51
  "test-js-base": "node ./js/src/test/base/test.base.js",
52
52
  "test-js-base-ws": "npm run test-js-cache && npm run test-js-orderbook",
@@ -103,7 +103,11 @@
103
103
  "static-js": "node js/src/test/test.js --static",
104
104
  "static-py": "python python/ccxt/test/test_async.py --static",
105
105
  "static-php": "php php/test/test_async.php --static",
106
- "static-tests": "npm run static-js && npm run static-py && npm run static-php"
106
+ "static-tests": "npm run static-js && npm run static-py && npm run static-php",
107
+ "id-tests-js": "node js/src/test/test.js --idTests",
108
+ "id-tests-py": "python python/ccxt/test/test_async.py --idTests",
109
+ "id-tests-php": "php php/test/test_async.php --idTests",
110
+ "id-tests": "npm run id-tests-js && npm run id-tests-py && npm run id-tests-php"
107
111
  },
108
112
  "types": "./js/ccxt.d.ts",
109
113
  "devDependencies": {
package/skip-tests.json CHANGED
@@ -1368,6 +1368,7 @@
1368
1368
  }
1369
1369
  },
1370
1370
  "tidex": {
1371
+ "skip": "exchange unavailable, probably api upgrade needed"
1371
1372
  },
1372
1373
  "kraken": {
1373
1374
  "skipWs": true,