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,9 +5,10 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
+ import asyncio
8
9
  import hashlib
9
10
  import numbers
10
- from ccxt.base.types import Balances, Currencies, Currency, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry, TransferEntries
11
+ from ccxt.base.types import Any, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
11
12
  from typing import List
12
13
  from ccxt.base.errors import ExchangeError
13
14
  from ccxt.base.errors import AuthenticationError
@@ -19,17 +20,17 @@ from ccxt.base.errors import BadSymbol
19
20
  from ccxt.base.errors import InsufficientFunds
20
21
  from ccxt.base.errors import InvalidOrder
21
22
  from ccxt.base.errors import OrderNotFound
22
- from ccxt.base.errors import CancelPending
23
23
  from ccxt.base.errors import DuplicateOrderId
24
24
  from ccxt.base.errors import DDoSProtection
25
25
  from ccxt.base.errors import RateLimitExceeded
26
+ from ccxt.base.errors import CancelPending
26
27
  from ccxt.base.decimal_to_precision import TICK_SIZE
27
28
  from ccxt.base.precise import Precise
28
29
 
29
30
 
30
31
  class phemex(Exchange, ImplicitAPI):
31
32
 
32
- def describe(self):
33
+ def describe(self) -> Any:
33
34
  return self.deep_extend(super(phemex, self).describe(), {
34
35
  'id': 'phemex',
35
36
  'name': 'Phemex',
@@ -50,6 +51,7 @@ class phemex(Exchange, ImplicitAPI):
50
51
  'cancelAllOrders': True,
51
52
  'cancelOrder': True,
52
53
  'closePosition': False,
54
+ 'createConvertTrade': True,
53
55
  'createOrder': True,
54
56
  'createReduceOnlyOrder': True,
55
57
  'createStopLimitOrder': True,
@@ -60,10 +62,15 @@ class phemex(Exchange, ImplicitAPI):
60
62
  'fetchBorrowRateHistories': False,
61
63
  'fetchBorrowRateHistory': False,
62
64
  'fetchClosedOrders': True,
65
+ 'fetchConvertQuote': True,
66
+ 'fetchConvertTrade': False,
67
+ 'fetchConvertTradeHistory': True,
63
68
  'fetchCrossBorrowRate': False,
64
69
  'fetchCrossBorrowRates': False,
65
70
  'fetchCurrencies': True,
66
71
  'fetchDepositAddress': True,
72
+ 'fetchDepositAddresses': False,
73
+ 'fetchDepositAddressesByNetwork': False,
67
74
  'fetchDeposits': True,
68
75
  'fetchFundingHistory': True,
69
76
  'fetchFundingRate': True,
@@ -80,6 +87,7 @@ class phemex(Exchange, ImplicitAPI):
80
87
  'fetchMarkOHLCV': False,
81
88
  'fetchMyTrades': True,
82
89
  'fetchOHLCV': True,
90
+ 'fetchOpenInterest': True,
83
91
  'fetchOpenOrders': True,
84
92
  'fetchOrder': True,
85
93
  'fetchOrderBook': True,
@@ -118,7 +126,7 @@ class phemex(Exchange, ImplicitAPI):
118
126
  'private': 'https://{hostname}',
119
127
  },
120
128
  'www': 'https://phemex.com',
121
- 'doc': 'https://github.com/phemex/phemex-api-docs',
129
+ 'doc': 'https://phemex-docs.github.io/#overview',
122
130
  'fees': 'https://phemex.com/fees-conditions',
123
131
  'referral': {
124
132
  'url': 'https://phemex.com/register?referralCode=EDNVJ',
@@ -176,6 +184,7 @@ class phemex(Exchange, ImplicitAPI):
176
184
  'v2': {
177
185
  'get': {
178
186
  'public/products': 5,
187
+ 'public/products-plus': 5,
179
188
  'md/v2/orderbook': 5, # ?symbol=<symbol>&id=<id>
180
189
  'md/v2/trade': 5, # ?symbol=<symbol>&id=<id>
181
190
  'md/v2/ticker/24hr': 5, # ?symbol=<symbol>&id=<id>
@@ -273,6 +282,7 @@ class phemex(Exchange, ImplicitAPI):
273
282
  # swap
274
283
  'orders/replace': 1, # ?symbol=<symbol>&orderID=<orderID>&origClOrdID=<origClOrdID>&clOrdID=<clOrdID>&price=<price>&priceEp=<priceEp>&orderQty=<orderQty>&stopPx=<stopPx>&stopPxEp=<stopPxEp>&takeProfit=<takeProfit>&takeProfitEp=<takeProfitEp>&stopLoss=<stopLoss>&stopLossEp=<stopLossEp>&pegOffsetValueEp=<pegOffsetValueEp>&pegPriceType=<pegPriceType>
275
284
  'g-orders/replace': 1, # ?symbol=<symbol>&orderID=<orderID>&origClOrdID=<origClOrdID>&clOrdID=<clOrdID>&price=<price>&priceEp=<priceEp>&orderQty=<orderQty>&stopPx=<stopPx>&stopPxEp=<stopPxEp>&takeProfit=<takeProfit>&takeProfitEp=<takeProfitEp>&stopLoss=<stopLoss>&stopLossEp=<stopLossEp>&pegOffsetValueEp=<pegOffsetValueEp>&pegPriceType=<pegPriceType>
285
+ 'g-orders/create': 1,
276
286
  'positions/leverage': 5, # ?symbol=<symbol>&leverage=<leverage>&leverageEr=<leverageEr>
277
287
  'g-positions/leverage': 5, # ?symbol=<symbol>&leverage=<leverage>&leverageEr=<leverageEr>
278
288
  'g-positions/switch-pos-mode-sync': 5, # ?symbol=<symbol>&targetPosMode=<targetPosMode>
@@ -302,6 +312,114 @@ class phemex(Exchange, ImplicitAPI):
302
312
  'maker': self.parse_number('0.001'),
303
313
  },
304
314
  },
315
+ 'features': {
316
+ 'default': {
317
+ 'sandbox': True,
318
+ 'createOrder': {
319
+ 'marginMode': False,
320
+ 'triggerPrice': True,
321
+ # todo
322
+ 'triggerPriceType': {
323
+ 'mark': True,
324
+ 'last': True,
325
+ 'index': True,
326
+ },
327
+ 'triggerDirection': False,
328
+ 'stopLossPrice': False, # todo
329
+ 'takeProfitPrice': False, # todo
330
+ 'attachedStopLossTakeProfit': None,
331
+ 'timeInForce': {
332
+ 'IOC': True,
333
+ 'FOK': True,
334
+ 'PO': True,
335
+ 'GTD': False,
336
+ },
337
+ 'hedged': False,
338
+ 'leverage': False,
339
+ 'marketBuyByCost': True,
340
+ 'marketBuyRequiresPrice': False,
341
+ 'selfTradePrevention': False,
342
+ 'trailing': False,
343
+ 'iceberg': False,
344
+ },
345
+ 'createOrders': None,
346
+ 'fetchMyTrades': {
347
+ 'marginMode': False,
348
+ 'limit': 200,
349
+ 'daysBack': 100000,
350
+ 'untilDays': 2, # todo implement
351
+ 'symbolRequired': False,
352
+ },
353
+ 'fetchOrder': {
354
+ 'marginMode': False,
355
+ 'trigger': False,
356
+ 'trailing': False,
357
+ 'symbolRequired': True,
358
+ },
359
+ 'fetchOpenOrders': {
360
+ 'marginMode': False,
361
+ 'limit': None,
362
+ 'trigger': False,
363
+ 'trailing': False,
364
+ 'symbolRequired': True,
365
+ },
366
+ 'fetchOrders': {
367
+ 'marginMode': False,
368
+ 'limit': None,
369
+ 'daysBack': None,
370
+ 'untilDays': None,
371
+ 'trigger': False,
372
+ 'trailing': False,
373
+ 'symbolRequired': True,
374
+ },
375
+ 'fetchClosedOrders': {
376
+ 'marginMode': False,
377
+ 'limit': 200,
378
+ 'daysBack': 100000,
379
+ 'daysBackCanceled': 100000,
380
+ 'untilDays': 2,
381
+ 'trigger': False,
382
+ 'trailing': False,
383
+ 'symbolRequired': False,
384
+ },
385
+ 'fetchOHLCV': {
386
+ 'limit': 1000,
387
+ },
388
+ },
389
+ 'spot': {
390
+ 'extends': 'default',
391
+ },
392
+ 'forDerivatives': {
393
+ 'extends': 'default',
394
+ 'createOrder': {
395
+ 'triggerDirection': True,
396
+ 'attachedStopLossTakeProfit': {
397
+ 'triggerPriceType': {
398
+ 'mark': True,
399
+ 'last': True,
400
+ 'index': True,
401
+ },
402
+ 'price': True,
403
+ },
404
+ 'hedged': True,
405
+ },
406
+ 'fetchOHLCV': {
407
+ 'limit': 2000,
408
+ },
409
+ },
410
+ 'swap': {
411
+ 'linear': {
412
+ 'extends': 'forDerivatives',
413
+ },
414
+ 'inverse': {
415
+ 'extends': 'forDerivatives',
416
+ },
417
+ },
418
+ 'future': {
419
+ 'linear': None,
420
+ 'inverse': None,
421
+ },
422
+ },
305
423
  'requiredCredentials': {
306
424
  'apiKey': True,
307
425
  'secret': True,
@@ -481,6 +599,7 @@ class phemex(Exchange, ImplicitAPI):
481
599
  },
482
600
  'defaultNetworks': {
483
601
  'USDT': 'ETH',
602
+ 'MKR': 'ETH',
484
603
  },
485
604
  'defaultSubType': 'linear',
486
605
  'accountsByType': {
@@ -500,6 +619,13 @@ class phemex(Exchange, ImplicitAPI):
500
619
  'transfer': {
501
620
  'fillResponseFromRequest': True,
502
621
  },
622
+ 'triggerPriceTypesMap': {
623
+ 'last': 'ByLastPrice',
624
+ 'mark': 'ByMarkPrice',
625
+ 'index': 'ByIndexPrice',
626
+ 'ask': 'ByAskPrice',
627
+ 'bid': 'ByBidPrice',
628
+ },
503
629
  },
504
630
  })
505
631
 
@@ -514,7 +640,7 @@ class phemex(Exchange, ImplicitAPI):
514
640
  def parse_swap_market(self, market: dict):
