ccxt 4.2.89 → 4.2.90

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 (78) hide show
  1. package/README.md +3 -3
  2. package/build.sh +1 -1
  3. package/dist/ccxt.browser.js +829 -114
  4. package/dist/ccxt.browser.min.js +6 -4
  5. package/dist/cjs/ccxt.js +1 -1
  6. package/dist/cjs/src/ascendex.js +1 -0
  7. package/dist/cjs/src/base/Exchange.js +38 -0
  8. package/dist/cjs/src/base/functions/crypto.js +37 -0
  9. package/dist/cjs/src/base/functions/rsa.js +19 -4
  10. package/dist/cjs/src/binance.js +90 -9
  11. package/dist/cjs/src/bingx.js +101 -1
  12. package/dist/cjs/src/bitfinex2.js +1 -0
  13. package/dist/cjs/src/bitget.js +2 -0
  14. package/dist/cjs/src/bitmex.js +1 -0
  15. package/dist/cjs/src/bitrue.js +1 -0
  16. package/dist/cjs/src/bybit.js +61 -0
  17. package/dist/cjs/src/coinbase.js +48 -24
  18. package/dist/cjs/src/coinbaseinternational.js +1 -0
  19. package/dist/cjs/src/coinex.js +102 -8
  20. package/dist/cjs/src/cryptocom.js +1 -0
  21. package/dist/cjs/src/delta.js +1 -0
  22. package/dist/cjs/src/digifinex.js +1 -0
  23. package/dist/cjs/src/exmo.js +1 -0
  24. package/dist/cjs/src/gate.js +2 -0
  25. package/dist/cjs/src/gemini.js +10 -9
  26. package/dist/cjs/src/hitbtc.js +1 -0
  27. package/dist/cjs/src/htx.js +1 -0
  28. package/dist/cjs/src/hyperliquid.js +1 -0
  29. package/dist/cjs/src/kucoin.js +1 -0
  30. package/dist/cjs/src/kucoinfutures.js +34 -3
  31. package/dist/cjs/src/mexc.js +1 -0
  32. package/dist/cjs/src/okx.js +157 -8
  33. package/dist/cjs/src/phemex.js +1 -0
  34. package/dist/cjs/src/static_dependencies/noble-curves/p256.js +48 -0
  35. package/dist/cjs/src/woo.js +1 -0
  36. package/js/ccxt.d.ts +1 -1
  37. package/js/ccxt.js +1 -1
  38. package/js/src/abstract/bingx.d.ts +2 -0
  39. package/js/src/abstract/bybit.d.ts +2 -0
  40. package/js/src/ascendex.js +1 -0
  41. package/js/src/base/Exchange.d.ts +5 -0
  42. package/js/src/base/Exchange.js +38 -0
  43. package/js/src/base/functions/crypto.js +37 -0
  44. package/js/src/base/functions/rsa.d.ts +1 -1
  45. package/js/src/base/functions/rsa.js +21 -5
  46. package/js/src/base/types.d.ts +1 -0
  47. package/js/src/binance.d.ts +1 -0
  48. package/js/src/binance.js +90 -9
  49. package/js/src/bingx.d.ts +1 -0
  50. package/js/src/bingx.js +101 -1
  51. package/js/src/bitfinex2.js +1 -0
  52. package/js/src/bitget.js +2 -0
  53. package/js/src/bitmex.js +1 -0
  54. package/js/src/bitrue.js +1 -0
  55. package/js/src/bybit.d.ts +2 -0
  56. package/js/src/bybit.js +61 -0
  57. package/js/src/coinbase.js +48 -24
  58. package/js/src/coinbaseinternational.js +1 -0
  59. package/js/src/coinex.d.ts +2 -0
  60. package/js/src/coinex.js +102 -8
  61. package/js/src/cryptocom.js +1 -0
  62. package/js/src/delta.js +1 -0
  63. package/js/src/digifinex.js +1 -0
  64. package/js/src/exmo.js +1 -0
  65. package/js/src/gate.js +2 -0
  66. package/js/src/gemini.js +10 -9
  67. package/js/src/hitbtc.js +1 -0
  68. package/js/src/htx.js +1 -0
  69. package/js/src/hyperliquid.js +1 -0
  70. package/js/src/kucoin.js +1 -0
  71. package/js/src/kucoinfutures.d.ts +2 -9
  72. package/js/src/kucoinfutures.js +34 -3
  73. package/js/src/mexc.js +1 -0
  74. package/js/src/okx.d.ts +1 -0
  75. package/js/src/okx.js +157 -8
  76. package/js/src/phemex.js +1 -0
  77. package/js/src/woo.js +1 -0
  78. package/package.json +1 -1
