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