ccxt 4.5.3 → 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 (44) 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 +67 -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 +7 -4
  9. package/dist/cjs/src/bitvavo.js +8 -0
  10. package/dist/cjs/src/bybit.js +20 -6
  11. package/dist/cjs/src/coinbase.js +28 -10
  12. package/dist/cjs/src/coincatch.js +32 -19
  13. package/dist/cjs/src/delta.js +1 -0
  14. package/dist/cjs/src/kucoinfutures.js +3 -2
  15. package/dist/cjs/src/okx.js +2 -1
  16. package/dist/cjs/src/pro/bitget.js +111 -14
  17. package/dist/cjs/src/pro/bybit.js +64 -8
  18. package/dist/cjs/src/pro/coinex.js +10 -11
  19. package/js/ccxt.d.ts +1 -1
  20. package/js/ccxt.js +1 -1
  21. package/js/src/abstract/myokx.d.ts +1 -0
  22. package/js/src/abstract/okx.d.ts +1 -0
  23. package/js/src/abstract/okxus.d.ts +1 -0
  24. package/js/src/base/Exchange.d.ts +4 -0
  25. package/js/src/base/Exchange.js +67 -5
  26. package/js/src/base/functions/encode.d.ts +2 -1
  27. package/js/src/base/functions/encode.js +8 -1
  28. package/js/src/base/functions/rsa.js +16 -3
  29. package/js/src/binance.js +7 -4
  30. package/js/src/bitvavo.js +8 -0
  31. package/js/src/bybit.js +20 -6
  32. package/js/src/coinbase.d.ts +1 -1
  33. package/js/src/coinbase.js +28 -10
  34. package/js/src/coincatch.d.ts +2 -0
  35. package/js/src/coincatch.js +32 -19
  36. package/js/src/delta.js +1 -0
  37. package/js/src/kucoinfutures.js +3 -2
  38. package/js/src/okx.js +2 -1
  39. package/js/src/pro/bitget.d.ts +3 -1
  40. package/js/src/pro/bitget.js +111 -14
  41. package/js/src/pro/bybit.d.ts +4 -0
  42. package/js/src/pro/bybit.js +64 -8
  43. package/js/src/pro/coinex.js +11 -12
  44. package/package.json +3 -3
@@ -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
@@ -11404,11 +11404,14 @@ export default class binance extends Exchange {
11404
11404
  * @returns {object} response from the exchange
11405
11405
  */
11406
11406
  async setPositionMode(hedged, symbol = undefined, params = {}) {
11407
- const defaultType = this.safeString(this.options, 'defaultType', 'future');
11408
- const type = this.safeString(params, 'type', defaultType);
11409
- 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);
11410
11413
  let subType = undefined;
11411
- [subType, params] = this.handleSubTypeAndParams('setPositionMode', undefined, params);
11414
+ [subType, params] = this.handleSubTypeAndParams('setPositionMode', market, params);
11412
11415
  let isPortfolioMargin = undefined;
11413
11416
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'setPositionMode', 'papi', 'portfolioMargin', false);
11414
11417
  let dualSidePosition = undefined;
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
  }
