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