515
641
  #
516
642
  # {
517
- # "symbol":"BTCUSD",
643
+ # "symbol":"BTCUSD", #
518
644
  # "code":"1",
519
645
  # "type":"Perpetual",
520
646
  # "displaySymbol":"BTC / USD",
@@ -522,7 +648,7 @@ class phemex(Exchange, ImplicitAPI):
522
648
  # "markSymbol":".MBTC",
523
649
  # "fundingRateSymbol":".BTCFR",
524
650
  # "fundingRate8hSymbol":".BTCFR8H",
525
- # "contractUnderlyingAssets":"USD",
651
+ # "contractUnderlyingAssets":"USD", # or eg. `1000 SHIB`
526
652
  # "settleCurrency":"BTC",
527
653
  # "quoteCurrency":"USD",
528
654
  # "contractSize":"1 USD",
@@ -562,15 +688,20 @@ class phemex(Exchange, ImplicitAPI):
562
688
  # }
563
689
  #
564
690
  id = self.safe_string(market, 'symbol')
565
- baseId = self.safe_string_2(market, 'baseCurrency', 'contractUnderlyingAssets')
691
+ contractUnderlyingAssets = self.safe_string(market, 'contractUnderlyingAssets')
692
+ baseId = self.safe_string(market, 'baseCurrency', contractUnderlyingAssets)
566
693
  quoteId = self.safe_string(market, 'quoteCurrency')
567
694
  settleId = self.safe_string(market, 'settleCurrency')
568
695
  base = self.safe_currency_code(baseId)
696
+ base = base.replace(' ', '') # replace space for junction codes, eg. `1000 SHIB`
569
697
  quote = self.safe_currency_code(quoteId)
570
698
  settle = self.safe_currency_code(settleId)
571
699
  inverse = False
572
700
  if settleId != quoteId:
573
701
  inverse = True
702
+ # some unhandled cases
703
+ if not ('baseCurrency' in market) and base == quote:
704
+ base = settle
574
705
  priceScale = self.safe_integer(market, 'priceScale')
575
706
  ratioScale = self.safe_integer(market, 'ratioScale')
576
707
  valueScale = self.safe_integer(market, 'valueScale')
@@ -743,17 +874,20 @@ class phemex(Exchange, ImplicitAPI):
743
874
  'max': self.parse_safe_number(self.safe_string(market, 'maxOrderValue')),
744
875
  },
745
876
  },
746
- 'created': None,
877
+ 'created': self.safe_integer(market, 'listTime'),
747
878
  'info': market,
748
879
  })
749
880
 
750
881
  async def fetch_markets(self, params={}) -> List[Market]:
751
882
  """
752
883
  retrieves data on all markets for phemex
884
+
885
+ https://phemex-docs.github.io/#query-product-information-3
886
+
753
887
  :param dict [params]: extra parameters specific to the exchange API endpoint
754
888
  :returns dict[]: an array of objects representing market data
755
889
  """
756
- v2Products = await self.v2GetPublicProducts(params)
890
+ v2ProductsPromise = self.v2GetPublicProducts(params)
757
891
  #
758
892
  # {
759
893
  # "code":0,
@@ -903,7 +1037,8 @@ class phemex(Exchange, ImplicitAPI):
903
1037
  # }
904
1038
  # }
905
1039
  #
906
- v1Products = await self.v1GetExchangePublicProducts(params)
1040
+ v1ProductsPromise = self.v1GetExchangePublicProducts(params)
1041
+ v2Products, v1Products = await asyncio.gather(*[v2ProductsPromise, v1ProductsPromise])
907
1042
  v1ProductsData = self.safe_value(v1Products, 'data', [])
908
1043
  #
909
1044
  # {
@@ -940,14 +1075,14 @@ class phemex(Exchange, ImplicitAPI):
940
1075
  # ]
941
1076
  # }
942
1077
  #
943
- v2ProductsData = self.safe_value(v2Products, 'data', {})
944
- products = self.safe_value(v2ProductsData, 'products', [])
945
- perpetualProductsV2 = self.safe_value(v2ProductsData, 'perpProductsV2', [])
1078
+ v2ProductsData = self.safe_dict(v2Products, 'data', {})
1079
+ products = self.safe_list(v2ProductsData, 'products', [])
1080
+ perpetualProductsV2 = self.safe_list(v2ProductsData, 'perpProductsV2', [])
946
1081
  products = self.array_concat(products, perpetualProductsV2)
947
- riskLimits = self.safe_value(v2ProductsData, 'riskLimits', [])
948
- riskLimitsV2 = self.safe_value(v2ProductsData, 'riskLimitsV2', [])
1082
+ riskLimits = self.safe_list(v2ProductsData, 'riskLimits', [])
1083
+ riskLimitsV2 = self.safe_list(v2ProductsData, 'riskLimitsV2', [])
949
1084
  riskLimits = self.array_concat(riskLimits, riskLimitsV2)
950
- currencies = self.safe_value(v2ProductsData, 'currencies', [])
1085
+ currencies = self.safe_list(v2ProductsData, 'currencies', [])
951
1086
  riskLimitsById = self.index_by(riskLimits, 'symbol')
952
1087
  v1ProductsById = self.index_by(v1ProductsData, 'symbol')
953
1088
  currenciesByCode = self.index_by(currencies, 'currency')
@@ -955,16 +1090,16 @@ class phemex(Exchange, ImplicitAPI):
955
1090
  for i in range(0, len(products)):
956
1091
  market = products[i]
957
1092
  type = self.safe_string_lower(market, 'type')
958
- if (type == 'perpetual') or (type == 'perpetualv2'):
1093
+ if (type == 'perpetual') or (type == 'perpetualv2') or (type == 'perpetualpilot'):
959
1094
  id = self.safe_string(market, 'symbol')
960
- riskLimitValues = self.safe_value(riskLimitsById, id, {})
1095
+ riskLimitValues = self.safe_dict(riskLimitsById, id, {})
961
1096
  market = self.extend(market, riskLimitValues)
962
- v1ProductsValues = self.safe_value(v1ProductsById, id, {})
1097
+ v1ProductsValues = self.safe_dict(v1ProductsById, id, {})
963
1098
  market = self.extend(market, v1ProductsValues)
964
1099
  market = self.parse_swap_market(market)
965
1100
  else:
966
1101
  baseCurrency = self.safe_string(market, 'baseCurrency')
967
- currencyValues = self.safe_value(currenciesByCode, baseCurrency, {})
1102
+ currencyValues = self.safe_dict(currenciesByCode, baseCurrency, {})
968
1103
  valueScale = self.safe_string(currencyValues, 'valueScale', '8')
969
1104
  market = self.extend(market, {'valueScale': valueScale})
970
1105
  market = self.parse_spot_market(market)
@@ -998,9 +1133,7 @@ class phemex(Exchange, ImplicitAPI):
998
1133
  for i in range(0, len(currencies)):
999
1134
  currency = currencies[i]
1000
1135
  id = self.safe_string(currency, 'currency')
1001
- name = self.safe_string(currency, 'name')
1002
1136
  code = self.safe_currency_code(id)
1003
- status = self.safe_string(currency, 'status')
1004
1137
  valueScaleString = self.safe_string(currency, 'valueScale')
1005
1138
  valueScale = int(valueScaleString)
1006
1139
  minValueEv = self.safe_string(currency, 'minValueEv')
@@ -1013,12 +1146,12 @@ class phemex(Exchange, ImplicitAPI):
1013
1146
  precision = self.parse_number(precisionString)
1014
1147
  minAmount = self.parse_number(Precise.string_mul(minValueEv, precisionString))
1015
1148
  maxAmount = self.parse_number(Precise.string_mul(maxValueEv, precisionString))
1016
- result[code] = {
1149
+ result[code] = self.safe_currency_structure({
1017
1150
  'id': id,
1018
1151
  'info': currency,
1019
1152
  'code': code,
1020
- 'name': name,
1021
- 'active': status == 'Listed',
1153
+ 'name': self.safe_string(currency, 'name'),
1154
+ 'active': self.safe_string(currency, 'status') == 'Listed',
1022
1155
  'deposit': None,
1023
1156
  'withdraw': None,
1024
1157
  'fee': None,
@@ -1034,8 +1167,9 @@ class phemex(Exchange, ImplicitAPI):
1034
1167
  },
1035
1168
  },
1036
1169
  'valueScale': valueScale,
1037
- 'networks': {},
1038
- }
1170
+ 'networks': None,
1171
+ 'type': 'crypto',
1172
+ })
1039
1173
  return result
1040
1174
 
1041
1175
  def custom_parse_bid_ask(self, bidask, priceKey=0, amountKey=1, market: Market = None):
@@ -1071,7 +1205,9 @@ class phemex(Exchange, ImplicitAPI):
1071
1205
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1072
1206
  """
1073
1207
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1074
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorderbook
1208
+
1209
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorderbook
1210
+
1075
1211
  :param str symbol: unified symbol of the market to fetch the order book for
1076
1212
  :param int [limit]: the maximum amount of order book entries to return
1077
1213
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1084,7 +1220,8 @@ class phemex(Exchange, ImplicitAPI):
1084
1220
  # 'id': 123456789, # optional request id
1085
1221
  }
1086
1222
  response = None
1087
- if market['linear'] and market['settle'] == 'USDT':
1223
+ isStableSettled = (market['settle'] == 'USDT') or (market['settle'] == 'USDC')
1224
+ if market['linear'] and isStableSettled:
1088
1225
  response = await self.v2GetMdV2Orderbook(self.extend(request, params))
1089
1226
  else:
1090
1227
  if (limit is not None) and (limit <= 30):
@@ -1129,7 +1266,7 @@ class phemex(Exchange, ImplicitAPI):
1129
1266
  precise.decimals = precise.decimals - scale
1130
1267
  precise.reduce()
1131
1268
  preciseString = str(precise)
1132
- return self.parse_to_int(preciseString)
1269
+ return self.parse_to_numeric(preciseString)
1133
1270
 
1134
1271
  def to_ev(self, amount, market: Market = None):
1135
1272
  if (amount is None) or (market is None):
@@ -1142,7 +1279,7 @@ class phemex(Exchange, ImplicitAPI):
1142
1279
  return self.to_en(price, market['priceScale'])
1143
1280
 
1144
1281
  def from_en(self, en, scale):
1145
- if en is None:
1282
+ if en is None or scale is None:
1146
1283
  return None
1147
1284
  precise = Precise(en)
1148
1285
  precise.decimals = self.sum(precise.decimals, scale)
@@ -1195,8 +1332,10 @@ class phemex(Exchange, ImplicitAPI):
1195
1332
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1196
1333
  """
