ccxt 4.4.69 → 4.4.71

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 (80) hide show
  1. package/README.md +5 -8
  2. package/dist/ccxt.browser.min.js +7 -7
  3. package/dist/cjs/ccxt.js +1 -6
  4. package/dist/cjs/src/abstract/poloniexfutures.js +1 -1
  5. package/dist/cjs/src/base/Exchange.js +22 -1
  6. package/dist/cjs/src/binance.js +107 -102
  7. package/dist/cjs/src/bingx.js +64 -42
  8. package/dist/cjs/src/bitget.js +50 -340
  9. package/dist/cjs/src/bitmart.js +15 -1
  10. package/dist/cjs/src/bitopro.js +1 -0
  11. package/dist/cjs/src/bitrue.js +1 -0
  12. package/dist/cjs/src/bybit.js +7 -0
  13. package/dist/cjs/src/cex.js +1 -0
  14. package/dist/cjs/src/coinbase.js +24 -4
  15. package/dist/cjs/src/coinbaseexchange.js +1 -0
  16. package/dist/cjs/src/deribit.js +1 -0
  17. package/dist/cjs/src/hashkey.js +4 -2
  18. package/dist/cjs/src/hyperliquid.js +18 -7
  19. package/dist/cjs/src/kraken.js +83 -6
  20. package/dist/cjs/src/kucoin.js +4 -2
  21. package/dist/cjs/src/mexc.js +8 -4
  22. package/dist/cjs/src/okx.js +62 -46
  23. package/dist/cjs/src/poloniex.js +1311 -81
  24. package/dist/cjs/src/poloniexfutures.js +1 -1
  25. package/dist/cjs/src/pro/binance.js +94 -94
  26. package/dist/cjs/src/pro/bingx.js +63 -52
  27. package/dist/cjs/src/pro/bitget.js +40 -7
  28. package/dist/cjs/src/pro/bybit.js +86 -38
  29. package/dist/cjs/src/pro/poloniexfutures.js +1 -1
  30. package/dist/cjs/src/tradeogre.js +22 -4
  31. package/dist/cjs/src/whitebit.js +4 -2
  32. package/js/ccxt.d.ts +3 -9
  33. package/js/ccxt.js +2 -6
  34. package/js/src/abstract/bingx.d.ts +1 -0
  35. package/js/src/abstract/bitmart.d.ts +1 -0
  36. package/js/src/abstract/bybit.d.ts +4 -0
  37. package/js/src/abstract/myokx.d.ts +3 -0
  38. package/js/src/abstract/okx.d.ts +3 -0
  39. package/js/src/abstract/poloniex.d.ts +36 -0
  40. package/js/src/abstract/poloniexfutures.js +6 -0
  41. package/js/src/abstract/tradeogre.d.ts +1 -1
  42. package/js/src/base/Exchange.d.ts +11 -2
  43. package/js/src/base/Exchange.js +22 -1
  44. package/js/src/base/types.d.ts +33 -2
  45. package/js/src/binance.d.ts +98 -97
  46. package/js/src/binance.js +107 -102
  47. package/js/src/bingx.js +64 -42
  48. package/js/src/bitget.d.ts +0 -1
  49. package/js/src/bitget.js +50 -340
  50. package/js/src/bitmart.d.ts +1 -0
  51. package/js/src/bitmart.js +15 -1
  52. package/js/src/bitopro.js +1 -0
  53. package/js/src/bitrue.js +1 -0
  54. package/js/src/bybit.js +7 -0
  55. package/js/src/cex.js +1 -0
  56. package/js/src/coinbase.js +24 -4
  57. package/js/src/coinbaseexchange.js +1 -0
  58. package/js/src/deribit.js +1 -0
  59. package/js/src/hashkey.js +4 -2
  60. package/js/src/hyperliquid.js +18 -7
  61. package/js/src/kraken.d.ts +1 -0
  62. package/js/src/kraken.js +83 -6
  63. package/js/src/kucoin.js +4 -2
  64. package/js/src/mexc.js +8 -4
  65. package/js/src/okx.d.ts +1 -0
  66. package/js/src/okx.js +62 -46
  67. package/js/src/poloniex.d.ts +109 -1
  68. package/js/src/poloniex.js +1311 -81
  69. package/js/src/poloniexfutures.js +6 -0
  70. package/js/src/pro/binance.d.ts +94 -94
  71. package/js/src/pro/binance.js +94 -94
  72. package/js/src/pro/bingx.js +63 -52
  73. package/js/src/pro/bitget.js +40 -7
  74. package/js/src/pro/bybit.d.ts +1 -0
  75. package/js/src/pro/bybit.js +86 -38
  76. package/js/src/pro/poloniexfutures.js +6 -0
  77. package/js/src/tradeogre.d.ts +1 -0
  78. package/js/src/tradeogre.js +22 -4
  79. package/js/src/whitebit.js +4 -2
  80. package/package.json +1 -1
