ccxt-ir 4.3.46.0.3__py2.py3-none-any.whl → 4.5.1__py2.py3-none-any.whl

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 (529) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +8 -8
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +8 -8
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +8 -8
  68. ccxt/async_support/afratether.py +10 -10
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +32 -38
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +32 -27
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +34 -30
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +15 -14
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +30 -36
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +29 -24
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +32 -28
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +13 -12
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.1.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/WHEEL +1 -1
  437. ccxt/__test__.py +0 -7
  438. ccxt/abstract/ace.py +0 -15
  439. ccxt/abstract/bitbay.py +0 -53
  440. ccxt/abstract/bitcoincom.py +0 -115
  441. ccxt/abstract/bitfinex2.py +0 -139
  442. ccxt/abstract/bitpanda.py +0 -35
  443. ccxt/abstract/bl3p.py +0 -19
  444. ccxt/abstract/coinlist.py +0 -54
  445. ccxt/abstract/currencycom.py +0 -68
  446. ccxt/abstract/hitbtc3.py +0 -115
  447. ccxt/abstract/idex.py +0 -26
  448. ccxt/abstract/kuna.py +0 -182
  449. ccxt/abstract/lykke.py +0 -29
  450. ccxt/abstract/poloniexfutures.py +0 -48
  451. ccxt/abstract/wazirx.py +0 -30
  452. ccxt/ace.py +0 -1012
  453. ccxt/async_support/ace.py +0 -1012
  454. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  455. ccxt/async_support/base/ws/fast_client.py +0 -96
  456. ccxt/async_support/bitbay.py +0 -17
  457. ccxt/async_support/bitcoincom.py +0 -17
  458. ccxt/async_support/bitfinex2.py +0 -3552
  459. ccxt/async_support/bitpanda.py +0 -16
  460. ccxt/async_support/bl3p.py +0 -485
  461. ccxt/async_support/coinlist.py +0 -2243
  462. ccxt/async_support/currencycom.py +0 -1950
  463. ccxt/async_support/hitbtc3.py +0 -16
  464. ccxt/async_support/idex.py +0 -1766
  465. ccxt/async_support/kuna.py +0 -1841
  466. ccxt/async_support/lykke.py +0 -1270
  467. ccxt/async_support/poloniexfutures.py +0 -1717
  468. ccxt/async_support/wazirx.py +0 -1224
  469. ccxt/bitbay.py +0 -17
  470. ccxt/bitcoincom.py +0 -17
  471. ccxt/bitfinex2.py +0 -3552
  472. ccxt/bitpanda.py +0 -16
  473. ccxt/bl3p.py +0 -485
  474. ccxt/coinlist.py +0 -2243
  475. ccxt/currencycom.py +0 -1950
  476. ccxt/hitbtc3.py +0 -16
  477. ccxt/idex.py +0 -1766
  478. ccxt/kuna.py +0 -1841
  479. ccxt/lykke.py +0 -1270
  480. ccxt/poloniexfutures.py +0 -1717
  481. ccxt/pro/bitcoincom.py +0 -34
  482. ccxt/pro/bitfinex2.py +0 -1083
  483. ccxt/pro/bitpanda.py +0 -15
  484. ccxt/pro/currencycom.py +0 -536
  485. ccxt/pro/idex.py +0 -672
  486. ccxt/pro/poloniexfutures.py +0 -990
  487. ccxt/pro/wazirx.py +0 -749
  488. ccxt/test/base/__init__.py +0 -29
  489. ccxt/test/base/test_account.py +0 -26
  490. ccxt/test/base/test_balance.py +0 -56
  491. ccxt/test/base/test_borrow_interest.py +0 -35
  492. ccxt/test/base/test_borrow_rate.py +0 -32
  493. ccxt/test/base/test_calculate_fee.py +0 -51
  494. ccxt/test/base/test_crypto.py +0 -127
  495. ccxt/test/base/test_currency.py +0 -76
  496. ccxt/test/base/test_datetime.py +0 -109
  497. ccxt/test/base/test_decimal_to_precision.py +0 -392
  498. ccxt/test/base/test_deep_extend.py +0 -68
  499. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  500. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  501. ccxt/test/base/test_funding_rate_history.py +0 -29
  502. ccxt/test/base/test_last_price.py +0 -31
  503. ccxt/test/base/test_ledger_entry.py +0 -45
  504. ccxt/test/base/test_ledger_item.py +0 -48
  505. ccxt/test/base/test_leverage_tier.py +0 -33
  506. ccxt/test/base/test_liquidation.py +0 -50
  507. ccxt/test/base/test_margin_mode.py +0 -24
  508. ccxt/test/base/test_margin_modification.py +0 -35
  509. ccxt/test/base/test_market.py +0 -193
  510. ccxt/test/base/test_number.py +0 -411
  511. ccxt/test/base/test_ohlcv.py +0 -33
  512. ccxt/test/base/test_open_interest.py +0 -32
  513. ccxt/test/base/test_order.py +0 -64
  514. ccxt/test/base/test_order_book.py +0 -69
  515. ccxt/test/base/test_position.py +0 -60
  516. ccxt/test/base/test_shared_methods.py +0 -353
  517. ccxt/test/base/test_status.py +0 -24
  518. ccxt/test/base/test_throttle.py +0 -126
  519. ccxt/test/base/test_ticker.py +0 -92
  520. ccxt/test/base/test_trade.py +0 -47
  521. ccxt/test/base/test_trading_fee.py +0 -26
  522. ccxt/test/base/test_transaction.py +0 -39
  523. ccxt/test/test_async.py +0 -1649
  524. ccxt/test/test_sync.py +0 -1648
  525. ccxt/wazirx.py +0 -1224
  526. ccxt_ir-4.3.46.0.3.dist-info/RECORD +0 -773
  527. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  528. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info/licenses}/LICENSE.txt +0 -0
  529. {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.1.dist-info}/top_level.txt +0 -0
ccxt/poloniex.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.poloniex import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
9
+ from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, DepositAddress, Int, Leverage, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -28,7 +28,7 @@ from ccxt.base.precise import Precise
28
28
 
29
29
  class poloniex(Exchange, ImplicitAPI):
30
30
 
31
- def describe(self):
31
+ def describe(self) -> Any:
32
32
  return self.deep_extend(super(poloniex, self).describe(), {
33
33
  'id': 'poloniex',
34
34
  'name': 'Poloniex',
@@ -41,39 +41,56 @@ class poloniex(Exchange, ImplicitAPI):
41
41
  'CORS': None,
42
42
  'spot': True,
43
43
  'margin': None, # has but not fully implemented
44
- 'swap': False,
45
- 'future': False,
44
+ 'swap': True,
45
+ 'future': True,
46
46
  'option': False,
47
+ 'addMargin': True,
47
48
  'cancelAllOrders': True,
48
49
  'cancelOrder': True,
50
+ 'cancelOrders': None, # not yet implemented, because RL is worse than cancelOrder
49
51
  'createDepositAddress': True,
50
52
  'createMarketBuyOrderWithCost': True,
51
53
  'createMarketOrderWithCost': False,
52
54
  'createMarketSellOrderWithCost': False,
53
55
  'createOrder': True,
56
+ 'createOrders': None, # not yet implemented, because RL is worse than createOrder
57
+ 'createStopOrder': True,
58
+ 'createTriggerOrder': True,
54
59
  'editOrder': True,
55
60
  'fetchBalance': True,
56
61
  'fetchClosedOrder': False,
62
+ 'fetchClosedOrders': True,
57
63
  'fetchCurrencies': True,
58
64
  'fetchDepositAddress': True,
65
+ 'fetchDepositAddresses': False,
66
+ 'fetchDepositAddressesByNetwork': False,
59
67
  'fetchDeposits': True,
60
68
  'fetchDepositsWithdrawals': True,
61
69
  'fetchDepositWithdrawFee': 'emulated',
62
70
  'fetchDepositWithdrawFees': True,
71
+ 'fetchFundingHistory': False,
72
+ 'fetchFundingInterval': False,
73
+ 'fetchFundingIntervals': False,
63
74
  'fetchFundingRate': False,
75
+ 'fetchFundingRateHistory': False,
76
+ 'fetchFundingRates': None, # has but not implemented
77
+ 'fetchLedger': None, # has but not implemented
78
+ 'fetchLeverage': True,
79
+ 'fetchLiquidations': None, # has but not implemented
64
80
  'fetchMarginMode': False,
65
81
  'fetchMarkets': True,
66
82
  'fetchMyTrades': True,
67
83
  'fetchOHLCV': True,
68
84
  'fetchOpenInterestHistory': False,
69
85
  'fetchOpenOrder': False,
70
- 'fetchOpenOrders': True, # True endpoint for open orders
86
+ 'fetchOpenOrders': True,
71
87
  'fetchOrder': True,
72
88
  'fetchOrderBook': True,
73
89
  'fetchOrderBooks': False,
74
- 'fetchOrderTrades': True, # True endpoint for trades of a single open or closed order
90
+ 'fetchOrderTrades': True,
75
91
  'fetchPosition': False,
76
- 'fetchPositionMode': False,
92
+ 'fetchPositionMode': True,
93
+ 'fetchPositions': True,
77
94
  'fetchTicker': True,
78
95
  'fetchTickers': True,
79
96
  'fetchTime': True,
@@ -84,36 +101,40 @@ class poloniex(Exchange, ImplicitAPI):
84
101
  'fetchTransfer': False,
85
102
  'fetchTransfers': False,
86
103
  'fetchWithdrawals': True,
104
+ 'reduceMargin': True,
87
105
  'sandbox': True,
106
+ 'setLeverage': True,
107
+ 'setPositionMode': True,
88
108
  'transfer': True,
89
109
  'withdraw': True,
90
110
  },
91
111
  'timeframes': {
92
112
  '1m': 'MINUTE_1',
93
113
  '5m': 'MINUTE_5',
94
- '10m': 'MINUTE_10',
114
+ '10m': 'MINUTE_10', # not in swap
95
115
  '15m': 'MINUTE_15',
96
116
  '30m': 'MINUTE_30',
97
117
  '1h': 'HOUR_1',
98
118
  '2h': 'HOUR_2',
99
119
  '4h': 'HOUR_4',
100
- '6h': 'HOUR_6',
120
+ '6h': 'HOUR_6', # not in swap
101
121
  '12h': 'HOUR_12',
102
122
  '1d': 'DAY_1',
103
123
  '3d': 'DAY_3',
104
124
  '1w': 'WEEK_1',
105
- '1M': 'MONTH_1',
125
+ '1M': 'MONTH_1', # not in swap
106
126
  },
107
127
  'urls': {
108
128
  'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
109
129
  'api': {
110
- 'rest': 'https://api.poloniex.com',
130
+ 'spot': 'https://api.poloniex.com',
131
+ 'swap': 'https://api.poloniex.com',
111
132
  },
112
133
  'test': {
113
- 'rest': 'https://sand-spot-api-gateway.poloniex.com',
134
+ 'spot': 'https://sand-spot-api-gateway.poloniex.com',
114
135
  },
115
136
  'www': 'https://www.poloniex.com',
116
- 'doc': 'https://docs.poloniex.com',
137
+ 'doc': 'https://api-docs.poloniex.com/spot/',
117
138
  'fees': 'https://poloniex.com/fees',
118
139
  'referral': 'https://poloniex.com/signup?c=UBFZJRPJ',
119
140
  },
@@ -197,6 +218,55 @@ class poloniex(Exchange, ImplicitAPI):
197
218
  'smartorders/{id}': 20,
198
219
  },
199
220
  },
221
+ 'swapPublic': {
222
+ 'get': {
223
+ # 300 calls / second
224
+ 'v3/market/allInstruments': 2 / 3,
225
+ 'v3/market/instruments': 2 / 3,
226
+ 'v3/market/orderBook': 2 / 3,
227
+ 'v3/market/candles': 10, # candles have differnt RL
228
+ 'v3/market/indexPriceCandlesticks': 10,
229
+ 'v3/market/premiumIndexCandlesticks': 10,
230
+ 'v3/market/markPriceCandlesticks': 10,
231
+ 'v3/market/trades': 2 / 3,
232
+ 'v3/market/liquidationOrder': 2 / 3,
233
+ 'v3/market/tickers': 2 / 3,
234
+ 'v3/market/markPrice': 2 / 3,
235
+ 'v3/market/indexPrice': 2 / 3,
236
+ 'v3/market/indexPriceComponents': 2 / 3,
237
+ 'v3/market/fundingRate': 2 / 3,
238
+ 'v3/market/openInterest': 2 / 3,
239
+ 'v3/market/insurance': 2 / 3,
240
+ 'v3/market/riskLimit': 2 / 3,
241
+ },
242
+ },
243
+ 'swapPrivate': {
244
+ 'get': {
245
+ 'v3/account/balance': 4,
246
+ 'v3/account/bills': 20,
247
+ 'v3/trade/order/opens': 20,
248
+ 'v3/trade/order/trades': 20,
249
+ 'v3/trade/order/history': 20,
250
+ 'v3/trade/position/opens': 20,
251
+ 'v3/trade/position/history': 20, # todo: method for self
252
+ 'v3/position/leverages': 20,
253
+ 'v3/position/mode': 20,
254
+ },
255
+ 'post': {
256
+ 'v3/trade/order': 4,
257
+ 'v3/trade/orders': 40,
258
+ 'v3/trade/position': 20,
259
+ 'v3/trade/positionAll': 100,
260
+ 'v3/position/leverage': 20,
261
+ 'v3/position/mode': 20,
262
+ 'v3/trade/position/margin': 20,
263
+ },
264
+ 'delete': {
265
+ 'v3/trade/order': 2,
266
+ 'v3/trade/batchOrders': 20,
267
+ 'v3/trade/allOrders': 20,
268
+ },
269
+ },
200
270
  },