1197
1334
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1198
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querykline
1199
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-kline
1335
+
1336
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querykline
1337
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-kline
1338
+
1200
1339
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1201
1340
  :param str timeframe: the length of time each candle represents
1202
1341
  :param int [since]: *only used for USDT settled contracts, otherwise is emulated and not supported by the exchange* timestamp in ms of the earliest candle to fetch
@@ -1214,7 +1353,8 @@ class phemex(Exchange, ImplicitAPI):
1214
1353
  }
1215
1354
  until = self.safe_integer_2(params, 'until', 'to')
1216
1355
  params = self.omit(params, ['until'])
1217
- usesSpecialFromToEndpoint = ((market['linear'] or market['settle'] == 'USDT')) and ((since is not None) or (until is not None))
1356
+ isStableSettled = (market['settle'] == 'USDT') or (market['settle'] == 'USDC')
1357
+ usesSpecialFromToEndpoint = ((market['linear'] or isStableSettled)) and ((since is not None) or (until is not None))
1218
1358
  maxLimit = 1000
1219
1359
  if usesSpecialFromToEndpoint:
1220
1360
  maxLimit = 2000
@@ -1222,7 +1362,7 @@ class phemex(Exchange, ImplicitAPI):
1222
1362
  limit = maxLimit
1223
1363
  request['limit'] = min(limit, maxLimit)
1224
1364
  response = None
1225
- if market['linear'] or market['settle'] == 'USDT':
1365
+ if market['linear'] or isStableSettled:
1226
1366
  if (until is not None) or (since is not None):
1227
1367
  candleDuration = self.parse_timeframe(timeframe)
1228
1368
  if since is not None:
@@ -1359,7 +1499,9 @@ class phemex(Exchange, ImplicitAPI):
1359
1499
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1360
1500
  """
1361
1501
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1362
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query24hrsticker
1502
+
1503
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query24hrsticker
1504
+
1363
1505
  :param str symbol: unified symbol of the market to fetch the ticker for
1364
1506
  :param dict [params]: extra parameters specific to the exchange API endpoint
1365
1507
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1428,9 +1570,11 @@ class phemex(Exchange, ImplicitAPI):
1428
1570
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1429
1571
  """
1430
1572
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1431
- :see: https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols-2 # spot
1432
- :see: https://phemex-docs.github.io/#query-24-ticker-for-all-symbols # linear
1433
- :see: https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols # inverse
1573
+
1574
+ https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols-2 # spot
1575
+ https://phemex-docs.github.io/#query-24-ticker-for-all-symbols # linear
1576
+ https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols # inverse
1577
+
1434
1578
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1435
1579
  :param dict [params]: extra parameters specific to the exchange API endpoint
1436
1580
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1458,7 +1602,9 @@ class phemex(Exchange, ImplicitAPI):
1458
1602
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1459
1603
  """
1460
1604
  get the list of most recent trades for a particular symbol
1461
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querytrades
1605
+
1606
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querytrades
1607
+
1462
1608
  :param str symbol: unified symbol of the market to fetch trades for
1463
1609
  :param int [since]: timestamp in ms of the earliest trade to fetch
1464
1610
  :param int [limit]: the maximum amount of trades to fetch
@@ -1472,7 +1618,8 @@ class phemex(Exchange, ImplicitAPI):
1472
1618
  # 'id': 123456789, # optional request id
1473
1619
  }
1474
1620
  response = None
1475
- if market['linear'] and market['settle'] == 'USDT':
1621
+ isStableSettled = (market['settle'] == 'USDT') or (market['settle'] == 'USDC')
1622
+ if market['linear'] and isStableSettled:
1476
1623
  response = await self.v2GetMdV2Trade(self.extend(request, params))
1477
1624
  else:
1478
1625
  response = await self.v1GetMdTrade(self.extend(request, params))
@@ -1711,7 +1858,7 @@ class phemex(Exchange, ImplicitAPI):
1711
1858
  timestamp = self.safe_integer(trade, 'createdAt')
1712
1859
  id = self.safe_string_2(trade, 'execId', 'execID')
1713
1860
  orderId = self.safe_string(trade, 'orderID')
1714
- if market['settle'] == 'USDT':
1861
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
1715
1862
  sideId = self.safe_string_lower(trade, 'side')
1716
1863
  if (sideId == 'buy') or (sideId == 'sell'):
1717
1864
  side = sideId
@@ -1881,9 +2028,11 @@ class phemex(Exchange, ImplicitAPI):
1881
2028
  async def fetch_balance(self, params={}) -> Balances:
1882
2029
  """
1883
2030
  query for balance and get the amount of funds available for trading or funds locked in orders
1884
- :see: https://phemex-docs.github.io/#query-wallets
1885
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
1886
- :see: https://phemex-docs.github.io/#query-trading-account-and-positions
2031
+
2032
+ https://phemex-docs.github.io/#query-wallets
2033
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
2034
+ https://phemex-docs.github.io/#query-trading-account-and-positions
2035
+
1887
2036
  :param dict [params]: extra parameters specific to the exchange API endpoint
1888
2037
  :param str [params.type]: spot or swap
1889
2038
  :param str [params.code]: *swap only* currency code of the balance to query(USD, USDT, etc), default is USDT
@@ -2037,8 +2186,9 @@ class phemex(Exchange, ImplicitAPI):
2037
2186
  # }
2038
2187
  # }
2039
2188
  #
2040
- result = self.parse_swap_balance(response) if (type == 'swap') else self.parse_spot_balance(response)
2041
- return result
2189
+ if type == 'swap':
2190
+ return self.parse_swap_balance(response)
2191
+ return self.parse_spot_balance(response)
2042
2192
 
2043
2193
  def parse_order_status(self, status: Str):
2044
2194
  statuses: dict = {
@@ -2051,6 +2201,7 @@ class phemex(Exchange, ImplicitAPI):
2051
2201
  'PartiallyFilled': 'open',
2052
2202
  'Filled': 'closed',
2053
2203
  'Canceled': 'canceled',
2204
+ 'Suspended': 'canceled',
2054
2205
  '1': 'open',
2055
2206
  '2': 'canceled',
2056
2207
  '3': 'closed',
@@ -2170,7 +2321,7 @@ class phemex(Exchange, ImplicitAPI):
2170
2321
  'currency': self.safe_currency_code(self.safe_string(order, 'feeCurrency')),
2171
2322
  }
2172
2323
  timeInForce = self.parse_time_in_force(self.safe_string(order, 'timeInForce'))
2173
- stopPrice = self.parse_number(self.omit_zero(self.from_ep(self.safe_string(order, 'stopPxEp'))))
2324
+ triggerPrice = self.parse_number(self.omit_zero(self.from_ep(self.safe_string(order, 'stopPxEp'))))
2174
2325
  postOnly = (timeInForce == 'PO')