@@ -23,21 +23,25 @@ export default class poloniex extends Exchange {
23
23
  'CORS': undefined,
24
24
  'spot': true,
25
25
  'margin': undefined,
26
- 'swap': false,
27
- 'future': false,
26
+ 'swap': true,
27
+ 'future': true,
28
28
  'option': false,
29
+ 'addMargin': true,
29
30
  'cancelAllOrders': true,
30
31
  'cancelOrder': true,
32
+ 'cancelOrders': undefined,
31
33
  'createDepositAddress': true,
32
34
  'createMarketBuyOrderWithCost': true,
33
35
  'createMarketOrderWithCost': false,
34
36
  'createMarketSellOrderWithCost': false,
35
37
  'createOrder': true,
38
+ 'createOrders': undefined,
36
39
  'createStopOrder': true,
37
40
  'createTriggerOrder': true,
38
41
  'editOrder': true,
39
42
  'fetchBalance': true,
40
43
  'fetchClosedOrder': false,
44
+ 'fetchClosedOrders': true,
41
45
  'fetchCurrencies': true,
42
46
  'fetchDepositAddress': true,
43
47
  'fetchDepositAddresses': false,
@@ -51,7 +55,10 @@ export default class poloniex extends Exchange {
51
55
  'fetchFundingIntervals': false,
52
56
  'fetchFundingRate': false,
53
57
  'fetchFundingRateHistory': false,
54
- 'fetchFundingRates': false,
58
+ 'fetchFundingRates': undefined,
59
+ 'fetchLedger': undefined,
60
+ 'fetchLeverage': true,
61
+ 'fetchLiquidations': undefined,
55
62
  'fetchMarginMode': false,
56
63
  'fetchMarkets': true,
57
64
  'fetchMyTrades': true,
@@ -64,7 +71,8 @@ export default class poloniex extends Exchange {
64
71
  'fetchOrderBooks': false,
65
72
  'fetchOrderTrades': true,
66
73
  'fetchPosition': false,
67
- 'fetchPositionMode': false,
74
+ 'fetchPositionMode': true,
75
+ 'fetchPositions': true,
68
76
  'fetchTicker': true,
69
77
  'fetchTickers': true,
70
78
  'fetchTime': true,
@@ -75,7 +83,10 @@ export default class poloniex extends Exchange {
75
83
  'fetchTransfer': false,
76
84
  'fetchTransfers': false,
77
85
  'fetchWithdrawals': true,
86
+ 'reduceMargin': true,
78
87
  'sandbox': true,
88
+ 'setLeverage': true,
89
+ 'setPositionMode': true,
79
90
  'transfer': true,
80
91
  'withdraw': true,
81
92
  },
@@ -93,15 +104,16 @@ export default class poloniex extends Exchange {
93
104
  '1d': 'DAY_1',
94
105
  '3d': 'DAY_3',
95
106
  '1w': 'WEEK_1',
96
- '1M': 'MONTH_1',
107
+ '1M': 'MONTH_1', // not in swap
97
108
  },
98
109
  'urls': {
99
110
  'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
100
111
  'api': {
101
- 'rest': 'https://api.poloniex.com',
112
+ 'spot': 'https://api.poloniex.com',
113
+ 'swap': 'https://api.poloniex.com',
102
114
  },
103
115
  'test': {
104
- 'rest': 'https://sand-spot-api-gateway.poloniex.com',
116
+ 'spot': 'https://sand-spot-api-gateway.poloniex.com',
105
117
  },
106
118
  'www': 'https://www.poloniex.com',
107
119
  'doc': 'https://api-docs.poloniex.com/spot/',
@@ -188,6 +200,55 @@ export default class poloniex extends Exchange {
188
200
  'smartorders/{id}': 20,
189
201
  },
190
202
  },
203
+ 'swapPublic': {
204
+ 'get': {
205
+ // 300 calls / second
206
+ 'v3/market/allInstruments': 2 / 3,
207
+ 'v3/market/instruments': 2 / 3,
208
+ 'v3/market/orderBook': 2 / 3,
209
+ 'v3/market/candles': 10,
210
+ 'v3/market/indexPriceCandlesticks': 10,
211
+ 'v3/market/premiumIndexCandlesticks': 10,
212
+ 'v3/market/markPriceCandlesticks': 10,
213
+ 'v3/market/trades': 2 / 3,
214
+ 'v3/market/liquidationOrder': 2 / 3,
215
+ 'v3/market/tickers': 2 / 3,
216
+ 'v3/market/markPrice': 2 / 3,
217
+ 'v3/market/indexPrice': 2 / 3,
218
+ 'v3/market/indexPriceComponents': 2 / 3,
219
+ 'v3/market/fundingRate': 2 / 3,
220
+ 'v3/market/openInterest': 2 / 3,
221
+ 'v3/market/insurance': 2 / 3,
222
+ 'v3/market/riskLimit': 2 / 3,
223
+ },
224
+ },
225
+ 'swapPrivate': {
226
+ 'get': {
227
+ 'v3/account/balance': 4,
228
+ 'v3/account/bills': 20,
229
+ 'v3/trade/order/opens': 20,
230
+ 'v3/trade/order/trades': 20,
231
+ 'v3/trade/order/history': 20,
232
+ 'v3/trade/position/opens': 20,
233
+ 'v3/trade/position/history': 20,
234
+ 'v3/position/leverages': 20,
235
+ 'v3/position/mode': 20,
236
+ },
237
+ 'post': {
238
+ 'v3/trade/order': 4,
239
+ 'v3/trade/orders': 40,
240
+ 'v3/trade/position': 20,
241
+ 'v3/trade/positionAll': 100,
242
+ 'v3/position/leverage': 20,
243
+ 'v3/position/mode': 20,
244
+ 'v3/trade/position/margin': 20,
245
+ },
246
+ 'delete': {
247
+ 'v3/trade/order': 2,
248
+ 'v3/trade/batchOrders': 20,
249
+ 'v3/trade/allOrders': 20,
250
+ },
251
+ },
191
252
  },
192
253
  'fees': {
193
254
  'trading': {
@@ -236,6 +297,7 @@ export default class poloniex extends Exchange {
236
297
  'UST': 'USTC',
237
298
  },
238
299
  'options': {
300
+ 'defaultType': 'spot',
239
301
  'createMarketBuyOrderRequiresPrice': true,
240
302
  'networks': {
241
303
  'BEP20': 'BSC',
@@ -282,7 +344,7 @@ export default class poloniex extends Exchange {
282
344
  'timeInForce': {
283
345
  'IOC': true,
284
346
  'FOK': true,
285
- 'PO': false,
347
+ 'PO': true,
286
348
  'GTD': false,
287
349
  },
288
350
  'hedged': false,
@@ -293,7 +355,9 @@ export default class poloniex extends Exchange {
293
355
  'trailing': false,
294
356
  'iceberg': false,
295
357
  },
296
- 'createOrders': undefined,
358
+ 'createOrders': {
359
+ 'max': 20,
360
+ },
297
361
  'fetchMyTrades': {
298
362
  'marginMode': false,
299
363
  'limit': 1000,
@@ -323,13 +387,50 @@ export default class poloniex extends Exchange {
323
387
  'spot': {
324
388
  'extends': 'default',
325
389
  },
390
+ 'forContracts': {
391
+ 'extends': 'default',
392
+ 'createOrder': {
393
+ 'marginMode': true,
394
+ 'triggerPrice': false,
395
+ 'hedged': true,
396
+ 'stpMode': true,
397
+ 'marketBuyByCost': false,
398
+ },
399
+ 'createOrders': {
400
+ 'max': 10,
401
+ },
402
+ 'fetchOpenOrders': {
403
+ 'limit': 100,
404
+ },
405
+ 'fetchClosedOrders': {
406
+ 'marginMode': false,
407
+ 'limit': 100,
408
+ 'daysBack': undefined,
409
+ 'daysBackCanceled': 1 / 6,
410
+ 'untilDays': undefined,
411
+ 'trigger': false,
412
+ 'trailing': false,
413
+ },
414
+ 'fetchMyTrades': {
415
+ 'limit': 100,
416
+ 'untilDays': 90,
417
+ },
418
+ },
326
419
  'swap': {
327
- 'linear': undefined,
328
- 'inverse': undefined,
420
+ 'linear': {
421
+ 'extends': 'forContracts',
422
+ },
423
+ 'inverse': {
424
+ 'extends': 'forContracts',
425
+ },
329
426
  },
330
427
  'future': {
331
- 'linear': undefined,
332
- 'inverse': undefined,
428
+ 'linear': {
429
+ 'extends': 'forContracts',
430
+ },
431
+ 'inverse': {
432
+ 'extends': 'forContracts',
433
+ },
333
434
  },
334
435
  },
335
436
  'precisionMode': TICK_SIZE,
@@ -448,6 +549,8 @@ export default class poloniex extends Exchange {
448
549
  });
449
550
  }
450
551
  parseOHLCV(ohlcv, market = undefined) {
552
+ //
553
+ // spot:
451
554
  //
452
555
  // [
453
556
  // [
@@ -468,6 +571,32 @@ export default class poloniex extends Exchange {
468
571
  // ]
469
572
  // ]
470
573
  //
574
+ // contract:
575
+ //
576
+ // [
577
+ // "84207.02",
578
+ // "84320.85",
579
+ // "84207.02",
580
+ // "84253.83",
581
+ // "3707.5395",
582
+ // "44",
583
+ // "14",
584
+ // "1740770040000",
585
+ // "1740770099999",
586
+ // ],
587
+ //
588
+ const ohlcvLength = ohlcv.length;
589
+ const isContract = ohlcvLength === 9;
590
+ if (isContract) {
591
+ return [
592
+ this.safeInteger(ohlcv, 7),
593
+ this.safeNumber(ohlcv, 2),
594
+ this.safeNumber(ohlcv, 1),
595
+ this.safeNumber(ohlcv, 0),
596
+ this.safeNumber(ohlcv, 3),
597
+ this.safeNumber(ohlcv, 5),
598
+ ];
599
+ }
471
600
  return [
472
601
  this.safeInteger(ohlcv, 12),
473
602
  this.safeNumber(ohlcv, 2),
@@ -482,6 +611,7 @@ export default class poloniex extends Exchange {
482
611
  * @name poloniex#fetchOHLCV
483
612
  * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
484
613
  * @see https://api-docs.poloniex.com/spot/api/public/market-data#candles
614
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-kline-data
485
615
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
486
616
  * @param {string} timeframe the length of time each candle represents
487
617
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
@@ -503,14 +633,41 @@ export default class poloniex extends Exchange {
503
633
  'symbol': market['id'],
504
634
  'interval': this.safeString(this.timeframes, timeframe, timeframe),
505
635
  };
636
+ const keyStart = market['spot'] ? 'startTime' : 'sTime';
637
+ const keyEnd = market['spot'] ? 'endTime' : 'eTime';
506
638
  if (since !== undefined) {
507
- request['startTime'] = since;
639
+ request[keyStart] = since;
508
640
  }
509
641
  if (limit !== undefined) {
510
642
  // limit should in between 100 and 500
511
643
  request['limit'] = limit;
512
644
  }
513
- [request, params] = this.handleUntilOption('endTime', request, params);
645
+ [request, params] = this.handleUntilOption(keyEnd, request, params);
646
+ if (market['contract']) {
647
+ if (this.inArray(timeframe, ['10m', '1M'])) {
648
+ throw new NotSupported(this.id + ' ' + timeframe + ' ' + market['type'] + ' fetchOHLCV is not supported');
649
+ }
650
+ const responseRaw = await this.swapPublicGetV3MarketCandles(this.extend(request, params));
651
+ //
652
+ // {
653
+ // code: "200",
654
+ // msg: "Success",
655
+ // data: [
656
+ // [
657
+ // "84207.02",
658
+ // "84320.85",
659
+ // "84207.02",
660
+ // "84253.83",
661
+ // "3707.5395",
662
+ // "44",
663
+ // "14",
664
+ // "1740770040000",
665
+ // "1740770099999",
666
+ // ],
667
+ //
668
+ const data = this.safeList(responseRaw, 'data');
669
+ return this.parseOHLCVs(data, market, timeframe, since, limit);
670
+ }
514
671
  const response = await this.publicGetMarketsSymbolCandles(this.extend(request, params));
515
672
  //
516
673
  // [
@@ -547,10 +704,16 @@ export default class poloniex extends Exchange {
547
704
  * @name poloniex#fetchMarkets
548
705
  * @description retrieves data on all markets for poloniex
549
706
  * @see https://api-docs.poloniex.com/spot/api/public/reference-data#symbol-information
707
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-all-product-info
550
708
  * @param {object} [params] extra parameters specific to the exchange API endpoint
551
709
  * @returns {object[]} an array of objects representing market data
552
710
  */
553
711
  async fetchMarkets(params = {}) {
712
+ const promises = [this.fetchSpotMarkets(params), this.fetchSwapMarkets(params)];
713
+ const results = await Promise.all(promises);
714
+ return this.arrayConcat(results[0], results[1]);
715
+ }
716
+ async fetchSpotMarkets(params = {}) {
554
717
  const markets = await this.publicGetMarkets(params);
555
718
  //
556
719
  // [
@@ -577,7 +740,59 @@ export default class poloniex extends Exchange {
577
740
  //
578
741
  return this.parseMarkets(markets);
579
742
  }
743
+ async fetchSwapMarkets(params = {}) {
744
+ // do similar as spot per https://api-docs.poloniex.com/v3/futures/api/market/get-product-info
745
+ const response = await this.swapPublicGetV3MarketAllInstruments(params);
746
+ //
747
+ // {
748
+ // "code": "200",
749
+ // "msg": "Success",
750
+ // "data": [
751
+ // {
752
+ // "symbol": "BNB_USDT_PERP",
753
+ // "bAsset": ".PBNBUSDT",
754
+ // "bCcy": "BNB",
755
+ // "qCcy": "USDT",
756
+ // "visibleStartTime": "1620390600000",
757
+ // "tradableStartTime": "1620390600000",
758
+ // "sCcy": "USDT",
759
+ // "tSz": "0.001",
760
+ // "pxScale": "0.001,0.01,0.1,1,10",
761
+ // "lotSz": "1",
762
+ // "minSz": "1",
763
+ // "ctVal": "0.1",
764
+ // "status": "OPEN",
765
+ // "oDate": "1620287590000",
766
+ // "maxPx": "1000000",
767
+ // "minPx": "0.001",
768
+ // "maxQty": "1000000",
769
+ // "minQty": "1",
770
+ // "maxLever": "50",
771
+ // "lever": "10",
772
+ // "ctType": "LINEAR",
773
+ // "alias": "",
774
+ // "iM": "0.02",
775
+ // "mM": "0.0115",
776
+ // "mR": "2000",
777
+ // "buyLmt": "",
778
+ // "sellLmt": "",
779
+ // "ordPxRange": "0.05",
780
+ // "marketMaxQty": "2800",
781
+ // "limitMaxQty": "1000000"
782
+ // },
783
+ //
784
+ const markets = this.safeList(response, 'data');
785
+ return this.parseMarkets(markets);
786
+ }
580
787
  parseMarket(market) {
788
+ if ('ctType' in market) {
789
+ return this.parseSwapMarket(market);
790
+ }
791
+ else {
792
+ return this.parseSpotMarket(market);
793
+ }
794
+ }
795
+ parseSpotMarket(market) {
581
796
  const id = this.safeString(market, 'symbol');
582
797
  const baseId = this.safeString(market, 'baseCurrencyName');
583
798
  const quoteId = this.safeString(market, 'quoteCurrencyName');
@@ -633,6 +848,116 @@ export default class poloniex extends Exchange {
633
848
  'info': market,
634
849
  };
635
850
  }
851
+ parseSwapMarket(market) {
852
+ //
853
+ // {
854
+ // "symbol": "BNB_USDT_PERP",
855
+ // "bAsset": ".PBNBUSDT",
856
+ // "bCcy": "BNB",
857
+ // "qCcy": "USDT",
858
+ // "visibleStartTime": "1620390600000",
859
+ // "tradableStartTime": "1620390600000",
860
+ // "sCcy": "USDT",
861
+ // "tSz": "0.001",
862
+ // "pxScale": "0.001,0.01,0.1,1,10",
863
+ // "lotSz": "1",
864
+ // "minSz": "1",
865
+ // "ctVal": "0.1",
866
+ // "status": "OPEN",
867
+ // "oDate": "1620287590000",
868
+ // "maxPx": "1000000",
869
+ // "minPx": "0.001",
870
+ // "maxQty": "1000000",
871
+ // "minQty": "1",
872
+ // "maxLever": "50",
873
+ // "lever": "10",
874
+ // "ctType": "LINEAR",
875
+ // "alias": "",
876
+ // "iM": "0.02",
877
+ // "mM": "0.0115",
878
+ // "mR": "2000",
879
+ // "buyLmt": "",
880
+ // "sellLmt": "",
881
+ // "ordPxRange": "0.05",
882
+ // "marketMaxQty": "2800",
883
+ // "limitMaxQty": "1000000"
884
+ // },
885
+ //
886
+ const id = this.safeString(market, 'symbol');
887
+ const baseId = this.safeString(market, 'bCcy');
888
+ const quoteId = this.safeString(market, 'qCcy');
889
+ const settleId = this.safeString(market, 'sCcy');
890
+ const base = this.safeCurrencyCode(baseId);
891
+ const quote = this.safeCurrencyCode(quoteId);
892
+ const settle = this.safeCurrencyCode(settleId);
893
+ const status = this.safeString(market, 'status');
894
+ const active = status === 'OPEN';
895
+ const linear = market['ctType'] === 'LINEAR';
896
+ let symbol = base + '/' + quote;
897
+ if (linear) {
898
+ symbol += ':' + settle;
899
+ }
900
+ else {
901
+ // actually, exchange does not have any inverse future now
902
+ symbol += ':' + base;
903
+ }
904
+ const alias = this.safeString(market, 'alias');
905
+ let type = 'swap';
906
+ if (alias !== undefined) {
907
+ type = 'future';
908
+ }
909
+ return {
910
+ 'id': id,
911
+ 'symbol': symbol,
912
+ 'base': base,
913
+ 'quote': quote,
914
+ 'settle': settle,
915
+ 'baseId': baseId,
916
+ 'quoteId': quoteId,
917
+ 'settleId': settleId,
918
+ 'type': (type === 'future') ? 'future' : 'swap',
919
+ 'spot': false,
920
+ 'margin': false,
921
+ 'swap': type === 'swap',
922
+ 'future': type === 'future',
923
+ 'option': false,
924
+ 'active': active,
925
+ 'contract': true,
926
+ 'linear': linear,
927
+ 'inverse': !linear,
928
+ 'contractSize': this.safeNumber(market, 'ctVal'),
929
+ 'expiry': undefined,
930
+ 'expiryDatetime': undefined,
931
+ 'strike': undefined,
932
+ 'optionType': undefined,
933
+ 'taker': this.safeNumber(market, 'tFee'),
934
+ 'maker': this.safeNumber(market, 'mFee'),
935
+ 'precision': {
936
+ 'amount': this.safeNumber(market, 'lotSz'),
937
+ 'price': this.safeNumber(market, 'tSz'),
938
+ },
939
+ 'limits': {
940
+ 'amount': {
941
+ 'min': this.safeNumber(market, 'minSz'),
942
+ 'max': this.safeNumber(market, 'limitMaxQty'),
943
+ },
944
+ 'price': {
945
+ 'min': this.safeNumber(market, 'minPx'),
946
+ 'max': this.safeNumber(market, 'maxPx'),
947
+ },
948
+ 'cost': {
949
+ 'min': undefined,
950
+ 'max': undefined,
951
+ },
952
+ 'leverage': {
953
+ 'max': this.safeNumber(market, 'maxLever'),
954
+ 'min': undefined,
955
+ },
956
+ },
957
+ 'created': this.safeInteger(market, 'oDate'),
958
+ 'info': market,
959
+ };
960
+ }
636
961
  /**
637
962
  * @method
638
963
  * @name poloniex#fetchTime
@@ -646,6 +971,8 @@ export default class poloniex extends Exchange {
646
971
  return this.safeInteger(response, 'serverTime');
647
972
  }
648
973
  parseTicker(ticker, market = undefined) {
974
+ //
975
+ // spot:
649
976
  //
650
977
  // {
651
978
  // "symbol" : "BTC_USDT",
@@ -668,36 +995,56 @@ export default class poloniex extends Exchange {
668
995
  // "markPrice" : "26444.11"
669
996
  // }
670
997
  //
671
- const timestamp = this.safeInteger(ticker, 'ts');
672
- const marketId = this.safeString(ticker, 'symbol');
998
+ // swap:
999
+ //
1000
+ // {
1001
+ // "s": "XRP_USDT_PERP",
1002
+ // "o": "2.0503",
1003
+ // "l": "2.0066",
1004
+ // "h": "2.216",
1005
+ // "c": "2.1798",
1006
+ // "qty": "21090",
1007
+ // "amt": "451339.65",
1008
+ // "tC": "3267",
1009
+ // "sT": "1740736380000",
1010
+ // "cT": "1740822777559",
1011
+ // "dN": "XRP/USDT/PERP",
1012
+ // "dC": "0.0632",
1013
+ // "bPx": "2.175",
1014
+ // "bSz": "3",
1015
+ // "aPx": "2.1831",
1016
+ // "aSz": "111",
1017
+ // "mPx": "2.1798",
1018
+ // "iPx": "2.1834"
1019
+ // },
1020
+ //
1021
+ const timestamp = this.safeInteger2(ticker, 'ts', 'cT');
1022
+ const marketId = this.safeString2(ticker, 'symbol', 's');
673
1023
  market = this.safeMarket(marketId);
674
- const close = this.safeString(ticker, 'close');
675
- const relativeChange = this.safeString(ticker, 'dailyChange');
1024
+ const relativeChange = this.safeString2(ticker, 'dailyChange', 'dc');
676
1025
  const percentage = Precise.stringMul(relativeChange, '100');
677
- const bidVolume = this.safeString(ticker, 'bidQuantity');
678
- const askVolume = this.safeString(ticker, 'askQuantity');
679
1026
  return this.safeTicker({
680
1027
  'id': marketId,
681
1028
  'symbol': market['symbol'],
682
1029
  'timestamp': timestamp,
683
1030
  'datetime': this.iso8601(timestamp),
684
- 'high': this.safeString(ticker, 'high'),
685
- 'low': this.safeString(ticker, 'low'),
686
- 'bid': this.safeString(ticker, 'bid'),
687
- 'bidVolume': bidVolume,
688
- 'ask': this.safeString(ticker, 'ask'),
689
- 'askVolume': askVolume,
1031
+ 'high': this.safeString2(ticker, 'high', 'h'),
1032
+ 'low': this.safeString2(ticker, 'low', 'l'),
1033
+ 'bid': this.safeString2(ticker, 'bid', 'bPx'),
1034
+ 'bidVolume': this.safeString2(ticker, 'bidQuantity', 'bSz'),
1035
+ 'ask': this.safeString2(ticker, 'ask', 'aPx'),
1036
+ 'askVolume': this.safeString2(ticker, 'askQuantity', 'aSz'),
690
1037
  'vwap': undefined,
691
- 'open': this.safeString(ticker, 'open'),
692
- 'close': close,
693
- 'last': close,
1038
+ 'open': this.safeString2(ticker, 'open', 'o'),
1039
+ 'close': this.safeString2(ticker, 'close', 'c'),
694
1040
  'previousClose': undefined,
695
1041
  'change': undefined,
696
1042
  'percentage': percentage,
697
1043
  'average': undefined,
698
- 'baseVolume': this.safeString(ticker, 'quantity'),
699
- 'quoteVolume': this.safeString(ticker, 'amount'),
700
- 'markPrice': this.safeString(ticker, 'markPrice'),
1044
+ 'baseVolume': this.safeString2(ticker, 'quantity', 'qty'),
1045
+ 'quoteVolume': this.safeString2(ticker, 'amount', 'amt'),
1046
+ 'markPrice': this.safeString2(ticker, 'markPrice', 'mPx'),
1047
+ 'indexPrice': this.safeString(ticker, 'iPx'),
701
1048
  'info': ticker,
702
1049
  }, market);
703
1050
  }
@@ -706,13 +1053,58 @@ export default class poloniex extends Exchange {
706
1053
  * @name poloniex#fetchTickers
707
1054
  * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
708
1055
  * @see https://api-docs.poloniex.com/spot/api/public/market-data#ticker
1056
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-market-info
709
1057
  * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
710
1058
  * @param {object} [params] extra parameters specific to the exchange API endpoint
711
1059
  * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
712
1060
  */
713
1061
  async fetchTickers(symbols = undefined, params = {}) {
714
1062
  await this.loadMarkets();
715
- symbols = this.marketSymbols(symbols);
1063
+ let market = undefined;
1064
+ const request = {};
1065
+ if (symbols !== undefined) {
1066
+ symbols = this.marketSymbols(symbols, undefined, true, true, false);
1067
+ const symbolsLength = symbols.length;
1068
+ if (symbolsLength > 0) {
1069
+ market = this.market(symbols[0]);
1070
+ if (symbolsLength === 1) {
1071
+ request['symbol'] = market['id'];
1072
+ }
1073
+ }
1074
+ }
1075
+ let marketType = undefined;
1076
+ [marketType, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
1077
+ if (marketType === 'swap') {
1078
+ const responseRaw = await this.swapPublicGetV3MarketTickers(this.extend(request, params));
1079
+ //
1080
+ // {
1081
+ // "code": "200",
1082
+ // "msg": "Success",
1083
+ // "data": [
1084
+ // {
1085
+ // "s": "XRP_USDT_PERP",
1086
+ // "o": "2.0503",
1087
+ // "l": "2.0066",
1088
+ // "h": "2.216",
1089
+ // "c": "2.1798",
1090
+ // "qty": "21090",
1091
+ // "amt": "451339.65",
1092
+ // "tC": "3267",
1093
+ // "sT": "1740736380000",
1094
+ // "cT": "1740822777559",
1095
+ // "dN": "XRP/USDT/PERP",
1096
+ // "dC": "0.0632",
1097
+ // "bPx": "2.175",
1098
+ // "bSz": "3",
1099
+ // "aPx": "2.1831",
1100
+ // "aSz": "111",
1101
+ // "mPx": "2.1798",
1102
+ // "iPx": "2.1834"
1103
+ // },
1104
+ //
1105
+ const data = this.safeList(responseRaw, 'data');
1106
+ return this.parseTickers(data, symbols);
1107
+ }
716
1108
  const response = await this.publicGetMarketsTicker24h(params);
717
1109
  //
718
1110
  // [
@@ -883,6 +1275,7 @@ export default class poloniex extends Exchange {
883
1275
  * @name poloniex#fetchTicker
884
1276
  * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
885
1277
  * @see https://api-docs.poloniex.com/spot/api/public/market-data#ticker
1278
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-market-info
886
1279
  * @param {string} symbol unified symbol of the market to fetch the ticker for
887
1280
  * @param {object} [params] extra parameters specific to the exchange API endpoint
888
1281
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -893,6 +1286,10 @@ export default class poloniex extends Exchange {
893
1286
  const request = {
894
1287
  'symbol': market['id'],
895
1288
  };
1289
+ if (market['contract']) {
1290
+ const tickers = await this.fetchTickers([market['symbol']], params);
1291
+ return this.safeDict(tickers, symbol);
1292
+ }
896
1293
  const response = await this.publicGetMarketsSymbolTicker24h(this.extend(request, params));
897
1294
  //
898
1295
  // {
@@ -922,6 +1319,8 @@ export default class poloniex extends Exchange {
922
1319
  //
923
1320
  // fetchTrades
924
1321
  //
1322
+ // spot:
1323
+ //
925
1324
  // {
926
1325
  // "id" : "60014521",
927
1326
  // "price" : "23162.94",
@@ -932,8 +1331,21 @@ export default class poloniex extends Exchange {
932
1331
  // "createTime" : 1659684602036
933
1332
  // }
934
1333
  //
1334
+ // swap:
1335
+ //
1336
+ // {
1337
+ // "id": "105807376",
1338
+ // "side": "buy",
1339
+ // "px": "84410.57",
1340
+ // "qty": "1",
1341
+ // "amt": "84.41057",
1342
+ // "cT": "1740777563557",
1343
+ // }
1344
+ //
935
1345
  // fetchMyTrades
936
1346
  //
1347
+ // spot:
1348
+ //
937
1349
  // {
938
1350
  // "id": "32164924331503616",
939
1351
  // "symbol": "LINK_USDT",
@@ -952,6 +1364,34 @@ export default class poloniex extends Exchange {
952
1364
  // "clientOrderId": "myOwnId-321"
953
1365
  // }
954
1366
  //
1367
+ // swap:
1368
+ //
1369
+ // {
1370
+ // "symbol": "BTC_USDT_PERP",
1371
+ // "trdId": "105813553",
1372
+ // "side": "SELL",
1373
+ // "type": "TRADE",
1374
+ // "mgnMode": "CROSS",
1375
+ // "ordType": "MARKET",
1376
+ // "clOrdId": "polo418912106147315112",
1377
+ // "role": "TAKER",
1378
+ // "px": "84704.9",
1379
+ // "qty": "1",
1380
+ // "cTime": "1740842829430",
1381
+ // "uTime": "1740842829450",
1382
+ // "feeCcy": "USDT",
1383
+ // "feeAmt": "0.04235245",
1384
+ // "deductCcy": "",
1385
+ // "deductAmt": "0",
1386
+ // "feeRate": "0.0005",
1387
+ // "id": "418912106342654592",
1388
+ // "posSide": "BOTH",
1389
+ // "ordId": "418912106147315112",
1390
+ // "qCcy": "USDT",
1391
+ // "value": "84.7049",
1392
+ // "actType": "TRADING"
1393
+ // },
1394
+ //
955
1395
  // fetchOrderTrades (taker trades)
956
1396
  //
957
1397
  // {
@@ -972,20 +1412,19 @@ export default class poloniex extends Exchange {
972
1412
  // "clientOrderId": ""
973
1413
  // }
974
1414
  //
975
- //
976
- const id = this.safeString2(trade, 'id', 'tradeID');
977
- const orderId = this.safeString(trade, 'orderId');
978
- const timestamp = this.safeInteger2(trade, 'ts', 'createTime');
1415
+ const id = this.safeStringN(trade, ['id', 'tradeID', 'trdId']);
1416
+ const orderId = this.safeString2(trade, 'orderId', 'ordId');
1417
+ const timestamp = this.safeIntegerN(trade, ['ts', 'createTime', 'cT', 'cTime']);
979
1418
  const marketId = this.safeString(trade, 'symbol');
980
1419
  market = this.safeMarket(marketId, market, '_');
981
1420
  const symbol = market['symbol'];
982
1421
  const side = this.safeStringLower2(trade, 'side', 'takerSide');
983
1422
  let fee = undefined;
984
- const priceString = this.safeString(trade, 'price');
985
- const amountString = this.safeString(trade, 'quantity');
986
- const costString = this.safeString(trade, 'amount');
987
- const feeCurrencyId = this.safeString(trade, 'feeCurrency');
988
- const feeCostString = this.safeString(trade, 'feeAmount');
1423
+ const priceString = this.safeString2(trade, 'price', 'px');
1424
+ const amountString = this.safeString2(trade, 'quantity', 'qty');
1425
+ const costString = this.safeString2(trade, 'amount', 'amt');
1426
+ const feeCurrencyId = this.safeString2(trade, 'feeCurrency', 'feeCcy');
1427
+ const feeCostString = this.safeString2(trade, 'feeAmount', 'feeAmt');
989
1428
  if (feeCostString !== undefined) {
990
1429
  const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
991
1430
  fee = {
@@ -1000,9 +1439,9 @@ export default class poloniex extends Exchange {
1000
1439
  'datetime': this.iso8601(timestamp),
1001
1440
  'symbol': symbol,
1002
1441
  'order': orderId,
1003
- 'type': this.safeStringLower(trade, 'type'),
1442
+ 'type': this.safeStringLower2(trade, 'ordType', 'type'),
1004
1443
  'side': side,
1005
- 'takerOrMaker': this.safeStringLower(trade, 'matchRole'),
1444
+ 'takerOrMaker': this.safeStringLower2(trade, 'matchRole', 'role'),
1006
1445
  'price': priceString,
1007
1446
  'amount': amountString,
1008
1447
  'cost': costString,
@@ -1014,6 +1453,7 @@ export default class poloniex extends Exchange {
1014
1453
  * @name poloniex#fetchTrades
1015
1454
  * @description get the list of most recent trades for a particular symbol
1016
1455
  * @see https://api-docs.poloniex.com/spot/api/public/market-data#trades
1456
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-execution-info
1017
1457
  * @param {string} symbol unified symbol of the market to fetch trades for
1018
1458
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
1019
1459
  * @param {int} [limit] the maximum amount of trades to fetch
@@ -1027,7 +1467,26 @@ export default class poloniex extends Exchange {
1027
1467
  'symbol': market['id'],
1028
1468
  };
1029
1469
  if (limit !== undefined) {
1030
- request['limit'] = limit;
1470
+ request['limit'] = limit; // max 1000, for spot & swap
1471
+ }
1472
+ if (market['contract']) {
1473
+ const response = await this.swapPublicGetV3MarketTrades(this.extend(request, params));
1474
+ //
1475
+ // {
1476
+ // code: "200",
1477
+ // msg: "Success",
1478
+ // data: [
1479
+ // {
1480
+ // id: "105807320", // descending order
1481
+ // side: "sell",
1482
+ // px: "84383.93",
1483
+ // qty: "1",
1484
+ // amt: "84.38393",
1485
+ // cT: "1740777074704",
1486
+ // },
1487
+ //
1488
+ const tradesList = this.safeList(response, 'data');
1489
+ return this.parseTrades(tradesList, market, since, limit);
1031
1490
  }
1032
1491
  const trades = await this.publicGetMarketsSymbolTrades(this.extend(request, params));
1033
1492
  //
@@ -1050,6 +1509,7 @@ export default class poloniex extends Exchange {
1050
1509
  * @name poloniex#fetchMyTrades
1051
1510
  * @description fetch all trades made by the user
1052
1511
  * @see https://api-docs.poloniex.com/spot/api/private/trade#trade-history
1512
+ * @see https://api-docs.poloniex.com/v3/futures/api/trade/get-execution-details
1053
1513
  * @param {string} symbol unified market symbol
1054
1514
  * @param {int} [since] the earliest time in ms to fetch trades for
1055
1515
  * @param {int} [limit] the maximum number of trades structures to retrieve
@@ -1069,17 +1529,61 @@ export default class poloniex extends Exchange {
1069
1529
  if (symbol !== undefined) {
1070
1530
  market = this.market(symbol);
1071
1531
  }
1532
+ let marketType = undefined;
1533
+ [marketType, params] = this.handleMarketTypeAndParams('fetchMyTrades', market, params);
1534
+ const isContract = this.inArray(marketType, ['swap', 'future']);
1072
1535
  let request = {
1073
1536
  // 'from': 12345678, // A 'trade Id'. The query begins at ‘from'.
1074
1537
  // 'direction': 'PRE', // PRE, NEXT The direction before or after ‘from'.
1075
1538
  };
1539
+ const startKey = isContract ? 'sTime' : 'startTime';
1540
+ const endKey = isContract ? 'eTime' : 'endTime';
1076
1541
  if (since !== undefined) {
1077
- request['startTime'] = since;
1542
+ request[startKey] = since;
1078
1543
  }
1079
1544
  if (limit !== undefined) {
1080
1545
  request['limit'] = limit;
1081
1546
  }
1082
- [request, params] = this.handleUntilOption('endTime', request, params);
1547
+ if (isContract && symbol !== undefined) {
1548
+ request['symbol'] = market['id'];
1549
+ }
1550
+ [request, params] = this.handleUntilOption(endKey, request, params);
1551
+ if (isContract) {
1552
+ const raw = await this.swapPrivateGetV3TradeOrderTrades(this.extend(request, params));
1553
+ //
1554
+ // {
1555
+ // "code": "200",
1556
+ // "msg": "",
1557
+ // "data": [
1558
+ // {
1559
+ // "symbol": "BTC_USDT_PERP",
1560
+ // "trdId": "105813553",
1561
+ // "side": "SELL",
1562
+ // "type": "TRADE",
1563
+ // "mgnMode": "CROSS",
1564
+ // "ordType": "MARKET",
1565
+ // "clOrdId": "polo418912106147315112",
1566
+ // "role": "TAKER",
1567
+ // "px": "84704.9",
1568
+ // "qty": "1",
1569
+ // "cTime": "1740842829430",
1570
+ // "uTime": "1740842829450",
1571
+ // "feeCcy": "USDT",
1572
+ // "feeAmt": "0.04235245",
1573
+ // "deductCcy": "",
1574
+ // "deductAmt": "0",
1575
+ // "feeRate": "0.0005",
1576
+ // "id": "418912106342654592",
1577
+ // "posSide": "BOTH",
1578
+ // "ordId": "418912106147315112",
1579
+ // "qCcy": "USDT",
1580
+ // "value": "84.7049",
1581
+ // "actType": "TRADING"
1582
+ // },
1583
+ //
1584
+ const data = this.safeList(raw, 'data');
1585
+ return this.parseTrades(data, market, since, limit);
1586
+ }
1083
1587
  const response = await this.privateGetTrades(this.extend(request, params));
1084
1588
  //
1085
1589
  // [
@@ -1140,7 +1644,9 @@ export default class poloniex extends Exchange {
1140
1644
  // "updateTime" : 16xxxxxxxxx36
1141
1645
  // }
1142
1646
  //
1143
- // fetchOpenOrders
1647
+ // fetchOpenOrders (and fetchClosedOrders same for contracts)
1648
+ //
1649
+ // spot:
1144
1650
  //
1145
1651
  // {
1146
1652
  // "id": "24993088082542592",
@@ -1161,14 +1667,60 @@ export default class poloniex extends Exchange {
1161
1667
  // "updateTime": 1646925216548
1162
1668
  // }
1163
1669
  //
1670
+ // contract:
1671
+ //
1672
+ // {
1673
+ // "symbol": "BTC_USDT_PERP",
1674
+ // "side": "BUY",
1675
+ // "type": "LIMIT",
1676
+ // "ordId": "418890767248232148",
1677
+ // "clOrdId": "polo418890767248232148",
1678
+ // "mgnMode": "CROSS",
1679
+ // "px": "81130.13",
1680
+ // "reduceOnly": false,
1681
+ // "lever": "20",
1682
+ // "state": "NEW",
1683
+ // "source": "WEB",
1684
+ // "timeInForce": "GTC",
1685
+ // "tpTrgPx": "",
1686
+ // "tpPx": "",
1687
+ // "tpTrgPxType": "",
1688
+ // "slTrgPx": "",
1689
+ // "slPx": "",
1690
+ // "slTrgPxType": "",
1691
+ // "avgPx": "0",
1692
+ // "execQty": "0",
1693
+ // "execAmt": "0",
1694
+ // "feeCcy": "",
1695
+ // "feeAmt": "0",
1696
+ // "deductCcy": "0",
1697
+ // "deductAmt": "0",
1698
+ // "stpMode": "NONE", // todo: selfTradePrevention
1699
+ // "cTime": "1740837741523",
1700
+ // "uTime": "1740840846882",
1701
+ // "sz": "1",
1702
+ // "posSide": "BOTH",
1703
+ // "qCcy": "USDT"
1704
+ // "cancelReason": "", // this field can only be in closed orders
1705
+ // },
1706
+ //
1164
1707
  // createOrder, editOrder
1165
1708
  //
1709
+ // spot:
1710
+ //
1166
1711
  // {
1167
1712
  // "id": "29772698821328896",
1168
1713
  // "clientOrderId": "1234Abc"
1169
1714
  // }
1170
1715
  //
1171
- let timestamp = this.safeInteger2(order, 'timestamp', 'createTime');
1716
+ // contract:
1717
+ //
1718
+ // {
1719
+ // "ordId":"418876147745775616",
1720
+ // "clOrdId":"polo418876147745775616"
1721
+ // }
1722
+ //
1723
+ let timestamp = this.safeIntegerN(order, ['timestamp', 'createTime', 'cTime']);
1172
1724
  if (timestamp === undefined) {
1173
1725
  timestamp = this.parse8601(this.safeString(order, 'date'));
1174
1726
  }
@@ -1181,16 +1733,16 @@ export default class poloniex extends Exchange {
1181
1733
  resultingTrades = this.safeValue(resultingTrades, this.safeString(market, 'id', marketId));
1182
1734
  }
1183
1735
  }
1184
- const price = this.safeString2(order, 'price', 'rate');
1185
- const amount = this.safeString(order, 'quantity');
1186
- const filled = this.safeString(order, 'filledQuantity');
1736
+ const price = this.safeStringN(order, ['price', 'rate', 'px']);
1737
+ const amount = this.safeString2(order, 'quantity', 'sz');
1738
+ const filled = this.safeString2(order, 'filledQuantity', 'execQty');
1187
1739
  const status = this.parseOrderStatus(this.safeString(order, 'state'));
1188
1740
  const side = this.safeStringLower(order, 'side');
1189
1741
  const rawType = this.safeString(order, 'type');
1190
1742
  const type = this.parseOrderType(rawType);
1191
- const id = this.safeStringN(order, ['orderNumber', 'id', 'orderId']);
1743
+ const id = this.safeStringN(order, ['orderNumber', 'id', 'orderId', 'ordId']);
1192
1744
  let fee = undefined;
1193
- const feeCurrency = this.safeString(order, 'tokenFeeCurrency');
1745
+ const feeCurrency = this.safeString2(order, 'tokenFeeCurrency', 'feeCcy');
1194
1746
  let feeCost = undefined;
1195
1747
  let feeCurrencyCode = undefined;
1196
1748
  const rate = this.safeString(order, 'fee');
@@ -1200,7 +1752,7 @@ export default class poloniex extends Exchange {
1200
1752
  else {
1201
1753
  // poloniex accepts a 30% discount to pay fees in TRX
1202
1754
  feeCurrencyCode = this.safeCurrencyCode(feeCurrency);
1203
- feeCost = this.safeString(order, 'tokenFee');
1755
+ feeCost = this.safeString2(order, 'tokenFee', 'feeAmt');
1204
1756
  }
1205
1757
  if (feeCost !== undefined) {
1206
1758
  fee = {
@@ -1209,7 +1761,11 @@ export default class poloniex extends Exchange {
1209
1761
  'currency': feeCurrencyCode,
1210
1762
  };
1211
1763
  }
1212
- const clientOrderId = this.safeString(order, 'clientOrderId');
1764
+ const clientOrderId = this.safeString2(order, 'clientOrderId', 'clOrdId');
1765
+ const marginMode = this.safeStringLower(order, 'mgnMode');
1766
+ const reduceOnly = this.safeBool(order, 'reduceOnly');
1767
+ const leverage = this.safeInteger(order, 'lever');
1768
+ const hedged = this.safeString(order, 'posSide') !== 'BOTH';
1213
1769
  return this.safeOrder({
1214
1770
  'info': order,
1215
1771
  'id': id,
@@ -1221,23 +1777,28 @@ export default class poloniex extends Exchange {
1221
1777
  'symbol': symbol,
1222
1778
  'type': type,
1223
1779
  'timeInForce': this.safeString(order, 'timeInForce'),
1224
- 'postOnly': undefined,
1780
+ 'postOnly': rawType === 'LIMIT_MAKER',
1225
1781
  'side': side,
1226
1782
  'price': price,
1227
1783
  'triggerPrice': this.safeString2(order, 'triggerPrice', 'stopPrice'),
1228
- 'cost': undefined,
1229
- 'average': this.safeString(order, 'avgPrice'),
1784
+ 'cost': this.safeString(order, 'execAmt'),
1785
+ 'average': this.safeString2(order, 'avgPrice', 'avgPx'),
1230
1786
  'amount': amount,
1231
1787
  'filled': filled,
1232
1788
  'remaining': undefined,
1233
1789
  'trades': resultingTrades,
1234
1790
  'fee': fee,
1791
+ 'marginMode': marginMode,
1792
+ 'reduceOnly': reduceOnly,
1793
+ 'leverage': leverage,
1794
+ 'hedged': hedged,
1235
1795
  }, market);
1236
1796
  }
1237
1797
  parseOrderType(status) {
1238
1798
  const statuses = {
1239
1799
  'MARKET': 'market',
1240
1800
  'LIMIT': 'limit',
1801
+ 'LIMIT_MAKER': 'limit',
1241
1802
  'STOP-LIMIT': 'limit',
1242
1803
  'STOP-MARKET': 'market',
1243
1804
  };
@@ -1262,6 +1823,7 @@ export default class poloniex extends Exchange {
1262
1823
  * @description fetch all unfilled currently open orders
1263
1824
  * @see https://api-docs.poloniex.com/spot/api/private/order#open-orders
1264
1825
  * @see https://api-docs.poloniex.com/spot/api/private/smart-order#open-orders // trigger orders
1826
+ * @see https://api-docs.poloniex.com/v3/futures/api/trade/get-current-orders
1265
1827
  * @param {string} symbol unified market symbol
1266
1828
  * @param {int} [since] the earliest time in ms to fetch open orders for
1267
1829
  * @param {int} [limit] the maximum number of open orders structures to retrieve
@@ -1277,13 +1839,59 @@ export default class poloniex extends Exchange {
1277
1839
  market = this.market(symbol);
1278
1840
  request['symbol'] = market['id'];
1279
1841
  }
1842
+ let marketType = undefined;
1843
+ [marketType, params] = this.handleMarketTypeAndParams('fetchOpenOrders', market, params);
1280
1844
  if (limit !== undefined) {
1281
- request['limit'] = limit;
1845
+ const max = (marketType === 'spot') ? 2000 : 100;
1846
+ request['limit'] = Math.max(limit, max);
1282
1847
  }
1283
1848
  const isTrigger = this.safeValue2(params, 'trigger', 'stop');
1284
1849
  params = this.omit(params, ['trigger', 'stop']);
1285
1850
  let response = undefined;
1286
- if (isTrigger) {
1851
+ if (!market['spot']) {
1852
+ const raw = await this.swapPrivateGetV3TradeOrderOpens(this.extend(request, params));
1853
+ //
1854
+ // {
1855
+ // "code": "200",
1856
+ // "msg": "",
1857
+ // "data": [
1858
+ // {
1859
+ // "symbol": "BTC_USDT_PERP",
1860
+ // "side": "BUY",
1861
+ // "type": "LIMIT",
1862
+ // "ordId": "418890767248232148",
1863
+ // "clOrdId": "polo418890767248232148",
1864
+ // "mgnMode": "CROSS",
1865
+ // "px": "81130.13",
1866
+ // "reduceOnly": false,
1867
+ // "lever": "20",
1868
+ // "state": "NEW",
1869
+ // "source": "WEB",
1870
+ // "timeInForce": "GTC",
1871
+ // "tpTrgPx": "",
1872
+ // "tpPx": "",
1873
+ // "tpTrgPxType": "",
1874
+ // "slTrgPx": "",
1875
+ // "slPx": "",
1876
+ // "slTrgPxType": "",
1877
+ // "avgPx": "0",
1878
+ // "execQty": "0",
1879
+ // "execAmt": "0",
1880
+ // "feeCcy": "",
1881
+ // "feeAmt": "0",
1882
+ // "deductCcy": "0",
1883
+ // "deductAmt": "0",
1884
+ // "stpMode": "NONE",
1885
+ // "cTime": "1740837741523",
1886
+ // "uTime": "1740840846882",
1887
+ // "sz": "1",
1888
+ // "posSide": "BOTH",
1889
+ // "qCcy": "USDT"
1890
+ // },
1891
+ //
1892
+ response = this.safeList(raw, 'data');
1893
+ }
1894
+ else if (isTrigger) {
1287
1895
  response = await this.privateGetSmartorders(this.extend(request, params));
1288
1896
  }
1289
1897
  else {
@@ -1315,6 +1923,82 @@ export default class poloniex extends Exchange {
1315
1923
  const extension = { 'status': 'open' };
1316
1924
  return this.parseOrders(response, market, since, limit, extension);
1317
1925
  }
1926
+ /**
1927
+ * @method
1928
+ * @name poloniex#fetchClosedOrders
1929
+ * @see https://api-docs.poloniex.com/v3/futures/api/trade/get-order-history
1930
+ * @description fetches information on multiple closed orders made by the user
1931
+ * @param {string} symbol unified market symbol of the market orders were made in
1932
+ * @param {int} [since] the earliest time in ms to fetch orders for
1933
+ * @param {int} [limit] the maximum number of order structures to retrieve
1934
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1935
+ * @param {int} [params.until] timestamp in ms of the latest entry
1936
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1937
+ */
1938
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1939
+ await this.loadMarkets();
1940
+ let market = undefined;
1941
+ let request = {};
1942
+ if (symbol !== undefined) {
1943
+ market = this.market(symbol);
1944
+ request['symbol'] = market['id'];
1945
+ }
1946
+ let marketType = undefined;
1947
+ [marketType, params] = this.handleMarketTypeAndParams('fetchClosedOrders', market, params, 'swap');
1948
+ if (marketType === 'spot') {
1949
+ throw new NotSupported(this.id + ' fetchClosedOrders() is not supported for spot markets yet');
1950
+ }
1951
+ if (limit !== undefined) {
1952
+ request['limit'] = Math.min(200, limit);
1953
+ }
1954
+ if (since !== undefined) {
1955
+ request['sTime'] = since;
1956
+ }
1957
+ [request, params] = this.handleUntilOption('eTime', request, params);
1958
+ const response = await this.swapPrivateGetV3TradeOrderHistory(this.extend(request, params));
1959
+ //
1960
+ // {
1961
+ // "code": "200",
1962
+ // "msg": "",
1963
+ // "data": [
1964
+ // {
1965
+ // "symbol": "BTC_USDT_PERP",
1966
+ // "side": "SELL",
1967
+ // "type": "MARKET",
1968
+ // "ordId": "418912106147315712",
1969
+ // "clOrdId": "polo418912106147315712",
1970
+ // "mgnMode": "CROSS",
1971
+ // "px": "0",
1972
+ // "sz": "2",
1973
+ // "lever": "20",
1974
+ // "state": "FILLED",
1975
+ // "cancelReason": "",
1976
+ // "source": "WEB",
1977
+ // "reduceOnly": "true",
1978
+ // "timeInForce": "GTC",
1979
+ // "tpTrgPx": "",
1980
+ // "tpPx": "",
1981
+ // "tpTrgPxType": "",
1982
+ // "slTrgPx": "",
1983
+ // "slPx": "",
1984
+ // "slTrgPxType": "",
1985
+ // "avgPx": "84705.56",
1986
+ // "execQty": "2",
1987
+ // "execAmt": "169.41112",
1988
+ // "feeCcy": "USDT",
1989
+ // "feeAmt": "0.08470556",
1990
+ // "deductCcy": "0",
1991
+ // "deductAmt": "0",
1992
+ // "stpMode": "NONE",
1993
+ // "cTime": "1740842829116",
1994
+ // "uTime": "1740842829130",
1995
+ // "posSide": "BOTH",
1996
+ // "qCcy": "USDT"
1997
+ // },
1998
+ //
1999
+ const data = this.safeList(response, 'data', []);
2000
+ return this.parseOrders(data, market, since, limit);
2001
+ }
1318
2002
  /**
1319
2003
  * @method
1320
2004
  * @name poloniex#createOrder
@@ -1334,20 +2018,24 @@ export default class poloniex extends Exchange {
1334
2018
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1335
2019
  await this.loadMarkets();
1336
2020
  const market = this.market(symbol);
1337
- if (!market['spot']) {
1338
- throw new NotSupported(this.id + ' createOrder() does not support ' + market['type'] + ' orders, only spot orders are accepted');
1339
- }
1340
2021
  let request = {
1341
2022
  'symbol': market['id'],
1342
- 'side': side,
1343
- // 'timeInForce': timeInForce,
2023
+ 'side': side.toUpperCase(), // uppercase, both for spot & swap
2024
+ // 'timeInForce': timeInForce, // matches unified values
1344
2025
  // 'accountType': 'SPOT',
1345
2026
  // 'amount': amount,
1346
2027
  };
1347
2028
  const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
1348
2029
  [request, params] = this.orderRequest(symbol, type, side, amount, request, price, params);
1349
2030
  let response = undefined;
1350
- if (triggerPrice !== undefined) {
2031
+ if (market['swap'] || market['future']) {
2032
+ const responseInitial = await this.swapPrivatePostV3TradeOrder(this.extend(request, params));
2033
+ //
2034
+ // {"code":200,"msg":"Success","data":{"ordId":"418876147745775616","clOrdId":"polo418876147745775616"}}
2035
+ //
2036
+ response = this.safeDict(responseInitial, 'data');
2037
+ }
2038
+ else if (triggerPrice !== undefined) {
1351
2039
  response = await this.privatePostSmartorders(this.extend(request, params));
1352
2040
  }
1353
2041
  else {
@@ -1359,19 +2047,37 @@ export default class poloniex extends Exchange {
1359
2047
  // "clientOrderId" : ""
1360
2048
  // }
1361
2049
  //
1362
- response = this.extend(response, {
1363
- 'type': type,
1364
- 'side': side,
1365
- });
1366
2050
  return this.parseOrder(response, market);
1367
2051
  }
1368
2052
  orderRequest(symbol, type, side, amount, request, price = undefined, params = {}) {
2053
+ const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
2054
+ const market = this.market(symbol);
2055
+ if (market['contract']) {
2056
+ let marginMode = undefined;
2057
+ [marginMode, params] = this.handleParamString(params, 'marginMode');
2058
+ if (marginMode !== undefined) {
2059
+ this.checkRequiredArgument('createOrder', marginMode, 'marginMode', ['cross', 'isolated']);
2060
+ request['mgnMode'] = marginMode.toUpperCase();
2061
+ }
2062
+ let hedged = undefined;
2063
+ [hedged, params] = this.handleParamString(params, 'hedged');
2064
+ if (hedged) {
2065
+ if (marginMode === undefined) {
2066
+ throw new ArgumentsRequired(this.id + ' createOrder() requires a marginMode parameter "cross" or "isolated" for hedged orders');
2067
+ }
2068
+ if (!('posSide' in params)) {
2069
+ throw new ArgumentsRequired(this.id + ' createOrder() requires a posSide parameter "LONG" or "SHORT" for hedged orders');
2070
+ }
2071
+ }
2072
+ }
1369
2073
  let upperCaseType = type.toUpperCase();
1370
2074
  const isMarket = upperCaseType === 'MARKET';
1371
2075
  const isPostOnly = this.isPostOnly(isMarket, upperCaseType === 'LIMIT_MAKER', params);
1372
- const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
1373
2076
  params = this.omit(params, ['postOnly', 'triggerPrice', 'stopPrice']);
1374
2077
  if (triggerPrice !== undefined) {
2078
+ if (!market['spot']) {
2079
+ throw new InvalidOrder(this.id + ' createOrder() does not support trigger orders for ' + market['type'] + ' markets');
2080
+ }
1375
2081
  upperCaseType = (price === undefined) ? 'STOP' : 'STOP_LIMIT';
1376
2082
  request['stopPrice'] = triggerPrice;
1377
2083
  }
@@ -1389,7 +2095,7 @@ export default class poloniex extends Exchange {
1389
2095
  if (cost !== undefined) {
1390
2096
  quoteAmount = this.costToPrecision(symbol, cost);
1391
2097
  }
1392
- else if (createMarketBuyOrderRequiresPrice) {
2098
+ else if (createMarketBuyOrderRequiresPrice && market['spot']) {
1393
2099
  if (price === undefined) {
1394
2100
  throw new InvalidOrder(this.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to false and pass the cost to spend (quote quantity) in the amount argument');
1395
2101
  }
@@ -1403,15 +2109,19 @@ export default class poloniex extends Exchange {
1403
2109
  else {
1404
2110
  quoteAmount = this.costToPrecision(symbol, amount);
1405
2111
  }
1406
- request['amount'] = quoteAmount;
2112
+ const amountKey = market['spot'] ? 'amount' : 'sz';
2113
+ request[amountKey] = quoteAmount;
1407
2114
  }
1408
2115
  else {
1409
- request['quantity'] = this.amountToPrecision(symbol, amount);
2116
+ const amountKey = market['spot'] ? 'quantity' : 'sz';
2117
+ request[amountKey] = this.amountToPrecision(symbol, amount);
1410
2118
  }
1411
2119
  }
1412
2120
  else {
1413
- request['quantity'] = this.amountToPrecision(symbol, amount);
1414
- request['price'] = this.priceToPrecision(symbol, price);
2121
+ const amountKey = market['spot'] ? 'quantity' : 'sz';
2122
+ request[amountKey] = this.amountToPrecision(symbol, amount);
2123
+ const priceKey = market['spot'] ? 'price' : 'px';
2124
+ request[priceKey] = this.priceToPrecision(symbol, price);
1415
2125
  }
1416
2126
  const clientOrderId = this.safeString(params, 'clientOrderId');
1417
2127
  if (clientOrderId !== undefined) {
@@ -1482,7 +2192,27 @@ export default class poloniex extends Exchange {
1482
2192
  // @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1483
2193
  //
1484
2194
  await this.loadMarkets();
2195
+ if (symbol === undefined) {
2196
+ throw new ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
2197
+ }
2198
+ const market = this.market(symbol);
1485
2199
  const request = {};
2200
+ if (!market['spot']) {
2201
+ request['symbol'] = market['id'];
2202
+ request['ordId'] = id;
2203
+ const raw = await this.swapPrivateDeleteV3TradeOrder(this.extend(request, params));
2204
+ //
2205
+ // {
2206
+ // "code": "200",
2207
+ // "msg": "Success",
2208
+ // "data": {
2209
+ // "ordId": "418886099910612040",
2210
+ // "clOrdId": "polo418886099910612040"
2211
+ // }
2212
+ // }
2213
+ //
2214
+ return this.parseOrder(this.safeDict(raw, 'data'));
2215
+ }
1486
2216
  const clientOrderId = this.safeValue(params, 'clientOrderId');
1487
2217
  if (clientOrderId !== undefined) {
1488
2218
  id = clientOrderId;
@@ -1514,6 +2244,7 @@ export default class poloniex extends Exchange {
1514
2244
  * @description cancel all open orders
1515
2245
  * @see https://api-docs.poloniex.com/spot/api/private/order#cancel-all-orders
1516
2246
  * @see https://api-docs.poloniex.com/spot/api/private/smart-order#cancel-all-orders // trigger orders
2247
+ * @see https://api-docs.poloniex.com/v3/futures/api/trade/cancel-all-orders - contract markets
1517
2248
  * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
1518
2249
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1519
2250
  * @param {boolean} [params.trigger] true if canceling trigger orders
@@ -1532,9 +2263,30 @@ export default class poloniex extends Exchange {
1532
2263
  market['id'],
1533
2264
  ];
1534
2265
  }
2266
+ let response = undefined;
2267
+ let marketType = undefined;
2268
+ [marketType, params] = this.handleMarketTypeAndParams('cancelAllOrders', market, params);
2269
+ if (marketType === 'swap' || marketType === 'future') {
2270
+ const raw = await this.swapPrivateDeleteV3TradeAllOrders(this.extend(request, params));
2271
+ //
2272
+ // {
2273
+ // "code": "200",
2274
+ // "msg": "Success",
2275
+ // "data": [
2276
+ // {
2277
+ // "code": "200",
2278
+ // "msg": "Success",
2279
+ // "ordId": "418885787866388511",
2280
+ // "clOrdId": "polo418885787866388511"
2281
+ // }
2282
+ // ]
2283
+ // }
2284
+ //
2285
+ response = this.safeList(raw, 'data');
2286
+ return this.parseOrders(response, market);
2287
+ }
1535
2288
  const isTrigger = this.safeValue2(params, 'trigger', 'stop');
1536
2289
  params = this.omit(params, ['trigger', 'stop']);
1537
- let response = undefined;
1538
2290
  if (isTrigger) {
1539
2291
  response = await this.privateDeleteSmartorders(this.extend(request, params));
1540
2292
  }
@@ -1578,6 +2330,16 @@ export default class poloniex extends Exchange {
1578
2330
  const request = {
1579
2331
  'id': id,
1580
2332
  };
2333
+ let market = undefined;
2334
+ if (symbol !== undefined) {
2335
+ market = this.market(symbol);
2336
+ request['symbol'] = market['id'];
2337
+ }
2338
+ let marketType = undefined;
2339
+ [marketType, params] = this.handleMarketTypeAndParams('fetchOrder', market, params);
2340
+ if (marketType !== 'spot') {
2341
+ throw new NotSupported(this.id + ' fetchOrder() is not supported for ' + marketType + ' markets yet');
2342
+ }
1581
2343
  const isTrigger = this.safeValue2(params, 'trigger', 'stop');
1582
2344
  params = this.omit(params, ['trigger', 'stop']);
1583
2345
  let response = undefined;
@@ -1666,6 +2428,24 @@ export default class poloniex extends Exchange {
1666
2428
  'timestamp': undefined,
1667
2429
  'datetime': undefined,
1668
2430
  };
2431
+ // for swap
2432
+ if (!Array.isArray(response)) {
2433
+ const ts = this.safeInteger(response, 'uTime');
2434
+ result['timestamp'] = ts;
2435
+ result['datetime'] = this.iso8601(ts);
2436
+ const details = this.safeList(response, 'details', []);
2437
+ for (let i = 0; i < details.length; i++) {
2438
+ const balance = details[i];
2439
+ const currencyId = this.safeString(balance, 'ccy');
2440
+ const code = this.safeCurrencyCode(currencyId);
2441
+ const account = this.account();
2442
+ account['total'] = this.safeString(balance, 'avail');
2443
+ account['used'] = this.safeString(balance, 'im');
2444
+ result[code] = account;
2445
+ }
2446
+ return this.safeBalance(result);
2447
+ }
2448
+ // for spot
1669
2449
  for (let i = 0; i < response.length; i++) {
1670
2450
  const account = this.safeValue(response, i, {});
1671
2451
  const balances = this.safeValue(account, 'balances');
@@ -1686,11 +2466,56 @@ export default class poloniex extends Exchange {
1686
2466
  * @name poloniex#fetchBalance
1687
2467
  * @description query for balance and get the amount of funds available for trading or funds locked in orders
1688
2468
  * @see https://api-docs.poloniex.com/spot/api/private/account#all-account-balances
2469
+ * @see https://api-docs.poloniex.com/v3/futures/api/account/balance
1689
2470
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1690
2471
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1691
2472
  */
1692
2473
  async fetchBalance(params = {}) {
1693
2474
  await this.loadMarkets();
2475
+ let marketType = undefined;
2476
+ [marketType, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
2477
+ if (marketType !== 'spot') {
2478
+ const responseRaw = await this.swapPrivateGetV3AccountBalance(params);
2479
+ //
2480
+ // {
2481
+ // "code": "200",
2482
+ // "msg": "",
2483
+ // "data": {
2484
+ // "state": "NORMAL",
2485
+ // "eq": "9.98571622",
2486
+ // "isoEq": "0",
2487
+ // "im": "0",
2488
+ // "mm": "0",
2489
+ // "mmr": "0",
2490
+ // "upl": "0",
2491
+ // "availMgn": "9.98571622",
2492
+ // "cTime": "1738093601775",
2493
+ // "uTime": "1740829116236",
2494
+ // "details": [
2495
+ // {
2496
+ // "ccy": "USDT",
2497
+ // "eq": "9.98571622",
2498
+ // "isoEq": "0",
2499
+ // "avail": "9.98571622",
2500
+ // "trdHold": "0",
2501
+ // "upl": "0",
2502
+ // "isoAvail": "0",
2503
+ // "isoHold": "0",
2504
+ // "isoUpl": "0",
2505
+ // "im": "0",
2506
+ // "mm": "0",
2507
+ // "mmr": "0",
2508
+ // "imr": "0",
2509
+ // "cTime": "1740829116236",
2510
+ // "uTime": "1740829116236"
2511
+ // }
2512
+ // ]
2513
+ // }
2514
+ // }
2515
+ //
2516
+ const data = this.safeDict(responseRaw, 'data', {});
2517
+ return this.parseBalance(data);
2518
+ }
1694
2519
  const request = {
1695
2520
  'accountType': 'SPOT',
1696
2521
  };
@@ -1751,6 +2576,7 @@ export default class poloniex extends Exchange {
1751
2576
  * @name poloniex#fetchOrderBook
1752
2577
  * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1753
2578
  * @see https://api-docs.poloniex.com/spot/api/public/market-data#order-book
2579
+ * @see https://api-docs.poloniex.com/v3/futures/api/market/get-order-book
1754
2580
  * @param {string} symbol unified symbol of the market to fetch the order book for
1755
2581
  * @param {int} [limit] the maximum amount of order book entries to return
1756
2582
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -1764,6 +2590,27 @@ export default class poloniex extends Exchange {
1764
2590
  };
1765
2591
  if (limit !== undefined) {
1766
2592
  request['limit'] = limit; // The default value of limit is 10. Valid limit values are: 5, 10, 20, 50, 100, 150.
2593
+ if (market['contract']) {
2594
+ request['limit'] = this.findNearestCeiling([5, 10, 20, 100, 150], limit);
2595
+ }
2596
+ }
2597
+ if (market['contract']) {
2598
+ const responseRaw = await this.swapPublicGetV3MarketOrderBook(this.extend(request, params));
2599
+ //
2600
+ // {
2601
+ // "code": 200,
2602
+ // "data": {
2603
+ // "asks": [ ["58700", "9934"], ..],
2604
+ // "bids": [ ["58600", "9952"], ..],
2605
+ // "s": "100",
2606
+ // "ts": 1719974138333
2607
+ // },
2608
+ // "msg": "Success"
2609
+ // }
2610
+ //
2611
+ const data = this.safeDict(responseRaw, 'data', {});
2612
+ const ts = this.safeInteger(data, 'ts');
2613
+ return this.parseOrderBook(data, symbol, ts);
1767
2614
  }
1768
2615
  const response = await this.publicGetMarketsSymbolOrderBook(this.extend(request, params));
1769
2616
  //
@@ -2363,14 +3210,397 @@ export default class poloniex extends Exchange {
2363
3210
  },
2364
3211
  };
2365
3212
  }
3213
+ /**
3214
+ * @method
3215
+ * @name poloniex#setLeverage
3216
+ * @description set the level of leverage for a market
3217
+ * @see https://api-docs.poloniex.com/v3/futures/api/positions/set-leverage
3218
+ * @param {int} leverage the rate of leverage
3219
+ * @param {string} symbol unified market symbol
3220
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3221
+ * @param {string} [params.marginMode] 'cross' or 'isolated'
3222
+ * @returns {object} response from the exchange
3223
+ */
3224
+ async setLeverage(leverage, symbol = undefined, params = {}) {
3225
+ if (symbol === undefined) {
3226
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
3227
+ }
3228
+ await this.loadMarkets();
3229
+ const market = this.market(symbol);
3230
+ let marginMode = undefined;
3231
+ [marginMode, params] = this.handleMarginModeAndParams('setLeverage', params);
3232
+ if (marginMode === undefined) {
3233
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a marginMode parameter "cross" or "isolated"');
3234
+ }
3235
+ let hedged = undefined;
3236
+ [hedged, params] = this.handleParamBool(params, 'hedged', false);
3237
+ if (hedged) {
3238
+ if (!('posSide' in params)) {
3239
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a posSide parameter for hedged mode: "LONG" or "SHORT"');
3240
+ }
3241
+ }
3242
+ const request = {
3243
+ 'lever': leverage,
3244
+ 'mgnMode': marginMode.toUpperCase(),
3245
+ 'symbol': market['id'],
3246
+ };
3247
+ const response = await this.swapPrivatePostV3PositionLeverage(this.extend(request, params));
3248
+ return response;
3249
+ }
3250
+ /**
3251
+ * @method
3252
+ * @name poloniex#fetchLeverage
3253
+ * @description fetch the set leverage for a market
3254
+ * @see https://api-docs.poloniex.com/v3/futures/api/positions/get-leverages
3255
+ * @param {string} symbol unified market symbol
3256
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3257
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
3258
+ */
3259
+ async fetchLeverage(symbol, params = {}) {
3260
+ await this.loadMarkets();
3261
+ const market = this.market(symbol);
3262
+ const request = {
3263
+ 'symbol': market['id'],
3264
+ };
3265
+ let marginMode = undefined;
3266
+ [marginMode, params] = this.handleMarginModeAndParams('fetchLeverage', params);
3267
+ if (marginMode === undefined) {
3268
+ throw new ArgumentsRequired(this.id + ' fetchLeverage() requires a marginMode parameter "cross" or "isolated"');
3269
+ }
3270
+ request['mgnMode'] = marginMode.toUpperCase();
3271
+ const response = await this.swapPrivateGetV3PositionLeverages(this.extend(request, params));
3272
+ //
3273
+ // for one-way mode:
3274
+ //
3275
+ // {
3276
+ // "code": "200",
3277
+ // "msg": "",
3278
+ // "data": [
3279
+ // {
3280
+ // "symbol": "BTC_USDT_PERP",
3281
+ // "lever": "10",
3282
+ // "mgnMode": "CROSS",
3283
+ // "posSide": "BOTH"
3284
+ // }
3285
+ // ]
3286
+ // }
3287
+ //
3288
+ // for hedge:
3289
+ //
3290
+ // {
3291
+ // "code": "200",
3292
+ // "msg": "",
3293
+ // "data": [
3294
+ // {
3295
+ // "symbol": "BTC_USDT_PERP",
3296
+ // "lever": "20",
3297
+ // "mgnMode": "CROSS",
3298
+ // "posSide": "SHORT"
3299
+ // },
3300
+ // {
3301
+ // "symbol": "BTC_USDT_PERP",
3302
+ // "lever": "20",
3303
+ // "mgnMode": "CROSS",
3304
+ // "posSide": "LONG"
3305
+ // }
3306
+ // ]
3307
+ // }
3308
+ //
3309
+ return this.parseLeverage(response, market);
3310
+ }
3311
+ parseLeverage(leverage, market = undefined) {
3312
+ let shortLeverage = undefined;
3313
+ let longLeverage = undefined;
3314
+ let marketId = undefined;
3315
+ let marginMode = undefined;
3316
+ const data = this.safeList(leverage, 'data');
3317
+ for (let i = 0; i < data.length; i++) {
3318
+ const entry = data[i];
3319
+ marketId = this.safeString(entry, 'symbol');
3320
+ marginMode = this.safeString(entry, 'mgnMode');
3321
+ const lever = this.safeInteger(entry, 'lever');
3322
+ const posSide = this.safeString(entry, 'posSide');
3323
+ if (posSide === 'LONG') {
3324
+ longLeverage = lever;
3325
+ }
3326
+ else if (posSide === 'SHORT') {
3327
+ shortLeverage = lever;
3328
+ }
3329
+ else {
3330
+ longLeverage = lever;
3331
+ shortLeverage = lever;
3332
+ }
3333
+ }
3334
+ return {
3335
+ 'info': leverage,
3336
+ 'symbol': this.safeSymbol(marketId, market),
3337
+ 'marginMode': marginMode,
3338
+ 'longLeverage': longLeverage,
3339
+ 'shortLeverage': shortLeverage,
3340
+ };
3341
+ }
3342
+ /**
3343
+ * @method
3344
+ * @name poloniex#fetchPositionMode
3345
+ * @description fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
3346
+ * @see https://api-docs.poloniex.com/v3/futures/api/positions/position-mode-switch
3347
+ * @param {string} symbol unified symbol of the market to fetch the order book for
3348
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3349
+ * @returns {object} an object detailing whether the market is in hedged or one-way mode
3350
+ */
3351
+ async fetchPositionMode(symbol = undefined, params = {}) {
3352
+ const response = await this.swapPrivateGetV3PositionMode(params);
3353
+ //
3354
+ // {
3355
+ // "code": "200",
3356
+ // "msg": "Success",
3357
+ // "data": {
3358
+ // "posMode": "ONE_WAY"
3359
+ // }
3360
+ // }
3361
+ //
3362
+ const data = this.safeDict(response, 'data', {});
3363
+ const posMode = this.safeString(data, 'posMode');
3364
+ const hedged = posMode === 'HEDGE';
3365
+ return {
3366
+ 'info': response,
3367
+ 'hedged': hedged,
3368
+ };
3369
+ }
3370
+ /**
3371
+ * @method
3372
+ * @name poloniex#setPositionMode
3373
+ * @description set hedged to true or false for a market
3374
+ * @see https://api-docs.poloniex.com/v3/futures/api/positions/position-mode-switch
3375
+ * @param {bool} hedged set to true to use dualSidePosition
3376
+ * @param {string} symbol not used by binance setPositionMode ()
3377
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3378
+ * @returns {object} response from the exchange
3379
+ */
3380
+ async setPositionMode(hedged, symbol = undefined, params = {}) {
3381
+ const mode = hedged ? 'HEDGE' : 'ONE_WAY';
3382
+ const request = {
3383
+ 'posMode': mode,
3384
+ };
3385
+ const response = await this.swapPrivatePostV3PositionMode(this.extend(request, params));
3386
+ //
3387
+ // {
3388
+ // "code": "200",
3389
+ // "msg": "Success",
3390
+ // "data": {}
3391
+ // }
3392
+ //
3393
+ return response;
3394
+ }
3395
+ /**
3396
+ * @method
3397
+ * @name poloniex#fetchPositions
3398
+ * @description fetch all open positions
3399
+ * @see https://api-docs.poloniex.com/v3/futures/api/positions/get-current-position
3400
+ * @param {string[]|undefined} symbols list of unified market symbols
3401
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3402
+ * @param {boolean} [params.standard] whether to fetch standard contract positions
3403
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
3404
+ */
3405
+ async fetchPositions(symbols = undefined, params = {}) {
3406
+ await this.loadMarkets();
3407
+ symbols = this.marketSymbols(symbols);
3408
+ const response = await this.swapPrivateGetV3TradePositionOpens(params);
3409
+ //
3410
+ // {
3411
+ // "code": "200",
3412
+ // "msg": "",
3413
+ // "data": [
3414
+ // {
3415
+ // "symbol": "BTC_USDT_PERP",
3416
+ // "posSide": "LONG",
3417
+ // "side": "BUY",
3418
+ // "mgnMode": "CROSS",
3419
+ // "openAvgPx": "94193.42",
3420
+ // "qty": "1",
3421
+ // "availQty": "1",
3422
+ // "lever": "20",
3423
+ // "adl": "0.3007",
3424
+ // "liqPx": "84918.201844064386317906",
3425
+ // "im": "4.7047795",
3426
+ // "mm": "0.56457354",
3427
+ // "upl": "-0.09783",
3428
+ // "uplRatio": "-0.0207",
3429
+ // "pnl": "0",
3430
+ // "markPx": "94095.59",
3431
+ // "mgnRatio": "0.0582",
3432
+ // "state": "NORMAL",
3433
+ // "cTime": "1740950344401",
3434
+ // "uTime": "1740950344401",
3435
+ // "mgn": "4.7047795",
3436
+ // "actType": "TRADING",
3437
+ // "maxWAmt": "0",
3438
+ // "tpTrgPx": "",
3439
+ // "slTrgPx": ""
3440
+ // }
3441
+ // ]
3442
+ // }
3443
+ //
3444
+ const positions = this.safeList(response, 'data', []);
3445
+ return this.parsePositions(positions, symbols);
3446
+ }
3447
+ parsePosition(position, market = undefined) {
3448
+ //
3449
+ // {
3450
+ // "symbol": "BTC_USDT_PERP",
3451
+ // "posSide": "LONG",
3452
+ // "side": "BUY",
3453
+ // "mgnMode": "CROSS",
3454
+ // "openAvgPx": "94193.42",
3455
+ // "qty": "1",
3456
+ // "availQty": "1",
3457
+ // "lever": "20",
3458
+ // "adl": "0.3007",
3459
+ // "liqPx": "84918.201844064386317906",
3460
+ // "im": "4.7047795",
3461
+ // "mm": "0.56457354",
3462
+ // "upl": "-0.09783",
3463
+ // "uplRatio": "-0.0207",
3464
+ // "pnl": "0",
3465
+ // "markPx": "94095.59",
3466
+ // "mgnRatio": "0.0582",
3467
+ // "state": "NORMAL",
3468
+ // "cTime": "1740950344401",
3469
+ // "uTime": "1740950344401",
3470
+ // "mgn": "4.7047795",
3471
+ // "actType": "TRADING",
3472
+ // "maxWAmt": "0",
3473
+ // "tpTrgPx": "",
3474
+ // "slTrgPx": ""
3475
+ // }
3476
+ //
3477
+ const marketId = this.safeString(position, 'symbol');
3478
+ market = this.safeMarket(marketId, market);
3479
+ const timestamp = this.safeInteger(position, 'cTime');
3480
+ const marginMode = this.safeStringLower(position, 'mgnMode');
3481
+ const leverage = this.safeString(position, 'lever');
3482
+ const initialMargin = this.safeString(position, 'im');
3483
+ const notional = Precise.stringMul(leverage, initialMargin);
3484
+ const qty = this.safeString(position, 'qty');
3485
+ const avgPrice = this.safeString(position, 'openAvgPx');
3486
+ const collateral = Precise.stringMul(qty, avgPrice);
3487
+ // todo: some more fields
3488
+ return this.safePosition({
3489
+ 'info': position,
3490
+ 'id': undefined,
3491
+ 'symbol': market['symbol'],
3492
+ 'notional': notional,
3493
+ 'marginMode': marginMode,
3494
+ 'liquidationPrice': this.safeNumber(position, 'liqPx'),
3495
+ 'entryPrice': this.safeNumber(position, 'openAvgPx'),
3496
+ 'unrealizedPnl': this.safeNumber(position, 'upl'),
3497
+ 'percentage': undefined,
3498
+ 'contracts': this.safeNumber(position, 'qty'),
3499
+ 'contractSize': undefined,
3500
+ 'markPrice': this.safeNumber(position, 'markPx'),
3501
+ 'lastPrice': undefined,
3502
+ 'side': this.safeStringLower(position, 'posSide'),
3503
+ 'hedged': undefined,
3504
+ 'timestamp': timestamp,
3505
+ 'datetime': this.iso8601(timestamp),
3506
+ 'lastUpdateTimestamp': undefined,
3507
+ 'maintenanceMargin': this.safeNumber(position, 'mm'),
3508
+ 'maintenanceMarginPercentage': undefined,
3509
+ 'collateral': collateral,
3510
+ 'initialMargin': initialMargin,
3511
+ 'initialMarginPercentage': undefined,
3512
+ 'leverage': parseInt(leverage),
3513
+ 'marginRatio': this.safeNumber(position, 'mgnRatio'),
3514
+ 'stopLossPrice': this.safeNumber(position, 'slTrgPx'),
3515
+ 'takeProfitPrice': this.safeNumber(position, 'tpTrgPx'),
3516
+ });
3517
+ }
3518
+ async modifyMarginHelper(symbol, amount, type, params = {}) {
3519
+ await this.loadMarkets();
3520
+ const market = this.market(symbol);
3521
+ amount = this.amountToPrecision(symbol, amount);
3522
+ const request = {
3523
+ 'symbol': market['id'],
3524
+ 'amt': Precise.stringAbs(amount),
3525
+ 'type': type.toUpperCase(), // 'ADD' or 'REDUCE'
3526
+ };
3527
+ // todo: hedged handling, tricky
3528
+ if (!('posMode' in params)) {
3529
+ request['posMode'] = 'BOTH';
3530
+ }
3531
+ const response = await this.swapPrivatePostV3TradePositionMargin(this.extend(request, params));
3532
+ //
3533
+ // {
3534
+ // "code": 200,
3535
+ // "data": {
3536
+ // "amt": "50",
3537
+ // "lever": "20",
3538
+ // "symbol": "DOT_USDT_PERP",
3539
+ // "posSide": "BOTH",
3540
+ // "type": "ADD"
3541
+ // },
3542
+ // "msg": "Success"
3543
+ // }
3544
+ //
3545
+ if (type === 'reduce') {
3546
+ amount = Precise.stringAbs(amount);
3547
+ }
3548
+ const data = this.safeDict(response, 'data');
3549
+ return this.parseMarginModification(data, market);
3550
+ }
3551
+ parseMarginModification(data, market = undefined) {
3552
+ const marketId = this.safeString(data, 'symbol');
3553
+ market = this.safeMarket(marketId, market);
3554
+ const rawType = this.safeString(data, 'type');
3555
+ const type = (rawType === 'ADD') ? 'add' : 'reduce';
3556
+ return {
3557
+ 'info': data,
3558
+ 'symbol': market['symbol'],
3559
+ 'type': type,
3560
+ 'marginMode': undefined,
3561
+ 'amount': this.safeNumber(data, 'amt'),
3562
+ 'total': undefined,
3563
+ 'code': undefined,
3564
+ 'status': 'ok',
3565
+ 'timestamp': undefined,
3566
+ 'datetime': undefined,
3567
+ };
3568
+ }
3569
+ /**
3570
+ * @method
3571
+ * @name poloniex#reduceMargin
3572
+ * @description remove margin from a position
3573
+ * @param {string} symbol unified market symbol
3574
+ * @param {float} amount the amount of margin to remove
3575
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3576
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
3577
+ */
3578
+ async reduceMargin(symbol, amount, params = {}) {
3579
+ return await this.modifyMarginHelper(symbol, -amount, 'reduce', params);
3580
+ }
3581
+ /**
3582
+ * @method
3583
+ * @name poloniex#addMargin
3584
+ * @description add margin
3585
+ * @param {string} symbol unified market symbol
3586
+ * @param {float} amount amount of margin to add
3587
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3588
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
3589
+ */
3590
+ async addMargin(symbol, amount, params = {}) {
3591
+ return await this.modifyMarginHelper(symbol, amount, 'add', params);
3592
+ }
2366
3593
  nonce() {
2367
3594
  return this.milliseconds();
2368
3595
  }
2369
3596
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2370
- let url = this.urls['api']['rest'];
3597
+ let url = this.urls['api']['spot'];
3598
+ if (this.inArray(api, ['swapPublic', 'swapPrivate'])) {
3599
+ url = this.urls['api']['swap'];
3600
+ }
2371
3601
  const query = this.omit(params, this.extractParams(path));
2372
3602
  const implodedPath = this.implodeParams(path, params);
2373
- if (api === 'public') {
3603
+ if (api === 'public' || api === 'swapPublic') {
2374
3604
  url += '/' + implodedPath;
2375
3605
  if (Object.keys(query).length) {
2376
3606
  url += '?' + this.urlencode(query);