package/js/src/binance.js CHANGED
@@ -101,6 +101,7 @@ export default class binance extends Exchange {
101
101
  'fetchLeverages': true,
102
102
  'fetchLeverageTiers': true,
103
103
  'fetchLiquidations': false,
104
+ 'fetchMarginAdjustmentHistory': true,
104
105
  'fetchMarginMode': 'emulated',
105
106
  'fetchMarginModes': true,
106
107
  'fetchMarketLeverageTiers': 'emulated',
@@ -11231,21 +11232,37 @@ export default class binance extends Exchange {
11231
11232
  // "type": 1
11232
11233
  // }
11233
11234
  //
11235
+ // fetchMarginAdjustmentHistory
11236
+ //
11237
+ // {
11238
+ // symbol: "XRPUSDT",
11239
+ // type: "1",
11240
+ // deltaType: "TRADE",
11241
+ // amount: "2.57148240",
11242
+ // asset: "USDT",
11243
+ // time: "1711046271555",
11244
+ // positionSide: "BOTH",
11245
+ // clientTranId: ""
11246
+ // }
11247
+ //
11234
11248
  const rawType = this.safeInteger(data, 'type');
11235
- const resultType = (rawType === 1) ? 'add' : 'reduce';
11236
- const resultAmount = this.safeNumber(data, 'amount');
11237
11249
  const errorCode = this.safeString(data, 'code');
11238
- const status = (errorCode === '200') ? 'ok' : 'failed';
11250
+ const marketId = this.safeString(data, 'symbol');
11251
+ const timestamp = this.safeInteger(data, 'time');
11252
+ market = this.safeMarket(marketId, market, undefined, 'swap');
11253
+ const noErrorCode = errorCode === undefined;
11254
+ const success = errorCode === '200';
11239
11255
  return {
11240
11256
  'info': data,
11241
11257
  'symbol': market['symbol'],
11242
- 'type': resultType,
11243
- 'amount': resultAmount,
11258
+ 'type': (rawType === 1) ? 'add' : 'reduce',
11259
+ 'marginMode': 'isolated',
11260
+ 'amount': this.safeNumber(data, 'amount'),
11261
+ 'code': this.safeString(data, 'asset'),
11244
11262
  'total': undefined,
11245
- 'code': undefined,
11246
- 'status': status,
11247
- 'timestamp': undefined,
11248
- 'datetime': undefined,
11263
+ 'status': (success || noErrorCode) ? 'ok' : 'failed',
11264
+ 'timestamp': timestamp,
11265
+ 'datetime': this.iso8601(timestamp),
11249
11266
  };
11250
11267
  }
11251
11268
  async reduceMargin(symbol, amount, params = {}) {
@@ -12508,4 +12525,68 @@ export default class binance extends Exchange {
12508
12525
  'quoteVolume': undefined,
12509
12526
  };
12510
12527
  }
12528
+ async fetchMarginAdjustmentHistory(symbol = undefined, type = undefined, since = undefined, limit = undefined, params = {}) {
12529
+ /**
12530
+ * @method
12531
+ * @description fetches the history of margin added or reduced from contract isolated positions
12532
+ * @see https://binance-docs.github.io/apidocs/futures/en/#get-position-margin-change-history-trade
12533
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#get-position-margin-change-history-trade
12534
+ * @param {string} symbol unified market symbol
12535
+ * @param {string} [type] "add" or "reduce"
12536
+ * @param {int} [since] timestamp in ms of the earliest change to fetch
12537
+ * @param {int} [limit] the maximum amount of changes to fetch
12538
+ * @param {object} params extra parameters specific to the exchange api endpoint
12539
+ * @param {int} [params.until] timestamp in ms of the latest change to fetch
12540
+ * @returns {object[]} a list of [margin structures]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
12541
+ */
12542
+ await this.loadMarkets();
12543
+ if (symbol === undefined) {
12544
+ throw new ArgumentsRequired(this.id + ' fetchMarginAdjustmentHistory () requires a symbol argument');
12545
+ }
12546
+ const market = this.market(symbol);
12547
+ const until = this.safeInteger(params, 'until');
12548
+ params = this.omit(params, 'until');
12549
+ const request = {
12550
+ 'symbol': market['id'],
12551
+ };
12552
+ if (type !== undefined) {
12553
+ request['type'] = (type === 'add') ? 1 : 2;
12554
+ }
12555
+ if (since !== undefined) {
12556
+ request['startTime'] = since;
12557
+ }
12558
+ if (limit !== undefined) {
12559
+ request['limit'] = limit;
12560
+ }
12561
+ if (until !== undefined) {
12562
+ request['endTime'] = until;
12563
+ }
12564
+ let response = undefined;
12565
+ if (market['linear']) {
12566
+ response = await this.fapiPrivateGetPositionMarginHistory(this.extend(request, params));
12567
+ }
12568
+ else if (market['inverse']) {
12569
+ response = await this.dapiPrivateGetPositionMarginHistory(this.extend(request, params));
12570
+ }
12571
+ else {
12572
+ throw new BadRequest(this.id + 'fetchMarginAdjustmentHistory () is not supported for markets of type ' + market['type']);
12573
+ }
12574
+ //
12575
+ // [
12576
+ // {
12577
+ // symbol: "XRPUSDT",
12578
+ // type: "1",
12579
+ // deltaType: "TRADE",
12580
+ // amount: "2.57148240",
12581
+ // asset: "USDT",
12582
+ // time: "1711046271555",
12583
+ // positionSide: "BOTH",
12584
+ // clientTranId: ""
12585
+ // }
12586
+ // ...
12587
+ // ]
12588
+ //
12589
+ const modifications = this.parseMarginModifications(response);
12590
+ return this.filterBySymbolSinceLimit(modifications, symbol, since, limit);
12591
+ }
12511
12592
  }