2175
2326
  return self.safe_order({
2176
2327
  'info': order,
@@ -2185,8 +2336,7 @@ class phemex(Exchange, ImplicitAPI):
2185
2336
  'postOnly': postOnly,
2186
2337
  'side': side,
2187
2338
  'price': price,
2188
- 'stopPrice': stopPrice,
2189
- 'triggerPrice': stopPrice,
2339
+ 'triggerPrice': triggerPrice,
2190
2340
  'amount': amount,
2191
2341
  'cost': cost,
2192
2342
  'average': average,
@@ -2330,7 +2480,7 @@ class phemex(Exchange, ImplicitAPI):
2330
2480
  if lastTradeTimestamp == 0:
2331
2481
  lastTradeTimestamp = None
2332
2482
  timeInForce = self.parse_time_in_force(self.safe_string(order, 'timeInForce'))
2333
- stopPrice = self.omit_zero(self.safe_string_2(order, 'stopPx', 'stopPxRp'))
2483
+ triggerPrice = self.omit_zero(self.safe_string_2(order, 'stopPx', 'stopPxRp'))
2334
2484
  postOnly = (timeInForce == 'PO')
2335
2485
  reduceOnly = self.safe_value(order, 'reduceOnly')
2336
2486
  execInst = self.safe_string(order, 'execInst')
@@ -2365,8 +2515,7 @@ class phemex(Exchange, ImplicitAPI):
2365
2515
  'reduceOnly': reduceOnly,
2366
2516
  'side': side,
2367
2517
  'price': price,
2368
- 'stopPrice': stopPrice,
2369
- 'triggerPrice': stopPrice,
2518
+ 'triggerPrice': triggerPrice,
2370
2519
  'takeProfitPrice': takeProfit,
2371
2520
  'stopLossPrice': stopLoss,
2372
2521
  'amount': amount,
@@ -2389,26 +2538,29 @@ class phemex(Exchange, ImplicitAPI):
2389
2538
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2390
2539
  """
2391
2540
  create a trade order
2392
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2393
- :see: https://phemex-docs.github.io/#place-order-http-put-prefered-3
2541
+
2542
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2543
+ https://phemex-docs.github.io/#place-order-http-put-prefered-3
2544
+
2394
2545
  :param str symbol: unified symbol of the market to create an order in
2395
2546
  :param str type: 'market' or 'limit'
2396
2547
  :param str side: 'buy' or 'sell'
2397
2548
  :param float amount: how much of currency you want to trade in units of base currency
2398
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2549
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2399
2550
  :param dict [params]: extra parameters specific to the exchange API endpoint
2400
2551
  :param float [params.trigger]: trigger price for conditional orders
2401
2552
  :param dict [params.takeProfit]: *swap only* *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered(perpetual swap markets only)
2402
2553
  :param float [params.takeProfit.triggerPrice]: take profit trigger price
2403
2554
  :param dict [params.stopLoss]: *swap only* *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered(perpetual swap markets only)
2404
2555
  :param float [params.stopLoss.triggerPrice]: stop loss trigger price
2556
+ :param str [params.posSide]: *swap only* "Merged" for one way mode, "Long" for buy side of hedged mode, "Short" for sell side of hedged mode
2557
+ :param bool [params.hedged]: *swap only* True for hedged mode, False for one way mode, default is False
2405
2558
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2406
2559
  """
2407
2560
  await self.load_markets()
2408
2561
  market = self.market(symbol)
2409
2562
  requestSide = self.capitalize(side)
2410
2563
  type = self.capitalize(type)
2411
- reduceOnly = self.safe_bool(params, 'reduceOnly')
2412
2564
  request: dict = {
2413
2565
  # common
2414
2566
  'symbol': market['id'],
@@ -2442,6 +2594,7 @@ class phemex(Exchange, ImplicitAPI):
2442
2594
  stopLossDefined = (stopLoss is not None)
2443
2595
  takeProfit = self.safe_value(params, 'takeProfit')
2444
2596
  takeProfitDefined = (takeProfit is not None)
2597
+ isStableSettled = (market['settle'] == 'USDT') or (market['settle'] == 'USDC')
2445
2598
  if clientOrderId is None:
2446
2599
  brokerId = self.safe_string(self.options, 'brokerId', 'CCXT123456')
2447
2600
  if brokerId is not None:
@@ -2451,7 +2604,7 @@ class phemex(Exchange, ImplicitAPI):
2451
2604
  params = self.omit(params, ['clOrdID', 'clientOrderId'])
2452
2605
  triggerPrice = self.safe_string_n(params, ['stopPx', 'stopPrice', 'triggerPrice'])
2453
2606
  if triggerPrice is not None:
2454
- if market['settle'] == 'USDT':
2607
+ if isStableSettled:
2455
2608
  request['stopPxRp'] = self.price_to_precision(symbol, triggerPrice)
2456
2609
  else:
2457
2610
  request['stopPxEp'] = self.to_ep(triggerPrice, market)
@@ -2486,78 +2639,94 @@ class phemex(Exchange, ImplicitAPI):
2486
2639
  amountString = self.number_to_string(amount)
2487
2640
  request['baseQtyEv'] = self.to_ev(amountString, market)
2488
2641
  elif market['swap']:
2642
+ hedged = self.safe_bool(params, 'hedged', False)
2643
+ params = self.omit(params, 'hedged')
2489
2644
  posSide = self.safe_string_lower(params, 'posSide')
2490
2645
  if posSide is None:
2491
- posSide = 'Merged'
2646
+ if hedged:
2647
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2648
+ if reduceOnly:
2649
+ side = 'sell' if (side == 'buy') else 'buy'
2650
+ params = self.omit(params, 'reduceOnly')
2651
+ posSide = 'Long' if (side == 'buy') else 'Short'
2652
+ else:
2653
+ posSide = 'Merged'
2492
2654
  posSide = self.capitalize(posSide)
2493
2655
  request['posSide'] = posSide
2494
- if reduceOnly is not None:
2495
- request['reduceOnly'] = reduceOnly
2496
- if market['settle'] == 'USDT':
2656
+ if isStableSettled:
2497
2657
  request['orderQtyRq'] = amount
2498
2658
  else:
2499
2659
  request['orderQty'] = self.parse_to_int(amount)
2500
2660
  if triggerPrice is not None:
2501
2661
  triggerType = self.safe_string(params, 'triggerType', 'ByMarkPrice')
2502
2662
  request['triggerType'] = triggerType
2663
+ # set direction & exchange specific order type
2664
+ triggerDirection = None
2665
+ triggerDirection, params = self.handle_param_string(params, 'triggerDirection')
2666
+ if triggerDirection is None:
2667
+ raise ArgumentsRequired(self.id + " createOrder() also requires a 'triggerDirection' parameter with either 'ascending' or 'descending' value")
2668
+ # the flow defined per https://phemex-docs.github.io/#more-order-type-examples
2669
+ if triggerDirection == 'ascending' or triggerDirection == 'up':
2670
+ if side == 'sell':
2671
+ request['ordType'] = 'MarketIfTouched' if (type == 'Market') else 'LimitIfTouched'
2672
+ elif side == 'buy':
2673
+ request['ordType'] = 'Stop' if (type == 'Market') else 'StopLimit'
2674
+ elif triggerDirection == 'descending' or triggerDirection == 'down':
2675
+ if side == 'sell':
2676
+ request['ordType'] = 'Stop' if (type == 'Market') else 'StopLimit'
2677
+ elif side == 'buy':
2678
+ request['ordType'] = 'MarketIfTouched' if (type == 'Market') else 'LimitIfTouched'
2503
2679
  if stopLossDefined or takeProfitDefined:
2504
2680
  if stopLossDefined:
2505
2681
  stopLossTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice')
2506
2682
  if stopLossTriggerPrice is None:
2507
- raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"], or params["stopLoss"]["stopPrice"] for a stop loss order')
2508
- if market['settle'] == 'USDT':
2683
+ raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"] for a stop loss order')
2684
+ if isStableSettled:
2509
2685
  request['stopLossRp'] = self.price_to_precision(symbol, stopLossTriggerPrice)
2510
2686
  else:
2511
2687
  request['stopLossEp'] = self.to_ep(stopLossTriggerPrice, market)
2512
2688
  stopLossTriggerPriceType = self.safe_string_2(stopLoss, 'triggerPriceType', 'slTrigger')
2513
2689
  if stopLossTriggerPriceType is not None:
2514
- if market['settle'] == 'USDT':
2515
- if (stopLossTriggerPriceType != 'ByMarkPrice') and (stopLossTriggerPriceType != 'ByLastPrice') and (stopLossTriggerPriceType != 'ByIndexPrice') and (stopLossTriggerPriceType != 'ByAskPrice') and (stopLossTriggerPriceType != 'ByBidPrice') and (stopLossTriggerPriceType != 'ByMarkPriceLimit') and (stopLossTriggerPriceType != 'ByLastPriceLimit'):
2516
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"')
2517
- else:
2518
- if (stopLossTriggerPriceType != 'ByMarkPrice') and (stopLossTriggerPriceType != 'ByLastPrice'):
2519
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"')
2520
- request['slTrigger'] = stopLossTriggerPriceType
2690
+ request['slTrigger'] = self.safe_string(self.options['triggerPriceTypesMap'], stopLossTriggerPriceType, stopLossTriggerPriceType)
2691
+ slLimitPrice = self.safe_string(stopLoss, 'price')
2692
+ if slLimitPrice is not None:
2693
+ request['slPxRp'] = self.price_to_precision(symbol, slLimitPrice)
2521
2694
  if takeProfitDefined:
2522
2695
  takeProfitTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice')
2523
2696
  if takeProfitTriggerPrice is None:
2524
- raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"], or params["takeProfit"]["stopPrice"] for a take profit order')
2525
- if market['settle'] == 'USDT':
2697
+ raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"] for a take profit order')
2698
+ if isStableSettled:
2526
2699
  request['takeProfitRp'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
2527
2700
  else:
2528
2701
  request['takeProfitEp'] = self.to_ep(takeProfitTriggerPrice, market)
2529
- takeProfitTriggerPriceType = self.safe_string_2(stopLoss, 'triggerPriceType', 'tpTrigger')
2702
+ takeProfitTriggerPriceType = self.safe_string_2(takeProfit, 'triggerPriceType', 'tpTrigger')
2530
2703
  if takeProfitTriggerPriceType is not None:
2531
- if market['settle'] == 'USDT':
2532
- if (takeProfitTriggerPriceType != 'ByMarkPrice') and (takeProfitTriggerPriceType != 'ByLastPrice') and (takeProfitTriggerPriceType != 'ByIndexPrice') and (takeProfitTriggerPriceType != 'ByAskPrice') and (takeProfitTriggerPriceType != 'ByBidPrice') and (takeProfitTriggerPriceType != 'ByMarkPriceLimit') and (takeProfitTriggerPriceType != 'ByLastPriceLimit'):
2533
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"')
2534
- else:
2535
- if (takeProfitTriggerPriceType != 'ByMarkPrice') and (takeProfitTriggerPriceType != 'ByLastPrice'):
2536
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"')
2537
- request['tpTrigger'] = takeProfitTriggerPriceType
2704
+ request['tpTrigger'] = self.safe_string(self.options['triggerPriceTypesMap'], takeProfitTriggerPriceType, takeProfitTriggerPriceType)
2705
+ tpLimitPrice = self.safe_string(takeProfit, 'price')
2706
+ if tpLimitPrice is not None:
2707
+ request['tpPxRp'] = self.price_to_precision(symbol, tpLimitPrice)
2538
2708
  if (type == 'Limit') or (type == 'StopLimit') or (type == 'LimitIfTouched'):
2539
- if market['settle'] == 'USDT':
2709
+ if isStableSettled:
2540
2710
  request['priceRp'] = self.price_to_precision(symbol, price)
2541
2711
  else:
2542
2712
  priceString = self.number_to_string(price)
2543
2713
  request['priceEp'] = self.to_ep(priceString, market)
2544
2714
  takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2545
2715
  if takeProfitPrice is not None:
2546
- if market['settle'] == 'USDT':
2716
+ if isStableSettled:
2547
2717
  request['takeProfitRp'] = self.price_to_precision(symbol, takeProfitPrice)
2548
2718
  else:
2549
2719
  request['takeProfitEp'] = self.to_ep(takeProfitPrice, market)
2550
2720
  params = self.omit(params, 'takeProfitPrice')
2551
2721
  stopLossPrice = self.safe_string(params, 'stopLossPrice')
2552
2722
  if stopLossPrice is not None:
2553
- if market['settle'] == 'USDT':
2723
+ if isStableSettled:
2554
2724
  request['stopLossRp'] = self.price_to_precision(symbol, stopLossPrice)
2555
2725
  else:
2556
2726
  request['stopLossEp'] = self.to_ep(stopLossPrice, market)
2557
2727
  params = self.omit(params, 'stopLossPrice')
2558
- params = self.omit(params, 'reduceOnly')
2559
2728
  response = None
2560
- if market['settle'] == 'USDT':
2729
+ if isStableSettled:
2561
2730
  response = await self.privatePostGOrders(self.extend(request, params))
2562
2731
  elif market['contract']:
2563
2732
  response = await self.privatePostOrders(self.extend(request, params))
@@ -2642,16 +2811,18 @@ class phemex(Exchange, ImplicitAPI):
2642
2811
  data = self.safe_dict(response, 'data', {})
2643
2812
  return self.parse_order(data, market)
2644
2813
 
2645
- async def edit_order(self, id: str, symbol: str, type: OrderType = None, side: OrderSide = None, amount: Num = None, price: Num = None, params={}):
2814
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
2646
2815
  """
2647
2816
  edit a trade order
2648
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
2817
+
2818
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
2819
+
2649
2820
  :param str id: cancel order id
2650
2821
  :param str symbol: unified symbol of the market to create an order in
2651
2822
  :param str type: 'market' or 'limit'
2652
2823
  :param str side: 'buy' or 'sell'
2653
2824
  :param float amount: how much of currency you want to trade in units of base currency
2654
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2825
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2655
2826
  :param dict [params]: extra parameters specific to the exchange API endpoint
2656
2827
  :param str [params.posSide]: either 'Merged' or 'Long' or 'Short'
2657
2828
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2663,13 +2834,13 @@ class phemex(Exchange, ImplicitAPI):
2663
2834
  }
2664
2835
  clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clOrdID')
2665
2836
  params = self.omit(params, ['clientOrderId', 'clOrdID'])
2666
- isUSDTSettled = (market['settle'] == 'USDT')
2837
+ isStableSettled = (market['settle'] == 'USDT') or (market['settle'] == 'USDC')
2667
2838
  if clientOrderId is not None:
2668
2839
  request['clOrdID'] = clientOrderId
2669
2840
  else:
2670
2841
  request['orderID'] = id
2671
2842
  if price is not None:
2672
- if isUSDTSettled:
2843
+ if isStableSettled:
2673
2844
  request['priceRp'] = self.price_to_precision(market['symbol'], price)
2674
2845
  else:
2675
2846
  request['priceEp'] = self.to_ep(price, market)
@@ -2679,19 +2850,19 @@ class phemex(Exchange, ImplicitAPI):
2679
2850
  if finalQty is not None:
2680
2851
  request['baseQtyEV'] = finalQty
2681
2852
  elif amount is not None:
2682
- if isUSDTSettled:
2853
+ if isStableSettled:
2683
2854
  request['orderQtyRq'] = self.amount_to_precision(market['symbol'], amount)
2684
2855
  else:
2685
2856
  request['baseQtyEV'] = self.to_ev(amount, market)
2686
- stopPrice = self.safe_string_2(params, 'stopPx', 'stopPrice')
2687
- if stopPrice is not None:
2688
- if isUSDTSettled:
2689
- request['stopPxRp'] = self.price_to_precision(symbol, stopPrice)
2857
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPx', 'stopPrice'])
2858
+ if triggerPrice is not None:
2859
+ if isStableSettled:
2860
+ request['stopPxRp'] = self.price_to_precision(symbol, triggerPrice)
2690
2861
  else:
2691
- request['stopPxEp'] = self.to_ep(stopPrice, market)
2692
- params = self.omit(params, ['stopPx', 'stopPrice'])
2862
+ request['stopPxEp'] = self.to_ep(triggerPrice, market)
2863
+ params = self.omit(params, ['triggerPrice', 'stopPx', 'stopPrice'])
2693
2864
  response = None
2694
- if isUSDTSettled:
2865
+ if isStableSettled:
2695
2866
  posSide = self.safe_string(params, 'posSide')
2696
2867
  if posSide is None:
2697
2868
  request['posSide'] = 'Merged'
@@ -2706,7 +2877,9 @@ class phemex(Exchange, ImplicitAPI):
2706
2877
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
2707
2878
  """
2708
2879
  cancels an open order
2709
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancel-single-order-by-orderid
2880
+
2881
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancel-single-order-by-orderid
2882
+
2710
2883
  :param str id: order id
2711
2884
  :param str symbol: unified symbol of the market the order was made in
2712
2885
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2727,7 +2900,7 @@ class phemex(Exchange, ImplicitAPI):
2727
2900
  else:
2728
2901
  request['orderID'] = id
2729
2902
  response = None
2730
- if market['settle'] == 'USDT':
2903
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
2731
2904
  posSide = self.safe_string(params, 'posSide')
2732
2905
  if posSide is None:
2733
2906
  request['posSide'] = 'Merged'
@@ -2742,7 +2915,9 @@ class phemex(Exchange, ImplicitAPI):
2742
2915
  async def cancel_all_orders(self, symbol: Str = None, params={}):
2743
2916
  """
2744
2917
  cancel all open orders in a market
2745
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancelall
2918
+
2919
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancelall
2920
+
2746
2921
  :param str symbol: unified market symbol of the market to cancel orders in
2747
2922
  :param dict [params]: extra parameters specific to the exchange API endpoint
2748
2923
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2751,28 +2926,58 @@ class phemex(Exchange, ImplicitAPI):
2751
2926
  raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
2752
2927
  await self.load_markets()
2753
2928
  market = self.market(symbol)
2754
- stop = self.safe_value_2(params, 'stop', 'trigger', False)
2755
- params = self.omit(params, 'stop', 'trigger')
2929
+ trigger = self.safe_value_2(params, 'stop', 'trigger', False)
2930
+ params = self.omit(params, ['stop', 'trigger'])
2756
2931
  request: dict = {
2757
2932
  'symbol': market['id'],
2758
2933
  # 'untriggerred': False, # False to cancel non-conditional orders, True to cancel conditional orders
2759
2934
  # 'text': 'up to 40 characters max',
2760
2935
  }
2761
- if stop:
2762
- request['untriggerred'] = stop
2936
+ if trigger:
2937
+ request['untriggerred'] = trigger
2763
2938
  response = None
2764
- if market['settle'] == 'USDT':
2939
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
2765
2940
  response = await self.privateDeleteGOrdersAll(self.extend(request, params))
2941
+ #
2942
+ # {
2943
+ # code: '0',
2944
+ # msg: '',
2945
+ # data: '1'
2946
+ # }
2947
+ #
2766
2948
  elif market['swap']:
2767
2949
  response = await self.privateDeleteOrdersAll(self.extend(request, params))
2950
+ #
2951
+ # {
2952
+ # code: '0',
2953
+ # msg: '',
2954
+ # data: '1'
2955
+ # }
2956
+ #
2768
2957
  else:
2769
2958
  response = await self.privateDeleteSpotOrdersAll(self.extend(request, params))
2770
- return response
2959
+ #
2960
+ # {
2961
+ # code: '0',
2962
+ # msg: '',
2963
+ # data: {
2964
+ # total: '1'
2965
+ # }
2966
+ # }
2967
+ #
2968
+ return [
2969
+ self.safe_order({
2970
+ 'info': response,
2971
+ }),
2972
+ ]
2771
2973
 
2772
2974
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
2773
2975
  """
2774
- :see: https://phemex-docs.github.io/#query-orders-by-ids
2976
+
2977
+ https://phemex-docs.github.io/#query-orders-by-ids
2978
+
2775
2979
  fetches information on an order made by the user
2980
+ :param str id: the order id
2776
2981
  :param str symbol: unified symbol of the market the order was made in
2777
2982
  :param dict [params]: extra parameters specific to the exchange API endpoint
2778
2983
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2791,10 +2996,10 @@ class phemex(Exchange, ImplicitAPI):
2791
2996
  else:
2792
2997
  request['orderID'] = id
2793
2998
  response = None
2794
- if market['settle'] == 'USDT':
2999
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
2795
3000
  response = await self.privateGetApiDataGFuturesOrdersByOrderId(self.extend(request, params))
2796
3001
  elif market['spot']:
2797
- response = await self.privateGetSpotOrdersActive(self.extend(request, params))
3002
+ response = await self.privateGetApiDataSpotsOrdersByOrderId(self.extend(request, params))
2798
3003
  else:
2799
3004
  response = await self.privateGetExchangeOrder(self.extend(request, params))
2800
3005
  data = self.safe_value(response, 'data', {})
@@ -2806,13 +3011,18 @@ class phemex(Exchange, ImplicitAPI):
2806
3011
  raise OrderNotFound(self.id + ' fetchOrder() ' + symbol + ' order with clientOrderId ' + clientOrderId + ' not found')
2807
3012
  else:
2808
3013
  raise OrderNotFound(self.id + ' fetchOrder() ' + symbol + ' order with id ' + id + ' not found')
2809
- order = self.safe_value(data, 0, {})
3014
+ order = self.safe_dict(data, 0, {})
3015
+ elif market['spot']:
3016
+ rows = self.safe_list(data, 'rows', [])
3017
+ order = self.safe_dict(rows, 0, {})
2810
3018
  return self.parse_order(order, market)
2811
3019
 
2812
3020
  async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2813
3021
  """
2814
3022
  fetches information on multiple orders made by the user
2815
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3023
+
3024
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3025
+
2816
3026
  :param str symbol: unified market symbol of the market orders were made in
2817
3027
  :param int [since]: the earliest time in ms to fetch orders for
2818
3028
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2831,13 +3041,13 @@ class phemex(Exchange, ImplicitAPI):
2831
3041
  if limit is not None:
2832
3042
  request['limit'] = limit
2833
3043
  response = None
2834
- if market['settle'] == 'USDT':
3044
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
2835
3045
  request['currency'] = market['settle']
2836
3046
  response = await self.privateGetExchangeOrderV2OrderList(self.extend(request, params))
2837
3047
  elif market['swap']:
2838
3048
  response = await self.privateGetExchangeOrderList(self.extend(request, params))
2839
3049
  else:
2840
- response = await self.privateGetSpotOrders(self.extend(request, params))
3050
+ response = await self.privateGetApiDataSpotsOrders(self.extend(request, params))
2841
3051
  data = self.safe_value(response, 'data', {})
2842
3052
  rows = self.safe_list(data, 'rows', data)
2843
3053
  return self.parse_orders(rows, market, since, limit)
@@ -2845,9 +3055,11 @@ class phemex(Exchange, ImplicitAPI):
2845
3055
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2846
3056
  """
2847
3057
  fetch all unfilled currently open orders
2848
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryopenorder
2849
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md
2850
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotListAllOpenOrder
3058
+
3059
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryopenorder
3060
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md
3061
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotListAllOpenOrder
3062
+
2851
3063
  :param str symbol: unified market symbol
2852
3064
  :param int [since]: the earliest time in ms to fetch open orders for
2853
3065
  :param int [limit]: the maximum number of open order structures to retrieve
@@ -2864,7 +3076,7 @@ class phemex(Exchange, ImplicitAPI):
2864
3076
  }
2865
3077
  response = None
2866
3078
  try:
2867
- if market['settle'] == 'USDT':
3079
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
2868
3080
  response = await self.privateGetGOrdersActiveList(self.extend(request, params))
2869
3081
  elif market['swap']:
2870
3082
  response = await self.privateGetOrdersActiveList(self.extend(request, params))
@@ -2884,10 +3096,12 @@ class phemex(Exchange, ImplicitAPI):
2884
3096
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2885
3097
  """
2886
3098
  fetches information on multiple closed orders made by the user
2887
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
2888
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#queryorder
2889
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedgedd-Perpetual-API.md#query-closed-orders-by-symbol
2890
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataOrdersByIds
3099
+
3100
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3101
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#queryorder
3102
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedgedd-Perpetual-API.md#query-closed-orders-by-symbol
3103
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataOrdersByIds
3104
+
2891
3105
  :param str symbol: unified market symbol of the market orders were made in
2892
3106
  :param int [since]: the earliest time in ms to fetch orders for
2893
3107
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2961,9 +3175,11 @@ class phemex(Exchange, ImplicitAPI):
2961
3175
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2962
3176
  """
2963
3177
  fetch all trades made by the user
2964
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-user-trade
2965
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-trade
2966
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataTradesHist
3178
+
3179
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-user-trade
3180
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-trade
3181
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataTradesHist
3182
+
2967
3183
  :param str symbol: unified market symbol
2968
3184
  :param int [since]: the earliest time in ms to fetch trades for
2969
3185
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -3107,11 +3323,12 @@ class phemex(Exchange, ImplicitAPI):
3107
3323
  data = self.safe_value(data, 'rows', [])
3108
3324
  return self.parse_trades(data, market, since, limit)
3109
3325
 
3110
- async def fetch_deposit_address(self, code: str, params={}):
3326
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
3111
3327
  """
3112
3328
  fetch the deposit address for a currency associated with self account
3113
3329
  :param str code: unified currency code
3114
3330
  :param dict [params]: extra parameters specific to the exchange API endpoint
3331
+ :param str [params.network]: the chain name to fetch the deposit address e.g. ETH, TRX, EOS, SOL, etc.
3115
3332
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
3116
3333
  """
3117
3334
  await self.load_markets()
@@ -3119,23 +3336,29 @@ class phemex(Exchange, ImplicitAPI):
3119
3336
  request: dict = {
3120
3337
  'currency': currency['id'],
3121
3338
  }
3122
- defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3339
+ defaultNetworks = self.safe_dict(self.options, 'defaultNetworks')
3123
3340
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3124
- networks = self.safe_value(self.options, 'networks', {})
3125
- network = self.safe_string_upper(params, 'network', defaultNetwork)
3341
+ networks = self.safe_dict(self.options, 'networks', {})
3342
+ network = self.safe_string_upper_2(params, 'network', 'chainName', defaultNetwork)
3126
3343
  network = self.safe_string(networks, network, network)
3127
3344
  if network is None:
3128
- request['chainName'] = currency['id']
3345
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires a network parameter')
3129
3346
  else:
3130
3347
  request['chainName'] = network
3131
3348
  params = self.omit(params, 'network')
3132
- response = await self.privateGetPhemexUserWalletsV2DepositAddress(self.extend(request, params))
3349
+ response = await self.privateGetExchangeWalletsV2DepositAddress(self.extend(request, params))
3350
+ #
3133
3351
  # {
3134
- # "code":0,
3135
- # "msg":"OK",
3136
- # "data":{
3137
- # "address":"0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3138
- # "tag":null
3352
+ # "code": 0,
3353
+ # "msg": "OK",
3354
+ # "data": {
3355
+ # "address": "tb1qxel5wq5gumt",
3356
+ # "tag": "",
3357
+ # "notice": False,
3358
+ # "accountType": 1,
3359
+ # "contractName": null,
3360
+ # "chainTokenUrl": null,
3361
+ # "sign": null
3139
3362
  # }
3140
3363
  # }
3141
3364
  #
@@ -3144,11 +3367,11 @@ class phemex(Exchange, ImplicitAPI):
3144
3367
  tag = self.safe_string(data, 'tag')
3145
3368
  self.check_address(address)
3146
3369
  return {
3370
+ 'info': response,
3147
3371
  'currency': code,
3372
+ 'network': None,
3148
3373
  'address': address,
3149
3374
  'tag': tag,
3150
- 'network': None,
3151
- 'info': response,
3152
3375
  }
3153
3376
 
3154
3377
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -3360,21 +3583,25 @@ class phemex(Exchange, ImplicitAPI):
3360
3583
  'fee': fee,
3361
3584
  }
3362
3585
 
3363
- async def fetch_positions(self, symbols: Strings = None, params={}):
3586
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3364
3587
  """
3365
3588
  fetch all open positions
3366
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-trading-account-and-positions
3367
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
3368
- :see: https://phemex-docs.github.io/#query-account-positions-with-unrealized-pnl
3589
+
3590
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-trading-account-and-positions
3591
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
3592
+ https://phemex-docs.github.io/#query-account-positions-with-unrealized-pnl
3593
+
3369
3594
  :param str[] [symbols]: list of unified market symbols
3370
3595
  :param dict [params]: extra parameters specific to the exchange API endpoint
3371
- :param str [param.method]: *USDT contracts only* 'privateGetGAccountsAccountPositions' or 'privateGetAccountsPositions' default is 'privateGetGAccountsAccountPositions'
3596
+ :param str [params.code]: the currency code to fetch positions for, USD, BTC or USDT, USDT is the default
3597
+ :param str [params.method]: *USDT contracts only* 'privateGetGAccountsAccountPositions' or 'privateGetAccountsPositions' default is 'privateGetGAccountsAccountPositions'
3372
3598
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3373
3599
  """
3374
3600
  await self.load_markets()
3375
3601
  symbols = self.market_symbols(symbols)
3376
3602
  subType = None
3377
- code = self.safe_string(params, 'currency')
3603
+ code = self.safe_string_2(params, 'currency', 'code', 'USDT')
3604
+ params = self.omit(params, ['currency', 'code'])
3378
3605
  settle = None
3379
3606
  market = None
3380
3607
  firstSymbol = self.safe_string(symbols, 0)
@@ -3383,15 +3610,15 @@ class phemex(Exchange, ImplicitAPI):
3383
3610
  settle = market['settle']
3384
3611
  code = market['settle']
3385
3612
  else:
3386
- settle, params = self.handle_option_and_params(params, 'fetchPositions', 'settle', 'USD')
3613
+ settle, params = self.handle_option_and_params(params, 'fetchPositions', 'settle', code)
3387
3614
  subType, params = self.handle_sub_type_and_params('fetchPositions', market, params)
3388
3615
  isUSDTSettled = settle == 'USDT'
3389
3616
  if isUSDTSettled:
3390
3617
  code = 'USDT'
3618
+ elif settle == 'BTC':
3619
+ code = 'BTC'
3391
3620
  elif code is None:
3392
3621
  code = 'USD' if (subType == 'linear') else 'BTC'
3393
- else:
3394
- params = self.omit(params, 'code')
3395
3622
  currency = self.currency(code)
3396
3623
  request: dict = {
3397
3624
  'currency': currency['id'],
@@ -3631,7 +3858,9 @@ class phemex(Exchange, ImplicitAPI):
3631
3858
  async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3632
3859
  """
3633
3860
  fetch the history of funding payments paid and received on self account
3634
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#futureDataFundingFeesHist
3861
+
3862
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#futureDataFundingFeesHist
3863
+
3635
3864
  :param str symbol: unified market symbol
3636
3865
  :param int [since]: the earliest time in ms to fetch funding history for
3637
3866
  :param int [limit]: the maximum number of funding history structures to retrieve
@@ -3652,8 +3881,8 @@ class phemex(Exchange, ImplicitAPI):
3652
3881
  raise BadRequest(self.id + ' fetchFundingHistory() limit argument cannot exceed 200')
3653
3882
  request['limit'] = limit
3654
3883
  response = None
3655
- isUsdt = market['settle'] == 'USDT'
3656
- if isUsdt:
3884
+ isStableSettled = market['settle'] == 'USDT' or market['settle'] == 'USDC'
3885
+ if isStableSettled:
3657
3886
  response = await self.privateGetApiDataGFuturesFundingFees(self.extend(request, params))
3658
3887
  else:
3659
3888
  response = await self.privateGetApiDataFuturesFundingFees(self.extend(request, params))
@@ -3702,15 +3931,15 @@ class phemex(Exchange, ImplicitAPI):
3702
3931
  if value is None or currencyCode is None:
3703
3932
  return value
3704
3933
  # it was confirmed by phemex support, that USDT contracts use direct amounts in funding fees, while USD & INVERSE needs 'valueScale'
3705
- isUsdt = market['settle'] == 'USDT'
3706
- if not isUsdt:
3934
+ isStableSettled = market['settle'] == 'USDT' or market['settle'] == 'USDC'
3935
+ if not isStableSettled:
3707
3936
  currency = self.safe_currency(currencyCode)
3708
3937
  scale = self.safe_string(currency['info'], 'valueScale')
3709
3938
  tickPrecision = self.parse_precision(scale)
3710
3939
  value = Precise.string_mul(value, tickPrecision)
3711
3940
  return value
3712
3941
 
3713
- async def fetch_funding_rate(self, symbol: str, params={}):
3942
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
3714
3943
  """
3715
3944
  fetch the current funding rate
3716
3945
  :param str symbol: unified market symbol
@@ -3755,7 +3984,7 @@ class phemex(Exchange, ImplicitAPI):
3755
3984
  result = self.safe_value(response, 'result', {})
3756
3985
  return self.parse_funding_rate(result, market)
3757
3986
 
3758
- def parse_funding_rate(self, contract, market: Market = None):
3987
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
3759
3988
  #
3760
3989
  # {
3761
3990
  # "askEp": 2332500,
@@ -3796,30 +4025,37 @@ class phemex(Exchange, ImplicitAPI):
3796
4025
  marketId = self.safe_string(contract, 'symbol')
3797
4026
  symbol = self.safe_symbol(marketId, market)
3798
4027
  timestamp = self.safe_integer_product(contract, 'timestamp', 0.000001)
4028
+ markEp = self.from_ep(self.safe_string(contract, 'markEp'), market)
4029
+ indexEp = self.from_ep(self.safe_string(contract, 'indexEp'), market)
4030
+ fundingRateEr = self.from_er(self.safe_string(contract, 'fundingRateEr'), market)
4031
+ nextFundingRateEr = self.from_er(self.safe_string(contract, 'predFundingRateEr'), market)
3799
4032
  return {
3800
4033
  'info': contract,
3801
4034
  'symbol': symbol,
3802
- 'markPrice': self.from_ep(self.safe_string_2(contract, 'markEp', 'markPriceRp'), market),
3803
- 'indexPrice': self.from_ep(self.safe_string_2(contract, 'indexEp', 'indexPriceRp'), market),
4035
+ 'markPrice': self.safe_number(contract, 'markPriceRp', markEp),
4036
+ 'indexPrice': self.safe_number(contract, 'indexPriceRp', indexEp),
3804
4037
  'interestRate': None,
3805
4038
  'estimatedSettlePrice': None,
3806
4039
  'timestamp': timestamp,
3807
4040
  'datetime': self.iso8601(timestamp),
3808
- 'fundingRate': self.from_er(self.safe_string(contract, 'fundingRateEr'), market),
4041
+ 'fundingRate': self.safe_number(contract, 'fundingRateRr', fundingRateEr),
3809
4042
  'fundingTimestamp': None,
3810
4043
  'fundingDatetime': None,
3811
- 'nextFundingRate': self.from_er(self.safe_string_2(contract, 'predFundingRateEr', 'predFundingRateRr'), market),
4044
+ 'nextFundingRate': self.safe_number(contract, 'predFundingRateRr', nextFundingRateEr),
3812
4045
  'nextFundingTimestamp': None,
3813
4046
  'nextFundingDatetime': None,
3814
4047
  'previousFundingRate': None,
3815
4048
  'previousFundingTimestamp': None,
3816
4049
  'previousFundingDatetime': None,
4050
+ 'interval': None,
3817
4051
  }
3818
4052
 
3819
4053
  async def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3820
4054
  """
3821
4055
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
3822
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
4056
+
4057
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
4058
+
3823
4059
  :param str symbol: unified market symbol of the market to set margin in
3824
4060
  :param float amount: the amount to set the margin to
3825
4061
  :param dict [params]: parameters specific to the exchange API endpoint
@@ -3876,6 +4112,9 @@ class phemex(Exchange, ImplicitAPI):
3876
4112
  async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
3877
4113
  """
3878
4114
  set margin mode to 'cross' or 'isolated'
4115
+
4116
+ https://phemex-docs.github.io/#set-leverage
4117
+
3879
4118
  :param str marginMode: 'cross' or 'isolated'
3880
4119
  :param str symbol: unified market symbol
3881
4120
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3885,8 +4124,8 @@ class phemex(Exchange, ImplicitAPI):
3885
4124
  raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
3886
4125
  await self.load_markets()
3887
4126
  market = self.market(symbol)
3888
- if not market['swap'] or market['settle'] == 'USDT':
3889
- raise BadSymbol(self.id + ' setMarginMode() supports swap(non USDT based) contracts only')
4127
+ if not market['swap'] or market['settle'] == 'USDT' or market['settle'] == 'USDC':
4128
+ raise BadSymbol(self.id + ' setMarginMode() supports swap(non USDT/USDC based) contracts only')
3890
4129
  marginMode = marginMode.lower()
3891
4130
  if marginMode != 'isolated' and marginMode != 'cross':
3892
4131
  raise BadRequest(self.id + ' setMarginMode() marginMode argument should be isolated or cross')
@@ -3904,7 +4143,9 @@ class phemex(Exchange, ImplicitAPI):
3904
4143
  async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
3905
4144
  """
3906
4145
  set hedged to True or False for a market
3907
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
4146
+
4147
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
4148
+
3908
4149
  :param bool hedged: set to True to use dualSidePosition
3909
4150
  :param str symbol: not used by binance setPositionMode()
3910
4151
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4036,7 +4277,8 @@ class phemex(Exchange, ImplicitAPI):
4036
4277
  # ]
4037
4278
  # },
4038
4279
  #
4039
- market = self.safe_market(None, market)
4280
+ marketId = self.safe_string(info, 'symbol')
4281
+ market = self.safe_market(marketId, market)
4040
4282
  riskLimits = (market['info']['riskLimits'])
4041
4283
  tiers = []
4042
4284
  minNotional = 0
@@ -4045,6 +4287,7 @@ class phemex(Exchange, ImplicitAPI):
4045
4287
  maxNotional = self.safe_integer(tier, 'limit')
4046
4288
  tiers.append({
4047
4289
  'tier': self.sum(i, 1),
4290
+ 'symbol': self.safe_symbol(marketId, market),
4048
4291
  'currency': market['settle'],
4049
4292
  'minNotional': minNotional,
4050
4293
  'maxNotional': maxNotional,
@@ -4089,10 +4332,12 @@ class phemex(Exchange, ImplicitAPI):
4089
4332
  url = self.implode_hostname(self.urls['api'][api]) + url
4090
4333
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
4091
4334
 
4092
- async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
4335
+ async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
4093
4336
  """
4094
4337
  set the level of leverage for a market
4095
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#set-leverage
4338
+
4339
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#set-leverage
4340
+
4096
4341
  :param float leverage: the rate of leverage, 100 > leverage > -100 excluding numbers between -1 to 1
4097
4342
  :param str symbol: unified market symbol
4098
4343
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4116,7 +4361,7 @@ class phemex(Exchange, ImplicitAPI):
4116
4361
  'symbol': market['id'],
4117
4362
  }
4118
4363
  response = None
4119
- if market['settle'] == 'USDT':
4364
+ if market['settle'] == 'USDT' or market['settle'] == 'USDC':
4120
4365
  if not isHedged and longLeverageRr is None and shortLeverageRr is None:
4121
4366
  request['leverageRr'] = leverage
4122
4367
  else:
@@ -4133,6 +4378,10 @@ class phemex(Exchange, ImplicitAPI):
4133
4378
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4134
4379
  """
4135
4380
  transfer currency internally between wallets on the same account
4381
+
4382
+ https://phemex-docs.github.io/#transfer-between-spot-and-futures
4383
+ https://phemex-docs.github.io/#universal-transfer-main-account-only-transfer-between-sub-to-main-main-to-sub-or-sub-to-sub
4384
+
4136
4385
  :param str code: unified currency code
4137
4386
  :param float amount: amount to transfer
4138
4387
  :param str fromAccount: account to transfer from
@@ -4206,9 +4455,12 @@ class phemex(Exchange, ImplicitAPI):
4206
4455
  transfer['currency'] = code
4207
4456
  return transfer
4208
4457
 
4209
- async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
4458
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
4210
4459
  """
4211
4460
  fetch a history of internal transfers made on an account
4461
+
4462
+ https://phemex-docs.github.io/#query-transfer-history
4463
+
4212
4464
  :param str code: unified currency code of the currency transferred
4213
4465
  :param int [since]: the earliest time in ms to fetch transfers for
4214
4466
  :param int [limit]: the maximum number of transfers structures to retrieve
@@ -4317,7 +4569,9 @@ class phemex(Exchange, ImplicitAPI):
4317
4569
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4318
4570
  """
4319
4571
  fetches historical funding rate prices
4320
- :see: https://phemex-docs.github.io/#query-funding-rate-history-2
4572
+
4573
+ https://phemex-docs.github.io/#query-funding-rate-history-2
4574
+
4321
4575
  :param str symbol: unified symbol of the market to fetch the funding rate history for
4322
4576
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
4323
4577
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
@@ -4330,7 +4584,7 @@ class phemex(Exchange, ImplicitAPI):
4330
4584
  raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
4331
4585
  await self.load_markets()
4332
4586
  market = self.market(symbol)
4333
- isUsdtSettled = market['settle'] == 'USDT'
4587
+ isUsdtSettled = market['settle'] == 'USDT' or market['settle'] == 'USDC'
4334
4588
  if not market['swap']:
4335
4589
  raise BadRequest(self.id + ' fetchFundingRateHistory() supports swap contracts only')
4336
4590
  paginate = False
@@ -4387,10 +4641,12 @@ class phemex(Exchange, ImplicitAPI):
4387
4641
  sorted = self.sort_by(result, 'timestamp')
4388
4642
  return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
4389
4643
 
4390
- async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
4644
+ async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
4391
4645
  """
4392
4646
  make a withdrawal
4393
- :see: https://phemex-docs.github.io/#create-withdraw-request
4647
+
4648
+ https://phemex-docs.github.io/#create-withdraw-request
4649
+
4394
4650
  :param str code: unified currency code
4395
4651
  :param float amount: the amount to withdraw
4396
4652
  :param str address: the address to withdraw to
@@ -4453,6 +4709,291 @@ class phemex(Exchange, ImplicitAPI):
4453
4709
  data = self.safe_dict(response, 'data', {})
4454
4710
  return self.parse_transaction(data, currency)
4455
4711
 
4712
+ async def fetch_open_interest(self, symbol: str, params={}):
4713
+ """
4714
+ retrieves the open interest of a trading pair
4715
+
4716
+ https://phemex-docs.github.io/#query-24-hours-ticker
4717
+
4718
+ :param str symbol: unified CCXT market symbol
4719
+ :param dict [params]: exchange specific parameters
4720
+ :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
4721
+ """
4722
+ await self.load_markets()
4723
+ market = self.market(symbol)
4724
+ if not market['contract']:
4725
+ raise BadRequest(self.id + ' fetchOpenInterest is only supported for contract markets.')
4726
+ request: dict = {
4727
+ 'symbol': market['id'],
4728
+ }
4729
+ response = await self.v2GetMdV2Ticker24hr(self.extend(request, params))
4730
+ #
4731
+ # {
4732
+ # error: null,
4733
+ # id: '0',
4734
+ # result: {
4735
+ # closeRp: '67550.1',
4736
+ # fundingRateRr: '0.0001',
4737
+ # highRp: '68400',
4738
+ # indexPriceRp: '67567.15389794',
4739
+ # lowRp: '66096.4',
4740
+ # markPriceRp: '67550.1',
4741
+ # openInterestRv: '1848.1144186',
4742
+ # openRp: '66330',
4743
+ # predFundingRateRr: '0.0001',
4744
+ # symbol: 'BTCUSDT',
4745
+ # timestamp: '1729114315443343001',
4746
+ # turnoverRv: '228863389.3237532',
4747
+ # volumeRq: '3388.5600312'
4748
+ # }
4749
+ # }
4750
+ #
4751
+ result = self.safe_dict(response, 'result')
4752
+ return self.parse_open_interest(result, market)
4753
+
4754
+ def parse_open_interest(self, interest, market: Market = None):
4755
+ #
4756
+ # {
4757
+ # closeRp: '67550.1',
4758
+ # fundingRateRr: '0.0001',
4759
+ # highRp: '68400',
4760
+ # indexPriceRp: '67567.15389794',
4761
+ # lowRp: '66096.4',
4762
+ # markPriceRp: '67550.1',
4763
+ # openInterestRv: '1848.1144186',
4764
+ # openRp: '66330',
4765
+ # predFundingRateRr: '0.0001',
4766
+ # symbol: 'BTCUSDT',
4767
+ # timestamp: '1729114315443343001',
4768
+ # turnoverRv: '228863389.3237532',
4769
+ # volumeRq: '3388.5600312'
4770
+ # }
4771
+ #
4772
+ timestamp = self.safe_integer(interest, 'timestamp') / 1000000
4773
+ id = self.safe_string(interest, 'symbol')
4774
+ return self.safe_open_interest({
4775
+ 'info': interest,
4776
+ 'symbol': self.safe_symbol(id, market),
4777
+ 'baseVolume': self.safe_string(interest, 'volumeRq'),
4778
+ 'quoteVolume': None, # deprecated
4779
+ 'openInterestAmount': self.safe_string(interest, 'openInterestRv'),
4780
+ 'openInterestValue': None,
4781
+ 'timestamp': timestamp,
4782
+ 'datetime': self.iso8601(timestamp),
4783
+ }, market)
4784
+
4785
+ async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
4786
+ """
4787
+ fetch a quote for converting from one currency to another
4788
+
4789
+ https://phemex-docs.github.io/#rfq-quote
4790
+
4791
+ :param str fromCode: the currency that you want to sell and convert from
4792
+ :param str toCode: the currency that you want to buy and convert into
4793
+ :param float amount: how much you want to trade in units of the from currency
4794
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4795
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
4796
+ """
4797
+ await self.load_markets()
4798
+ fromCurrency = self.currency(fromCode)
4799
+ toCurrency = self.currency(toCode)
4800
+ valueScale = self.safe_integer(fromCurrency, 'valueScale')
4801
+ request: dict = {
4802
+ 'fromCurrency': fromCode,
4803
+ 'toCurrency': toCode,
4804
+ 'fromAmountEv': self.to_en(amount, valueScale),
4805
+ }
4806
+ response = await self.privateGetAssetsQuote(self.extend(request, params))
4807
+ #
4808
+ # {
4809
+ # "code": 0,
4810
+ # "msg": "OK",
4811
+ # "data": {
4812
+ # "code": "GIF...AAA",
4813
+ # "quoteArgs": {
4814
+ # "origin": 10,
4815
+ # "price": "0.00000939",
4816
+ # "proceeds": "0.00000000",
4817
+ # "ttlMs": 7000,
4818
+ # "expireAt": 1739875826009,
4819
+ # "requestAt": 1739875818009,
4820
+ # "quoteAt": 1739875816594
4821
+ # }
4822
+ # }
4823
+ # }
4824
+ #
4825
+ data = self.safe_dict(response, 'data', {})
4826
+ return self.parse_conversion(data, fromCurrency, toCurrency)
4827
+
4828
+ async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
4829
+ """
4830
+ convert from one currency to another
4831
+
4832
+ https://phemex-docs.github.io/#convert
4833
+
4834
+ :param str id: the id of the trade that you want to make
4835
+ :param str fromCode: the currency that you want to sell and convert from
4836
+ :param str toCode: the currency that you want to buy and convert into
4837
+ :param float [amount]: how much you want to trade in units of the from currency
4838
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4839
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
4840
+ """
4841
+ await self.load_markets()
4842
+ fromCurrency = self.currency(fromCode)
4843
+ toCurrency = self.currency(toCode)
4844
+ valueScale = self.safe_integer(fromCurrency, 'valueScale')
4845
+ request: dict = {
4846
+ 'code': id,
4847
+ 'fromCurrency': fromCode,
4848
+ 'toCurrency': toCode,
4849
+ }
4850
+ if amount is not None:
4851
+ request['fromAmountEv'] = self.to_en(amount, valueScale)
4852
+ response = await self.privatePostAssetsConvert(self.extend(request, params))
4853
+ #
4854
+ # {
4855
+ # "code": 0,
4856
+ # "msg": "OK",
4857
+ # "data": {
4858
+ # "moveOp": 0,
4859
+ # "fromCurrency": "USDT",
4860
+ # "toCurrency": "BTC",
4861
+ # "fromAmountEv": 4000000000,
4862
+ # "toAmountEv": 41511,
4863
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4864
+ # "status": 10
4865
+ # }
4866
+ # }
4867
+ #
4868
+ data = self.safe_dict(response, 'data', {})
4869
+ fromCurrencyId = self.safe_string(data, 'fromCurrency')
4870
+ fromResult = self.safe_currency(fromCurrencyId, fromCurrency)
4871
+ toCurrencyId = self.safe_string(data, 'toCurrency')
4872
+ to = self.safe_currency(toCurrencyId, toCurrency)
4873
+ return self.parse_conversion(data, fromResult, to)
4874
+
4875
+ async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
4876
+ """
4877
+ fetch the users history of conversion trades
4878
+
4879
+ https://phemex-docs.github.io/#query-convert-history
4880
+
4881
+ :param str [code]: the unified currency code
4882
+ :param int [since]: the earliest time in ms to fetch conversions for
4883
+ :param int [limit]: the maximum number of conversion structures to retrieve, default 20, max 200
4884
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4885
+ :param str [params.until]: the end time in ms
4886
+ :param str [params.fromCurrency]: the currency that you sold and converted from
4887
+ :param str [params.toCurrency]: the currency that you bought and converted into
4888
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
4889
+ """
4890
+ await self.load_markets()
4891
+ request: dict = {}
4892
+ if code is not None:
4893
+ request['fromCurrency'] = code
4894
+ if since is not None:
4895
+ request['startTime'] = since
4896
+ if limit is not None:
4897
+ request['limit'] = limit
4898
+ request, params = self.handle_until_option('endTime', request, params)
4899
+ response = await self.privateGetAssetsConvert(self.extend(request, params))
4900
+ #
4901
+ # {
4902
+ # "code": 0,
4903
+ # "msg": "OK",
4904
+ # "data": {
4905
+ # "total": 2,
4906
+ # "rows": [
4907
+ # {
4908
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4909
+ # "createTime": 1739882294000,
4910
+ # "fromCurrency": "USDT",
4911
+ # "toCurrency": "BTC",
4912
+ # "fromAmountEv": 4000000000,
4913
+ # "toAmountEv": 41511,
4914
+ # "status": 10,
4915
+ # "conversionRate": 1037,
4916
+ # "errorCode": 0
4917
+ # },
4918
+ # ]
4919
+ # }
4920
+ # }
4921
+ #
4922
+ data = self.safe_dict(response, 'data', {})
4923
+ rows = self.safe_list(data, 'rows', [])
4924
+ return self.parse_conversions(rows, code, 'fromCurrency', 'toCurrency', since, limit)
4925
+
4926
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
4927
+ #
4928
+ # fetchConvertQuote
4929
+ #
4930
+ # {
4931
+ # "code": "GIF...AAA",
4932
+ # "quoteArgs": {
4933
+ # "origin": 10,
4934
+ # "price": "0.00000939",
4935
+ # "proceeds": "0.00000000",
4936
+ # "ttlMs": 7000,
4937
+ # "expireAt": 1739875826009,
4938
+ # "requestAt": 1739875818009,
4939
+ # "quoteAt": 1739875816594
4940
+ # }
4941
+ # }
4942
+ #
4943
+ # createConvertTrade
4944
+ #
4945
+ # {
4946
+ # "moveOp": 0,
4947
+ # "fromCurrency": "USDT",
4948
+ # "toCurrency": "BTC",
4949
+ # "fromAmountEv": 4000000000,
4950
+ # "toAmountEv": 41511,
4951
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4952
+ # "status": 10
4953
+ # }
4954
+ #
4955
+ # fetchConvertTradeHistory
4956
+ #
4957
+ # {
4958
+ # "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
4959
+ # "createTime": 1739882294000,
4960
+ # "fromCurrency": "USDT",
4961
+ # "toCurrency": "BTC",
4962
+ # "fromAmountEv": 4000000000,
4963
+ # "toAmountEv": 41511,
4964
+ # "status": 10,
4965
+ # "conversionRate": 1037,
4966
+ # "errorCode": 0
4967
+ # }
4968
+ #
4969
+ quoteArgs = self.safe_dict(conversion, 'quoteArgs', {})
4970
+ requestTime = self.safe_integer(quoteArgs, 'requestAt')
4971
+ timestamp = self.safe_integer(conversion, 'createTime', requestTime)
4972
+ fromCoin = self.safe_string(conversion, 'fromCurrency', self.safe_string(fromCurrency, 'code'))
4973
+ fromCode = self.safe_currency_code(fromCoin, fromCurrency)
4974
+ toCoin = self.safe_string(conversion, 'toCurrency', self.safe_string(toCurrency, 'code'))
4975
+ toCode = self.safe_currency_code(toCoin, toCurrency)
4976
+ fromValueScale = self.safe_integer(fromCurrency, 'valueScale')
4977
+ toValueScale = self.safe_integer(toCurrency, 'valueScale')
4978
+ fromAmount = self.from_en(self.safe_string(conversion, 'fromAmountEv'), fromValueScale)
4979
+ if fromAmount is None and quoteArgs is not None:
4980
+ fromAmount = self.from_en(self.safe_string(quoteArgs, 'origin'), fromValueScale)
4981
+ toAmount = self.from_en(self.safe_string(conversion, 'toAmountEv'), toValueScale)
4982
+ if toAmount is None and quoteArgs is not None:
4983
+ toAmount = self.from_en(self.safe_string(quoteArgs, 'proceeds'), toValueScale)
4984
+ return {
4985
+ 'info': conversion,
4986
+ 'timestamp': timestamp,
4987
+ 'datetime': self.iso8601(timestamp),
4988
+ 'id': self.safe_string(conversion, 'code'),
4989
+ 'fromCurrency': fromCode,
4990
+ 'fromAmount': self.parse_number(fromAmount),
4991
+ 'toCurrency': toCode,
4992
+ 'toAmount': self.parse_number(toAmount),
4993
+ 'price': self.safe_number(quoteArgs, 'price'),
4994
+ 'fee': None,
4995
+ }
4996
+
4456
4997
  def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
4457
4998
  if response is None:
4458
4999
  return None # fallback to default error handler