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