ccxt 4.5.36 → 4.5.38

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 (48) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.min.js +18 -20
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +3 -0
  5. package/dist/cjs/src/bitmex.js +19 -3
  6. package/dist/cjs/src/bitstamp.js +9 -0
  7. package/dist/cjs/src/bybit.js +2 -1
  8. package/dist/cjs/src/gate.js +4 -2
  9. package/dist/cjs/src/htx.js +67 -12
  10. package/dist/cjs/src/hyperliquid.js +250 -2
  11. package/dist/cjs/src/krakenfutures.js +74 -6
  12. package/dist/cjs/src/kucoin.js +43 -4
  13. package/dist/cjs/src/mexc.js +2 -2
  14. package/dist/cjs/src/pro/aster.js +11 -2
  15. package/dist/cjs/src/pro/binance.js +4 -2
  16. package/dist/cjs/src/pro/bitmex.js +2 -1
  17. package/dist/cjs/src/pro/bybit.js +4 -2
  18. package/dist/cjs/src/pro/gate.js +2 -1
  19. package/dist/cjs/src/pro/okx.js +4 -2
  20. package/dist/cjs/src/whitebit.js +14 -4
  21. package/js/ccxt.d.ts +1 -1
  22. package/js/ccxt.js +1 -1
  23. package/js/src/abstract/bitstamp.d.ts +8 -0
  24. package/js/src/abstract/bybit.d.ts +1 -0
  25. package/js/src/abstract/kucoin.d.ts +33 -1
  26. package/js/src/abstract/kucoinfutures.d.ts +33 -1
  27. package/js/src/base/Exchange.d.ts +1 -0
  28. package/js/src/base/Exchange.js +3 -0
  29. package/js/src/bitmex.js +19 -3
  30. package/js/src/bitstamp.js +9 -0
  31. package/js/src/bybit.js +2 -1
  32. package/js/src/gate.js +4 -2
  33. package/js/src/htx.d.ts +5 -2
  34. package/js/src/htx.js +67 -12
  35. package/js/src/hyperliquid.d.ts +64 -0
  36. package/js/src/hyperliquid.js +251 -3
  37. package/js/src/krakenfutures.js +74 -6
  38. package/js/src/kucoin.js +43 -4
  39. package/js/src/mexc.js +2 -2
  40. package/js/src/pro/aster.js +11 -2
  41. package/js/src/pro/binance.js +4 -2
  42. package/js/src/pro/bitmex.js +2 -1
  43. package/js/src/pro/bybit.js +4 -2
  44. package/js/src/pro/gate.js +2 -1
  45. package/js/src/pro/okx.js +4 -2
  46. package/js/src/whitebit.d.ts +1 -0
  47. package/js/src/whitebit.js +14 -4
  48. package/package.json +1 -1
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import Exchange from './abstract/hyperliquid.js';
9
- import { ExchangeError, ArgumentsRequired, NotSupported, InvalidOrder, OrderNotFound, BadRequest, InsufficientFunds } from './base/errors.js';
9
+ import { ExchangeError, ArgumentsRequired, NotSupported, InvalidOrder, OrderNotFound, BadRequest, InsufficientFunds, RateLimitExceeded } from './base/errors.js';
10
10
  import { Precise } from './base/Precise.js';
11
11
  import { ROUND, SIGNIFICANT_DIGITS, DECIMAL_PLACES, TICK_SIZE } from './base/functions/number.js';
12
12
  import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
@@ -214,6 +214,9 @@ export default class hyperliquid extends Exchange {
214
214
  'Insufficient spot balance asset': InsufficientFunds,
215
215
  'Insufficient balance for withdrawal': InsufficientFunds,
216
216
  'Insufficient balance for token transfer': InsufficientFunds,
217
+ 'TWAP order value too small. Min is $1200, which is $10 per minute.': InvalidOrder,
218
+ 'TWAP was never placed, already canceled, or filled.': OrderNotFound,
219
+ 'Too many cumulative requests sent': RateLimitExceeded, // {"status":"err","response":"Too many cumulative requests sent (37986 > 10436) for cumulative volume traded $437.92. Place taker orders to free up 1 request per USDC traded."}
217
220
  },
218
221
  },
219
222
  'precisionMode': TICK_SIZE,
@@ -1709,6 +1712,17 @@ export default class hyperliquid extends Exchange {
1709
1712
  };
1710
1713
  return this.signUserSignedAction(messageTypes, message);