@@ -284,6 +284,7 @@ export default class coincatch extends Exchange {
284
284
  * @param {float} amount how much of you want to trade in units of the base currency
285
285
  * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
286
286
  * @param {object} [params] extra parameters specific to the exchange API endpoint
287
+ * @param {bool} [params.hedged] *swap markets only* must be set to true if position mode is hedged (default false)
287
288
  * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
288
289
  * @param {float} [params.triggerPrice] the price that the order is to be triggered
289
290
  * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
@@ -328,6 +329,7 @@ export default class coincatch extends Exchange {
328
329
  * @param {float} amount how much of you want to trade in units of the base currency
329
330
  * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
330
331
  * @param {object} [params] extra parameters specific to the exchange API endpoint
332
+ * @param {bool} [params.hedged] must be set to true if position mode is hedged (default false)
331
333
  * @param {bool} [params.postOnly] *non-trigger orders only* if true, the order will only be posted to the order book and not executed immediately
332
334
  * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
333
335
  * @param {string} [params.timeInForce] *non-trigger orders only* 'GTC', 'FOK', 'IOC' or 'PO'
@@ -2307,6 +2307,7 @@ export default class coincatch extends Exchange {
2307
2307
  * @param {float} amount how much of you want to trade in units of the base currency
2308
2308
  * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2309
2309
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2310
+ * @param {bool} [params.hedged] *swap markets only* must be set to true if position mode is hedged (default false)
2310
2311
  * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
2311
2312
  * @param {float} [params.triggerPrice] the price that the order is to be triggered
2312
2313
  * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
@@ -2509,6 +2510,7 @@ export default class coincatch extends Exchange {
2509
2510
  * @param {float} amount how much of you want to trade in units of the base currency
2510
2511
  * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2511
2512
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2513
+ * @param {bool} [params.hedged] must be set to true if position mode is hedged (default false)
2512
2514
  * @param {bool} [params.postOnly] *non-trigger orders only* if true, the order will only be posted to the order book and not executed immediately
2513
2515
  * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
2514
2516
  * @param {string} [params.timeInForce] *non-trigger orders only* 'GTC', 'FOK', 'IOC' or 'PO'
@@ -2566,7 +2568,7 @@ export default class coincatch extends Exchange {
2566
2568
  * @param {float} amount how much of you want to trade in units of the base currency
2567
2569
  * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2568
2570
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2569
- * @param {bool} [params.hedged] default false
2571
+ * @param {bool} [params.hedged] must be set to true if position mode is hedged (default false)
2570
2572
  * @param {bool} [params.postOnly] *non-trigger orders only* if true, the order will only be posted to the order book and not executed immediately
2571
2573
  * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
2572
2574
  * @param {string} [params.timeInForce] *non-trigger orders only* 'GTC', 'FOK', 'IOC' or 'PO'
@@ -2605,31 +2607,42 @@ export default class coincatch extends Exchange {
2605
2607
  }
2606
2608
  if ((endpointType !== 'tpsl')) {
2607
2609
  request['orderType'] = type;
2610
+ let sideIsExchangeSpecific = false;
2608
2611
  let hedged = false;
2609
- [hedged, params] = this.handleOptionAndParams(params, methodName, 'hedged', hedged);
2610
- // hedged and non-hedged orders have different side values and reduceOnly handling
2611
- let reduceOnly = false;
2612
- [reduceOnly, params] = this.handleParamBool(params, 'reduceOnly', reduceOnly);
2613
- if (hedged) {
2614
- if (reduceOnly) {
2615
- if (side === 'buy') {
2616
- side = 'close_short';
2612
+ if ((side === 'buy_single') || (side === 'sell_single') || (side === 'open_long') || (side === 'open_short') || (side === 'close_long') || (side === 'close_short')) {
2613
+ sideIsExchangeSpecific = true;
2614
+ if ((side !== 'buy_single') && (side !== 'sell_single')) {
2615
+ hedged = true;
2616
+ }
2617
+ }
2618
+ if (!sideIsExchangeSpecific) {
2619
+ [hedged, params] = this.handleOptionAndParams(params, methodName, 'hedged', hedged);
2620
+ // hedged and non-hedged orders have different side values and reduceOnly handling
2621
+ const reduceOnly = this.safeBool(params, 'reduceOnly');
2622
+ if (hedged) {
2623
+ if ((reduceOnly !== undefined) && reduceOnly) {
2624
+ if (side === 'buy') {
2625
+ side = 'close_short';
2626
+ }
2627
+ else if (side === 'sell') {
2628
+ side = 'close_long';
2629
+ }
2617
2630
  }
2618
- else if (side === 'sell') {
2619
- side = 'close_long';
2631
+ else {
2632
+ if (side === 'buy') {
2633
+ side = 'open_long';
2634
+ }
2635
+ else if (side === 'sell') {
2636
+ side = 'open_short';
2637
+ }
2620
2638
  }
2621
2639
  }
2622
2640
  else {
2623
- if (side === 'buy') {
2624
- side = 'open_long';
2625
- }
2626
- else if (side === 'sell') {
2627
- side = 'open_short';
2628
- }
2641
+ side = side.toLowerCase() + '_single';
2629
2642
  }
2630
2643
  }
2631
- else {
2632
- side = side.toLowerCase() + '_single';
2644
+ if (hedged) {
2645
+ params = this.omit(params, 'reduceOnly');
2633
2646
  }
2634
2647
  request['side'] = side;
2635
2648
  }
package/js/src/delta.js CHANGED
@@ -216,6 +216,7 @@ export default class delta extends Exchange {
216
216
  },
217
217
  },
218
218
  },
219
+ 'userAgent': this.userAgents['chrome39'],
219
220
  'options': {
220
221
  'networks': {
221
222
  'TRC20': 'TRC20(TRON)',
@@ -229,7 +229,7 @@ export default class kucoinfutures extends kucoin {
229
229
  '429': RateLimitExceeded,
230
230
  '500': ExchangeNotAvailable,
231
231
  '503': ExchangeNotAvailable,
232
- '100001': InvalidOrder,
232
+ '100001': OrderNotFound,
233
233
  '100004': BadRequest,
234
234
  '101030': PermissionDenied,
235
235
  '200004': InsufficientFunds,
@@ -248,7 +248,8 @@ export default class kucoinfutures extends kucoin {
248
248
  '400100': BadRequest,
249
249
  '411100': AccountSuspended,
250
250
  '500000': ExchangeNotAvailable,
251
- '300009': InvalidOrder, // {"msg":"No open positions to close.","code":"300009"}
251
+ '300009': InvalidOrder,
252
+ '330008': InsufficientFunds, // {"msg":"Your current margin and leverage have reached the maximum open limit. Please increase your margin or raise your leverage to open larger positions.","code":"330008"}
252
253
  },
253
254
  'broad': {
254
255
  'Position does not exist': OrderNotFound, // { "code":"200000", "msg":"Position does not exist" }
package/js/src/okx.js CHANGED
@@ -214,6 +214,7 @@ export default class okx extends Exchange {
214
214
  'market/open-oracle': 50,
215
215
  'market/exchange-rate': 20,
216
216
  'market/index-components': 1,
217
+ 'public/market-data-history': 4,
217
218
  'public/economic-calendar': 50,
218
219
  'market/block-tickers': 1,
219
220
  'market/block-ticker': 1,
@@ -365,7 +366,7 @@ export default class okx extends Exchange {
365
366
  'account/fixed-loan/borrowing-limit': 4,
366
367
  'account/fixed-loan/borrowing-quote': 5,
367
368
  'account/fixed-loan/borrowing-orders-list': 5,
368
- 'account/spot-manual-borrow-repay': 10,
369
+ 'account/spot-manual-borrow-repay': 30,
369
370
  'account/set-auto-repay': 4,
370
371
  'account/spot-borrow-repay-history': 4,
371
372
  'account/move-positions-history': 10,
@@ -223,11 +223,13 @@ export default class bitget extends bitgetRest {
223
223
  * @method
224
224
  * @name bitget#watchMyTrades
225
225
  * @description watches trades made by the user
226
- * @see https://www.bitget.com/api-doc/contract/websocket/private/Order-Channel
226
+ * @see https://www.bitget.com/api-doc/contract/websocket/private/Fill-Channel
227
+ * @see https://www.bitget.com/api-doc/uta/websocket/private/Fill-Channel
227
228
  * @param {str} symbol unified market symbol
228
229
  * @param {int} [since] the earliest time in ms to fetch trades for
229
230
  * @param {int} [limit] the maximum number of trades structures to retrieve
230
231
  * @param {object} [params] extra parameters specific to the exchange API endpoint
232
+ * @param {boolean} [params.uta] set to true for the unified trading account (uta), defaults to false
231
233
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
232
234
  */
233
235
  watchMyTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
@@ -1132,6 +1132,32 @@ export default class bitget extends bitgetRest {
1132
1132
  // "uTime": "1714471204194"
1133
1133
  // }
1134
1134
  //
1135
+ // uta private
1136
+ //
1137
+ // {
1138
+ // "symbol": "BTCUSDT",
1139
+ // "orderType": "market",
1140
+ // "updatedTime": "1736378720623",
1141
+ // "side": "buy",
1142
+ // "orderId": "1288888888888888888",
1143
+ // "execPnl": "0",
1144
+ // "feeDetail": [
1145
+ // {
1146
+ // "feeCoin": "USDT",
1147
+ // "fee": "0.569958"
1148
+ // }
1149
+ // ],
1150
+ // "execTime": "1736378720623",
1151
+ // "tradeScope": "taker",
1152
+ // "tradeSide": "open",
1153
+ // "execId": "1288888888888888888",
1154
+ // "execLinkId": "1288888888888888888",
1155
+ // "execPrice": "94993",
1156
+ // "holdSide": "long",
1157
+ // "execValue": "949.93",
1158
+ // "category": "USDT-FUTURES",
1159
+ // "execQty": "0.01",
1160
+ // "clientOid": "1288888888888888889"
1135
1161
  // uta
1136
1162
  //
1137
1163
  // {
@@ -1145,11 +1171,18 @@ export default class bitget extends bitgetRest {
1145
1171
  //
1146
1172
  const instId = this.safeString2(trade, 'symbol', 'instId');
1147
1173
  const posMode = this.safeString(trade, 'posMode');
1148
- const defaultType = (posMode !== undefined) ? 'contract' : 'spot';
1174
+ const category = this.safeString(trade, 'category');
1175
+ let defaultType = undefined;
1176
+ if (category !== undefined) {
1177
+ defaultType = (category !== 'SPOT') ? 'contract' : 'spot';
1178
+ }
1179
+ else {
1180
+ defaultType = (posMode !== undefined) ? 'contract' : 'spot';
1181
+ }
1149
1182
  if (market === undefined) {
1150
1183
  market = this.safeMarket(instId, undefined, undefined, defaultType);
1151
1184
  }
1152
- const timestamp = this.safeIntegerN(trade, ['uTime', 'cTime', 'ts', 'T']);
1185
+ const timestamp = this.safeIntegerN(trade, ['uTime', 'cTime', 'ts', 'T', 'execTime']);
1153
1186
  const feeDetail = this.safeList(trade, 'feeDetail', []);
1154
1187
  const first = this.safeDict(feeDetail, 0);
1155
1188
  let fee = undefined;
@@ -1157,13 +1190,13 @@ export default class bitget extends bitgetRest {
1157
1190
  const feeCurrencyId = this.safeString(first, 'feeCoin');
1158
1191
  const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
1159
1192
  fee = {
1160
- 'cost': Precise.stringAbs(this.safeString(first, 'totalFee')),
1193
+ 'cost': Precise.stringAbs(this.safeString2(first, 'totalFee', 'fee')),
1161
1194
  'currency': feeCurrencyCode,
1162
1195
  };
1163
1196
  }
1164
1197
  return this.safeTrade({
1165
1198
  'info': trade,
1166
- 'id': this.safeString2(trade, 'tradeId', 'i'),
1199
+ 'id': this.safeStringN(trade, ['tradeId', 'i', 'execId']),
1167
1200
  'order': this.safeString2(trade, 'orderId', 'L'),
1168
1201
  'timestamp': timestamp,
1169
1202
  'datetime': this.iso8601(timestamp),
@@ -1171,9 +1204,9 @@ export default class bitget extends bitgetRest {
1171
1204
  'type': this.safeString(trade, 'orderType'),
1172
1205
  'side': this.safeString2(trade, 'side', 'S'),
1173
1206
  'takerOrMaker': this.safeString(trade, 'tradeScope'),
1174
- 'price': this.safeStringN(trade, ['priceAvg', 'price', 'P']),
1175
- 'amount': this.safeStringN(trade, ['size', 'baseVolume', 'v']),
1176
- 'cost': this.safeString2(trade, 'amount', 'quoteVolume'),
1207
+ 'price': this.safeStringN(trade, ['priceAvg', 'price', 'execPrice', 'P']),
1208
+ 'amount': this.safeStringN(trade, ['size', 'baseVolume', 'execQty', 'v']),
1209
+ 'cost': this.safeStringN(trade, ['amount', 'quoteVolume', 'execValue']),
1177
1210
  'fee': fee,
1178
1211
  }, market);
1179
1212
  }
@@ -1769,11 +1802,13 @@ export default class bitget extends bitgetRest {
1769
1802
  * @method
1770
1803
  * @name bitget#watchMyTrades
1771
1804
  * @description watches trades made by the user
1772
- * @see https://www.bitget.com/api-doc/contract/websocket/private/Order-Channel
1805
+ * @see https://www.bitget.com/api-doc/contract/websocket/private/Fill-Channel
1806
+ * @see https://www.bitget.com/api-doc/uta/websocket/private/Fill-Channel
1773
1807
  * @param {str} symbol unified market symbol
1774
1808
  * @param {int} [since] the earliest time in ms to fetch trades for
1775
1809
  * @param {int} [limit] the maximum number of trades structures to retrieve
1776
1810
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1811
+ * @param {boolean} [params.uta] set to true for the unified trading account (uta), defaults to false
1777
1812
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1778
1813
  */
1779
1814
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
@@ -1788,18 +1823,29 @@ export default class bitget extends bitgetRest {
1788
1823
  let type = undefined;
1789
1824
  [type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
1790
1825
  let instType = undefined;
1826
+ let uta = undefined;
1827
+ [uta, params] = this.handleOptionAndParams(params, 'watchMyTrades', 'uta', false);
1791
1828
  if (market === undefined && type === 'spot') {
1792
- instType = 'spot';
1829
+ instType = 'SPOT';
1793
1830
  }
1794
1831
  else {
1795
- [instType, params] = this.getInstType(market, false, params);
1832
+ [instType, params] = this.getInstType(market, uta, params);
1833
+ }
1834
+ if (uta) {
1835
+ instType = 'UTA';
1796
1836
  }
1797
1837
  const subscriptionHash = 'fill:' + instType;
1798
1838
  const args = {
1799
1839
  'instType': instType,
1800
- 'channel': 'fill',
1801
- 'instId': 'default',
1802
1840
  };
1841
+ const topicOrChannel = uta ? 'topic' : 'channel';
1842
+ args[topicOrChannel] = 'fill';
1843
+ if (!uta) {
1844
+ args['instId'] = 'default';
1845
+ }
1846
+ else {
1847
+ params['uta'] = true;
1848
+ }
1803
1849
  const trades = await this.watchPrivate(messageHash, subscriptionHash, args, params);
1804
1850
  if (this.newUpdates) {
1805
1851
  limit = trades.getLimit(symbol, limit);
@@ -1878,6 +1924,44 @@ export default class bitget extends bitgetRest {
1878
1924
  // "ts": 1714471276629
1879
1925
  // }
1880
1926
  //
1927
+ // uta
1928
+ //
1929
+ // {
1930
+ // "data": [
1931
+ // {
1932
+ // "symbol": "BTCUSDT",
1933
+ // "orderType": "market",
1934
+ // "updatedTime": "1736378720623",
1935
+ // "side": "buy",
1936
+ // "orderId": "1288888888888888888",
1937
+ // "execPnl": "0",
1938
+ // "feeDetail": [
1939
+ // {
1940
+ // "feeCoin": "USDT",
1941
+ // "fee": "0.569958"
1942
+ // }
1943
+ // ],
1944
+ // "execTime": "1736378720623",
1945
+ // "tradeScope": "taker",
1946
+ // "tradeSide": "open",
1947
+ // "execId": "1288888888888888888",
1948
+ // "execLinkId": "1288888888888888888",
1949
+ // "execPrice": "94993",
1950
+ // "holdSide": "long",
1951
+ // "execValue": "949.93",
1952
+ // "category": "USDT-FUTURES",
1953
+ // "execQty": "0.01",
1954
+ // "clientOid": "1288888888888888889"
1955
+ // }
1956
+ // ],
1957
+ // "arg": {
1958
+ // "instType": "UTA",
1959
+ // "topic": "fill"
1960
+ // },
1961
+ // "action": "snapshot",
1962
+ // "ts": 1733904123981
1963
+ // }
1964
+ //
1881
1965
  if (this.myTrades === undefined) {
1882
1966
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
1883
1967
  this.myTrades = new ArrayCache(limit);
@@ -2140,12 +2224,25 @@ export default class bitget extends bitgetRest {
2140
2224
  return await future;
2141
2225
  }
2142
2226
  async watchPrivate(messageHash, subscriptionHash, args, params = {}) {
2143
- let url = this.urls['api']['ws']['private'];
2227
+ let uta = undefined;
2228
+ let url = undefined;
2229
+ [uta, params] = this.handleOptionAndParams(params, 'watchPrivate', 'uta', false);
2230
+ if (uta) {
2231
+ url = this.urls['api']['ws']['utaPrivate'];
2232
+ }
2233
+ else {
2234
+ url = this.urls['api']['ws']['private'];
2235
+ }
2144
2236
  const sandboxMode = this.safeBool2(this.options, 'sandboxMode', 'sandbox', false);
2145
2237
  if (sandboxMode) {
2146
2238
  const instType = this.safeString(args, 'instType');
2147
2239
  if ((instType !== 'SCOIN-FUTURES') && (instType !== 'SUSDT-FUTURES') && (instType !== 'SUSDC-FUTURES')) {
2148
- url = this.urls['api']['demo']['private'];
2240
+ if (uta) {
2241
+ url = this.urls['api']['demo']['utaPrivate'];
2242
+ }
2243
+ else {
2244
+ url = this.urls['api']['demo']['private'];
2245
+ }
2149
2246
  }
2150
2247
  }
2151
2248
  await this.authenticate({ 'url': url });
@@ -285,11 +285,13 @@ export default class bybit extends bybitRest {
285
285
  * @name bybit#watchMyTrades
286
286
  * @description watches information on multiple trades made by the user
287
287
  * @see https://bybit-exchange.github.io/docs/v5/websocket/private/execution
288
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/private/fast-execution
288
289
  * @param {string} symbol unified market symbol of the market orders were made in
289
290
  * @param {int} [since] the earliest time in ms to fetch orders for
290
291
  * @param {int} [limit] the maximum number of order structures to retrieve
291
292
  * @param {object} [params] extra parameters specific to the exchange API endpoint
292
293
  * @param {boolean} [params.unifiedMargin] use unified margin account
294
+ * @param {boolean} [params.executionFast] use fast execution
293
295
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
294
296
  */
295
297
  watchMyTrades(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
@@ -298,9 +300,11 @@ export default class bybit extends bybitRest {
298
300
  * @name bybit#unWatchMyTrades
299
301
  * @description unWatches information on multiple trades made by the user
300
302
  * @see https://bybit-exchange.github.io/docs/v5/websocket/private/execution
303
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/private/fast-execution
301
304
  * @param {string} symbol unified market symbol of the market orders were made in
302
305
  * @param {object} [params] extra parameters specific to the exchange API endpoint
303
306
  * @param {boolean} [params.unifiedMargin] use unified margin account
307
+ * @param {boolean} [params.executionFast] use fast execution
304
308
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
305
309
  */
306
310
  unWatchMyTrades(symbol?: Str, params?: {}): Promise<any>;