package/js/src/bingx.d.ts CHANGED
@@ -80,6 +80,7 @@ export default class bingx extends Exchange {
80
80
  cancelAllOrders(symbol?: Str, params?: {}): Promise<any>;
81
81
  cancelOrders(ids: string[], symbol?: Str, params?: {}): Promise<any>;
82
82
  fetchOrder(id: string, symbol?: Str, params?: {}): Promise<Order>;
83
+ fetchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
83
84
  fetchOpenOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
84
85
  fetchClosedOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
85
86
  transfer(code: string, amount: number, fromAccount: string, toAccount: string, params?: {}): Promise<TransferEntry>;
package/js/src/bingx.js CHANGED
@@ -63,6 +63,7 @@ export default class bingx extends Exchange {
63
63
  'fetchFundingRates': true,
64
64
  'fetchLeverage': true,
65
65
  'fetchLiquidations': false,
66
+ 'fetchMarginAdjustmentHistory': false,
66
67
  'fetchMarginMode': true,
67
68
  'fetchMarkets': true,
68
69
  'fetchMarkOHLCV': true,
@@ -72,6 +73,7 @@ export default class bingx extends Exchange {
72
73
  'fetchOpenOrders': true,
73
74
  'fetchOrder': true,
74
75
  'fetchOrderBook': true,
76
+ 'fetchOrders': true,
75
77
  'fetchPositionMode': true,
76
78
  'fetchPositions': true,
77
79
  'fetchTicker': true,
@@ -183,6 +185,7 @@ export default class bingx extends Exchange {
183
185
  'positionSide/dual': 1,
184
186
  'market/markPriceKlines': 1,
185
187
  'trade/batchCancelReplace': 1,
188
+ 'trade/fullOrder': 1,
186
189
  },
187
190
  'post': {
188
191
  'trade/cancelReplace': 1,
@@ -330,6 +333,7 @@ export default class bingx extends Exchange {
330
333
  'post': {
331
334
  'swap/trace/closeTrackOrder': 1,
332
335
  'swap/trace/setTPSL': 1,
336
+ 'spot/trader/sellOrder': 1,
333
337
  },
334
338
  },
335
339
  },
@@ -2760,7 +2764,7 @@ export default class bingx extends Exchange {
2760
2764
  * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2761
2765
  */
2762
2766
  if (symbol === undefined) {
2763
- throw new ArgumentsRequired(this.id + ' fetchOrders() requires a symbol argument');
2767
+ throw new ArgumentsRequired(this.id + ' fetchOrder() requires a symbol argument');
2764
2768
  }
2765
2769
  await this.loadMarkets();
2766
2770
  const market = this.market(symbol);
@@ -2831,6 +2835,101 @@ export default class bingx extends Exchange {
2831
2835
  const first = this.safeDict(data, 'order', data);
2832
2836
  return this.parseOrder(first, market);
2833
2837
  }
2838
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2839
+ /**
2840
+ * @method
2841
+ * @name bingx#fetchOrders
2842
+ * @description fetches information on multiple orders made by the user
2843
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#User's%20All%20Orders
2844
+ * @param {string} symbol unified market symbol of the market orders were made in
2845
+ * @param {int} [since] the earliest time in ms to fetch orders for
2846
+ * @param {int} [limit] the maximum number of order structures to retrieve
2847
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2848
+ * @param {int} [params.until] the latest time in ms to fetch entries for
2849
+ * @param {int} [params.orderId] Only return subsequent orders, and return the latest order by default
2850
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2851
+ */
2852
+ await this.loadMarkets();
2853
+ const request = {};
2854
+ let market = undefined;
2855
+ if (symbol !== undefined) {
2856
+ market = this.market(symbol);
2857
+ request['symbol'] = market['id'];
2858
+ }
2859
+ let type = undefined;
2860
+ [type, params] = this.handleMarketTypeAndParams('fetchOrders', market, params);
2861
+ if (type !== 'swap') {
2862
+ throw new NotSupported(this.id + ' fetchOrders() is only supported for swap markets');
2863
+ }
2864
+ if (limit !== undefined) {
2865
+ request['limit'] = limit;
2866
+ }
2867
+ if (since !== undefined) {
2868
+ request['startTime'] = since;
2869
+ }
2870
+ const until = this.safeInteger2(params, 'until', 'till'); // unified in milliseconds
2871
+ const endTime = this.safeInteger(params, 'endTime', until); // exchange-specific in milliseconds
2872
+ params = this.omit(params, ['endTime', 'till', 'until']);
2873
+ if (endTime !== undefined) {
2874
+ request['endTime'] = endTime;
2875
+ }
2876
+ const response = await this.swapV1PrivateGetTradeFullOrder(this.extend(request, params));
2877
+ //
2878
+ // {
2879
+ // "code": 0,
2880
+ // "msg": "",
2881
+ // "data": {
2882
+ // "orders": [
2883
+ // {
2884
+ // "symbol": "PYTH-USDT",
2885
+ // "orderId": 1736007506620112100,
2886
+ // "side": "SELL",
2887
+ // "positionSide": "SHORT",
2888
+ // "type": "LIMIT",
2889
+ // "origQty": "33",
2890
+ // "price": "0.3916",
2891
+ // "executedQty": "33",
2892
+ // "avgPrice": "0.3916",
2893
+ // "cumQuote": "13",
2894
+ // "stopPrice": "",
2895
+ // "profit": "0.0000",
2896
+ // "commission": "-0.002585",
2897
+ // "status": "FILLED",
2898
+ // "time": 1702731418000,
2899
+ // "updateTime": 1702731470000,
2900
+ // "clientOrderId": "",
2901
+ // "leverage": "15X",
2902
+ // "takeProfit": {
2903
+ // "type": "TAKE_PROFIT",
2904
+ // "quantity": 0,
2905
+ // "stopPrice": 0,
2906
+ // "price": 0,
2907
+ // "workingType": ""
2908
+ // },
2909
+ // "stopLoss": {
2910
+ // "type": "STOP",
2911
+ // "quantity": 0,
2912
+ // "stopPrice": 0,
2913
+ // "price": 0,
2914
+ // "workingType": ""
2915
+ // },
2916
+ // "advanceAttr": 0,
2917
+ // "positionID": 0,
2918
+ // "takeProfitEntrustPrice": 0,
2919
+ // "stopLossEntrustPrice": 0,
2920
+ // "orderType": "",
2921
+ // "workingType": "MARK_PRICE",
2922
+ // "stopGuaranteed": false,
2923
+ // "triggerOrderId": 1736012449498123500
2924
+ // }
2925
+ // ]
2926
+ // }
2927
+ // }
2928
+ //
2929
+ const data = this.safeDict(response, 'data', {});
2930
+ const orders = this.safeList(data, 'orders', []);
2931
+ return this.parseOrders(orders, market, since, limit);
2932
+ }
2834
2933
  async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2835
2934
  /**
2836
2935
  * @method
@@ -3531,6 +3630,7 @@ export default class bingx extends Exchange {
3531
3630
  'info': data,
3532
3631
  'symbol': this.safeString(market, 'symbol'),
3533
3632
  'type': (type === '1') ? 'add' : 'reduce',
3633
+ 'marginMode': 'isolated',
3534
3634
  'amount': this.safeNumber(data, 'amount'),
3535
3635
  'total': this.safeNumber(data, 'margin'),
3536
3636
  'code': this.safeString(market, 'settle'),
@@ -3522,6 +3522,7 @@ export default class bitfinex2 extends Exchange {
3522
3522
  'info': data,
3523
3523
  'symbol': market['symbol'],
3524
3524
  'type': undefined,
3525
+ 'marginMode': 'isolated',
3525
3526
  'amount': undefined,
3526
3527
  'total': undefined,
3527
3528
  'code': undefined,
package/js/src/bitget.js CHANGED
@@ -87,6 +87,7 @@ export default class bitget extends Exchange {
87
87
  'fetchLeverage': true,
88
88
  'fetchLeverageTiers': false,
89
89
  'fetchLiquidations': false,
90
+ 'fetchMarginAdjustmentHistory': false,
90
91
  'fetchMarginMode': true,
91
92
  'fetchMarketLeverageTiers': true,
92
93
  'fetchMarkets': true,
@@ -6987,6 +6988,7 @@ export default class bitget extends Exchange {
6987
6988
  'info': data,
6988
6989
  'symbol': market['symbol'],
6989
6990
  'type': undefined,
6991
+ 'marginMode': 'isolated',
6990
6992
  'amount': undefined,
6991
6993
  'total': undefined,
6992
6994
  'code': market['settle'],
package/js/src/bitmex.js CHANGED
@@ -66,6 +66,7 @@ export default class bitmex extends Exchange {
66
66
  'fetchLeverages': true,
67
67
  'fetchLeverageTiers': false,
68
68
  'fetchLiquidations': true,
69
+ 'fetchMarginAdjustmentHistory': false,
69
70
  'fetchMarketLeverageTiers': false,
70
71
  'fetchMarkets': true,
71
72
  'fetchMarkOHLCV': false,
package/js/src/bitrue.js CHANGED
@@ -3053,6 +3053,7 @@ export default class bitrue extends Exchange {
3053
3053
  'info': data,
3054
3054
  'symbol': market['symbol'],
3055
3055
  'type': undefined,
3056
+ 'marginMode': 'isolated',
3056
3057
  'amount': undefined,
3057
3058
  'total': undefined,
3058
3059
  'code': undefined,
package/js/src/bybit.d.ts CHANGED
@@ -6,6 +6,8 @@ import type { Int, OrderSide, OrderType, Trade, Order, OHLCV, FundingRateHistory
6
6
  */
7
7
  export default class bybit extends Exchange {
8
8
  describe(): any;
9
+ setSandboxMode(enable: boolean): void;
10
+ enableDemoTrading(enable: boolean): void;
9
11
  nonce(): number;
10
12
  addPaginationCursorToResult(response: any): any;
11
13
  isUnifiedEnabled(params?: {}): Promise<any[]>;
package/js/src/bybit.js CHANGED
@@ -84,6 +84,7 @@ export default class bybit extends Exchange {
84
84
  'fetchLedger': true,
85
85
  'fetchLeverage': true,
86
86
  'fetchLeverageTiers': true,
87
+ 'fetchMarginAdjustmentHistory': false,
87
88
  'fetchMarketLeverageTiers': true,
88
89
  'fetchMarkets': true,
89
90
  'fetchMarkOHLCV': true,
@@ -154,6 +155,13 @@ export default class bybit extends Exchange {
154
155
  'public': 'https://api.{hostname}',
155
156
  'private': 'https://api.{hostname}',
156
157
  },
158
+ 'demotrading': {
159
+ 'spot': 'https://api-demo.{hostname}',
160
+ 'futures': 'https://api-demo.{hostname}',
161
+ 'v2': 'https://api-demo.{hostname}',
162
+ 'public': 'https://api-demo.{hostname}',
163
+ 'private': 'https://api-demo.{hostname}',
164
+ },
157
165
  'www': 'https://www.bybit.com',
158
166
  'doc': [
159
167
  'https://bybit-exchange.github.io/docs/inverse/',
@@ -342,6 +350,7 @@ export default class bybit extends Exchange {
342
350
  'v5/user/get-member-type': 5,
343
351
  'v5/user/aff-customer-info': 5,
344
352
  'v5/user/del-submember': 5,
353
+ 'v5/user/submembers': 5,
345
354
  // spot leverage token
346
355
  'v5/spot-lever-token/order-record': 1,
347
356
  // spot margin trade
@@ -502,6 +511,8 @@ export default class bybit extends Exchange {
502
511
  'v5/lending/redeem-cancel': 5,
503
512
  'v5/account/set-collateral-switch': 5,
504
513
  'v5/account/set-collateral-switch-batch': 5,
514
+ // demo trading
515
+ 'v5/account/demo-apply-money': 5,
505
516
  },
506
517
  },
507
518
  },
@@ -968,6 +979,8 @@ export default class bybit extends Exchange {
968
979
  },
969
980
  'precisionMode': TICK_SIZE,
970
981
  'options': {
982
+ 'sandboxMode': false,
983
+ 'enableDemoTrading': false,
971
984
  'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
972
985
  'createOrder': {
973
986
  'method': 'privatePostV5OrderCreate', // 'privatePostV5PositionTradingStop'
@@ -1051,6 +1064,39 @@ export default class bybit extends Exchange {
1051
1064
  },
1052
1065
  });
1053
1066
  }
1067
+ setSandboxMode(enable) {
1068
+ /**
1069
+ * @method
1070
+ * @name bybit#setSandboxMode
1071
+ * @description enables or disables sandbox mode
1072
+ * @param {boolean} [enable] true if demo trading should be enabled, false otherwise
1073
+ */
1074
+ super.setSandboxMode(enable);
1075
+ this.options['sandboxMode'] = enable;
1076
+ }
1077
+ enableDemoTrading(enable) {
1078
+ /**
1079
+ * @method
1080
+ * @name bybit#enableDemoTrading
1081
+ * @description enables or disables demo trading mode
1082
+ * @see https://bybit-exchange.github.io/docs/v5/demo
1083
+ * @param {boolean} [enable] true if demo trading should be enabled, false otherwise
1084
+ */
1085
+ if (this.options['sandboxMode']) {
1086
+ throw new NotSupported(this.id + ' demo trading does not support in sandbox environment');
1087
+ }
1088
+ // enable demo trading in bybit, see: https://bybit-exchange.github.io/docs/v5/demo
1089
+ if (enable) {
1090
+ this.urls['apiBackupDemoTrading'] = this.urls['api'];
1091
+ this.urls['api'] = this.urls['demotrading'];
1092
+ }
1093
+ else if ('apiBackupDemoTrading' in this.urls) {
1094
+ this.urls['api'] = this.urls['apiBackupDemoTrading'];
1095
+ const newUrls = this.omit(this.urls, 'apiBackupDemoTrading');
1096
+ this.urls = newUrls;
1097
+ }
1098
+ this.options['enableDemoTrading'] = enable;
1099
+ }
1054
1100
  nonce() {
1055
1101
  return this.milliseconds() - this.options['timeDifference'];
1056
1102
  }
@@ -1067,12 +1113,24 @@ export default class bybit extends Exchange {
1067
1113
  return data;
1068
1114
  }
1069
1115
  async isUnifiedEnabled(params = {}) {
1116
+ /**
1117
+ * @method
1118
+ * @name bybit#isUnifiedEnabled
1119
+ * @description returns [enableUnifiedMargin, enableUnifiedAccount] so the user can check if unified account is enabled
1120
+ */
1070
1121
  // The API key of user id must own one of permissions will be allowed to call following API endpoints.
1071
1122
  // SUB UID: "Account Transfer"
1072
1123
  // MASTER UID: "Account Transfer", "Subaccount Transfer", "Withdrawal"
1073
1124
  const enableUnifiedMargin = this.safeValue(this.options, 'enableUnifiedMargin');
1074
1125
  const enableUnifiedAccount = this.safeValue(this.options, 'enableUnifiedAccount');
1075
1126
  if (enableUnifiedMargin === undefined || enableUnifiedAccount === undefined) {
1127
+ if (this.options['enableDemoTrading']) {
1128
+ // info endpoint is not available in demo trading
1129
+ // so we're assuming UTA is enabled
1130
+ this.options['enableUnifiedMargin'] = false;
1131
+ this.options['enableUnifiedAccount'] = true;
1132
+ return [this.options['enableUnifiedMargin'], this.options['enableUnifiedAccount']];
1133
+ }
1076
1134
  const response = await this.privateGetV5UserQueryApi(params);
1077
1135
  //
1078
1136
  // {
@@ -1242,6 +1300,9 @@ export default class bybit extends Exchange {
1242
1300
  if (!this.checkRequiredCredentials(false)) {
1243
1301
  return undefined;
1244
1302
  }
1303
+ if (this.options['enableDemoTrading']) {
1304
+ return undefined;
1305
+ }
1245
1306
  const response = await this.privateGetV5AssetCoinQueryInfo(params);
1246
1307
  //
1247
1308
  // {
@@ -10,6 +10,7 @@ import { ExchangeError, ArgumentsRequired, AuthenticationError, BadRequest, Inva
10
10
  import { Precise } from './base/Precise.js';
11
11
  import { TICK_SIZE } from './base/functions/number.js';
12
12
  import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
13
+ import { jwt } from './base/functions/rsa.js';
13
14
  // ----------------------------------------------------------------------------
14
15
  /**
15
16
  * @class coinbase
@@ -3786,31 +3787,16 @@ export default class coinbase extends Exchange {
3786
3787
  const url = this.urls['api']['rest'] + fullPath;
3787
3788
  if (signed) {
3788
3789
  const authorization = this.safeString(this.headers, 'Authorization');
3790
+ let authorizationString = undefined;
3789
3791
  if (authorization !== undefined) {
3790
- headers = {
3791
- 'Authorization': authorization,
3792
- 'Content-Type': 'application/json',
3793
- };
3794
- if (method !== 'GET') {
3795
- if (Object.keys(query).length) {
3796
- body = this.json(query);
3797
- }
3798
- }
3792
+ authorizationString = authorization;
3799
3793
  }
3800
3794
  else if (this.token && !this.checkRequiredCredentials(false)) {
3801
- headers = {
3802
- 'Authorization': 'Bearer ' + this.token,
3803
- 'Content-Type': 'application/json',
3804
- };
3805
- if (method !== 'GET') {
3806
- if (Object.keys(query).length) {
3807
- body = this.json(query);
3808
- }
3809
- }
3795
+ authorizationString = 'Bearer ' + this.token;
3810
3796
  }
3811
3797
  else {
3812
3798
  this.checkRequiredCredentials();
3813
- const timestampString = this.seconds().toString();
3799
+ const seconds = this.seconds();
3814
3800
  let payload = '';
3815
3801
  if (method !== 'GET') {
3816
3802
  if (Object.keys(query).length) {
@@ -3829,14 +3815,52 @@ export default class coinbase extends Exchange {
3829
3815
  // https://docs.cloud.coinbase.com/advanced-trade-api/docs/auth#example-request
3830
3816
  // v2: 'GET' require payload in the signature
3831
3817
  // https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
3832
- const auth = timestampString + method + savedPath + payload;
3833
- const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha256);
3818
+ const isCloudAPiKey = (this.apiKey.indexOf('organizations/') >= 0) || (this.secret.startsWith('-----BEGIN'));
3819
+ if (isCloudAPiKey) {
3820
+ if (this.apiKey.startsWith('-----BEGIN')) {
3821
+ throw new ArgumentsRequired(this.id + ' apiKey should contain the name (eg: organizations/3b910e93....) and not the public key');
3822
+ }
3823
+ // it may not work for v2
3824
+ let uri = method + ' ' + url.replace('https://', '');
3825
+ const quesPos = uri.indexOf('?');
3826
+ if (quesPos >= 0) {
3827
+ uri = uri.slice(0, quesPos);
3828
+ }
3829
+ const nonce = this.randomBytes(16);
3830
+ const request = {
3831
+ 'aud': ['retail_rest_api_proxy'],
3832
+ 'iss': 'coinbase-cloud',
3833
+ 'nbf': seconds,
3834
+ 'exp': seconds + 120,
3835
+ 'sub': this.apiKey,
3836
+ 'uri': uri,
3837
+ 'iat': seconds,
3838
+ };
3839
+ const token = jwt(request, this.encode(this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
3840
+ authorizationString = 'Bearer ' + token;
3841
+ }
3842
+ else {
3843
+ const timestampString = this.seconds().toString();
3844
+ const auth = timestampString + method + savedPath + payload;
3845
+ const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha256);
3846
+ headers = {
3847
+ 'CB-ACCESS-KEY': this.apiKey,
3848
+ 'CB-ACCESS-SIGN': signature,
3849
+ 'CB-ACCESS-TIMESTAMP': timestampString,
3850
+ 'Content-Type': 'application/json',
3851
+ };
3852
+ }
3853
+ }
3854
+ if (authorizationString !== undefined) {
3834
3855
  headers = {
3835
- 'CB-ACCESS-KEY': this.apiKey,
3836
- 'CB-ACCESS-SIGN': signature,
3837
- 'CB-ACCESS-TIMESTAMP': timestampString,
3856
+ 'Authorization': authorizationString,
3838
3857
  'Content-Type': 'application/json',
3839
3858
  };
3859
+ if (method !== 'GET') {
3860
+ if (Object.keys(query).length) {
3861
+ body = this.json(query);
3862
+ }
3863
+ }
3840
3864
  }
3841
3865
  }
3842
3866
  return { 'url': url, 'method': method, 'body': body, 'headers': headers };
@@ -79,6 +79,7 @@ export default class coinbaseinternational extends Exchange {
79
79
  'fetchLedger': false,
80
80
  'fetchLeverage': false,
81
81
  'fetchLeverageTiers': false,
82
+ 'fetchMarginAdjustmentHistory': false,
82
83
  'fetchMarginMode': false,
83
84
  'fetchMarkets': true,
84
85
  'fetchMarkOHLCV': false,
@@ -124,6 +124,7 @@ export default class coinex extends Exchange {
124
124
  transfer(code: string, amount: number, fromAccount: string, toAccount: string, params?: {}): Promise<TransferEntry>;
125
125
  parseTransferStatus(status: any): string;
126
126
  parseTransfer(transfer: any, currency?: Currency): {
127
+ info: any;
127
128
  id: number;
128
129
  timestamp: number;
129
130
  datetime: string;
@@ -197,4 +198,5 @@ export default class coinex extends Exchange {
197
198
  headers: any;
198
199
  };
199
200
  handleErrors(httpCode: any, reason: any, url: any, method: any, headers: any, body: any, response: any, requestHeaders: any, requestBody: any): any;
201
+ fetchMarginAdjustmentHistory(symbol?: Str, type?: Str, since?: Num, limit?: Num, params?: {}): Promise<MarginModification[]>;
200
202
  }