1711
1714
  }
1715
+ buildUserAbstractionSig(message) {
1716
+ const messageTypes = {
1717
+ 'HyperliquidTransaction:UserSetAbstraction': [
1718
+ { 'name': 'hyperliquidChain', 'type': 'string' },
1719
+ { 'name': 'user', 'type': 'address' },
1720
+ { 'name': 'abstraction', 'type': 'string' },
1721
+ { 'name': 'nonce', 'type': 'uint64' },
1722
+ ],
1723
+ };
1724
+ return this.signUserSignedAction(messageTypes, message);
1725
+ }
1712
1726
  buildApproveBuilderFeeSig(message) {
1713
1727
  const messageTypes = {
1714
1728
  'HyperliquidTransaction:ApproveBuilderFee': [
@@ -1809,11 +1823,70 @@ export default class hyperliquid extends Exchange {
1809
1823
  }
1810
1824
  return true;
1811
1825
  }
1826
+ /**
1827
+ * @method
1828
+ * @name hyperliquid#setUserAbstraction
1829
+ * @description set user abstraction mode
1830
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#set-user-abstraction
1831
+ * @param {string} abstraction one of the strings ["disabled", "unifiedAccount", "portfolioMargin"],
1832
+ * @param {object} [params]
1833
+ * @param {string} [params.type] 'userSetAbstraction' or 'agentSetAbstraction' default is 'userSetAbstraction'
1834
+ * @returns dictionary response from the exchange
1835
+ */
1836
+ async setUserAbstraction(abstraction, params = {}) {
1837
+ let userAddress = undefined;
1838
+ [userAddress, params] = this.handlePublicAddress('setUserAbstraction', params);
1839
+ const nonce = this.milliseconds();
1840
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1841
+ const type = this.safeString(params, 'type', 'userSetAbstraction');
1842
+ params = this.omit(params, 'type');
1843
+ const payload = {
1844
+ 'hyperliquidChain': isSandboxMode ? 'Testnet' : 'Mainnet',
1845
+ 'user': userAddress,
1846
+ 'abstraction': abstraction,
1847
+ 'nonce': nonce,
1848
+ };
1849
+ const sig = this.buildUserAbstractionSig(payload);
1850
+ const action = {
1851
+ 'hyperliquidChain': payload['hyperliquidChain'],
1852
+ 'signatureChainId': '0x66eee',
1853
+ 'abstraction': payload['abstraction'],
1854
+ 'user': payload['user'],
1855
+ 'nonce': nonce,
1856
+ 'type': type,
1857
+ };
1858
+ const request = {
1859
+ 'action': action,
1860
+ 'nonce': nonce,
1861
+ 'signature': sig,
1862
+ 'vaultAddress': undefined,
1863
+ };
1864
+ //
1865
+ // {
1866
+ // "status": "ok",
1867
+ // "response": {
1868
+ // "type": "default"
1869
+ // }
1870
+ // }
1871
+ //
1872
+ return await this.privatePostExchange(request);
1873
+ }
1874
+ /**
1875
+ * @method
1876
+ * @name hyperliquid#enableUserDexAbstraction
1877
+ * @description If set, actions on HIP-3 perps will automatically transfer collateral from validator-operated USDC perps balance for HIP-3 DEXs where USDC is the collateral token, and spot otherwise
1878
+ * @param enabled
1879
+ * @param params
1880
+ * @param {string} [params.type] 'userDexAbstraction' or 'agentEnableDexAbstraction' default is 'userDexAbstraction'
1881
+ * @returns dictionary response from the exchange
1882
+ */
1812
1883
  async enableUserDexAbstraction(enabled, params = {}) {
1813
1884
  let userAddress = undefined;
1814
1885
  [userAddress, params] = this.handlePublicAddress('enableUserDexAbstraction', params);
1815
1886
  const nonce = this.milliseconds();
1816
1887
  const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1888
+ const type = this.safeString(params, 'type', 'userDexAbstraction');
1889
+ params = this.omit(params, 'type');
1817
1890
  const payload = {
1818
1891
  'hyperliquidChain': isSandboxMode ? 'Testnet' : 'Mainnet',
1819
1892
  'user': userAddress,
@@ -1827,7 +1900,7 @@ export default class hyperliquid extends Exchange {
1827
1900
  'enabled': payload['enabled'],
1828
1901
  'user': payload['user'],
1829
1902
  'nonce': nonce,
1830
- 'type': 'userDexAbstraction',
1903
+ 'type': type,
1831
1904
  };
1832
1905
  const request = {
1833
1906
  'action': action,
@@ -1845,6 +1918,29 @@ export default class hyperliquid extends Exchange {
1845
1918
  //
1846
1919
  return await this.privatePostExchange(request);
1847
1920
  }
1921
+ /**
1922
+ * @method
1923
+ * @name hyperliquid#setAgentAbstraction
1924
+ * @description set agent abstraction mode
1925
+ * @param {string} abstraction one of the strings ["i", "u", "p"] where "i" is "disabled", "u" is "unifiedAccount", and "p" is "portfolioMargin"
1926
+ * @param {object} [params]
1927
+ * @returns dictionary response from the exchange
1928
+ */
1929
+ async setAgentAbstraction(abstraction, params = {}) {
1930
+ const nonce = this.milliseconds();
1931
+ const request = {
1932
+ 'nonce': nonce,
1933
+ };
1934
+ const action = {
1935
+ 'type': 'agentSetAbstraction',
1936
+ 'abstraction': abstraction,
1937
+ };
1938
+ const signature = this.signL1Action(action, nonce);
1939
+ request['action'] = action;
1940
+ request['signature'] = signature;
1941
+ const response = await this.privatePostExchange(this.extend(request, params));
1942
+ return response;
1943
+ }
1848
1944
  /**
1849
1945
  * @method
1850
1946
  * @name hyperliquid#createOrder
@@ -1872,6 +1968,82 @@ export default class hyperliquid extends Exchange {
1872
1968
  const orders = await this.createOrders([order], globalParams);
1873
1969
  return orders[0];
1874
1970
  }
1971
+ /**
1972
+ * @method
1973
+ * @name hyperliquid#createTwapOrder
1974
+ * @description create a trade order that is executed as a TWAP order over a specified duration.
1975
+ * @param {string} symbol unified symbol of the market to create an order in
1976
+ * @param {string} side 'buy' or 'sell'
1977
+ * @param {float} amount how much of currency you want to trade in units of base currency
1978
+ * @param {int} duration the duration of the TWAP order in milliseconds
1979
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1980
+ * @param {bool} [params.randomize] whether to randomize the time intervals of the TWAP order slices (default is false, meaning equal intervals)
1981
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
1982
+ * @param {int} [params.expiresAfter] time in ms after which the twap order expires
1983
+ * @param {string} [params.vaultAddress] the vault address for order
1984
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1985
+ */
1986
+ async createTwapOrder(symbol, side, amount, duration, params = {}) {
1987
+ await this.loadMarkets();
1988
+ await this.initializeClient();
1989
+ const market = this.market(symbol);
1990
+ const nonce = this.milliseconds();
1991
+ const isBuy = (side === 'BUY');
1992
+ let vaultAddress = undefined;
1993
+ const randomize = this.safeBool(params, 'randomize', false);
1994
+ params = this.omit(params, 'randomize');
1995
+ [vaultAddress, params] = this.handleOptionAndParams(params, 'createOrder', 'vaultAddress');
1996
+ vaultAddress = this.formatVaultAddress(vaultAddress);
1997
+ const durationMins = Math.floor(duration / 1000 / 60); // convert from ms to minutes
1998
+ const orderObj = {
1999
+ 'a': this.parseToInt(market['baseId']),
2000
+ 'b': isBuy,
2001
+ 's': this.amountToPrecision(symbol, amount),
2002
+ 'r': this.safeBool(params, 'reduceOnly', false),
2003
+ 'm': durationMins,
2004
+ 't': randomize,
2005
+ };
2006
+ const orderAction = {
2007
+ 'type': 'twapOrder',
2008
+ 'twap': orderObj,
2009
+ };
2010
+ const signature = this.signL1Action(orderAction, nonce, vaultAddress);
2011
+ const request = {
2012
+ 'action': orderAction,
2013
+ 'nonce': nonce,
2014
+ 'signature': signature,
2015
+ // 'vaultAddress': vaultAddress,
2016
+ };
2017
+ if (vaultAddress !== undefined) {
2018
+ params = this.omit(params, 'vaultAddress');
2019
+ request['vaultAddress'] = vaultAddress;
2020
+ }
2021
+ const expiresAfter = this.safeInteger(params, 'expiresAfter');
2022
+ if (expiresAfter !== undefined) {
2023
+ request['expiresAfter'] = expiresAfter;
2024
+ params = this.omit(params, 'expiresAfter');
2025
+ }
2026
+ const response = await this.privatePostExchange(request);
2027
+ // {
2028
+ // "status":"ok",
2029
+ // "response":{
2030
+ // "type":"twapOrder",
2031
+ // "data":{
2032
+ // "status": {
2033
+ // "running":{
2034
+ // "twapId":77738308
2035
+ // }
2036
+ // }
2037
+ // }
2038
+ // }
2039
+ // }
2040
+ const responseObj = this.safeDict(response, 'response', {});
2041
+ const data = this.safeDict(responseObj, 'data', {});
2042
+ const status = this.safeDict(data, 'status', {});
2043
+ const running = this.safeDict(status, 'running', {});
2044
+ const orderId = this.safeString(running, 'twapId');
2045
+ return this.parseOrder({ 'status': 'running', 'oid': orderId }, market);
2046
+ }
1875
2047
  /**
1876
2048
  * @method
1877
2049
  * @name hyperliquid#createOrders
@@ -2110,9 +2282,14 @@ export default class hyperliquid extends Exchange {
2110
2282
  * @param {string} [params.clientOrderId] client order id, (optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
2111
2283
  * @param {string} [params.vaultAddress] the vault address for order
2112
2284
  * @param {string} [params.subAccountAddress] sub account user address
2285
+ * @param {boolean} [params.twap] whether the order to cancel is a twap order, (default is false)
2113
2286
  * @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
2114
2287
  */
2115
2288
  async cancelOrder(id, symbol = undefined, params = {}) {
2289
+ if (this.safeBool(params, 'twap', false)) {
2290
+ params = this.omit(params, 'twap');
2291
+ return await this.cancelTwapOrder(id, symbol, params);
2292
+ }
2116
2293
  const orders = await this.cancelOrders([id], symbol, params);
2117
2294
  return this.safeDict(orders, 0);
2118
2295
  }
@@ -2165,6 +2342,66 @@ export default class hyperliquid extends Exchange {
2165
2342
  }
2166
2343
  return orders;
2167
2344
  }
2345
+ /**
2346
+ * @method
2347
+ * @name hyperliquid#cancelTwapOrder
2348
+ * @description cancels a running twap order
2349
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-a-twap-order
2350
+ * @param {string} id order id
2351
+ * @param {string} symbol unified symbol of the market the order was made in
2352
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2353
+ * @param {int} [params.expiresAfter] time in ms after which the twap order expires
2354
+ * @param {string} [params.vaultAddress] the vault address for order
2355
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
2356
+ */
2357
+ async cancelTwapOrder(id, symbol = undefined, params = {}) {
2358
+ await this.loadMarkets();
2359
+ if (symbol === undefined) {
2360
+ throw new ArgumentsRequired(this.id + ' cancelTwapOrder() requires a symbol argument');
2361
+ }
2362
+ const market = this.market(symbol);
2363
+ let vaultAddress = undefined;
2364
+ [vaultAddress, params] = this.handleOptionAndParams(params, 'cancelTwapOrder', 'vaultAddress');
2365
+ vaultAddress = this.formatVaultAddress(vaultAddress);
2366
+ const action = {
2367
+ 'type': 'twapCancel',
2368
+ 'a': this.parseToInt(market['baseId']),
2369
+ 't': this.parseToNumeric(id),
2370
+ };
2371
+ const nonce = this.milliseconds();
2372
+ const signature = this.signL1Action(action, nonce, vaultAddress);
2373
+ const request = {
2374
+ 'action': action,
2375
+ 'nonce': nonce,
2376
+ 'signature': signature,
2377
+ // 'vaultAddress': vaultAddress,
2378
+ };
2379
+ if (vaultAddress !== undefined) {
2380
+ params = this.omit(params, 'vaultAddress');
2381
+ request['vaultAddress'] = vaultAddress;
2382
+ }
2383
+ const expiresAfter = this.safeInteger(params, 'expiresAfter');
2384
+ if (expiresAfter !== undefined) {
2385
+ request['expiresAfter'] = expiresAfter;
2386
+ params = this.omit(params, 'expiresAfter');
2387
+ }
2388
+ const response = await this.privatePostExchange(request);
2389
+ //
2390
+ // {
2391
+ // "status":"ok",
2392
+ // "response":{
2393
+ // "type":"twapCancel",
2394
+ // "data":{
2395
+ // "status": "success"
2396
+ // }
2397
+ // }
2398
+ // }
2399
+ //
2400
+ const responseObj = this.safeDict(response, 'response', {});
2401
+ const data = this.safeDict(responseObj, 'data', {});
2402
+ const status = this.safeString(data, 'status');
2403
+ return this.parseOrder({ 'status': status, 'oid': id }, market);
2404
+ }
2168
2405
  cancelOrdersRequest(ids, symbol = undefined, params = {}) {
2169
2406
  /**
2170
2407
  * @method
@@ -3162,12 +3399,16 @@ export default class hyperliquid extends Exchange {
3162
3399
  if (side !== undefined) {
3163
3400
  side = (side === 'A') ? 'sell' : 'buy';
3164
3401
  }
3165
- const fee = this.safeString(trade, 'fee');
3402
+ let fee = this.safeString(trade, 'fee');
3166
3403
  let takerOrMaker = undefined;
3167
3404
  const crossed = this.safeBool(trade, 'crossed');
3168
3405
  if (crossed !== undefined) {
3169
3406
  takerOrMaker = crossed ? 'taker' : 'maker';
3170
3407
  }
3408
+ const builderFee = this.safeString(trade, 'builderFee');
3409
+ if (builderFee !== undefined) {
3410
+ fee = Precise.stringAdd(fee, builderFee);
3411
+ }
3171
3412
  return this.safeTrade({
3172
3413
  'info': trade,
3173
3414
  'timestamp': timestamp,
@@ -4445,6 +4686,13 @@ export default class hyperliquid extends Exchange {
4445
4686
  break;
4446
4687
  }
4447
4688
  }
4689
+ if ('status' in data) {
4690
+ const errorStatus = this.safeDict(data, 'status', {});
4691
+ const errorMsg = this.safeString(errorStatus, 'error');
4692
+ if (errorStatus !== undefined) {
4693
+ message = errorMsg;
4694
+ }
4695
+ }
4448
4696
  }
4449
4697
  const feedback = this.id + ' ' + body;
4450
4698
  const nonEmptyMessage = ((message !== undefined) && (message !== ''));
@@ -1681,7 +1681,9 @@ export default class krakenfutures extends Exchange {
1681
1681
  'filled': 'closed',
1682
1682
  'notFound': 'rejected',
1683
1683
  'untouched': 'open',
1684
- 'partiallyFilled': 'open', // the size of the order is partially but not entirely filled
1684
+ 'partiallyFilled': 'open',
1685
+ 'ENTERED_BOOK': 'open',
1686
+ 'FULLY_EXECUTED': 'closed',
1685
1687
  };
1686
1688
  return this.safeString(statuses, status, status);
1687
1689
  }
@@ -1920,6 +1922,72 @@ export default class krakenfutures extends Exchange {
1920
1922
  // status: 'closed'
1921
1923
  // }
1922
1924
  //
1925
+ // order: {
1926
+ // type: 'ORDER',
1927
+ // orderId: 'a111f276-95fd-47fc-b77b-709c5ab2e9e1',
1928
+ // cliOrdId: null,
1929
+ // symbol: 'PF_LTCUSD',
1930
+ // side: 'buy',
1931
+ // quantity: '0.1',
1932
+ // filled: '0',
1933
+ // limitPrice: '40',
1934
+ // reduceOnly: false,
1935
+ // timestamp: '2026-02-13T12:09:03.738Z',
1936
+ // lastUpdateTimestamp: '2026-02-13T12:09:03.738Z'
1937
+ // },
1938
+ // status: 'ENTERED_BOOK',
1939
+ // updateReason: null,
1940
+ // error: null
1941
+ // }
1942
+ //
1943
+ const orderDictFromFetchOrder = this.safeDict(order, 'order');
1944
+ if (orderDictFromFetchOrder !== undefined) {
1945
+ // order: {
1946
+ // type: 'ORDER',
1947
+ // orderId: 'a111f276-95fd-47fc-b77b-709c5ab2e9e1',
1948
+ // cliOrdId: null,
1949
+ // symbol: 'PF_LTCUSD',
1950
+ // side: 'buy',
1951
+ // quantity: '0.1',
1952
+ // filled: '0',
1953
+ // limitPrice: '40',
1954
+ // reduceOnly: false,
1955
+ // timestamp: '2026-02-13T12:09:03.738Z',
1956
+ // lastUpdateTimestamp: '2026-02-13T12:09:03.738Z'
1957
+ // },
1958
+ // status: 'ENTERED_BOOK',
1959
+ // updateReason: null,
1960
+ // error: null
1961
+ //
1962
+ const datetime = this.safeString(orderDictFromFetchOrder, 'timestamp');
1963
+ const innerStatus = this.safeString(order, 'status');
1964
+ return this.safeOrder({
1965
+ 'info': order,
1966
+ 'id': this.safeString(orderDictFromFetchOrder, 'orderId'),
1967
+ 'clientOrderId': this.safeStringN(orderDictFromFetchOrder, ['cliOrdId']),
1968
+ 'timestamp': this.parse8601(datetime),
1969
+ 'datetime': datetime,
1970
+ 'lastTradeTimestamp': undefined,
1971
+ 'lastUpdateTimestamp': this.parse8601(this.safeString(orderDictFromFetchOrder, 'lastUpdateTimestamp')),
1972
+ 'symbol': this.safeSymbol(this.safeString(orderDictFromFetchOrder, 'symbol'), market),
1973
+ 'type': undefined,
1974
+ 'timeInForce': undefined,
1975
+ 'postOnly': undefined,
1976
+ 'reduceOnly': this.safeBool(orderDictFromFetchOrder, 'reduceOnly'),
1977
+ 'side': this.safeString(orderDictFromFetchOrder, 'side'),
1978
+ 'price': this.safeString(orderDictFromFetchOrder, 'limitPrice'),
1979
+ 'triggerPrice': undefined,
1980
+ 'amount': this.safeString(orderDictFromFetchOrder, 'quantity'),
1981
+ 'cost': undefined,
1982
+ 'average': undefined,
1983
+ 'filled': this.safeString(orderDictFromFetchOrder, 'filled'),
1984
+ 'remaining': undefined,
1985
+ 'status': this.parseOrderStatus(innerStatus),
1986
+ 'fee': undefined,
1987
+ 'fees': undefined,
1988
+ 'trades': undefined,
1989
+ });
1990
+ }
1923
1991
  const orderEvents = this.safeValue(order, 'orderEvents', []);
1924
1992
  const errorStatus = this.safeString(order, 'status');
1925
1993
  const orderEventsLength = orderEvents.length;
@@ -2390,7 +2458,7 @@ export default class krakenfutures extends Exchange {
2390
2458
  // "fundingRate": -0.000000756414717067,
2391
2459
  // "fundingRatePrediction": 0.000000195218676,
2392
2460
  // "suspended": false,
2393
- // "indexPrice": 0.043392,
2461
+ // "indexPrice": 0.043391,
2394
2462
  // "postOnly": false,
2395
2463
  // "change24h": -0.46
2396
2464
  // }
@@ -2403,16 +2471,16 @@ export default class krakenfutures extends Exchange {
2403
2471
  let fundingRateResult = Precise.stringDiv(fundingRateString, markPriceString);
2404
2472
  const nextFundingRateString = this.safeString(ticker, 'fundingRatePrediction');
2405
2473
  let nextFundingRateResult = Precise.stringDiv(nextFundingRateString, markPriceString);
2406
- if (fundingRateResult > '0.25') {
2474
+ if (Precise.stringGt(fundingRateResult, '0.25')) {
2407
2475
  fundingRateResult = '0.25';
2408
2476
  }
2409
- else if (fundingRateResult > '-0.25') {
2477
+ else if (Precise.stringLt(fundingRateResult, '-0.25')) {
2410
2478
  fundingRateResult = '-0.25';
2411
2479
  }
2412
- if (nextFundingRateResult > '0.25') {
2480
+ if (Precise.stringGt(nextFundingRateResult, '0.25')) {
2413
2481
  nextFundingRateResult = '0.25';
2414
2482
  }
2415
- else if (nextFundingRateResult > '-0.25') {
2483
+ else if (Precise.stringLt(nextFundingRateResult, '-0.25')) {
2416
2484
  nextFundingRateResult = '-0.25';
2417
2485
  }
2418
2486
  return {
package/js/src/kucoin.js CHANGED
@@ -129,6 +129,7 @@ export default class kucoin extends Exchange {
129
129
  'broker': 'https://api-broker.kucoin.com',
130
130
  'earn': 'https://api.kucoin.com',
131
131
  'uta': 'https://api.kucoin.com',
132
+ 'utaPrivate': 'https://api.kucoin.com',
132
133
  },
133
134
  'www': 'https://www.kucoin.com',
134
135
  'doc': [
@@ -485,17 +486,55 @@ export default class kucoin extends Exchange {
485
486
  'get': {
486
487
  'market/announcement': 20,
487
488
  'market/currency': 3,
489
+ 'market/currencies': 3,
488
490
  'market/instrument': 4,
489
491
  'market/ticker': 15,
490
- 'market/orderbook': 3,
491
492
  'market/trade': 3,
492
493
  'market/kline': 3,
493
494
  'market/funding-rate': 2,
494
495
  'market/funding-rate-history': 5,
495
496
  'market/cross-config': 25,
497
+ 'market/collateral-discount-ratio': 10,
498
+ 'market/index-price': 20,
499
+ 'market/position-tiers': 20,
500
+ 'market/open-interest': 10,
496
501
  'server/status': 3,
497
502
  },
498
503
  },
504
+ 'utaPrivate': {
505
+ 'get': {
506
+ 'market/orderbook': 3,
507
+ 'account/balance': 5,
508
+ 'account/transfer-quota': 20,
509
+ 'account/mode': 30,
510
+ 'account/ledger': 2,
511
+ 'account/interest-history': 15,
512
+ 'account/deposit/address': 5,
513
+ '{accountMode}/account/balance': 5,
514
+ '{accountMode}/account/overview': 5,
515
+ '{accountMode}/order/detail': 4,
516
+ '{accountMode}/order/open-list': 4,
517
+ '{accountMode}/order/history': 4,
518
+ '{accountMode}/order/execution': 4,
519
+ '{accountMode}/position/open-list': 3,
520
+ '{accountMode}/position/history': 2,
521
+ '{accountMode}/position/tiers': 20,
522
+ 'sub-account/balance': 5,
523
+ 'user/fee-rate': 3,
524
+ 'dcp/query': 2,
525
+ },
526
+ 'post': {
527
+ 'account/transfer': 4,
528
+ 'account/mode': 30,
529
+ '{accountMode}/account/modify-leverage': 20,
530
+ '{accountMode}/order/place': 1,
531
+ '{accountMode}/order/place-batch': 4,
532
+ '{accountMode}/order/cancel': 1,
533
+ '{accountMode}/order/cancel-batch': 4,
534
+ 'sub-account/canTransferOut': 5,
535
+ 'dcp/set': 2,
536
+ },
537
+ },
499
538
  },
500
539
  'timeframes': {
501
540
  '1m': '1min',
@@ -2580,7 +2619,7 @@ export default class kucoin extends Exchange {
2580
2619
  else {
2581
2620
  request['tradeType'] = 'FUTURES';
2582
2621
  }
2583
- response = await this.utaGetMarketOrderbook(this.extend(request, params));
2622
+ response = await this.utaPrivateGetMarketOrderbook(this.extend(request, params));
2584
2623
  //
2585
2624
  // {
2586
2625
  // "code": "200000",
@@ -5758,9 +5797,9 @@ export default class kucoin extends Exchange {
5758
5797
  endpoint = '/api/v1/' + this.implodeParams(path, params);
5759
5798
  }
5760
5799
  let isUtaPrivate = false;
5761
- if (api === 'uta') {
5800
+ if ((api === 'uta') || (api === 'utaPrivate')) {
5762
5801
  endpoint = '/api/ua/v1/' + this.implodeParams(path, params);
5763
- if (path === 'market/orderbook') {
5802
+ if (api === 'utaPrivate') {
5764
5803
  isUtaPrivate = true;
5765
5804
  }
5766
5805
  }
package/js/src/mexc.js CHANGED
@@ -153,8 +153,8 @@ export default class mexc extends Exchange {
153
153
  'private': 'https://www.mexc.com/open/api/v2',
154
154
  },
155
155
  'contract': {
156
- 'public': 'https://contract.mexc.com/api/v1/contract',
157
- 'private': 'https://contract.mexc.com/api/v1/private',
156
+ 'public': 'https://api.mexc.com/api/v1/contract',
157
+ 'private': 'https://api.mexc.com/api/v1/private',
158
158
  },
159
159
  'broker': {
160
160
  'private': 'https://api.mexc.com/api/v3/broker',
@@ -779,10 +779,19 @@ export default class aster extends asterRest {
779
779
  // "ss": 0
780
780
  // }
781
781
  //
782
+ const e = this.safeString(trade, 'e');
783
+ const isPublicTrade = (e === 'trade') || (e === 'aggTrade');
782
784
  const id = this.safeString2(trade, 't', 'a');
783
785
  const timestamp = this.safeInteger(trade, 'T');
784
786
  const price = this.safeString2(trade, 'L', 'p');
785
- const amount = this.safeString2(trade, 'q', 'l');
787
+ let amount = undefined;
788
+ if (isPublicTrade) {
789
+ amount = this.safeString(trade, 'q');
790
+ }
791
+ else {
792
+ // private trades, amount is in 'l' field, quantity of the last filled trade
793
+ amount = this.safeString(trade, 'l');
794
+ }
786
795
  let cost = this.safeString(trade, 'Y');
787
796
  if (cost === undefined) {
788
797
  if ((price !== undefined) && (amount !== undefined)) {
@@ -1712,7 +1721,7 @@ export default class aster extends asterRest {
1712
1721
  const myTrades = this.myTrades;
1713
1722
  myTrades.append(trade);
1714
1723
  client.resolve(this.myTrades, messageHash);
1715
- const messageHashSymbol = messageHash + ':' + symbol;
1724
+ const messageHashSymbol = messageHash + '::' + symbol;
1716
1725
  client.resolve(this.myTrades, messageHashSymbol);
1717
1726
  }
1718
1727
  }
@@ -353,7 +353,8 @@ export default class binance extends binanceRest {
353
353
  const symbol = market['symbol'];
354
354
  const liquidation = this.parseWsLiquidation(rawLiquidation, market);
355
355
  if (this.liquidations === undefined) {
356
- this.liquidations = new ArrayCacheBySymbolBySide();
356
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
357
+ this.liquidations = new ArrayCache(limit);
357
358
  }
358
359
  const cache = this.liquidations;
359
360
  cache.append(liquidation);
@@ -563,7 +564,8 @@ export default class binance extends binanceRest {
563
564
  const liquidation = this.parseWsLiquidation(message, market);
564
565
  let cache = this.myLiquidations;
565
566
  if (cache === undefined) {
566
- cache = new ArrayCacheBySymbolBySide();
567
+ const limit = this.safeInteger(this.options, 'myLiquidationsLimit', 1000);
568
+ cache = new ArrayCache(limit);
567
569
  }
568
570
  cache.append(liquidation);
569
571
  this.myLiquidations = cache;
@@ -443,7 +443,8 @@ export default class bitmex extends bitmexRest {
443
443
  const rawLiquidations = this.safeValue(message, 'data', []);
444
444
  const newLiquidations = [];
445
445
  if (this.liquidations === undefined) {
446
- this.liquidations = new ArrayCacheBySymbolBySide();
446
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
447
+ this.liquidations = new ArrayCache(limit);
447
448
  }
448
449
  const cache = this.liquidations;
449
450
  for (let i = 0; i < rawLiquidations.length; i++) {
@@ -1697,7 +1697,8 @@ export default class bybit extends bybitRest {
1697
1697
  const symbol = market['symbol'];
1698
1698
  const liquidation = this.parseWsLiquidation(rawLiquidation, market);
1699
1699
  if (this.liquidations === undefined) {
1700
- this.liquidations = new ArrayCacheBySymbolBySide();
1700
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
1701
+ this.liquidations = new ArrayCache(limit);
1701
1702
  }
1702
1703
  const cache = this.liquidations;
1703
1704
  cache.append(liquidation);
@@ -1712,7 +1713,8 @@ export default class bybit extends bybitRest {
1712
1713
  const symbol = market['symbol'];
1713
1714
  const liquidation = this.parseWsLiquidation(rawLiquidation, market);
1714
1715
  if (this.liquidations === undefined) {
1715
- this.liquidations = new ArrayCacheBySymbolBySide();
1716
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
1717
+ this.liquidations = new ArrayCache(limit);
1716
1718
  }
1717
1719
  const cache = this.liquidations;
1718
1720
  cache.append(liquidation);
@@ -1525,7 +1525,8 @@ export default class gate extends gateRest {
1525
1525
  const rawLiquidations = this.safeList(message, 'result', []);
1526
1526
  const newLiquidations = [];
1527
1527
  if (this.liquidations === undefined) {
1528
- this.liquidations = new ArrayCacheBySymbolBySide();
1528
+ const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000);
1529
+ this.liquidations = new ArrayCache(limit);
1529
1530
  }
1530
1531
  const cache = this.liquidations;
1531
1532
  for (let i = 0; i < rawLiquidations.length; i++) {