201
271
  'fees': {
202
272
  'trading': {
@@ -245,11 +315,17 @@ class poloniex(Exchange, ImplicitAPI):
245
315
  'UST': 'USTC',
246
316
  },
247
317
  'options': {
318
+ 'defaultType': 'spot',
248
319
  'createMarketBuyOrderRequiresPrice': True,
249
320
  'networks': {
250
321
  'BEP20': 'BSC',
251
322
  'ERC20': 'ETH',
252
323
  'TRC20': 'TRON',
324
+ 'TRX': 'TRON',
325
+ },
326
+ 'networksById': {
327
+ 'TRX': 'TRC20',
328
+ 'TRON': 'TRC20',
253
329
  },
254
330
  'limits': {
255
331
  'cost': {
@@ -277,6 +353,110 @@ class poloniex(Exchange, ImplicitAPI):
277
353
  'futures': 'future',
278
354
  },
279
355
  },
356
+ 'features': {
357
+ 'default': {
358
+ 'sandbox': True,
359
+ 'createOrder': {
360
+ 'marginMode': True, # todo
361
+ 'triggerPrice': True,
362
+ 'triggerPriceType': None,
363
+ 'triggerDirection': False,
364
+ 'stopLossPrice': False, # todo
365
+ 'takeProfitPrice': False, # todo
366
+ 'attachedStopLossTakeProfit': None,
367
+ 'timeInForce': {
368
+ 'IOC': True,
369
+ 'FOK': True,
370
+ 'PO': True,
371
+ 'GTD': False,
372
+ },
373
+ 'hedged': False,
374
+ 'leverage': False,
375
+ 'marketBuyByCost': True,
376
+ 'marketBuyRequiresPrice': False,
377
+ 'selfTradePrevention': True, # todo, only for non-trigger orders
378
+ 'trailing': False,
379
+ 'iceberg': False,
380
+ },
381
+ 'createOrders': {
382
+ 'max': 20,
383
+ },
384
+ 'fetchMyTrades': {
385
+ 'marginMode': False,
386
+ 'limit': 1000,
387
+ 'daysBack': 100000,
388
+ 'untilDays': 100000,
389
+ 'symbolRequired': False,
390
+ },
391
+ 'fetchOrder': {
392
+ 'marginMode': False,
393
+ 'trigger': False,
394
+ 'trailing': False,
395
+ 'symbolRequired': False,
396
+ },
397
+ 'fetchOpenOrders': {
398
+ 'marginMode': False,
399
+ 'limit': 2000,
400
+ 'trigger': False,
401
+ 'trailing': False,
402
+ 'symbolRequired': False,
403
+ },
404
+ 'fetchOrders': None,
405
+ 'fetchClosedOrders': None, # todo implement
406
+ 'fetchOHLCV': {
407
+ 'limit': 500,
408
+ },
409
+ },
410
+ 'spot': {
411
+ 'extends': 'default',
412
+ },
413
+ 'forContracts': {
414
+ 'extends': 'default',
415
+ 'createOrder': {
416
+ 'marginMode': True,
417
+ 'triggerPrice': False,
418
+ 'hedged': True,
419
+ 'stpMode': True, # todo
420
+ 'marketBuyByCost': False,
421
+ },
422
+ 'createOrders': {
423
+ 'max': 10,
424
+ },
425
+ 'fetchOpenOrders': {
426
+ 'limit': 100,
427
+ },
428
+ 'fetchClosedOrders': {
429
+ 'marginMode': False,
430
+ 'limit': 100,
431
+ 'daysBack': None,
432
+ 'daysBackCanceled': 1 / 6,
433
+ 'untilDays': None,
434
+ 'trigger': False,
435
+ 'trailing': False,
436
+ 'symbolRequired': False,
437
+ },
438
+ 'fetchMyTrades': {
439
+ 'limit': 100,
440
+ 'untilDays': 90,
441
+ },
442
+ },
443
+ 'swap': {
444
+ 'linear': {
445
+ 'extends': 'forContracts',
446
+ },
447
+ 'inverse': {
448
+ 'extends': 'forContracts',
449
+ },
450
+ },
451
+ 'future': {
452
+ 'linear': {
453
+ 'extends': 'forContracts',
454
+ },
455
+ 'inverse': {
456
+ 'extends': 'forContracts',
457
+ },
458
+ },
459
+ },
280
460
  'precisionMode': TICK_SIZE,
281
461
  'exceptions': {
282
462
  'exact': {
@@ -359,6 +539,7 @@ class poloniex(Exchange, ImplicitAPI):
359
539
  '21350': InvalidOrder, # Amount must be greater than 1 USDT
360
540
  '21355': ExchangeError, # Interval between startTime and endTime in trade/order history has exceeded 7 day limit
361
541
  '21356': BadRequest, # Order size would cause too much price movement. Reduce order size.
542
+ '21721': InsufficientFunds,
362
543
  '24101': BadSymbol, # Invalid symbol
363
544
  '24102': InvalidOrder, # Invalid K-line type
364
545
  '24103': InvalidOrder, # Invalid endTime
@@ -393,6 +574,8 @@ class poloniex(Exchange, ImplicitAPI):
393
574
  })
394
575
 
395
576
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
577
+ #
578
+ # spot:
396
579
  #
397
580
  # [
398
581
  # [
@@ -413,6 +596,31 @@ class poloniex(Exchange, ImplicitAPI):
413
596
  # ]
414
597
  # ]
415
598
  #
599
+ # contract:
600
+ #
601
+ # [
602
+ # "84207.02",
603
+ # "84320.85",
604
+ # "84207.02",
605
+ # "84253.83",
606
+ # "3707.5395",
607
+ # "44",
608
+ # "14",
609
+ # "1740770040000",
610
+ # "1740770099999",
611
+ # ],
612
+ #
613
+ ohlcvLength = len(ohlcv)
614
+ isContract = ohlcvLength == 9
615
+ if isContract:
616
+ return [
617
+ self.safe_integer(ohlcv, 7),
618
+ self.safe_number(ohlcv, 2),
619
+ self.safe_number(ohlcv, 1),
620
+ self.safe_number(ohlcv, 0),
621
+ self.safe_number(ohlcv, 3),
622
+ self.safe_number(ohlcv, 5),
623
+ ]
416
624
  return [
417
625
  self.safe_integer(ohlcv, 12),
418
626
  self.safe_number(ohlcv, 2),
@@ -425,7 +633,10 @@ class poloniex(Exchange, ImplicitAPI):
425
633
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
426
634
  """
427
635
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
428
- :see: https://docs.poloniex.com/#public-endpoints-market-data-candles
636
+
637
+ https://api-docs.poloniex.com/spot/api/public/market-data#candles
638
+ https://api-docs.poloniex.com/v3/futures/api/market/get-kline-data
639
+
429
640
  :param str symbol: unified symbol of the market to fetch OHLCV data for
430
641
  :param str timeframe: the length of time each candle represents
431
642
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -445,12 +656,37 @@ class poloniex(Exchange, ImplicitAPI):
445
656
  'symbol': market['id'],
446
657
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
447
658
  }
659
+ keyStart = 'startTime' if market['spot'] else 'sTime'
660
+ keyEnd = 'endTime' if market['spot'] else 'eTime'
448
661
  if since is not None:
449
- request['startTime'] = since
662
+ request[keyStart] = since
450
663
  if limit is not None:
451
664
  # limit should in between 100 and 500
452
665
  request['limit'] = limit
453
- request, params = self.handle_until_option('endTime', request, params)
666
+ request, params = self.handle_until_option(keyEnd, request, params)
667
+ if market['contract']:
668
+ if self.in_array(timeframe, ['10m', '1M']):
669
+ raise NotSupported(self.id + ' ' + timeframe + ' ' + market['type'] + ' fetchOHLCV is not supported')
670
+ responseRaw = self.swapPublicGetV3MarketCandles(self.extend(request, params))
671
+ #
672
+ # {
673
+ # code: "200",
674
+ # msg: "Success",
675
+ # data: [
676
+ # [
677
+ # "84207.02",
678
+ # "84320.85",
679
+ # "84207.02",
680
+ # "84253.83",
681
+ # "3707.5395",
682
+ # "44",
683
+ # "14",
684
+ # "1740770040000",
685
+ # "1740770099999",
686
+ # ],
687
+ #
688
+ data = self.safe_list(responseRaw, 'data')
689
+ return self.parse_ohlcvs(data, market, timeframe, since, limit)
454
690
  response = self.publicGetMarketsSymbolCandles(self.extend(request, params))
455
691
  #
456
692
  # [
@@ -484,10 +720,18 @@ class poloniex(Exchange, ImplicitAPI):
484
720
  def fetch_markets(self, params={}) -> List[Market]:
485
721
  """
486
722
  retrieves data on all markets for poloniex
487
- :see: https://docs.poloniex.com/#public-endpoints-reference-data-symbol-information
723
+
724
+ https://api-docs.poloniex.com/spot/api/public/reference-data#symbol-information
725
+ https://api-docs.poloniex.com/v3/futures/api/market/get-all-product-info
726
+
488
727
  :param dict [params]: extra parameters specific to the exchange API endpoint
489
728
  :returns dict[]: an array of objects representing market data
490
729
  """
730
+ promises = [self.fetch_spot_markets(params), self.fetch_swap_markets(params)]
731
+ results = promises
732
+ return self.array_concat(results[0], results[1])
733
+
734
+ def fetch_spot_markets(self, params={}) -> List[Market]:
491
735
  markets = self.publicGetMarkets(params)
492
736
  #
493
737
  # [
@@ -514,7 +758,57 @@ class poloniex(Exchange, ImplicitAPI):
514
758
  #
515
759
  return self.parse_markets(markets)
516
760
 
761
+ def fetch_swap_markets(self, params={}) -> List[Market]:
762
+ # do similar per https://api-docs.poloniex.com/v3/futures/api/market/get-product-info
763
+ response = self.swapPublicGetV3MarketAllInstruments(params)
764
+ #
765
+ # {
766
+ # "code": "200",
767
+ # "msg": "Success",
768
+ # "data": [
769
+ # {
770
+ # "symbol": "BNB_USDT_PERP",
771
+ # "bAsset": ".PBNBUSDT",
772
+ # "bCcy": "BNB",
773
+ # "qCcy": "USDT",
774
+ # "visibleStartTime": "1620390600000",
775
+ # "tradableStartTime": "1620390600000",
776
+ # "sCcy": "USDT",
777
+ # "tSz": "0.001",
778
+ # "pxScale": "0.001,0.01,0.1,1,10",
779
+ # "lotSz": "1",
780
+ # "minSz": "1",
781
+ # "ctVal": "0.1",
782
+ # "status": "OPEN",
783
+ # "oDate": "1620287590000",
784
+ # "maxPx": "1000000",
785
+ # "minPx": "0.001",
786
+ # "maxQty": "1000000",
787
+ # "minQty": "1",
788
+ # "maxLever": "50",
789
+ # "lever": "10",
790
+ # "ctType": "LINEAR",
791
+ # "alias": "",
792
+ # "iM": "0.02",
793
+ # "mM": "0.0115",
794
+ # "mR": "2000",
795
+ # "buyLmt": "",
796
+ # "sellLmt": "",
797
+ # "ordPxRange": "0.05",
798
+ # "marketMaxQty": "2800",
799
+ # "limitMaxQty": "1000000"
800
+ # },
801
+ #
802
+ markets = self.safe_list(response, 'data')
803
+ return self.parse_markets(markets)
804
+
517
805
  def parse_market(self, market: dict) -> Market:
806
+ if 'ctType' in market:
807
+ return self.parse_swap_market(market)
808
+ else:
809
+ return self.parse_spot_market(market)
810
+
811
+ def parse_spot_market(self, market: dict) -> Market:
518
812
  id = self.safe_string(market, 'symbol')
519
813
  baseId = self.safe_string(market, 'baseCurrencyName')
520
814
  quoteId = self.safe_string(market, 'quoteCurrencyName')
@@ -570,10 +864,119 @@ class poloniex(Exchange, ImplicitAPI):
570
864
  'info': market,
571
865
  }
572
866
 
573
- def fetch_time(self, params={}):
867
+ def parse_swap_market(self, market: dict) -> Market:
868
+ #
869
+ # {
870
+ # "symbol": "BNB_USDT_PERP",
871
+ # "bAsset": ".PBNBUSDT",
872
+ # "bCcy": "BNB",
873
+ # "qCcy": "USDT",
874
+ # "visibleStartTime": "1620390600000",
875
+ # "tradableStartTime": "1620390600000",
876
+ # "sCcy": "USDT",
877
+ # "tSz": "0.001",
878
+ # "pxScale": "0.001,0.01,0.1,1,10",
879
+ # "lotSz": "1",
880
+ # "minSz": "1",
881
+ # "ctVal": "0.1",
882
+ # "status": "OPEN",
883
+ # "oDate": "1620287590000",
884
+ # "maxPx": "1000000",
885
+ # "minPx": "0.001",
886
+ # "maxQty": "1000000",
887
+ # "minQty": "1",
888
+ # "maxLever": "50",
889
+ # "lever": "10",
890
+ # "ctType": "LINEAR",
891
+ # "alias": "",
892
+ # "iM": "0.02",
893
+ # "mM": "0.0115",
894
+ # "mR": "2000",
895
+ # "buyLmt": "",
896
+ # "sellLmt": "",
897
+ # "ordPxRange": "0.05",
898
+ # "marketMaxQty": "2800",
899
+ # "limitMaxQty": "1000000"
900
+ # },
901
+ #
902
+ id = self.safe_string(market, 'symbol')
903
+ baseId = self.safe_string(market, 'bCcy')
904
+ quoteId = self.safe_string(market, 'qCcy')
905
+ settleId = self.safe_string(market, 'sCcy')
906
+ base = self.safe_currency_code(baseId)
907
+ quote = self.safe_currency_code(quoteId)
908
+ settle = self.safe_currency_code(settleId)
909
+ status = self.safe_string(market, 'status')
910
+ active = status == 'OPEN'
911
+ linear = market['ctType'] == 'LINEAR'
912
+ symbol = base + '/' + quote
913
+ if linear:
914
+ symbol += ':' + settle
915
+ else:
916
+ # actually, exchange does not have any inverse future now
917
+ symbol += ':' + base
918
+ alias = self.safe_string(market, 'alias')
919
+ type = 'swap'
920
+ if alias is not None:
921
+ type = 'future'
922
+ return {
923
+ 'id': id,
924
+ 'symbol': symbol,
925
+ 'base': base,
926
+ 'quote': quote,
927
+ 'settle': settle,
928
+ 'baseId': baseId,
929
+ 'quoteId': quoteId,
930
+ 'settleId': settleId,
931
+ 'type': 'future' if (type == 'future') else 'swap',
932
+ 'spot': False,
933
+ 'margin': False,
934
+ 'swap': type == 'swap',
935
+ 'future': type == 'future',
936
+ 'option': False,
937
+ 'active': active,
938
+ 'contract': True,
939
+ 'linear': linear,
940
+ 'inverse': not linear,
941
+ 'contractSize': self.safe_number(market, 'ctVal'),
942
+ 'expiry': None,
943
+ 'expiryDatetime': None,
944
+ 'strike': None,
945
+ 'optionType': None,
946
+ 'taker': self.safe_number(market, 'tFee'),
947
+ 'maker': self.safe_number(market, 'mFee'),
948
+ 'precision': {
949
+ 'amount': self.safe_number(market, 'lotSz'),
950
+ 'price': self.safe_number(market, 'tSz'),
951
+ },
952
+ 'limits': {
953
+ 'amount': {
954
+ 'min': self.safe_number(market, 'minSz'),
955
+ 'max': self.safe_number(market, 'limitMaxQty'),
956
+ },
957
+ 'price': {
958
+ 'min': self.safe_number(market, 'minPx'),
959
+ 'max': self.safe_number(market, 'maxPx'),
960
+ },
961
+ 'cost': {
962
+ 'min': None,
963
+ 'max': None,
964
+ },
965
+ 'leverage': {
966
+ 'max': self.safe_number(market, 'maxLever'),
967
+ 'min': None,
968
+ },
969
+ },
970
+ 'created': self.safe_integer(market, 'oDate'),
971
+ 'info': market,
972
+ }
973
+
974
+ def fetch_time(self, params={}) -> Int:
574
975
  """
575
976
  fetches the current integer timestamp in milliseconds from the exchange server
576
- :see: https://docs.poloniex.com/#public-endpoints-reference-data-system-timestamp
977
+
978
+ https://api-docs.poloniex.com/spot/api/public/reference-data#system-timestamp
979
+
577
980
  :param dict [params]: extra parameters specific to the exchange API endpoint
578
981
  :returns int: the current integer timestamp in milliseconds from the exchange server
579
982
  """
@@ -581,6 +984,8 @@ class poloniex(Exchange, ImplicitAPI):
581
984
  return self.safe_integer(response, 'serverTime')
582
985
 
583
986
  def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
987
+ #
988
+ # spot:
584
989
  #
585
990
  # {
586
991
  # "symbol" : "BTC_USDT",
@@ -603,48 +1008,112 @@ class poloniex(Exchange, ImplicitAPI):
603
1008
  # "markPrice" : "26444.11"
604
1009
  # }
605
1010
  #
606
- timestamp = self.safe_integer(ticker, 'ts')
607
- marketId = self.safe_string(ticker, 'symbol')
1011
+ # swap:
1012
+ #
1013
+ # {
1014
+ # "s": "XRP_USDT_PERP",
1015
+ # "o": "2.0503",
1016
+ # "l": "2.0066",
1017
+ # "h": "2.216",
1018
+ # "c": "2.1798",
1019
+ # "qty": "21090",
1020
+ # "amt": "451339.65",
1021
+ # "tC": "3267",
1022
+ # "sT": "1740736380000",
1023
+ # "cT": "1740822777559",
1024
+ # "dN": "XRP/USDT/PERP",
1025
+ # "dC": "0.0632",
1026
+ # "bPx": "2.175",
1027
+ # "bSz": "3",
1028
+ # "aPx": "2.1831",
1029
+ # "aSz": "111",
1030
+ # "mPx": "2.1798",
1031
+ # "iPx": "2.1834"
1032
+ # },
1033
+ #
1034
+ timestamp = self.safe_integer_2(ticker, 'ts', 'cT')
1035
+ marketId = self.safe_string_2(ticker, 'symbol', 's')
608
1036
  market = self.safe_market(marketId)
609
- close = self.safe_string(ticker, 'close')
610
- relativeChange = self.safe_string(ticker, 'dailyChange')
1037
+ relativeChange = self.safe_string_2(ticker, 'dailyChange', 'dc')
611
1038
  percentage = Precise.string_mul(relativeChange, '100')
612
- bidVolume = self.safe_string(ticker, 'bidQuantity')
613
- askVolume = self.safe_string(ticker, 'askQuantity')
614
1039
  return self.safe_ticker({
615
1040
  'id': marketId,
616
1041
  'symbol': market['symbol'],
617
1042
  'timestamp': timestamp,
618
1043
  'datetime': self.iso8601(timestamp),
619
- 'high': self.safe_string(ticker, 'high'),
620
- 'low': self.safe_string(ticker, 'low'),
621
- 'bid': self.safe_string(ticker, 'bid'),
622
- 'bidVolume': bidVolume,
623
- 'ask': self.safe_string(ticker, 'ask'),
624
- 'askVolume': askVolume,
1044
+ 'high': self.safe_string_2(ticker, 'high', 'h'),
1045
+ 'low': self.safe_string_2(ticker, 'low', 'l'),
1046
+ 'bid': self.safe_string_2(ticker, 'bid', 'bPx'),
1047
+ 'bidVolume': self.safe_string_2(ticker, 'bidQuantity', 'bSz'),
1048
+ 'ask': self.safe_string_2(ticker, 'ask', 'aPx'),
1049
+ 'askVolume': self.safe_string_2(ticker, 'askQuantity', 'aSz'),
625
1050
  'vwap': None,
626
- 'open': self.safe_string(ticker, 'open'),
627
- 'close': close,
628
- 'last': close,
1051
+ 'open': self.safe_string_2(ticker, 'open', 'o'),
1052
+ 'close': self.safe_string_2(ticker, 'close', 'c'),
629
1053
  'previousClose': None,
630
1054
  'change': None,
631
1055
  'percentage': percentage,
632
1056
  'average': None,
633
- 'baseVolume': self.safe_string(ticker, 'quantity'),
634
- 'quoteVolume': self.safe_string(ticker, 'amount'),
1057
+ 'baseVolume': self.safe_string_2(ticker, 'quantity', 'qty'),
1058
+ 'quoteVolume': self.safe_string_2(ticker, 'amount', 'amt'),
1059
+ 'markPrice': self.safe_string_2(ticker, 'markPrice', 'mPx'),
1060
+ 'indexPrice': self.safe_string(ticker, 'iPx'),
635
1061
  'info': ticker,
636
1062
  }, market)
637
1063
 
638
1064
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
639
1065
  """
640
1066
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
641
- :see: https://docs.poloniex.com/#public-endpoints-market-data-ticker
1067
+
1068
+ https://api-docs.poloniex.com/spot/api/public/market-data#ticker
1069
+ https://api-docs.poloniex.com/v3/futures/api/market/get-market-info
1070
+
642
1071
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
643
1072
  :param dict [params]: extra parameters specific to the exchange API endpoint
644
1073
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
645
1074
  """
646
1075
  self.load_markets()
647
- symbols = self.market_symbols(symbols)
1076
+ market = None
1077
+ request: dict = {}
1078
+ if symbols is not None:
1079
+ symbols = self.market_symbols(symbols, None, True, True, False)
1080
+ symbolsLength = len(symbols)
1081
+ if symbolsLength > 0:
1082
+ market = self.market(symbols[0])
1083
+ if symbolsLength == 1:
1084
+ request['symbol'] = market['id']
1085
+ marketType = None
1086
+ marketType, params = self.handle_market_type_and_params('fetchTickers', market, params)
1087
+ if marketType == 'swap':
1088
+ responseRaw = self.swapPublicGetV3MarketTickers(self.extend(request, params))
1089
+ #
1090
+ # {
1091
+ # "code": "200",
1092
+ # "msg": "Success",
1093
+ # "data": [
1094
+ # {
1095
+ # "s": "XRP_USDT_PERP",
1096
+ # "o": "2.0503",
1097
+ # "l": "2.0066",
1098
+ # "h": "2.216",
1099
+ # "c": "2.1798",
1100
+ # "qty": "21090",
1101
+ # "amt": "451339.65",
1102
+ # "tC": "3267",
1103
+ # "sT": "1740736380000",
1104
+ # "cT": "1740822777559",
1105
+ # "dN": "XRP/USDT/PERP",
1106
+ # "dC": "0.0632",
1107
+ # "bPx": "2.175",
1108
+ # "bSz": "3",
1109
+ # "aPx": "2.1831",
1110
+ # "aSz": "111",
1111
+ # "mPx": "2.1798",
1112
+ # "iPx": "2.1834"
1113
+ # },
1114
+ #
1115
+ data = self.safe_list(responseRaw, 'data')
1116
+ return self.parse_tickers(data, symbols)
648
1117
  response = self.publicGetMarketsTicker24h(params)
649
1118
  #
650
1119
  # [
@@ -675,108 +1144,112 @@ class poloniex(Exchange, ImplicitAPI):
675
1144
  def fetch_currencies(self, params={}) -> Currencies:
676
1145
  """
677
1146
  fetches all available currencies on an exchange
678
- :see: https://docs.poloniex.com/#public-endpoints-reference-data-currency-information
1147
+
1148
+ https://api-docs.poloniex.com/spot/api/public/reference-data#currency-information
1149
+
679
1150
  :param dict [params]: extra parameters specific to the exchange API endpoint
680
1151
  :returns dict: an associative dictionary of currencies
681
1152
  """
682
1153
  response = self.publicGetCurrencies(self.extend(params, {'includeMultiChainCurrencies': True}))
683
1154
  #
684
1155
  # [
685
- # {
686
- # "1CR": {
687
- # "id": 1,
688
- # "name": "1CRedit",
689
- # "description": "BTC Clone",
690
- # "type": "address",
691
- # "withdrawalFee": "0.01000000",
692
- # "minConf": 10000,
693
- # "depositAddress": null,
694
- # "blockchain": "1CR",
695
- # "delisted": False,
696
- # "tradingState": "NORMAL",
697
- # "walletState": "DISABLED",
698
- # "walletDepositState": "DISABLED",
699
- # "walletWithdrawalState": "DISABLED",
700
- # "parentChain": null,
701
- # "isMultiChain": False,
702
- # "isChildChain": False,
703
- # "childChains": []
704
- # }
705
- # }
1156
+ # {
1157
+ # "USDT": {
1158
+ # "id": 214,
1159
+ # "name": "Tether USD",
1160
+ # "description": "Sweep to Main Account",
1161
+ # "type": "address",
1162
+ # "withdrawalFee": "0.00000000",
1163
+ # "minConf": 2,
1164
+ # "depositAddress": null,
1165
+ # "blockchain": "OMNI",
1166
+ # "delisted": False,
1167
+ # "tradingState": "NORMAL",
1168
+ # "walletState": "DISABLED",
1169
+ # "walletDepositState": "DISABLED",
1170
+ # "walletWithdrawalState": "DISABLED",
1171
+ # "supportCollateral": True,
1172
+ # "supportBorrow": True,
1173
+ # "parentChain": null,
1174
+ # "isMultiChain": True,
1175
+ # "isChildChain": False,
1176
+ # "childChains": [
1177
+ # "USDTBSC",
1178
+ # "USDTETH",
1179
+ # "USDTSOL",
1180
+ # "USDTTRON"
1181
+ # ]
1182
+ # }
1183
+ # },
1184
+ # ...
1185
+ # {
1186
+ # "USDTBSC": {
1187
+ # "id": 582,
1188
+ # "name": "Binance-Peg BSC-USD",
1189
+ # "description": "Sweep to Main Account",
1190
+ # "type": "address",
1191
+ # "withdrawalFee": "0.00000000",
1192
+ # "minConf": 15,
1193
+ # "depositAddress": null,
1194
+ # "blockchain": "BSC",
1195
+ # "delisted": False,
1196
+ # "tradingState": "OFFLINE",
1197
+ # "walletState": "ENABLED",
1198
+ # "walletDepositState": "ENABLED",
1199
+ # "walletWithdrawalState": "DISABLED",
1200
+ # "supportCollateral": False,
1201
+ # "supportBorrow": False,
1202
+ # "parentChain": "USDT",
1203
+ # "isMultiChain": True,
1204
+ # "isChildChain": True,
1205
+ # "childChains": []
1206
+ # }
1207
+ # },
1208
+ # ...
706
1209
  # ]
707
1210
  #
708
1211
  result: dict = {}
1212
+ # poloniex has a complicated structure of currencies, so we handle them differently
1213
+ # at first, turn the response into a normal dictionary
1214
+ currenciesDict = {}
709
1215
  for i in range(0, len(response)):
710
- item = self.safe_value(response, i)
1216
+ item = self.safe_dict(response, i)
711
1217
  ids = list(item.keys())
712
- id = self.safe_value(ids, 0)
713
- currency = self.safe_value(item, id)
1218
+ id = self.safe_string(ids, 0)
1219
+ currenciesDict[id] = item[id]
1220
+ keys = list(currenciesDict.keys())
1221
+ for i in range(0, len(keys)):
1222
+ id = keys[i]
1223
+ entry = currenciesDict[id]
714
1224
  code = self.safe_currency_code(id)
715
- name = self.safe_string(currency, 'name')
716
- networkId = self.safe_string(currency, 'blockchain')
717
- networkCode = None
718
- if networkId is not None:
719
- networkCode = self.network_id_to_code(networkId, code)
720
- delisted = self.safe_value(currency, 'delisted')
721
- walletEnabled = self.safe_string(currency, 'walletState') == 'ENABLED'
722
- depositEnabled = self.safe_string(currency, 'walletDepositState') == 'ENABLED'
723
- withdrawEnabled = self.safe_string(currency, 'walletWithdrawalState') == 'ENABLED'
724
- active = not delisted and walletEnabled and depositEnabled and withdrawEnabled
725
- numericId = self.safe_integer(currency, 'id')
726
- feeString = self.safe_string(currency, 'withdrawalFee')
727
- parentChain = self.safe_value(currency, 'parentChain')
728
- noParentChain = parentChain is None
729
- if self.safe_value(result, code) is None:
730
- result[code] = {
731
- 'id': id,
732
- 'code': code,
733
- 'info': None,
734
- 'name': name,
735
- 'active': active,
736
- 'deposit': depositEnabled,
737
- 'withdraw': withdrawEnabled,
738
- 'fee': self.parse_number(feeString),
739
- 'precision': None,
740
- 'limits': {
741
- 'amount': {
742
- 'min': None,
743
- 'max': None,
744
- },
745
- 'deposit': {
746
- 'min': None,
747
- 'max': None,
748
- },
749
- 'withdraw': {
750
- 'min': None,
751
- 'max': None,
752
- },
753
- },
754
- }
755
- minFeeString = self.safe_string(result[code], 'fee')
756
- if feeString is not None:
757
- minFeeString = feeString if (minFeeString is None) else Precise.string_min(feeString, minFeeString)
758
- depositAvailable = self.safe_value(result[code], 'deposit')
759
- depositAvailable = depositEnabled if (depositEnabled) else depositAvailable
760
- withdrawAvailable = self.safe_value(result[code], 'withdraw')
761
- withdrawAvailable = withdrawEnabled if (withdrawEnabled) else withdrawAvailable
762
- networks = self.safe_value(result[code], 'networks', {})
763
- if networkCode is not None:
1225
+ # skip childChains, are collected in parentChain loop
1226
+ if self.safe_bool(entry, 'isChildChain'):
1227
+ continue
1228
+ allChainEntries = []
1229
+ childChains = self.safe_list(entry, 'childChains', [])
1230
+ if childChains is not None:
1231
+ for j in range(0, len(childChains)):
1232
+ childChainId = childChains[j]
1233
+ childNetworkEntry = self.safe_dict(currenciesDict, childChainId)
1234
+ allChainEntries.append(childNetworkEntry)
1235
+ allChainEntries.append(entry)
1236
+ networks: dict = {}
1237
+ for j in range(0, len(allChainEntries)):
1238
+ chainEntry = allChainEntries[j]
1239
+ networkName = self.safe_string(chainEntry, 'blockchain')
1240
+ networkCode = self.network_id_to_code(networkName, code)
1241
+ specialNetworkId = self.safe_string(childChains, j, id) # in case it's primary chain, defeault to ID
764
1242
  networks[networkCode] = {
765
- 'info': currency,
766
- 'id': networkId,
1243
+ 'info': chainEntry,
1244
+ 'id': specialNetworkId, # we need self for deposit/withdrawal, instead of friendly name
1245
+ 'numericId': self.safe_integer(chainEntry, 'id'),
767
1246
  'network': networkCode,
768
- 'currencyId': id,
769
- 'numericId': numericId,
770
- 'deposit': depositEnabled,
771
- 'withdraw': withdrawEnabled,
772
- 'active': active,
773
- 'fee': self.parse_number(feeString),
1247
+ 'active': self.safe_bool(chainEntry, 'walletState'),
1248
+ 'deposit': self.safe_string(chainEntry, 'walletDepositState') == 'ENABLED',
1249
+ 'withdraw': self.safe_string(chainEntry, 'walletWithdrawalState') == 'ENABLED',
1250
+ 'fee': self.safe_number(chainEntry, 'withdrawalFee'),
774
1251
  'precision': None,
775
1252
  'limits': {
776
- 'amount': {
777
- 'min': None,
778
- 'max': None,
779
- },
780
1253
  'withdraw': {
781
1254
  'min': None,
782
1255
  'max': None,
@@ -787,25 +1260,43 @@ class poloniex(Exchange, ImplicitAPI):
787
1260
  },
788
1261
  },
789
1262
  }
790
- result[code]['networks'] = networks
791
- info = self.safe_value(result[code], 'info', [])
792
- rawInfo: dict = {}
793
- rawInfo[id] = currency
794
- info.append(rawInfo)
795
- result[code]['info'] = info
796
- if noParentChain:
797
- result[code]['id'] = id
798
- result[code]['name'] = name
799
- result[code]['active'] = depositAvailable and withdrawAvailable
800
- result[code]['deposit'] = depositAvailable
801
- result[code]['withdraw'] = withdrawAvailable
802
- result[code]['fee'] = self.parse_number(minFeeString)
1263
+ result[code] = self.safe_currency_structure({
1264
+ 'info': entry,
1265
+ 'code': code,
1266
+ 'id': id,
1267
+ 'numericId': self.safe_integer(entry, 'id'),
1268
+ 'type': 'crypto',
1269
+ 'name': self.safe_string(entry, 'name'),
1270
+ 'active': None,
1271
+ 'deposit': None,
1272
+ 'withdraw': None,
1273
+ 'fee': None,
1274
+ 'precision': None,
1275
+ 'limits': {
1276
+ 'amount': {
1277
+ 'min': None,
1278
+ 'max': None,
1279
+ },
1280
+ 'withdraw': {
1281
+ 'min': None,
1282
+ 'max': None,
1283
+ },
1284
+ 'deposit': {
1285
+ 'min': None,
1286
+ 'max': None,
1287
+ },
1288
+ },
1289
+ 'networks': networks,
1290
+ })
803
1291
  return result
804
1292
 
805
1293
  def fetch_ticker(self, symbol: str, params={}) -> Ticker:
806
1294
  """
807
1295
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
808
- :see: https://docs.poloniex.com/#public-endpoints-market-data-ticker
1296
+
1297
+ https://api-docs.poloniex.com/spot/api/public/market-data#ticker
1298
+ https://api-docs.poloniex.com/v3/futures/api/market/get-market-info
1299
+
809
1300
  :param str symbol: unified symbol of the market to fetch the ticker for
810
1301
  :param dict [params]: extra parameters specific to the exchange API endpoint
811
1302
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -815,6 +1306,9 @@ class poloniex(Exchange, ImplicitAPI):
815
1306
  request: dict = {
816
1307
  'symbol': market['id'],
817
1308
  }
1309
+ if market['contract']:
1310
+ tickers = self.fetch_tickers([market['symbol']], params)
1311
+ return self.safe_dict(tickers, symbol)
818
1312
  response = self.publicGetMarketsSymbolTicker24h(self.extend(request, params))
819
1313
  #
820
1314
  # {
@@ -844,6 +1338,8 @@ class poloniex(Exchange, ImplicitAPI):
844
1338
  #
845
1339
  # fetchTrades
846
1340
  #
1341
+ # spot:
1342
+ #
847
1343
  # {
848
1344
  # "id" : "60014521",
849
1345
  # "price" : "23162.94",
@@ -854,8 +1350,21 @@ class poloniex(Exchange, ImplicitAPI):
854
1350
  # "createTime" : 1659684602036
855
1351
  # }
856
1352
  #
1353
+ # swap:
1354
+ #
1355
+ # {
1356
+ # "id": "105807376",
1357
+ # "side": "buy",
1358
+ # "px": "84410.57",
1359
+ # "qty": "1",
1360
+ # "amt": "84.41057",
1361
+ # "cT": "1740777563557",
1362
+ # }
1363
+ #
857
1364
  # fetchMyTrades
858
1365
  #
1366
+ # spot:
1367
+ #
859
1368
  # {
860
1369
  # "id": "32164924331503616",
861
1370
  # "symbol": "LINK_USDT",
@@ -874,6 +1383,34 @@ class poloniex(Exchange, ImplicitAPI):
874
1383
  # "clientOrderId": "myOwnId-321"
875
1384
  # }
876
1385
  #
1386
+ # swap:
1387
+ #
1388
+ # {
1389
+ # "symbol": "BTC_USDT_PERP",
1390
+ # "trdId": "105813553",
1391
+ # "side": "SELL",
1392
+ # "type": "TRADE",
1393
+ # "mgnMode": "CROSS",
1394
+ # "ordType": "MARKET",
1395
+ # "clOrdId": "polo418912106147315112",
1396
+ # "role": "TAKER",
1397
+ # "px": "84704.9",
1398
+ # "qty": "1",
1399
+ # "cTime": "1740842829430",
1400
+ # "uTime": "1740842829450",
1401
+ # "feeCcy": "USDT",
1402
+ # "feeAmt": "0.04235245",
1403
+ # "deductCcy": "",
1404
+ # "deductAmt": "0",
1405
+ # "feeRate": "0.0005",
1406
+ # "id": "418912106342654592",
1407
+ # "posSide": "BOTH",
1408
+ # "ordId": "418912106147315112",
1409
+ # "qCcy": "USDT",
1410
+ # "value": "84.7049",
1411
+ # "actType": "TRADING"
1412
+ # },
1413
+ #
877
1414
  # fetchOrderTrades(taker trades)
878
1415
  #
879
1416
  # {
@@ -894,20 +1431,19 @@ class poloniex(Exchange, ImplicitAPI):
894
1431
  # "clientOrderId": ""
895
1432
  # }
896
1433
  #
897
- #
898
- id = self.safe_string_2(trade, 'id', 'tradeID')
899
- orderId = self.safe_string(trade, 'orderId')
900
- timestamp = self.safe_integer_2(trade, 'ts', 'createTime')
1434
+ id = self.safe_string_n(trade, ['id', 'tradeID', 'trdId'])
1435
+ orderId = self.safe_string_2(trade, 'orderId', 'ordId')
1436
+ timestamp = self.safe_integer_n(trade, ['ts', 'createTime', 'cT', 'cTime'])
901
1437
  marketId = self.safe_string(trade, 'symbol')
902
1438
  market = self.safe_market(marketId, market, '_')
903
1439
  symbol = market['symbol']
904
1440
  side = self.safe_string_lower_2(trade, 'side', 'takerSide')
905
1441
  fee = None
906
- priceString = self.safe_string(trade, 'price')
907
- amountString = self.safe_string(trade, 'quantity')
908
- costString = self.safe_string(trade, 'amount')
909
- feeCurrencyId = self.safe_string(trade, 'feeCurrency')
910
- feeCostString = self.safe_string(trade, 'feeAmount')
1442
+ priceString = self.safe_string_2(trade, 'price', 'px')
1443
+ amountString = self.safe_string_2(trade, 'quantity', 'qty')
1444
+ costString = self.safe_string_2(trade, 'amount', 'amt')
1445
+ feeCurrencyId = self.safe_string_2(trade, 'feeCurrency', 'feeCcy')
1446
+ feeCostString = self.safe_string_2(trade, 'feeAmount', 'feeAmt')
911
1447
  if feeCostString is not None:
912
1448
  feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
913
1449
  fee = {
@@ -921,9 +1457,9 @@ class poloniex(Exchange, ImplicitAPI):
921
1457
  'datetime': self.iso8601(timestamp),
922
1458
  'symbol': symbol,
923
1459
  'order': orderId,
924
- 'type': self.safe_string_lower(trade, 'type'),
1460
+ 'type': self.safe_string_lower_2(trade, 'ordType', 'type'), # ordType should take precedence
925
1461
  'side': side,
926
- 'takerOrMaker': self.safe_string_lower(trade, 'matchRole'),
1462
+ 'takerOrMaker': self.safe_string_lower_2(trade, 'matchRole', 'role'),
927
1463
  'price': priceString,
928
1464
  'amount': amountString,
929
1465
  'cost': costString,
@@ -933,7 +1469,10 @@ class poloniex(Exchange, ImplicitAPI):
933
1469
  def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
934
1470
  """
935
1471
  get the list of most recent trades for a particular symbol
936
- :see: https://docs.poloniex.com/#public-endpoints-market-data-trades
1472
+
1473
+ https://api-docs.poloniex.com/spot/api/public/market-data#trades
1474
+ https://api-docs.poloniex.com/v3/futures/api/market/get-execution-info
1475
+
937
1476
  :param str symbol: unified symbol of the market to fetch trades for
938
1477
  :param int [since]: timestamp in ms of the earliest trade to fetch
939
1478
  :param int [limit]: the maximum amount of trades to fetch
@@ -946,7 +1485,25 @@ class poloniex(Exchange, ImplicitAPI):
946
1485
  'symbol': market['id'],
947
1486
  }
948
1487
  if limit is not None:
949
- request['limit'] = limit
1488
+ request['limit'] = limit # max 1000, for spot & swap
1489
+ if market['contract']:
1490
+ response = self.swapPublicGetV3MarketTrades(self.extend(request, params))
1491
+ #
1492
+ # {
1493
+ # code: "200",
1494
+ # msg: "Success",
1495
+ # data: [
1496
+ # {
1497
+ # id: "105807320", # descending order
1498
+ # side: "sell",
1499
+ # px: "84383.93",
1500
+ # qty: "1",
1501
+ # amt: "84.38393",
1502
+ # cT: "1740777074704",
1503
+ # },
1504
+ #
1505
+ tradesList = self.safe_list(response, 'data')
1506
+ return self.parse_trades(tradesList, market, since, limit)
950
1507
  trades = self.publicGetMarketsSymbolTrades(self.extend(request, params))
951
1508
  #
952
1509
  # [
@@ -966,7 +1523,10 @@ class poloniex(Exchange, ImplicitAPI):
966
1523
  def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
967
1524
  """
968
1525
  fetch all trades made by the user
969
- :see: https://docs.poloniex.com/#authenticated-endpoints-trades-trade-history
1526
+
1527
+ https://api-docs.poloniex.com/spot/api/private/trade#trade-history
1528
+ https://api-docs.poloniex.com/v3/futures/api/trade/get-execution-details
1529
+
970
1530
  :param str symbol: unified market symbol
971
1531
  :param int [since]: the earliest time in ms to fetch trades for
972
1532
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -983,15 +1543,57 @@ class poloniex(Exchange, ImplicitAPI):
983
1543
  market: Market = None
984
1544
  if symbol is not None:
985
1545
  market = self.market(symbol)
1546
+ marketType = None
1547
+ marketType, params = self.handle_market_type_and_params('fetchMyTrades', market, params)
1548
+ isContract = self.in_array(marketType, ['swap', 'future'])
986
1549
  request: dict = {
987
1550
  # 'from': 12345678, # A 'trade Id'. The query begins at ‘from'.
988
1551
  # 'direction': 'PRE', # PRE, NEXT The direction before or after ‘from'.
989
1552
  }
1553
+ startKey = 'sTime' if isContract else 'startTime'
1554
+ endKey = 'eTime' if isContract else 'endTime'
990
1555
  if since is not None:
991
- request['startTime'] = since
1556
+ request[startKey] = since
992
1557
  if limit is not None:
993
1558
  request['limit'] = limit
994
- request, params = self.handle_until_option('endTime', request, params)
1559
+ if isContract and symbol is not None:
1560
+ request['symbol'] = market['id']
1561
+ request, params = self.handle_until_option(endKey, request, params)
1562
+ if isContract:
1563
+ raw = self.swapPrivateGetV3TradeOrderTrades(self.extend(request, params))
1564
+ #
1565
+ # {
1566
+ # "code": "200",
1567
+ # "msg": "",
1568
+ # "data": [
1569
+ # {
1570
+ # "symbol": "BTC_USDT_PERP",
1571
+ # "trdId": "105813553",
1572
+ # "side": "SELL",
1573
+ # "type": "TRADE",
1574
+ # "mgnMode": "CROSS",
1575
+ # "ordType": "MARKET",
1576
+ # "clOrdId": "polo418912106147315112",
1577
+ # "role": "TAKER",
1578
+ # "px": "84704.9",
1579
+ # "qty": "1",
1580
+ # "cTime": "1740842829430",
1581
+ # "uTime": "1740842829450",
1582
+ # "feeCcy": "USDT",
1583
+ # "feeAmt": "0.04235245",
1584
+ # "deductCcy": "",
1585
+ # "deductAmt": "0",
1586
+ # "feeRate": "0.0005",
1587
+ # "id": "418912106342654592",
1588
+ # "posSide": "BOTH",
1589
+ # "ordId": "418912106147315112",
1590
+ # "qCcy": "USDT",
1591
+ # "value": "84.7049",
1592
+ # "actType": "TRADING"
1593
+ # },
1594
+ #
1595
+ data = self.safe_list(raw, 'data')
1596
+ return self.parse_trades(data, market, since, limit)
995
1597
  response = self.privateGetTrades(self.extend(request, params))
996
1598
  #
997
1599
  # [
@@ -1052,7 +1654,9 @@ class poloniex(Exchange, ImplicitAPI):
1052
1654
  # "updateTime" : 16xxxxxxxxx36
1053
1655
  # }
1054
1656
  #
1055
- # fetchOpenOrders
1657
+ # fetchOpenOrders(and fetchClosedOrders same for contracts)
1658
+ #
1659
+ # spot:
1056
1660
  #
1057
1661
  # {
1058
1662
  # "id": "24993088082542592",
@@ -1073,32 +1677,79 @@ class poloniex(Exchange, ImplicitAPI):
1073
1677
  # "updateTime": 1646925216548
1074
1678
  # }
1075
1679
  #
1680
+ # contract:
1681
+ #
1682
+ # {
1683
+ # "symbol": "BTC_USDT_PERP",
1684
+ # "side": "BUY",
1685
+ # "type": "LIMIT",
1686
+ # "ordId": "418890767248232148",
1687
+ # "clOrdId": "polo418890767248232148",
1688
+ # "mgnMode": "CROSS",
1689
+ # "px": "81130.13",
1690
+ # "reduceOnly": False,
1691
+ # "lever": "20",
1692
+ # "state": "NEW",
1693
+ # "source": "WEB",
1694
+ # "timeInForce": "GTC",
1695
+ # "tpTrgPx": "",
1696
+ # "tpPx": "",
1697
+ # "tpTrgPxType": "",
1698
+ # "slTrgPx": "",
1699
+ # "slPx": "",
1700
+ # "slTrgPxType": "",
1701
+ # "avgPx": "0",
1702
+ # "execQty": "0",
1703
+ # "execAmt": "0",
1704
+ # "feeCcy": "",
1705
+ # "feeAmt": "0",
1706
+ # "deductCcy": "0",
1707
+ # "deductAmt": "0",
1708
+ # "stpMode": "NONE", # todo: selfTradePrevention
1709
+ # "cTime": "1740837741523",
1710
+ # "uTime": "1740840846882",
1711
+ # "sz": "1",
1712
+ # "posSide": "BOTH",
1713
+ # "qCcy": "USDT"
1714
+ # "cancelReason": "", # self field can only be in closed orders
1715
+ # },
1716
+ #
1076
1717
  # createOrder, editOrder
1077
1718
  #
1719
+ # spot:
1720
+ #
1078
1721
  # {
1079
1722
  # "id": "29772698821328896",
1080
1723
  # "clientOrderId": "1234Abc"
1081
1724
  # }
1082
1725
  #
1083
- timestamp = self.safe_integer_2(order, 'timestamp', 'createTime')
1726
+ # contract:
1727
+ #
1728
+ # {
1729
+ # "ordId":"418876147745775616",
1730
+ # "clOrdId":"polo418876147745775616"
1731
+ # }
1732
+ #
1733
+ timestamp = self.safe_integer_n(order, ['timestamp', 'createTime', 'cTime'])
1084
1734
  if timestamp is None:
1085
1735
  timestamp = self.parse8601(self.safe_string(order, 'date'))
1086
1736
  marketId = self.safe_string(order, 'symbol')
1087
1737
  market = self.safe_market(marketId, market, '_')
1088
1738
  symbol = market['symbol']
1089
1739
  resultingTrades = self.safe_value(order, 'resultingTrades')
1090
- if not isinstance(resultingTrades, list):
1091
- resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1092
- price = self.safe_string_2(order, 'price', 'rate')
1093
- amount = self.safe_string(order, 'quantity')
1094
- filled = self.safe_string(order, 'filledQuantity')
1740
+ if resultingTrades is not None:
1741
+ if not isinstance(resultingTrades, list):
1742
+ resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1743
+ price = self.safe_string_n(order, ['price', 'rate', 'px'])
1744
+ amount = self.safe_string_2(order, 'quantity', 'sz')
1745
+ filled = self.safe_string_2(order, 'filledQuantity', 'execQty')
1095
1746
  status = self.parse_order_status(self.safe_string(order, 'state'))
1096
1747
  side = self.safe_string_lower(order, 'side')
1097
1748
  rawType = self.safe_string(order, 'type')
1098
1749
  type = self.parse_order_type(rawType)
1099
- id = self.safe_string_n(order, ['orderNumber', 'id', 'orderId'])
1750
+ id = self.safe_string_n(order, ['orderNumber', 'id', 'orderId', 'ordId'])
1100
1751
  fee = None
1101
- feeCurrency = self.safe_string(order, 'tokenFeeCurrency')
1752
+ feeCurrency = self.safe_string_2(order, 'tokenFeeCurrency', 'feeCcy')
1102
1753
  feeCost: Str = None
1103
1754
  feeCurrencyCode: Str = None
1104
1755
  rate = self.safe_string(order, 'fee')
@@ -1107,15 +1758,18 @@ class poloniex(Exchange, ImplicitAPI):
1107
1758
  else:
1108
1759
  # poloniex accepts a 30% discount to pay fees in TRX
1109
1760
  feeCurrencyCode = self.safe_currency_code(feeCurrency)
1110
- feeCost = self.safe_string(order, 'tokenFee')
1761
+ feeCost = self.safe_string_2(order, 'tokenFee', 'feeAmt')
1111
1762
  if feeCost is not None:
1112
1763
  fee = {
1113
1764
  'rate': rate,
1114
1765
  'cost': feeCost,
1115
1766
  'currency': feeCurrencyCode,
1116
1767
  }
1117
- clientOrderId = self.safe_string(order, 'clientOrderId')
1118
- triggerPrice = self.safe_string_2(order, 'triggerPrice', 'stopPrice')
1768
+ clientOrderId = self.safe_string_2(order, 'clientOrderId', 'clOrdId')
1769
+ marginMode = self.safe_string_lower(order, 'mgnMode')
1770
+ reduceOnly = self.safe_bool(order, 'reduceOnly')
1771
+ leverage = self.safe_integer(order, 'lever')
1772
+ hedged = self.safe_string(order, 'posSide') != 'BOTH'
1119
1773
  return self.safe_order({
1120
1774
  'info': order,
1121
1775
  'id': id,
@@ -1127,24 +1781,28 @@ class poloniex(Exchange, ImplicitAPI):
1127
1781
  'symbol': symbol,
1128
1782
  'type': type,
1129
1783
  'timeInForce': self.safe_string(order, 'timeInForce'),
1130
- 'postOnly': None,
1784
+ 'postOnly': rawType == 'LIMIT_MAKER',
1131
1785
  'side': side,
1132
1786
  'price': price,
1133
- 'stopPrice': triggerPrice,
1134
- 'triggerPrice': triggerPrice,
1135
- 'cost': None,
1136
- 'average': self.safe_string(order, 'avgPrice'),
1787
+ 'triggerPrice': self.safe_string_2(order, 'triggerPrice', 'stopPrice'),
1788
+ 'cost': self.safe_string(order, 'execAmt'),
1789
+ 'average': self.safe_string_2(order, 'avgPrice', 'avgPx'),
1137
1790
  'amount': amount,
1138
1791
  'filled': filled,
1139
1792
  'remaining': None,
1140
1793
  'trades': resultingTrades,
1141
1794
  'fee': fee,
1795
+ 'marginMode': marginMode,
1796
+ 'reduceOnly': reduceOnly,
1797
+ 'leverage': leverage,
1798
+ 'hedged': hedged,
1142
1799
  }, market)
1143
1800
 
1144
1801
  def parse_order_type(self, status):
1145
1802
  statuses: dict = {
1146
1803
  'MARKET': 'market',
1147
1804
  'LIMIT': 'limit',
1805
+ 'LIMIT_MAKER': 'limit',
1148
1806
  'STOP-LIMIT': 'limit',
1149
1807
  'STOP-MARKET': 'market',
1150
1808
  }
@@ -1165,13 +1823,16 @@ class poloniex(Exchange, ImplicitAPI):
1165
1823
  def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1166
1824
  """
1167
1825
  fetch all unfilled currently open orders
1168
- :see: https://docs.poloniex.com/#authenticated-endpoints-orders-open-orders
1169
- :see: https://docs.poloniex.com/#authenticated-endpoints-smart-orders-open-orders # trigger orders
1826
+
1827
+ https://api-docs.poloniex.com/spot/api/private/order#open-orders
1828
+ https://api-docs.poloniex.com/spot/api/private/smart-order#open-orders # trigger orders
1829
+ https://api-docs.poloniex.com/v3/futures/api/trade/get-current-orders
1830
+
1170
1831
  :param str symbol: unified market symbol
1171
1832
  :param int [since]: the earliest time in ms to fetch open orders for
1172
1833
  :param int [limit]: the maximum number of open orders structures to retrieve
1173
1834
  :param dict [params]: extra parameters specific to the exchange API endpoint
1174
- :param boolean [params.stop]: set True to fetch trigger orders instead of regular orders
1835
+ :param boolean [params.trigger]: set True to fetch trigger orders instead of regular orders
1175
1836
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1176
1837
  """
1177
1838
  self.load_markets()
@@ -1180,12 +1841,57 @@ class poloniex(Exchange, ImplicitAPI):
1180
1841
  if symbol is not None:
1181
1842
  market = self.market(symbol)
1182
1843
  request['symbol'] = market['id']
1844
+ marketType = None
1845
+ marketType, params = self.handle_market_type_and_params('fetchOpenOrders', market, params)
1183
1846
  if limit is not None:
1184
- request['limit'] = limit
1847
+ max = 2000 if (marketType == 'spot') else 100
1848
+ request['limit'] = max(limit, max)
1185
1849
  isTrigger = self.safe_value_2(params, 'trigger', 'stop')
1186
1850
  params = self.omit(params, ['trigger', 'stop'])
1187
1851
  response = None
1188
- if isTrigger:
1852
+ if marketType != 'spot':
1853
+ raw = self.swapPrivateGetV3TradeOrderOpens(self.extend(request, params))
1854
+ #
1855
+ # {
1856
+ # "code": "200",
1857
+ # "msg": "",
1858
+ # "data": [
1859
+ # {
1860
+ # "symbol": "BTC_USDT_PERP",
1861
+ # "side": "BUY",
1862
+ # "type": "LIMIT",
1863
+ # "ordId": "418890767248232148",
1864
+ # "clOrdId": "polo418890767248232148",
1865
+ # "mgnMode": "CROSS",
1866
+ # "px": "81130.13",
1867
+ # "reduceOnly": False,
1868
+ # "lever": "20",
1869
+ # "state": "NEW",
1870
+ # "source": "WEB",
1871
+ # "timeInForce": "GTC",
1872
+ # "tpTrgPx": "",
1873
+ # "tpPx": "",
1874
+ # "tpTrgPxType": "",
1875
+ # "slTrgPx": "",
1876
+ # "slPx": "",
1877
+ # "slTrgPxType": "",
1878
+ # "avgPx": "0",
1879
+ # "execQty": "0",
1880
+ # "execAmt": "0",
1881
+ # "feeCcy": "",
1882
+ # "feeAmt": "0",
1883
+ # "deductCcy": "0",
1884
+ # "deductAmt": "0",
1885
+ # "stpMode": "NONE",
1886
+ # "cTime": "1740837741523",
1887
+ # "uTime": "1740840846882",
1888
+ # "sz": "1",
1889
+ # "posSide": "BOTH",
1890
+ # "qCcy": "USDT"
1891
+ # },
1892
+ #
1893
+ response = self.safe_list(raw, 'data')
1894
+ elif isTrigger:
1189
1895
  response = self.privateGetSmartorders(self.extend(request, params))
1190
1896
  else:
1191
1897
  response = self.privateGetOrders(self.extend(request, params))
@@ -1215,36 +1921,114 @@ class poloniex(Exchange, ImplicitAPI):
1215
1921
  extension: dict = {'status': 'open'}
1216
1922
  return self.parse_orders(response, market, since, limit, extension)
1217
1923
 
1924
+ def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1925
+ """
1926
+
1927
+ https://api-docs.poloniex.com/v3/futures/api/trade/get-order-history
1928
+
1929
+ fetches information on multiple closed orders made by the user
1930
+ :param str symbol: unified market symbol of the market orders were made in
1931
+ :param int [since]: the earliest time in ms to fetch orders for
1932
+ :param int [limit]: the maximum number of order structures to retrieve
1933
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1934
+ :param int [params.until]: timestamp in ms of the latest entry
1935
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1936
+ """
1937
+ self.load_markets()
1938
+ market = None
1939
+ request: dict = {}
1940
+ if symbol is not None:
1941
+ market = self.market(symbol)
1942
+ request['symbol'] = market['id']
1943
+ marketType = None
1944
+ marketType, params = self.handle_market_type_and_params('fetchClosedOrders', market, params, 'swap')
1945
+ if marketType == 'spot':
1946
+ raise NotSupported(self.id + ' fetchClosedOrders() is not supported for spot markets yet')
1947
+ if limit is not None:
1948
+ request['limit'] = min(200, limit)
1949
+ if since is not None:
1950
+ request['sTime'] = since
1951
+ request, params = self.handle_until_option('eTime', request, params)
1952
+ response = self.swapPrivateGetV3TradeOrderHistory(self.extend(request, params))
1953
+ #
1954
+ # {
1955
+ # "code": "200",
1956
+ # "msg": "",
1957
+ # "data": [
1958
+ # {
1959
+ # "symbol": "BTC_USDT_PERP",
1960
+ # "side": "SELL",
1961
+ # "type": "MARKET",
1962
+ # "ordId": "418912106147315712",
1963
+ # "clOrdId": "polo418912106147315712",
1964
+ # "mgnMode": "CROSS",
1965
+ # "px": "0",
1966
+ # "sz": "2",
1967
+ # "lever": "20",
1968
+ # "state": "FILLED",
1969
+ # "cancelReason": "",
1970
+ # "source": "WEB",
1971
+ # "reduceOnly": "true",
1972
+ # "timeInForce": "GTC",
1973
+ # "tpTrgPx": "",
1974
+ # "tpPx": "",
1975
+ # "tpTrgPxType": "",
1976
+ # "slTrgPx": "",
1977
+ # "slPx": "",
1978
+ # "slTrgPxType": "",
1979
+ # "avgPx": "84705.56",
1980
+ # "execQty": "2",
1981
+ # "execAmt": "169.41112",
1982
+ # "feeCcy": "USDT",
1983
+ # "feeAmt": "0.08470556",
1984
+ # "deductCcy": "0",
1985
+ # "deductAmt": "0",
1986
+ # "stpMode": "NONE",
1987
+ # "cTime": "1740842829116",
1988
+ # "uTime": "1740842829130",
1989
+ # "posSide": "BOTH",
1990
+ # "qCcy": "USDT"
1991
+ # },
1992
+ #
1993
+ data = self.safe_list(response, 'data', [])
1994
+ return self.parse_orders(data, market, since, limit)
1995
+
1218
1996
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1219
1997
  """
1220
1998
  create a trade order
1221
- :see: https://docs.poloniex.com/#authenticated-endpoints-orders-create-order
1222
- :see: https://docs.poloniex.com/#authenticated-endpoints-smart-orders-create-order # trigger orders
1999
+
2000
+ https://api-docs.poloniex.com/spot/api/private/order#create-order
2001
+ https://api-docs.poloniex.com/spot/api/private/smart-order#create-order # trigger orders
2002
+
1223
2003
  :param str symbol: unified symbol of the market to create an order in
1224
2004
  :param str type: 'market' or 'limit'
1225
2005
  :param str side: 'buy' or 'sell'
1226
2006
  :param float amount: how much of currency you want to trade in units of base currency
1227
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2007
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1228
2008
  :param dict [params]: extra parameters specific to the exchange API endpoint
1229
- :param float [params.triggerPrice]: *spot only* The price at which a trigger order is triggered at
2009
+ :param float [params.triggerPrice]: the price at which a trigger order is triggered at
1230
2010
  :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
1231
2011
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1232
2012
  """
1233
2013
  self.load_markets()
1234
2014
  market = self.market(symbol)
1235
- if not market['spot']:
1236
- raise NotSupported(self.id + ' createOrder() does not support ' + market['type'] + ' orders, only spot orders are accepted')
1237
2015
  request: dict = {
1238
2016
  'symbol': market['id'],
1239
- 'side': side,
1240
- # 'timeInForce': timeInForce,
2017
+ 'side': side.upper(), # uppercase, both for spot & swap
2018
+ # 'timeInForce': timeInForce, # matches unified values
1241
2019
  # 'accountType': 'SPOT',
1242
2020
  # 'amount': amount,
1243
2021
  }
1244
2022
  triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
1245
2023
  request, params = self.order_request(symbol, type, side, amount, request, price, params)
1246
2024
  response = None
1247
- if triggerPrice is not None:
2025
+ if market['swap'] or market['future']:
2026
+ responseInitial = self.swapPrivatePostV3TradeOrder(self.extend(request, params))
2027
+ #
2028
+ # {"code":200,"msg":"Success","data":{"ordId":"418876147745775616","clOrdId":"polo418876147745775616"}}
2029
+ #
2030
+ response = self.safe_dict(responseInitial, 'data')
2031
+ elif triggerPrice is not None:
1248
2032
  response = self.privatePostSmartorders(self.extend(request, params))
1249
2033
  else:
1250
2034
  response = self.privatePostOrders(self.extend(request, params))
@@ -1254,18 +2038,31 @@ class poloniex(Exchange, ImplicitAPI):
1254
2038
  # "clientOrderId" : ""
1255
2039
  # }
1256
2040
  #
1257
- response = self.extend(response, {
1258
- 'type': side,
1259
- })
1260
2041
  return self.parse_order(response, market)
1261
2042
 
1262
2043
  def order_request(self, symbol, type, side, amount, request, price=None, params={}):
2044
+ triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
2045
+ market = self.market(symbol)
2046
+ if market['contract']:
2047
+ marginMode = None
2048
+ marginMode, params = self.handle_param_string(params, 'marginMode')
2049
+ if marginMode is not None:
2050
+ self.check_required_argument('createOrder', marginMode, 'marginMode', ['cross', 'isolated'])
2051
+ request['mgnMode'] = marginMode.upper()
2052
+ hedged = None
2053
+ hedged, params = self.handle_param_string(params, 'hedged')
2054
+ if hedged:
2055
+ if marginMode is None:
2056
+ raise ArgumentsRequired(self.id + ' createOrder() requires a marginMode parameter "cross" or "isolated" for hedged orders')
2057
+ if not ('posSide' in params):
2058
+ raise ArgumentsRequired(self.id + ' createOrder() requires a posSide parameter "LONG" or "SHORT" for hedged orders')
1263
2059
  upperCaseType = type.upper()
1264
2060
  isMarket = upperCaseType == 'MARKET'
1265
2061
  isPostOnly = self.is_post_only(isMarket, upperCaseType == 'LIMIT_MAKER', params)
1266
- triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
1267
2062
  params = self.omit(params, ['postOnly', 'triggerPrice', 'stopPrice'])
1268
2063
  if triggerPrice is not None:
2064
+ if not market['spot']:
2065
+ raise InvalidOrder(self.id + ' createOrder() does not support trigger orders for ' + market['type'] + ' markets')
1269
2066
  upperCaseType = 'STOP' if (price is None) else 'STOP_LIMIT'
1270
2067
  request['stopPrice'] = triggerPrice
1271
2068
  elif isPostOnly:
@@ -1280,7 +2077,7 @@ class poloniex(Exchange, ImplicitAPI):
1280
2077
  params = self.omit(params, 'cost')
1281
2078
  if cost is not None:
1282
2079
  quoteAmount = self.cost_to_precision(symbol, cost)
1283
- elif createMarketBuyOrderRequiresPrice:
2080
+ elif createMarketBuyOrderRequiresPrice and market['spot']:
1284
2081
  if price is None:
1285
2082
  raise InvalidOrder(self.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')
1286
2083
  else:
@@ -1290,12 +2087,16 @@ class poloniex(Exchange, ImplicitAPI):
1290
2087
  quoteAmount = self.cost_to_precision(symbol, costRequest)
1291
2088
  else:
1292
2089
  quoteAmount = self.cost_to_precision(symbol, amount)
1293
- request['amount'] = quoteAmount
2090
+ amountKey = 'amount' if market['spot'] else 'sz'
2091
+ request[amountKey] = quoteAmount
1294
2092
  else:
1295
- request['quantity'] = self.amount_to_precision(symbol, amount)
2093
+ amountKey = 'quantity' if market['spot'] else 'sz'
2094
+ request[amountKey] = self.amount_to_precision(symbol, amount)
1296
2095
  else:
1297
- request['quantity'] = self.amount_to_precision(symbol, amount)
1298
- request['price'] = self.price_to_precision(symbol, price)
2096
+ amountKey = 'quantity' if market['spot'] else 'sz'
2097
+ request[amountKey] = self.amount_to_precision(symbol, amount)
2098
+ priceKey = 'price' if market['spot'] else 'px'
2099
+ request[priceKey] = self.price_to_precision(symbol, price)
1299
2100
  clientOrderId = self.safe_string(params, 'clientOrderId')
1300
2101
  if clientOrderId is not None:
1301
2102
  request['clientOrderId'] = clientOrderId
@@ -1306,14 +2107,16 @@ class poloniex(Exchange, ImplicitAPI):
1306
2107
  def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1307
2108
  """
1308
2109
  edit a trade order
1309
- :see: https://docs.poloniex.com/#authenticated-endpoints-orders-cancel-replace-order
1310
- :see: https://docs.poloniex.com/#authenticated-endpoints-smart-orders-cancel-replace-order
2110
+
2111
+ https://api-docs.poloniex.com/spot/api/private/order#cancel-replace-order
2112
+ https://api-docs.poloniex.com/spot/api/private/smart-order#cancel-replace-order
2113
+
1311
2114
  :param str id: order id
1312
2115
  :param str symbol: unified symbol of the market to create an order in
1313
2116
  :param str type: 'market' or 'limit'
1314
2117
  :param str side: 'buy' or 'sell'
1315
2118
  :param float [amount]: how much of the currency you want to trade in units of the base currency
1316
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2119
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1317
2120
  :param dict [params]: extra parameters specific to the exchange API endpoint
1318
2121
  :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1319
2122
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -1340,7 +2143,8 @@ class poloniex(Exchange, ImplicitAPI):
1340
2143
  # }
1341
2144
  #
1342
2145
  response = self.extend(response, {
1343
- 'type': side,
2146
+ 'side': side,
2147
+ 'type': type,
1344
2148
  })
1345
2149
  return self.parse_order(response, market)
1346
2150
 
@@ -1349,8 +2153,8 @@ class poloniex(Exchange, ImplicitAPI):
1349
2153
  # @method
1350
2154
  # @name poloniex#cancelOrder
1351
2155
  # @description cancels an open order
1352
- # @see https://docs.poloniex.com/#authenticated-endpoints-orders-cancel-order-by-id
1353
- # @see https://docs.poloniex.com/#authenticated-endpoints-smart-orders-cancel-order-by-id # trigger orders
2156
+ # @see https://api-docs.poloniex.com/spot/api/private/order#cancel-order-by-id
2157
+ # @see https://api-docs.poloniex.com/spot/api/private/smart-order#cancel-order-by-id # trigger orders
1354
2158
  # @param {string} id order id
1355
2159
  # @param {string} symbol unified symbol of the market the order was made in
1356
2160
  # @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -1358,7 +2162,25 @@ class poloniex(Exchange, ImplicitAPI):
1358
2162
  # @returns {object} An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1359
2163
  #
1360
2164
  self.load_markets()
2165
+ if symbol is None:
2166
+ raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
2167
+ market = self.market(symbol)
1361
2168
  request: dict = {}
2169
+ if not market['spot']:
2170
+ request['symbol'] = market['id']
2171
+ request['ordId'] = id
2172
+ raw = self.swapPrivateDeleteV3TradeOrder(self.extend(request, params))
2173
+ #
2174
+ # {
2175
+ # "code": "200",
2176
+ # "msg": "Success",
2177
+ # "data": {
2178
+ # "ordId": "418886099910612040",
2179
+ # "clOrdId": "polo418886099910612040"
2180
+ # }
2181
+ # }
2182
+ #
2183
+ return self.parse_order(self.safe_dict(raw, 'data'))
1362
2184
  clientOrderId = self.safe_value(params, 'clientOrderId')
1363
2185
  if clientOrderId is not None:
1364
2186
  id = clientOrderId
@@ -1384,8 +2206,11 @@ class poloniex(Exchange, ImplicitAPI):
1384
2206
  def cancel_all_orders(self, symbol: Str = None, params={}):
1385
2207
  """
1386
2208
  cancel all open orders
1387
- :see: https://docs.poloniex.com/#authenticated-endpoints-orders-cancel-all-orders
1388
- :see: https://docs.poloniex.com/#authenticated-endpoints-smart-orders-cancel-all-orders # trigger orders
2209
+
2210
+ https://api-docs.poloniex.com/spot/api/private/order#cancel-all-orders
2211
+ https://api-docs.poloniex.com/spot/api/private/smart-order#cancel-all-orders # trigger orders
2212
+ https://api-docs.poloniex.com/v3/futures/api/trade/cancel-all-orders - contract markets
2213
+
1389
2214
  :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1390
2215
  :param dict [params]: extra parameters specific to the exchange API endpoint
1391
2216
  :param boolean [params.trigger]: True if canceling trigger orders
@@ -1402,9 +2227,29 @@ class poloniex(Exchange, ImplicitAPI):
1402
2227
  request['symbols'] = [
1403
2228
  market['id'],
1404
2229
  ]
2230
+ response = None
2231
+ marketType = None
2232
+ marketType, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
2233
+ if marketType == 'swap' or marketType == 'future':
2234
+ raw = self.swapPrivateDeleteV3TradeAllOrders(self.extend(request, params))
2235
+ #
2236
+ # {
2237
+ # "code": "200",
2238
+ # "msg": "Success",
2239
+ # "data": [
2240
+ # {
2241
+ # "code": "200",
2242
+ # "msg": "Success",
2243
+ # "ordId": "418885787866388511",
2244
+ # "clOrdId": "polo418885787866388511"
2245
+ # }
2246
+ # ]
2247
+ # }
2248
+ #
2249
+ response = self.safe_list(raw, 'data')
2250
+ return self.parse_orders(response, market)
1405
2251
  isTrigger = self.safe_value_2(params, 'trigger', 'stop')
1406
2252
  params = self.omit(params, ['trigger', 'stop'])
1407
- response = None
1408
2253
  if isTrigger:
1409
2254
  response = self.privateDeleteSmartorders(self.extend(request, params))
1410
2255
  else:
@@ -1431,8 +2276,10 @@ class poloniex(Exchange, ImplicitAPI):
1431
2276
  def fetch_order(self, id: str, symbol: Str = None, params={}):
1432
2277
  """
1433
2278
  fetch an order by it's id
1434
- :see: https://docs.poloniex.com/#authenticated-endpoints-orders-order-details
1435
- :see: https://docs.poloniex.com/#authenticated-endpoints-smart-orders-open-orders # trigger orders
2279
+
2280
+ https://api-docs.poloniex.com/spot/api/private/order#order-details
2281
+ https://api-docs.poloniex.com/spot/api/private/smart-order#open-orders # trigger orders
2282
+
1436
2283
  :param str id: order id
1437
2284
  :param str symbol: unified market symbol, default is None
1438
2285
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1444,6 +2291,14 @@ class poloniex(Exchange, ImplicitAPI):
1444
2291
  request: dict = {
1445
2292
  'id': id,
1446
2293
  }
2294
+ market = None
2295
+ if symbol is not None:
2296
+ market = self.market(symbol)
2297
+ request['symbol'] = market['id']
2298
+ marketType = None
2299
+ marketType, params = self.handle_market_type_and_params('fetchOrder', market, params)
2300
+ if marketType != 'spot':
2301
+ raise NotSupported(self.id + ' fetchOrder() is not supported for ' + marketType + ' markets yet')
1447
2302
  isTrigger = self.safe_value_2(params, 'trigger', 'stop')
1448
2303
  params = self.omit(params, ['trigger', 'stop'])
1449
2304
  response = None
@@ -1486,7 +2341,9 @@ class poloniex(Exchange, ImplicitAPI):
1486
2341
  def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1487
2342
  """
1488
2343
  fetch all the trades made from a single order
1489
- :see: https://docs.poloniex.com/#authenticated-endpoints-trades-trades-by-order-id
2344
+
2345
+ https://api-docs.poloniex.com/spot/api/private/trade#trades-by-order-id
2346
+
1490
2347
  :param str id: order id
1491
2348
  :param str symbol: unified market symbol
1492
2349
  :param int [since]: the earliest time in ms to fetch trades for
@@ -1528,6 +2385,22 @@ class poloniex(Exchange, ImplicitAPI):
1528
2385
  'timestamp': None,
1529
2386
  'datetime': None,
1530
2387
  }
2388
+ # for swap
2389
+ if not isinstance(response, list):
2390
+ ts = self.safe_integer(response, 'uTime')
2391
+ result['timestamp'] = ts
2392
+ result['datetime'] = self.iso8601(ts)
2393
+ details = self.safe_list(response, 'details', [])
2394
+ for i in range(0, len(details)):
2395
+ balance = details[i]
2396
+ currencyId = self.safe_string(balance, 'ccy')
2397
+ code = self.safe_currency_code(currencyId)
2398
+ account = self.account()
2399
+ account['total'] = self.safe_string(balance, 'avail')
2400
+ account['used'] = self.safe_string(balance, 'im')
2401
+ result[code] = account
2402
+ return self.safe_balance(result)
2403
+ # for spot
1531
2404
  for i in range(0, len(response)):
1532
2405
  account = self.safe_value(response, i, {})
1533
2406
  balances = self.safe_value(account, 'balances')
@@ -1544,11 +2417,57 @@ class poloniex(Exchange, ImplicitAPI):
1544
2417
  def fetch_balance(self, params={}) -> Balances:
1545
2418
  """
1546
2419
  query for balance and get the amount of funds available for trading or funds locked in orders
1547
- :see: https://docs.poloniex.com/#authenticated-endpoints-accounts-all-account-balances
2420
+
2421
+ https://api-docs.poloniex.com/spot/api/private/account#all-account-balances
2422
+ https://api-docs.poloniex.com/v3/futures/api/account/balance
2423
+
1548
2424
  :param dict [params]: extra parameters specific to the exchange API endpoint
1549
2425
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1550
2426
  """
1551
2427
  self.load_markets()
2428
+ marketType = None
2429
+ marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
2430
+ if marketType != 'spot':
2431
+ responseRaw = self.swapPrivateGetV3AccountBalance(params)
2432
+ #
2433
+ # {
2434
+ # "code": "200",
2435
+ # "msg": "",
2436
+ # "data": {
2437
+ # "state": "NORMAL",
2438
+ # "eq": "9.98571622",
2439
+ # "isoEq": "0",
2440
+ # "im": "0",
2441
+ # "mm": "0",
2442
+ # "mmr": "0",
2443
+ # "upl": "0",
2444
+ # "availMgn": "9.98571622",
2445
+ # "cTime": "1738093601775",
2446
+ # "uTime": "1740829116236",
2447
+ # "details": [
2448
+ # {
2449
+ # "ccy": "USDT",
2450
+ # "eq": "9.98571622",
2451
+ # "isoEq": "0",
2452
+ # "avail": "9.98571622",
2453
+ # "trdHold": "0",
2454
+ # "upl": "0",
2455
+ # "isoAvail": "0",
2456
+ # "isoHold": "0",
2457
+ # "isoUpl": "0",
2458
+ # "im": "0",
2459
+ # "mm": "0",
2460
+ # "mmr": "0",
2461
+ # "imr": "0",
2462
+ # "cTime": "1740829116236",
2463
+ # "uTime": "1740829116236"
2464
+ # }
2465
+ # ]
2466
+ # }
2467
+ # }
2468
+ #
2469
+ data = self.safe_dict(responseRaw, 'data', {})
2470
+ return self.parse_balance(data)
1552
2471
  request: dict = {
1553
2472
  'accountType': 'SPOT',
1554
2473
  }
@@ -1574,7 +2493,9 @@ class poloniex(Exchange, ImplicitAPI):
1574
2493
  def fetch_trading_fees(self, params={}) -> TradingFees:
1575
2494
  """
1576
2495
  fetch the trading fees for multiple markets
1577
- :see: https://docs.poloniex.com/#authenticated-endpoints-accounts-fee-info
2496
+
2497
+ https://api-docs.poloniex.com/spot/api/private/account#fee-info
2498
+
1578
2499
  :param dict [params]: extra parameters specific to the exchange API endpoint
1579
2500
  :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1580
2501
  """
@@ -1604,7 +2525,10 @@ class poloniex(Exchange, ImplicitAPI):
1604
2525
  def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1605
2526
  """
1606
2527
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1607
- :see: https://docs.poloniex.com/#public-endpoints-market-data-order-book
2528
+
2529
+ https://api-docs.poloniex.com/spot/api/public/market-data#order-book
2530
+ https://api-docs.poloniex.com/v3/futures/api/market/get-order-book
2531
+
1608
2532
  :param str symbol: unified symbol of the market to fetch the order book for
1609
2533
  :param int [limit]: the maximum amount of order book entries to return
1610
2534
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1617,6 +2541,25 @@ class poloniex(Exchange, ImplicitAPI):
1617
2541
  }
1618
2542
  if limit is not None:
1619
2543
  request['limit'] = limit # The default value of limit is 10. Valid limit values are: 5, 10, 20, 50, 100, 150.
2544
+ if market['contract']:
2545
+ request['limit'] = self.find_nearest_ceiling([5, 10, 20, 100, 150], limit)
2546
+ if market['contract']:
2547
+ responseRaw = self.swapPublicGetV3MarketOrderBook(self.extend(request, params))
2548
+ #
2549
+ # {
2550
+ # "code": 200,
2551
+ # "data": {
2552
+ # "asks": [["58700", "9934"], ..],
2553
+ # "bids": [["58600", "9952"], ..],
2554
+ # "s": "100",
2555
+ # "ts": 1719974138333
2556
+ # },
2557
+ # "msg": "Success"
2558
+ # }
2559
+ #
2560
+ data = self.safe_dict(responseRaw, 'data', {})
2561
+ ts = self.safe_integer(data, 'ts')
2562
+ return self.parse_order_book(data, symbol, ts)
1620
2563
  response = self.publicGetMarketsSymbolOrderBook(self.extend(request, params))
1621
2564
  #
1622
2565
  # {
@@ -1651,98 +2594,98 @@ class poloniex(Exchange, ImplicitAPI):
1651
2594
  'nonce': None,
1652
2595
  }
1653
2596
 
1654
- def create_deposit_address(self, code: str, params={}):
2597
+ def create_deposit_address(self, code: str, params={}) -> DepositAddress:
1655
2598
  """
1656
2599
  create a currency deposit address
1657
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-deposit-addresses
2600
+
2601
+ https://api-docs.poloniex.com/spot/api/private/wallet#deposit-addresses
2602
+
1658
2603
  :param str code: unified currency code of the currency for the deposit address
1659
2604
  :param dict [params]: extra parameters specific to the exchange API endpoint
1660
2605
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1661
2606
  """
1662
2607
  self.load_markets()
1663
- currency = self.currency(code)
1664
- request: dict = {
1665
- 'currency': currency['id'],
1666
- }
1667
- networks = self.safe_value(self.options, 'networks', {})
1668
- network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
1669
- network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
1670
- if network is not None:
1671
- request['currency'] += network # when network the currency need to be changed to currency+network https://docs.poloniex.com/#withdraw on MultiChain Currencies section
1672
- params = self.omit(params, 'network')
1673
- else:
1674
- if currency['id'] == 'USDT':
1675
- raise ArgumentsRequired(self.id + ' createDepositAddress requires a network parameter for ' + code + '.')
2608
+ request, extraParams, currency, networkEntry = self.prepare_request_for_deposit_address(code, params)
2609
+ params = extraParams
1676
2610
  response = self.privatePostWalletsAddress(self.extend(request, params))
1677
2611
  #
1678
2612
  # {
1679
2613
  # "address" : "0xfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxf"
1680
2614
  # }
1681
2615
  #
1682
- address = self.safe_string(response, 'address')
1683
- tag: Str = None
1684
- self.check_address(address)
1685
- if currency is not None:
1686
- depositAddress = self.safe_string(currency['info'], 'depositAddress')
1687
- if depositAddress is not None:
1688
- tag = address
1689
- address = depositAddress
1690
- return {
1691
- 'currency': code,
1692
- 'address': address,
1693
- 'tag': tag,
1694
- 'network': network,
1695
- 'info': response,
1696
- }
2616
+ return self.parse_deposit_address_special(response, currency, networkEntry)
1697
2617
 
1698
- def fetch_deposit_address(self, code: str, params={}):
2618
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1699
2619
  """
1700
2620
  fetch the deposit address for a currency associated with self account
1701
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-deposit-addresses
2621
+
2622
+ https://api-docs.poloniex.com/spot/api/private/wallet#deposit-addresses
2623
+
1702
2624
  :param str code: unified currency code
1703
2625
  :param dict [params]: extra parameters specific to the exchange API endpoint
1704
2626
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1705
2627
  """
1706
2628
  self.load_markets()
1707
- currency = self.currency(code)
1708
- request: dict = {
1709
- 'currency': currency['id'],
1710
- }
1711
- networks = self.safe_value(self.options, 'networks', {})
1712
- network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
1713
- network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
1714
- if network is not None:
1715
- request['currency'] += network # when network the currency need to be changed to currency+network https://docs.poloniex.com/#withdraw on MultiChain Currencies section
1716
- params = self.omit(params, 'network')
1717
- else:
1718
- if currency['id'] == 'USDT':
1719
- raise ArgumentsRequired(self.id + ' fetchDepositAddress requires a network parameter for ' + code + '.')
2629
+ request, extraParams, currency, networkEntry = self.prepare_request_for_deposit_address(code, params)
2630
+ params = extraParams
1720
2631
  response = self.privateGetWalletsAddresses(self.extend(request, params))
1721
2632
  #
1722
2633
  # {
1723
2634
  # "USDTTRON" : "Txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxp"
1724
2635
  # }
1725
2636
  #
1726
- address = self.safe_string(response, request['currency'])
2637
+ keys = list(response.keys())
2638
+ length = len(keys)
2639
+ if length < 1:
2640
+ raise ExchangeError(self.id + ' fetchDepositAddress() returned an empty response, you might need to try "createDepositAddress" at first and then use "fetchDepositAddress"')
2641
+ return self.parse_deposit_address_special(response, currency, networkEntry)
2642
+
2643
+ def prepare_request_for_deposit_address(self, code: str, params: dict = {}) -> Any:
2644
+ if not (code in self.currencies):
2645
+ raise BadSymbol(self.id + ' fetchDepositAddress(): can not recognize ' + code + ' currency, you might try using unified currency-code and add provide specific "network" parameter, like: fetchDepositAddress("USDT", {"network": "TRC20"})')
2646
+ currency = self.currency(code)
2647
+ networkCode = None
2648
+ networkCode, params = self.handle_network_code_and_params(params)
2649
+ if networkCode is None:
2650
+ # we need to know the network to find out the currency-junction
2651
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress requires a network parameter for ' + code + '.')
2652
+ exchangeNetworkId = None
2653
+ networkCode = self.network_id_to_code(networkCode, code)
2654
+ networkEntry = self.safe_dict(currency['networks'], networkCode)
2655
+ if networkEntry is not None:
2656
+ exchangeNetworkId = networkEntry['id']
2657
+ else:
2658
+ exchangeNetworkId = networkCode
2659
+ request = {
2660
+ 'currency': exchangeNetworkId,
2661
+ }
2662
+ return [request, params, currency, networkEntry]
2663
+
2664
+ def parse_deposit_address_special(self, response, currency, networkEntry) -> DepositAddress:
2665
+ address = self.safe_string(response, 'address')
2666
+ if address is None:
2667
+ address = self.safe_string(response, networkEntry['id'])
1727
2668
  tag: Str = None
1728
2669
  self.check_address(address)
1729
- if currency is not None:
1730
- depositAddress = self.safe_string(currency['info'], 'depositAddress')
2670
+ if networkEntry is not None:
2671
+ depositAddress = self.safe_string(networkEntry['info'], 'depositAddress')
1731
2672
  if depositAddress is not None:
1732
2673
  tag = address
1733
2674
  address = depositAddress
1734
2675
  return {
1735
- 'currency': code,
2676
+ 'info': response,
2677
+ 'currency': currency['code'],
2678
+ 'network': self.safe_string(networkEntry, 'network'),
1736
2679
  'address': address,
1737
2680
  'tag': tag,
1738
- 'network': network,
1739
- 'info': response,
1740
2681
  }
1741
2682
 
1742
2683
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1743
2684
  """
1744
2685
  transfer currency internally between wallets on the same account
1745
- :see: https://docs.poloniex.com/#authenticated-endpoints-accounts-accounts-transfer
2686
+
2687
+ https://api-docs.poloniex.com/spot/api/private/account#accounts-transfer
2688
+
1746
2689
  :param str code: unified currency code
1747
2690
  :param float amount: amount to transfer
1748
2691
  :param str fromAccount: account to transfer from
@@ -1787,10 +2730,12 @@ class poloniex(Exchange, ImplicitAPI):
1787
2730
  'status': None,
1788
2731
  }
1789
2732
 
1790
- def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2733
+ def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
1791
2734
  """
1792
2735
  make a withdrawal
1793
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-withdraw-currency
2736
+
2737
+ https://api-docs.poloniex.com/spot/api/private/wallet#withdraw-currency
2738
+
1794
2739
  :param str code: unified currency code
1795
2740
  :param float amount: the amount to withdraw
1796
2741
  :param str address: the address to withdraw to
@@ -1800,21 +2745,12 @@ class poloniex(Exchange, ImplicitAPI):
1800
2745
  """
1801
2746
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
1802
2747
  self.check_address(address)
1803
- self.load_markets()
1804
- currency = self.currency(code)
1805
- request: dict = {
1806
- 'currency': currency['id'],
1807
- 'amount': amount,
1808
- 'address': address,
1809
- }
2748
+ request, extraParams, currency, networkEntry = self.prepare_request_for_deposit_address(code, params)
2749
+ params = extraParams
2750
+ request['amount'] = self.currency_to_precision(code, amount)
2751
+ request['address'] = address
1810
2752
  if tag is not None:
1811
2753
  request['paymentId'] = tag
1812
- networks = self.safe_value(self.options, 'networks', {})
1813
- network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
1814
- network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
1815
- if network is not None:
1816
- request['currency'] += network # when network the currency need to be changed to currency+network https://docs.poloniex.com/#withdraw on MultiChain Currencies section
1817
- params = self.omit(params, 'network')
1818
2754
  response = self.privatePostWalletsWithdraw(self.extend(request, params))
1819
2755
  #
1820
2756
  # {
@@ -1823,7 +2759,11 @@ class poloniex(Exchange, ImplicitAPI):
1823
2759
  # "withdrawalNumber": 13449869
1824
2760
  # }
1825
2761
  #
1826
- return self.parse_transaction(response, currency)
2762
+ withdrawResponse = {
2763
+ 'response': response,
2764
+ 'withdrawNetworkEntry': networkEntry,
2765
+ }
2766
+ return self.parse_transaction(withdrawResponse, currency)
1827
2767
 
1828
2768
  def fetch_transactions_helper(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1829
2769
  self.load_markets()
@@ -1911,7 +2851,9 @@ class poloniex(Exchange, ImplicitAPI):
1911
2851
  def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1912
2852
  """
1913
2853
  fetch history of deposits and withdrawals
1914
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-wallets-activity-records
2854
+
2855
+ https://api-docs.poloniex.com/spot/api/private/wallet#wallets-activity-records
2856
+
1915
2857
  :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
1916
2858
  :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
1917
2859
  :param int [limit]: max number of deposit/withdrawals to return, default is None
@@ -1933,7 +2875,9 @@ class poloniex(Exchange, ImplicitAPI):
1933
2875
  def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1934
2876
  """
1935
2877
  fetch all withdrawals made from an account
1936
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-wallets-activity-records
2878
+
2879
+ https://api-docs.poloniex.com/spot/api/private/wallet#wallets-activity-records
2880
+
1937
2881
  :param str code: unified currency code
1938
2882
  :param int [since]: the earliest time in ms to fetch withdrawals for
1939
2883
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -1951,7 +2895,9 @@ class poloniex(Exchange, ImplicitAPI):
1951
2895
  def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
1952
2896
  """
1953
2897
  fetch deposit and withdraw fees
1954
- :see: https://docs.poloniex.com/#public-endpoints-reference-data-currency-information
2898
+
2899
+ https://api-docs.poloniex.com/spot/api/public/reference-data#currency-information
2900
+
1955
2901
  :param str[]|None codes: list of unified currency codes
1956
2902
  :param dict [params]: extra parameters specific to the exchange API endpoint
1957
2903
  :returns dict[]: a list of `fees structures <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -2069,7 +3015,9 @@ class poloniex(Exchange, ImplicitAPI):
2069
3015
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2070
3016
  """
2071
3017
  fetch all deposits made to an account
2072
- :see: https://docs.poloniex.com/#authenticated-endpoints-wallets-wallets-activity-records
3018
+
3019
+ https://api-docs.poloniex.com/spot/api/private/wallet#wallets-activity-records
3020
+
2073
3021
  :param str code: unified currency code
2074
3022
  :param int [since]: the earliest time in ms to fetch deposits for
2075
3023
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -2133,6 +3081,9 @@ class poloniex(Exchange, ImplicitAPI):
2133
3081
  # "withdrawalRequestsId": 33485231
2134
3082
  # }
2135
3083
  #
3084
+ # if it's being parsed from "withdraw()" method, get the original response
3085
+ if 'withdrawNetworkEntry' in transaction:
3086
+ transaction = transaction['response']
2136
3087
  timestamp = self.safe_timestamp(transaction, 'timestamp')
2137
3088
  currencyId = self.safe_string(transaction, 'currency')
2138
3089
  code = self.safe_currency_code(currencyId)
@@ -2174,14 +3125,381 @@ class poloniex(Exchange, ImplicitAPI):
2174
3125
  },
2175
3126
  }
2176
3127
 
3128
+ def set_leverage(self, leverage: int, symbol: Str = None, params={}):
3129
+ """
3130
+ set the level of leverage for a market
3131
+
3132
+ https://api-docs.poloniex.com/v3/futures/api/positions/set-leverage
3133
+
3134
+ :param int leverage: the rate of leverage
3135
+ :param str symbol: unified market symbol
3136
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3137
+ :param str [params.marginMode]: 'cross' or 'isolated'
3138
+ :returns dict: response from the exchange
3139
+ """
3140
+ if symbol is None:
3141
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
3142
+ self.load_markets()
3143
+ market = self.market(symbol)
3144
+ marginMode = None
3145
+ marginMode, params = self.handle_margin_mode_and_params('setLeverage', params)
3146
+ if marginMode is None:
3147
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a marginMode parameter "cross" or "isolated"')
3148
+ hedged: Bool = None
3149
+ hedged, params = self.handle_param_bool(params, 'hedged', False)
3150
+ if hedged:
3151
+ if not ('posSide' in params):
3152
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a posSide parameter for hedged mode: "LONG" or "SHORT"')
3153
+ request: dict = {
3154
+ 'lever': leverage,
3155
+ 'mgnMode': marginMode.upper(),
3156
+ 'symbol': market['id'],
3157
+ }
3158
+ response = self.swapPrivatePostV3PositionLeverage(self.extend(request, params))
3159
+ return response
3160
+
3161
+ def fetch_leverage(self, symbol: str, params={}) -> Leverage:
3162
+ """
3163
+ fetch the set leverage for a market
3164
+
3165
+ https://api-docs.poloniex.com/v3/futures/api/positions/get-leverages
3166
+
3167
+ :param str symbol: unified market symbol
3168
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3169
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
3170
+ """
3171
+ self.load_markets()
3172
+ market = self.market(symbol)
3173
+ request: dict = {
3174
+ 'symbol': market['id'],
3175
+ }
3176
+ marginMode = None
3177
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params)
3178
+ if marginMode is None:
3179
+ raise ArgumentsRequired(self.id + ' fetchLeverage() requires a marginMode parameter "cross" or "isolated"')
3180
+ request['mgnMode'] = marginMode.upper()
3181
+ response = self.swapPrivateGetV3PositionLeverages(self.extend(request, params))
3182
+ #
3183
+ # for one-way mode:
3184
+ #
3185
+ # {
3186
+ # "code": "200",
3187
+ # "msg": "",
3188
+ # "data": [
3189
+ # {
3190
+ # "symbol": "BTC_USDT_PERP",
3191
+ # "lever": "10",
3192
+ # "mgnMode": "CROSS",
3193
+ # "posSide": "BOTH"
3194
+ # }
3195
+ # ]
3196
+ # }
3197
+ #
3198
+ # for hedge:
3199
+ #
3200
+ # {
3201
+ # "code": "200",
3202
+ # "msg": "",
3203
+ # "data": [
3204
+ # {
3205
+ # "symbol": "BTC_USDT_PERP",
3206
+ # "lever": "20",
3207
+ # "mgnMode": "CROSS",
3208
+ # "posSide": "SHORT"
3209
+ # },
3210
+ # {
3211
+ # "symbol": "BTC_USDT_PERP",
3212
+ # "lever": "20",
3213
+ # "mgnMode": "CROSS",
3214
+ # "posSide": "LONG"
3215
+ # }
3216
+ # ]
3217
+ # }
3218
+ #
3219
+ return self.parse_leverage(response, market)
3220
+
3221
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
3222
+ shortLeverage: Int = None
3223
+ longLeverage: Int = None
3224
+ marketId: Str = None
3225
+ marginMode: Str = None
3226
+ data = self.safe_list(leverage, 'data')
3227
+ for i in range(0, len(data)):
3228
+ entry = data[i]
3229
+ marketId = self.safe_string(entry, 'symbol')
3230
+ marginMode = self.safe_string(entry, 'mgnMode')
3231
+ lever = self.safe_integer(entry, 'lever')
3232
+ posSide = self.safe_string(entry, 'posSide')
3233
+ if posSide == 'LONG':
3234
+ longLeverage = lever
3235
+ elif posSide == 'SHORT':
3236
+ shortLeverage = lever
3237
+ else:
3238
+ longLeverage = lever
3239
+ shortLeverage = lever
3240
+ return {
3241
+ 'info': leverage,
3242
+ 'symbol': self.safe_symbol(marketId, market),
3243
+ 'marginMode': marginMode,
3244
+ 'longLeverage': longLeverage,
3245
+ 'shortLeverage': shortLeverage,
3246
+ }
3247
+
3248
+ def fetch_position_mode(self, symbol: Str = None, params={}):
3249
+ """
3250
+ fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
3251
+
3252
+ https://api-docs.poloniex.com/v3/futures/api/positions/position-mode-switch
3253
+
3254
+ :param str symbol: unified symbol of the market to fetch the order book for
3255
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3256
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
3257
+ """
3258
+ response = self.swapPrivateGetV3PositionMode(params)
3259
+ #
3260
+ # {
3261
+ # "code": "200",
3262
+ # "msg": "Success",
3263
+ # "data": {
3264
+ # "posMode": "ONE_WAY"
3265
+ # }
3266
+ # }
3267
+ #
3268
+ data = self.safe_dict(response, 'data', {})
3269
+ posMode = self.safe_string(data, 'posMode')
3270
+ hedged = posMode == 'HEDGE'
3271
+ return {
3272
+ 'info': response,
3273
+ 'hedged': hedged,
3274
+ }
3275
+
3276
+ def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
3277
+ """
3278
+ set hedged to True or False for a market
3279
+
3280
+ https://api-docs.poloniex.com/v3/futures/api/positions/position-mode-switch
3281
+
3282
+ :param bool hedged: set to True to use dualSidePosition
3283
+ :param str symbol: not used by binance setPositionMode()
3284
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3285
+ :returns dict: response from the exchange
3286
+ """
3287
+ mode = 'HEDGE' if hedged else 'ONE_WAY'
3288
+ request: dict = {
3289
+ 'posMode': mode,
3290
+ }
3291
+ response = self.swapPrivatePostV3PositionMode(self.extend(request, params))
3292
+ #
3293
+ # {
3294
+ # "code": "200",
3295
+ # "msg": "Success",
3296
+ # "data": {}
3297
+ # }
3298
+ #
3299
+ return response
3300
+
3301
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3302
+ """
3303
+ fetch all open positions
3304
+
3305
+ https://api-docs.poloniex.com/v3/futures/api/positions/get-current-position
3306
+
3307
+ :param str[]|None symbols: list of unified market symbols
3308
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3309
+ :param boolean [params.standard]: whether to fetch standard contract positions
3310
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
3311
+ """
3312
+ self.load_markets()
3313
+ symbols = self.market_symbols(symbols)
3314
+ response = self.swapPrivateGetV3TradePositionOpens(params)
3315
+ #
3316
+ # {
3317
+ # "code": "200",
3318
+ # "msg": "",
3319
+ # "data": [
3320
+ # {
3321
+ # "symbol": "BTC_USDT_PERP",
3322
+ # "posSide": "LONG",
3323
+ # "side": "BUY",
3324
+ # "mgnMode": "CROSS",
3325
+ # "openAvgPx": "94193.42",
3326
+ # "qty": "1",
3327
+ # "availQty": "1",
3328
+ # "lever": "20",
3329
+ # "adl": "0.3007",
3330
+ # "liqPx": "84918.201844064386317906",
3331
+ # "im": "4.7047795",
3332
+ # "mm": "0.56457354",
3333
+ # "upl": "-0.09783",
3334
+ # "uplRatio": "-0.0207",
3335
+ # "pnl": "0",
3336
+ # "markPx": "94095.59",
3337
+ # "mgnRatio": "0.0582",
3338
+ # "state": "NORMAL",
3339
+ # "cTime": "1740950344401",
3340
+ # "uTime": "1740950344401",
3341
+ # "mgn": "4.7047795",
3342
+ # "actType": "TRADING",
3343
+ # "maxWAmt": "0",
3344
+ # "tpTrgPx": "",
3345
+ # "slTrgPx": ""
3346
+ # }
3347
+ # ]
3348
+ # }
3349
+ #
3350
+ positions = self.safe_list(response, 'data', [])
3351
+ return self.parse_positions(positions, symbols)
3352
+
3353
+ def parse_position(self, position: dict, market: Market = None):
3354
+ #
3355
+ # {
3356
+ # "symbol": "BTC_USDT_PERP",
3357
+ # "posSide": "LONG",
3358
+ # "side": "BUY",
3359
+ # "mgnMode": "CROSS",
3360
+ # "openAvgPx": "94193.42",
3361
+ # "qty": "1",
3362
+ # "availQty": "1",
3363
+ # "lever": "20",
3364
+ # "adl": "0.3007",
3365
+ # "liqPx": "84918.201844064386317906",
3366
+ # "im": "4.7047795",
3367
+ # "mm": "0.56457354",
3368
+ # "upl": "-0.09783",
3369
+ # "uplRatio": "-0.0207",
3370
+ # "pnl": "0",
3371
+ # "markPx": "94095.59",
3372
+ # "mgnRatio": "0.0582",
3373
+ # "state": "NORMAL",
3374
+ # "cTime": "1740950344401",
3375
+ # "uTime": "1740950344401",
3376
+ # "mgn": "4.7047795",
3377
+ # "actType": "TRADING",
3378
+ # "maxWAmt": "0",
3379
+ # "tpTrgPx": "",
3380
+ # "slTrgPx": ""
3381
+ # }
3382
+ #
3383
+ marketId = self.safe_string(position, 'symbol')
3384
+ market = self.safe_market(marketId, market)
3385
+ timestamp = self.safe_integer(position, 'cTime')
3386
+ marginMode = self.safe_string_lower(position, 'mgnMode')
3387
+ leverage = self.safe_string(position, 'lever')
3388
+ initialMargin = self.safe_string(position, 'im')
3389
+ notional = Precise.string_mul(leverage, initialMargin)
3390
+ qty = self.safe_string(position, 'qty')
3391
+ avgPrice = self.safe_string(position, 'openAvgPx')
3392
+ collateral = Precise.string_mul(qty, avgPrice)
3393
+ # todo: some more fields
3394
+ return self.safe_position({
3395
+ 'info': position,
3396
+ 'id': None,
3397
+ 'symbol': market['symbol'],
3398
+ 'notional': notional,
3399
+ 'marginMode': marginMode,
3400
+ 'liquidationPrice': self.safe_number(position, 'liqPx'),
3401
+ 'entryPrice': self.safe_number(position, 'openAvgPx'),
3402
+ 'unrealizedPnl': self.safe_number(position, 'upl'),
3403
+ 'percentage': None,
3404
+ 'contracts': self.safe_number(position, 'qty'),
3405
+ 'contractSize': None,
3406
+ 'markPrice': self.safe_number(position, 'markPx'),
3407
+ 'lastPrice': None,
3408
+ 'side': self.safe_string_lower(position, 'posSide'),
3409
+ 'hedged': None,
3410
+ 'timestamp': timestamp,
3411
+ 'datetime': self.iso8601(timestamp),
3412
+ 'lastUpdateTimestamp': None,
3413
+ 'maintenanceMargin': self.safe_number(position, 'mm'),
3414
+ 'maintenanceMarginPercentage': None,
3415
+ 'collateral': collateral,
3416
+ 'initialMargin': initialMargin,
3417
+ 'initialMarginPercentage': None,
3418
+ 'leverage': int(leverage),
3419
+ 'marginRatio': self.safe_number(position, 'mgnRatio'),
3420
+ 'stopLossPrice': self.safe_number(position, 'slTrgPx'),
3421
+ 'takeProfitPrice': self.safe_number(position, 'tpTrgPx'),
3422
+ })
3423
+
3424
+ def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
3425
+ self.load_markets()
3426
+ market = self.market(symbol)
3427
+ amount = self.amount_to_precision(symbol, amount)
3428
+ request: dict = {
3429
+ 'symbol': market['id'],
3430
+ 'amt': Precise.string_abs(amount),
3431
+ 'type': type.upper(), # 'ADD' or 'REDUCE'
3432
+ }
3433
+ # todo: hedged handling, tricky
3434
+ if not ('posMode' in params):
3435
+ request['posMode'] = 'BOTH'
3436
+ response = self.swapPrivatePostV3TradePositionMargin(self.extend(request, params))
3437
+ #
3438
+ # {
3439
+ # "code": 200,
3440
+ # "data": {
3441
+ # "amt": "50",
3442
+ # "lever": "20",
3443
+ # "symbol": "DOT_USDT_PERP",
3444
+ # "posSide": "BOTH",
3445
+ # "type": "ADD"
3446
+ # },
3447
+ # "msg": "Success"
3448
+ # }
3449
+ #
3450
+ if type == 'reduce':
3451
+ amount = Precise.string_abs(amount)
3452
+ data = self.safe_dict(response, 'data')
3453
+ return self.parse_margin_modification(data, market)
3454
+
3455
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
3456
+ marketId = self.safe_string(data, 'symbol')
3457
+ market = self.safe_market(marketId, market)
3458
+ rawType = self.safe_string(data, 'type')
3459
+ type = 'add' if (rawType == 'ADD') else 'reduce'
3460
+ return {
3461
+ 'info': data,
3462
+ 'symbol': market['symbol'],
3463
+ 'type': type,
3464
+ 'marginMode': None,
3465
+ 'amount': self.safe_number(data, 'amt'),
3466
+ 'total': None,
3467
+ 'code': None,
3468
+ 'status': 'ok',
3469
+ 'timestamp': None,
3470
+ 'datetime': None,
3471
+ }
3472
+
3473
+ def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3474
+ """
3475
+ remove margin from a position
3476
+ :param str symbol: unified market symbol
3477
+ :param float amount: the amount of margin to remove
3478
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3479
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
3480
+ """
3481
+ return self.modify_margin_helper(symbol, -amount, 'reduce', params)
3482
+
3483
+ def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3484
+ """
3485
+ add margin
3486
+ :param str symbol: unified market symbol
3487
+ :param float amount: amount of margin to add
3488
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3489
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
3490
+ """
3491
+ return self.modify_margin_helper(symbol, amount, 'add', params)
3492
+
2177
3493
  def nonce(self):
2178
3494
  return self.milliseconds()
2179
3495
 
2180
3496
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2181
- url = self.urls['api']['rest']
3497
+ url = self.urls['api']['spot']
3498
+ if self.in_array(api, ['swapPublic', 'swapPrivate']):
3499
+ url = self.urls['api']['swap']
2182
3500
  query = self.omit(params, self.extract_params(path))
2183
3501
  implodedPath = self.implode_params(path, params)
2184
- if api == 'public':
3502
+ if api == 'public' or api == 'swapPublic':
2185
3503
  url += '/' + implodedPath
2186
3504
  if query:
2187
3505
  url += '?' + self.urlencode(query)