ccxt-ir 4.3.46.0.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2822 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.cryptocom import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Account, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import AccountNotEnabled
15
+ from ccxt.base.errors import ArgumentsRequired
16
+ from ccxt.base.errors import BadRequest
17
+ from ccxt.base.errors import BadSymbol
18
+ from ccxt.base.errors import InsufficientFunds
19
+ from ccxt.base.errors import InvalidOrder
20
+ from ccxt.base.errors import NotSupported
21
+ from ccxt.base.errors import DDoSProtection
22
+ from ccxt.base.errors import OnMaintenance
23
+ from ccxt.base.errors import InvalidNonce
24
+ from ccxt.base.decimal_to_precision import TICK_SIZE
25
+ from ccxt.base.precise import Precise
26
+
27
+
28
+ class cryptocom(Exchange, ImplicitAPI):
29
+
30
+ def describe(self):
31
+ return self.deep_extend(super(cryptocom, self).describe(), {
32
+ 'id': 'cryptocom',
33
+ 'name': 'Crypto.com',
34
+ 'countries': ['MT'],
35
+ 'version': 'v2',
36
+ 'rateLimit': 10, # 100 requests per second
37
+ 'certified': True,
38
+ 'pro': True,
39
+ 'has': {
40
+ 'CORS': False,
41
+ 'spot': True,
42
+ 'margin': True,
43
+ 'swap': True,
44
+ 'future': True,
45
+ 'option': True,
46
+ 'addMargin': False,
47
+ 'cancelAllOrders': True,
48
+ 'cancelOrder': True,
49
+ 'cancelOrders': True,
50
+ 'cancelOrdersForSymbols': True,
51
+ 'closeAllPositions': False,
52
+ 'closePosition': True,
53
+ 'createMarketBuyOrderWithCost': False,
54
+ 'createMarketOrderWithCost': False,
55
+ 'createMarketSellOrderWithCost': False,
56
+ 'createOrder': True,
57
+ 'createOrders': True,
58
+ 'fetchAccounts': True,
59
+ 'fetchBalance': True,
60
+ 'fetchBidsAsks': False,
61
+ 'fetchBorrowInterest': False,
62
+ 'fetchBorrowRateHistories': False,
63
+ 'fetchBorrowRateHistory': False,
64
+ 'fetchClosedOrders': 'emulated',
65
+ 'fetchCrossBorrowRate': False,
66
+ 'fetchCrossBorrowRates': False,
67
+ 'fetchCurrencies': False,
68
+ 'fetchDepositAddress': True,
69
+ 'fetchDepositAddressesByNetwork': True,
70
+ 'fetchDeposits': True,
71
+ 'fetchDepositsWithdrawals': False,
72
+ 'fetchDepositWithdrawFee': 'emulated',
73
+ 'fetchDepositWithdrawFees': True,
74
+ 'fetchFundingHistory': False,
75
+ 'fetchFundingRate': False,
76
+ 'fetchFundingRateHistory': True,
77
+ 'fetchFundingRates': False,
78
+ 'fetchGreeks': False,
79
+ 'fetchIndexOHLCV': False,
80
+ 'fetchIsolatedBorrowRate': False,
81
+ 'fetchIsolatedBorrowRates': False,
82
+ 'fetchLedger': True,
83
+ 'fetchLeverage': False,
84
+ 'fetchLeverageTiers': False,
85
+ 'fetchMarginAdjustmentHistory': False,
86
+ 'fetchMarginMode': False,
87
+ 'fetchMarketLeverageTiers': False,
88
+ 'fetchMarkets': True,
89
+ 'fetchMarkOHLCV': False,
90
+ 'fetchMySettlementHistory': False,
91
+ 'fetchMyTrades': True,
92
+ 'fetchOHLCV': True,
93
+ 'fetchOpenOrders': True,
94
+ 'fetchOrder': True,
95
+ 'fetchOrderBook': True,
96
+ 'fetchOrders': True,
97
+ 'fetchPosition': True,
98
+ 'fetchPositionHistory': False,
99
+ 'fetchPositionMode': False,
100
+ 'fetchPositions': True,
101
+ 'fetchPositionsHistory': False,
102
+ 'fetchPremiumIndexOHLCV': False,
103
+ 'fetchSettlementHistory': True,
104
+ 'fetchStatus': False,
105
+ 'fetchTicker': True,
106
+ 'fetchTickers': True,
107
+ 'fetchTime': False,
108
+ 'fetchTrades': True,
109
+ 'fetchTradingFee': False,
110
+ 'fetchTradingFees': False,
111
+ 'fetchTransactionFees': False,
112
+ 'fetchTransactions': False,
113
+ 'fetchTransfers': False,
114
+ 'fetchUnderlyingAssets': False,
115
+ 'fetchVolatilityHistory': False,
116
+ 'fetchWithdrawals': True,
117
+ 'reduceMargin': False,
118
+ 'repayCrossMargin': False,
119
+ 'repayIsolatedMargin': False,
120
+ 'sandbox': True,
121
+ 'setLeverage': False,
122
+ 'setMarginMode': False,
123
+ 'setPositionMode': False,
124
+ 'transfer': False,
125
+ 'withdraw': True,
126
+ },
127
+ 'timeframes': {
128
+ '1m': '1m',
129
+ '5m': '5m',
130
+ '15m': '15m',
131
+ '30m': '30m',
132
+ '1h': '1h',
133
+ '4h': '4h',
134
+ '6h': '6h',
135
+ '12h': '12h',
136
+ '1d': '1D',
137
+ '1w': '7D',
138
+ '2w': '14D',
139
+ '1M': '1M',
140
+ },
141
+ 'urls': {
142
+ 'logo': 'https://user-images.githubusercontent.com/1294454/147792121-38ed5e36-c229-48d6-b49a-48d05fc19ed4.jpeg',
143
+ 'test': {
144
+ 'v1': 'https://uat-api.3ona.co/exchange/v1',
145
+ 'v2': 'https://uat-api.3ona.co/v2',
146
+ 'derivatives': 'https://uat-api.3ona.co/v2',
147
+ },
148
+ 'api': {
149
+ 'v1': 'https://api.crypto.com/exchange/v1',
150
+ 'v2': 'https://api.crypto.com/v2',
151
+ 'derivatives': 'https://deriv-api.crypto.com/v1',
152
+ },
153
+ 'www': 'https://crypto.com/',
154
+ 'referral': {
155
+ 'url': 'https://crypto.com/exch/kdacthrnxt',
156
+ 'discount': 0.15,
157
+ },
158
+ 'doc': [
159
+ 'https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html',
160
+ 'https://exchange-docs.crypto.com/spot/index.html',
161
+ 'https://exchange-docs.crypto.com/derivatives/index.html',
162
+ ],
163
+ 'fees': 'https://crypto.com/exchange/document/fees-limits',
164
+ },
165
+ 'api': {
166
+ 'v1': {
167
+ 'public': {
168
+ 'get': {
169
+ 'public/auth': 10 / 3,
170
+ 'public/get-instruments': 10 / 3,
171
+ 'public/get-book': 1,
172
+ 'public/get-candlestick': 1,
173
+ 'public/get-trades': 1,
174
+ 'public/get-tickers': 1,
175
+ 'public/get-valuations': 1,
176
+ 'public/get-expired-settlement-price': 10 / 3,
177
+ 'public/get-insurance': 1,
178
+ },
179
+ },
180
+ 'private': {
181
+ 'post': {
182
+ 'private/set-cancel-on-disconnect': 10 / 3,
183
+ 'private/get-cancel-on-disconnect': 10 / 3,
184
+ 'private/user-balance': 10 / 3,
185
+ 'private/user-balance-history': 10 / 3,
186
+ 'private/get-positions': 10 / 3,
187
+ 'private/create-order': 2 / 3,
188
+ 'private/create-order-list': 10 / 3,
189
+ 'private/cancel-order': 2 / 3,
190
+ 'private/cancel-order-list': 10 / 3,
191
+ 'private/cancel-all-orders': 2 / 3,
192
+ 'private/close-position': 10 / 3,
193
+ 'private/get-order-history': 100,
194
+ 'private/get-open-orders': 10 / 3,
195
+ 'private/get-order-detail': 1 / 3,
196
+ 'private/get-trades': 100,
197
+ 'private/change-account-leverage': 10 / 3,
198
+ 'private/get-transactions': 10 / 3,
199
+ 'private/create-subaccount-transfer': 10 / 3,
200
+ 'private/get-subaccount-balances': 10 / 3,
201
+ 'private/get-order-list': 10 / 3,
202
+ 'private/create-withdrawal': 10 / 3,
203
+ 'private/get-currency-networks': 10 / 3,
204
+ 'private/get-deposit-address': 10 / 3,
205
+ 'private/get-accounts': 10 / 3,
206
+ 'private/get-withdrawal-history': 10 / 3,
207
+ 'private/get-deposit-history': 10 / 3,
208
+ },
209
+ },
210
+ },
211
+ 'v2': {
212
+ 'public': {
213
+ 'get': {
214
+ 'public/auth': 1,
215
+ 'public/get-instruments': 1,
216
+ 'public/get-book': 1,
217
+ 'public/get-candlestick': 1,
218
+ 'public/get-ticker': 1,
219
+ 'public/get-trades': 1,
220
+ 'public/margin/get-transfer-currencies': 1,
221
+ 'public/margin/get-load-currenices': 1,
222
+ 'public/respond-heartbeat': 1,
223
+ },
224
+ },
225
+ 'private': {
226
+ 'post': {
227
+ 'private/set-cancel-on-disconnect': 10 / 3,
228
+ 'private/get-cancel-on-disconnect': 10 / 3,
229
+ 'private/create-withdrawal': 10 / 3,
230
+ 'private/get-withdrawal-history': 10 / 3,
231
+ 'private/get-currency-networks': 10 / 3,
232
+ 'private/get-deposit-history': 10 / 3,
233
+ 'private/get-deposit-address': 10 / 3,
234
+ 'private/export/create-export-request': 10 / 3,
235
+ 'private/export/get-export-requests': 10 / 3,
236
+ 'private/export/download-export-output': 10 / 3,
237
+ 'private/get-account-summary': 10 / 3,
238
+ 'private/create-order': 2 / 3,
239
+ 'private/cancel-order': 2 / 3,
240
+ 'private/cancel-all-orders': 2 / 3,
241
+ 'private/create-order-list': 10 / 3,
242
+ 'private/get-order-history': 10 / 3,
243
+ 'private/get-open-orders': 10 / 3,
244
+ 'private/get-order-detail': 1 / 3,
245
+ 'private/get-trades': 100,
246
+ 'private/get-accounts': 10 / 3,
247
+ 'private/get-subaccount-balances': 10 / 3,
248
+ 'private/create-subaccount-transfer': 10 / 3,
249
+ 'private/otc/get-otc-user': 10 / 3,
250
+ 'private/otc/get-instruments': 10 / 3,
251
+ 'private/otc/request-quote': 100,
252
+ 'private/otc/accept-quote': 100,
253
+ 'private/otc/get-quote-history': 10 / 3,
254
+ 'private/otc/get-trade-history': 10 / 3,
255
+ 'private/otc/create-order': 10 / 3,
256
+ },
257
+ },
258
+ },
259
+ 'derivatives': {
260
+ 'public': {
261
+ 'get': {
262
+ 'public/auth': 10 / 3,
263
+ 'public/get-instruments': 10 / 3,
264
+ 'public/get-book': 1,
265
+ 'public/get-candlestick': 1,
266
+ 'public/get-trades': 1,
267
+ 'public/get-tickers': 1,
268
+ 'public/get-valuations': 1,
269
+ 'public/get-expired-settlement-price': 10 / 3,
270
+ 'public/get-insurance': 1,
271
+ },
272
+ },
273
+ 'private': {
274
+ 'post': {
275
+ 'private/set-cancel-on-disconnect': 10 / 3,
276
+ 'private/get-cancel-on-disconnect': 10 / 3,
277
+ 'private/user-balance': 10 / 3,
278
+ 'private/user-balance-history': 10 / 3,
279
+ 'private/get-positions': 10 / 3,
280
+ 'private/create-order': 2 / 3,
281
+ 'private/create-order-list': 10 / 3,
282
+ 'private/cancel-order': 2 / 3,
283
+ 'private/cancel-order-list': 10 / 3,
284
+ 'private/cancel-all-orders': 2 / 3,
285
+ 'private/close-position': 10 / 3,
286
+ 'private/convert-collateral': 10 / 3,
287
+ 'private/get-order-history': 100,
288
+ 'private/get-open-orders': 10 / 3,
289
+ 'private/get-order-detail': 1 / 3,
290
+ 'private/get-trades': 100,
291
+ 'private/change-account-leverage': 10 / 3,
292
+ 'private/get-transactions': 10 / 3,
293
+ 'private/create-subaccount-transfer': 10 / 3,
294
+ 'private/get-subaccount-balances': 10 / 3,
295
+ 'private/get-order-list': 10 / 3,
296
+ },
297
+ },
298
+ },
299
+ },
300
+ 'fees': {
301
+ 'trading': {
302
+ 'maker': self.parse_number('0.004'),
303
+ 'taker': self.parse_number('0.004'),
304
+ 'tiers': {
305
+ 'maker': [
306
+ [self.parse_number('0'), self.parse_number('0.004')],
307
+ [self.parse_number('25000'), self.parse_number('0.0035')],
308
+ [self.parse_number('50000'), self.parse_number('0.0015')],
309
+ [self.parse_number('100000'), self.parse_number('0.001')],
310
+ [self.parse_number('250000'), self.parse_number('0.0009')],
311
+ [self.parse_number('1000000'), self.parse_number('0.0008')],
312
+ [self.parse_number('20000000'), self.parse_number('0.0007')],
313
+ [self.parse_number('100000000'), self.parse_number('0.0006')],
314
+ [self.parse_number('200000000'), self.parse_number('0.0004')],
315
+ ],
316
+ 'taker': [
317
+ [self.parse_number('0'), self.parse_number('0.004')],
318
+ [self.parse_number('25000'), self.parse_number('0.0035')],
319
+ [self.parse_number('50000'), self.parse_number('0.0025')],
320
+ [self.parse_number('100000'), self.parse_number('0.0016')],
321
+ [self.parse_number('250000'), self.parse_number('0.00015')],
322
+ [self.parse_number('1000000'), self.parse_number('0.00014')],
323
+ [self.parse_number('20000000'), self.parse_number('0.00013')],
324
+ [self.parse_number('100000000'), self.parse_number('0.00012')],
325
+ [self.parse_number('200000000'), self.parse_number('0.0001')],
326
+ ],
327
+ },
328
+ },
329
+ },
330
+ 'options': {
331
+ 'defaultType': 'spot',
332
+ 'accountsById': {
333
+ 'funding': 'SPOT',
334
+ 'spot': 'SPOT',
335
+ 'margin': 'MARGIN',
336
+ 'derivatives': 'DERIVATIVES',
337
+ 'swap': 'DERIVATIVES',
338
+ 'future': 'DERIVATIVES',
339
+ },
340
+ 'networks': {
341
+ 'BEP20': 'BSC',
342
+ 'ERC20': 'ETH',
343
+ 'TRC20': 'TRON',
344
+ },
345
+ 'broker': 'CCXT',
346
+ },
347
+ # https://exchange-docs.crypto.com/spot/index.html#response-and-reason-codes
348
+ 'commonCurrencies': {
349
+ 'USD_STABLE_COIN': 'USDC',
350
+ },
351
+ 'precisionMode': TICK_SIZE,
352
+ 'exceptions': {
353
+ 'exact': {
354
+ '219': InvalidOrder,
355
+ '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
356
+ '10001': ExchangeError,
357
+ '10002': PermissionDenied,
358
+ '10003': PermissionDenied,
359
+ '10004': BadRequest,
360
+ '10005': PermissionDenied,
361
+ '10006': DDoSProtection,
362
+ '10007': InvalidNonce,
363
+ '10008': BadRequest,
364
+ '10009': BadRequest,
365
+ '20001': BadRequest,
366
+ '20002': InsufficientFunds,
367
+ '20005': AccountNotEnabled, # {"id":"123xxx","method":"private/margin/xxx","code":"20005","message":"ACCOUNT_NOT_FOUND"}
368
+ '30003': BadSymbol,
369
+ '30004': BadRequest,
370
+ '30005': BadRequest,
371
+ '30006': InvalidOrder,
372
+ '30007': InvalidOrder,
373
+ '30008': InvalidOrder,
374
+ '30009': InvalidOrder,
375
+ '30010': BadRequest,
376
+ '30013': InvalidOrder,
377
+ '30014': InvalidOrder,
378
+ '30016': InvalidOrder,
379
+ '30017': InvalidOrder,
380
+ '30023': InvalidOrder,
381
+ '30024': InvalidOrder,
382
+ '30025': InvalidOrder,
383
+ '40001': BadRequest,
384
+ '40002': BadRequest,
385
+ '40003': BadRequest,
386
+ '40004': BadRequest,
387
+ '40005': BadRequest,
388
+ '40006': BadRequest,
389
+ '40007': BadRequest,
390
+ '40101': AuthenticationError,
391
+ '50001': BadRequest,
392
+ '9010001': OnMaintenance, # {"code":9010001,"message":"SYSTEM_MAINTENANCE","details":"Crypto.com Exchange is currently under maintenance. Please refer to https://status.crypto.com for more details."}
393
+ },
394
+ 'broad': {},
395
+ },
396
+ })
397
+
398
+ async def fetch_markets(self, params={}) -> List[Market]:
399
+ """
400
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-instruments
401
+ retrieves data on all markets for cryptocom
402
+ :param dict [params]: extra parameters specific to the exchange API endpoint
403
+ :returns dict[]: an array of objects representing market data
404
+ """
405
+ response = await self.v1PublicGetPublicGetInstruments(params)
406
+ #
407
+ # {
408
+ # "id": 1,
409
+ # "method": "public/get-instruments",
410
+ # "code": 0,
411
+ # "result": {
412
+ # "data": [
413
+ # {
414
+ # "symbol": "BTC_USDT",
415
+ # "inst_type": "CCY_PAIR",
416
+ # "display_name": "BTC/USDT",
417
+ # "base_ccy": "BTC",
418
+ # "quote_ccy": "USDT",
419
+ # "quote_decimals": 2,
420
+ # "quantity_decimals": 5,
421
+ # "price_tick_size": "0.01",
422
+ # "qty_tick_size": "0.00001",
423
+ # "max_leverage": "50",
424
+ # "tradable": True,
425
+ # "expiry_timestamp_ms": 0,
426
+ # "beta_product": False,
427
+ # "margin_buy_enabled": False,
428
+ # "margin_sell_enabled": True
429
+ # },
430
+ # {
431
+ # "symbol": "RUNEUSD-PERP",
432
+ # "inst_type": "PERPETUAL_SWAP",
433
+ # "display_name": "RUNEUSD Perpetual",
434
+ # "base_ccy": "RUNE",
435
+ # "quote_ccy": "USD",
436
+ # "quote_decimals": 3,
437
+ # "quantity_decimals": 1,
438
+ # "price_tick_size": "0.001",
439
+ # "qty_tick_size": "0.1",
440
+ # "max_leverage": "50",
441
+ # "tradable": True,
442
+ # "expiry_timestamp_ms": 0,
443
+ # "beta_product": False,
444
+ # "underlying_symbol": "RUNEUSD-INDEX",
445
+ # "contract_size": "1",
446
+ # "margin_buy_enabled": False,
447
+ # "margin_sell_enabled": False
448
+ # },
449
+ # {
450
+ # "symbol": "ETHUSD-230825",
451
+ # "inst_type": "FUTURE",
452
+ # "display_name": "ETHUSD Futures 20230825",
453
+ # "base_ccy": "ETH",
454
+ # "quote_ccy": "USD",
455
+ # "quote_decimals": 2,
456
+ # "quantity_decimals": 4,
457
+ # "price_tick_size": "0.01",
458
+ # "qty_tick_size": "0.0001",
459
+ # "max_leverage": "100",
460
+ # "tradable": True,
461
+ # "expiry_timestamp_ms": 1692950400000,
462
+ # "beta_product": False,
463
+ # "underlying_symbol": "ETHUSD-INDEX",
464
+ # "contract_size": "1",
465
+ # "margin_buy_enabled": False,
466
+ # "margin_sell_enabled": False
467
+ # },
468
+ # {
469
+ # "symbol": "BTCUSD-230630-CW30000",
470
+ # "inst_type": "WARRANT",
471
+ # "display_name": "BTCUSD-230630-CW30000",
472
+ # "base_ccy": "BTC",
473
+ # "quote_ccy": "USD",
474
+ # "quote_decimals": 3,
475
+ # "quantity_decimals": 0,
476
+ # "price_tick_size": "0.001",
477
+ # "qty_tick_size": "10",
478
+ # "max_leverage": "50",
479
+ # "tradable": True,
480
+ # "expiry_timestamp_ms": 1688112000000,
481
+ # "beta_product": False,
482
+ # "underlying_symbol": "BTCUSD-INDEX",
483
+ # "put_call": "CALL",
484
+ # "strike": "30000",
485
+ # "contract_size": "0.0001",
486
+ # "margin_buy_enabled": False,
487
+ # "margin_sell_enabled": False
488
+ # },
489
+ # ]
490
+ # }
491
+ # }
492
+ #
493
+ resultResponse = self.safe_value(response, 'result', {})
494
+ data = self.safe_value(resultResponse, 'data', [])
495
+ result = []
496
+ for i in range(0, len(data)):
497
+ market = data[i]
498
+ inst_type = self.safe_string(market, 'inst_type')
499
+ spot = inst_type == 'CCY_PAIR'
500
+ swap = inst_type == 'PERPETUAL_SWAP'
501
+ future = inst_type == 'FUTURE'
502
+ option = inst_type == 'WARRANT'
503
+ baseId = self.safe_string(market, 'base_ccy')
504
+ quoteId = self.safe_string(market, 'quote_ccy')
505
+ settleId = None if spot else quoteId
506
+ base = self.safe_currency_code(baseId)
507
+ quote = self.safe_currency_code(quoteId)
508
+ settle = None if spot else self.safe_currency_code(settleId)
509
+ optionType = self.safe_string_lower(market, 'put_call')
510
+ strike = self.safe_string(market, 'strike')
511
+ marginBuyEnabled = self.safe_value(market, 'margin_buy_enabled')
512
+ marginSellEnabled = self.safe_value(market, 'margin_sell_enabled')
513
+ expiryString = self.omit_zero(self.safe_string(market, 'expiry_timestamp_ms'))
514
+ expiry = int(expiryString) if (expiryString is not None) else None
515
+ symbol = base + '/' + quote
516
+ type = None
517
+ contract = None
518
+ if inst_type == 'CCY_PAIR':
519
+ type = 'spot'
520
+ contract = False
521
+ elif inst_type == 'PERPETUAL_SWAP':
522
+ type = 'swap'
523
+ symbol = symbol + ':' + quote
524
+ contract = True
525
+ elif inst_type == 'FUTURE':
526
+ type = 'future'
527
+ symbol = symbol + ':' + quote + '-' + self.yymmdd(expiry)
528
+ contract = True
529
+ elif inst_type == 'WARRANT':
530
+ type = 'option'
531
+ symbolOptionType = 'C' if (optionType == 'call') else 'P'
532
+ symbol = symbol + ':' + quote + '-' + self.yymmdd(expiry) + '-' + strike + '-' + symbolOptionType
533
+ contract = True
534
+ result.append({
535
+ 'id': self.safe_string(market, 'symbol'),
536
+ 'symbol': symbol,
537
+ 'base': base,
538
+ 'quote': quote,
539
+ 'settle': settle,
540
+ 'baseId': baseId,
541
+ 'quoteId': quoteId,
542
+ 'settleId': settleId,
543
+ 'type': type,
544
+ 'spot': spot,
545
+ 'margin': ((marginBuyEnabled) or (marginSellEnabled)),
546
+ 'swap': swap,
547
+ 'future': future,
548
+ 'option': option,
549
+ 'active': self.safe_value(market, 'tradable'),
550
+ 'contract': contract,
551
+ 'linear': True if (contract) else None,
552
+ 'inverse': False if (contract) else None,
553
+ 'contractSize': self.safe_number(market, 'contract_size'),
554
+ 'expiry': expiry,
555
+ 'expiryDatetime': self.iso8601(expiry),
556
+ 'strike': self.parse_number(strike),
557
+ 'optionType': optionType,
558
+ 'precision': {
559
+ 'price': self.parse_number(self.safe_string(market, 'price_tick_size')),
560
+ 'amount': self.parse_number(self.safe_string(market, 'qty_tick_size')),
561
+ },
562
+ 'limits': {
563
+ 'leverage': {
564
+ 'min': self.parse_number('1'),
565
+ 'max': self.safe_number(market, 'max_leverage'),
566
+ },
567
+ 'amount': {
568
+ 'min': None,
569
+ 'max': None,
570
+ },
571
+ 'price': {
572
+ 'min': None,
573
+ 'max': None,
574
+ },
575
+ 'cost': {
576
+ 'min': None,
577
+ 'max': None,
578
+ },
579
+ },
580
+ 'created': None,
581
+ 'info': market,
582
+ })
583
+ return result
584
+
585
+ async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
586
+ """
587
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
588
+ :see: https://exchange-docs.crypto.com/spot/index.html#public-get-ticker
589
+ :see: https://exchange-docs.crypto.com/derivatives/index.html#public-get-tickers
590
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
591
+ :param dict [params]: extra parameters specific to the exchange API endpoint
592
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
593
+ """
594
+ await self.load_markets()
595
+ market = None
596
+ request: dict = {}
597
+ if symbols is not None:
598
+ symbol = None
599
+ if isinstance(symbols, list):
600
+ symbolsLength = len(symbols)
601
+ if symbolsLength > 1:
602
+ raise BadRequest(self.id + ' fetchTickers() symbols argument cannot contain more than 1 symbol')
603
+ symbol = symbols[0]
604
+ else:
605
+ symbol = symbols
606
+ market = self.market(symbol)
607
+ request['instrument_name'] = market['id']
608
+ response = await self.v1PublicGetPublicGetTickers(self.extend(request, params))
609
+ #
610
+ # {
611
+ # "id": -1,
612
+ # "method": "public/get-tickers",
613
+ # "code": 0,
614
+ # "result": {
615
+ # "data": [
616
+ # {
617
+ # "i": "AVAXUSD-PERP",
618
+ # "h": "13.209",
619
+ # "l": "12.148",
620
+ # "a": "13.209",
621
+ # "v": "1109.8",
622
+ # "vv": "14017.33",
623
+ # "c": "0.0732",
624
+ # "b": "13.210",
625
+ # "k": "13.230",
626
+ # "oi": "10888.9",
627
+ # "t": 1687402657575
628
+ # },
629
+ # ]
630
+ # }
631
+ # }
632
+ #
633
+ result = self.safe_value(response, 'result', {})
634
+ data = self.safe_list(result, 'data', [])
635
+ return self.parse_tickers(data, symbols)
636
+
637
+ async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
638
+ """
639
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-tickers
640
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
641
+ :param str symbol: unified symbol of the market to fetch the ticker for
642
+ :param dict [params]: extra parameters specific to the exchange API endpoint
643
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
644
+ """
645
+ await self.load_markets()
646
+ symbol = self.symbol(symbol)
647
+ tickers = await self.fetch_tickers([symbol], params)
648
+ return self.safe_value(tickers, symbol)
649
+
650
+ async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
651
+ """
652
+ fetches information on multiple orders made by the user
653
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-order-history
654
+ :param str symbol: unified market symbol of the market the orders were made in
655
+ :param int [since]: the earliest time in ms to fetch orders for, max date range is one day
656
+ :param int [limit]: the maximum number of order structures to retrieve, default 100 max 100
657
+ :param dict [params]: extra parameters specific to the exchange API endpoint
658
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
659
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
660
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
661
+ """
662
+ await self.load_markets()
663
+ paginate = False
664
+ paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
665
+ if paginate:
666
+ return await self.fetch_paginated_call_dynamic('fetchOrders', symbol, since, limit, params)
667
+ market = None
668
+ request: dict = {}
669
+ if symbol is not None:
670
+ market = self.market(symbol)
671
+ request['instrument_name'] = market['id']
672
+ if since is not None:
673
+ request['start_time'] = since
674
+ if limit is not None:
675
+ request['limit'] = limit
676
+ until = self.safe_integer(params, 'until')
677
+ params = self.omit(params, ['until'])
678
+ if until is not None:
679
+ request['end_time'] = until
680
+ response = await self.v1PrivatePostPrivateGetOrderHistory(self.extend(request, params))
681
+ #
682
+ # {
683
+ # "id": 1686881486183,
684
+ # "method": "private/get-order-history",
685
+ # "code": 0,
686
+ # "result": {
687
+ # "data": [
688
+ # {
689
+ # "account_id": "ce075bef-1234-4321-bd6g-ff9007252e63",
690
+ # "order_id": "6142909895014042762",
691
+ # "client_oid": "4e918597-1234-4321-8201-a7577e1e1d91",
692
+ # "order_type": "MARKET",
693
+ # "time_in_force": "GOOD_TILL_CANCEL",
694
+ # "side": "SELL",
695
+ # "exec_inst": [],
696
+ # "quantity": "0.00024",
697
+ # "order_value": "5.7054672",
698
+ # "maker_fee_rate": "0",
699
+ # "taker_fee_rate": "0",
700
+ # "avg_price": "25023.97",
701
+ # "trigger_price": "0",
702
+ # "ref_price": "0",
703
+ # "ref_price_type": "NULL_VAL",
704
+ # "cumulative_quantity": "0.00024",
705
+ # "cumulative_value": "6.0057528",
706
+ # "cumulative_fee": "0.001501438200",
707
+ # "status": "FILLED",
708
+ # "update_user_id": "ce075bef-1234-4321-bd6g-ff9007252e63",
709
+ # "order_date": "2023-06-15",
710
+ # "instrument_name": "BTC_USD",
711
+ # "fee_instrument_name": "USD",
712
+ # "create_time": 1686805465891,
713
+ # "create_time_ns": "1686805465891812578",
714
+ # "update_time": 1686805465891
715
+ # }
716
+ # ]
717
+ # }
718
+ # }
719
+ #
720
+ data = self.safe_value(response, 'result', {})
721
+ orders = self.safe_list(data, 'data', [])
722
+ return self.parse_orders(orders, market, since, limit)
723
+
724
+ async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
725
+ """
726
+ get a list of the most recent trades for a particular symbol
727
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-trades
728
+ :param str symbol: unified symbol of the market to fetch trades for
729
+ :param int [since]: timestamp in ms of the earliest trade to fetch, maximum date range is one day
730
+ :param int [limit]: the maximum number of trades to fetch
731
+ :param dict [params]: extra parameters specific to the exchange API endpoint
732
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
733
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
734
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
735
+ """
736
+ await self.load_markets()
737
+ paginate = False
738
+ paginate, params = self.handle_option_and_params(params, 'fetchTrades', 'paginate')
739
+ if paginate:
740
+ return await self.fetch_paginated_call_dynamic('fetchTrades', symbol, since, limit, params)
741
+ market = self.market(symbol)
742
+ request: dict = {
743
+ 'instrument_name': market['id'],
744
+ }
745
+ if since is not None:
746
+ request['start_ts'] = since
747
+ if limit is not None:
748
+ request['count'] = limit
749
+ until = self.safe_integer(params, 'until')
750
+ params = self.omit(params, ['until'])
751
+ if until is not None:
752
+ request['end_ts'] = until
753
+ response = await self.v1PublicGetPublicGetTrades(self.extend(request, params))
754
+ #
755
+ # {
756
+ # "id": -1,
757
+ # "method": "public/get-trades",
758
+ # "code": 0,
759
+ # "result": {
760
+ # "data": [
761
+ # {
762
+ # "s": "sell",
763
+ # "p": "26386.00",
764
+ # "q": "0.00453",
765
+ # "t": 1686944282062,
766
+ # "tn" : 1704476468851524373,
767
+ # "d": "4611686018455979970",
768
+ # "i": "BTC_USD"
769
+ # },
770
+ # ]
771
+ # }
772
+ # }
773
+ #
774
+ result = self.safe_value(response, 'result', {})
775
+ trades = self.safe_list(result, 'data', [])
776
+ return self.parse_trades(trades, market, since, limit)
777
+
778
+ async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
779
+ """
780
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
781
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-candlestick
782
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
783
+ :param str timeframe: the length of time each candle represents
784
+ :param int [since]: timestamp in ms of the earliest candle to fetch
785
+ :param int [limit]: the maximum amount of candles to fetch
786
+ :param dict [params]: extra parameters specific to the exchange API endpoint
787
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
788
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
789
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
790
+ """
791
+ await self.load_markets()
792
+ paginate = False
793
+ paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate', False)
794
+ if paginate:
795
+ return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 300)
796
+ market = self.market(symbol)
797
+ request: dict = {
798
+ 'instrument_name': market['id'],
799
+ 'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
800
+ }
801
+ if since is not None:
802
+ request['start_ts'] = since
803
+ if limit is not None:
804
+ request['count'] = limit
805
+ until = self.safe_integer(params, 'until')
806
+ params = self.omit(params, ['until'])
807
+ if until is not None:
808
+ request['end_ts'] = until
809
+ response = await self.v1PublicGetPublicGetCandlestick(self.extend(request, params))
810
+ #
811
+ # {
812
+ # "id": -1,
813
+ # "method": "public/get-candlestick",
814
+ # "code": 0,
815
+ # "result": {
816
+ # "interval": "1m",
817
+ # "data": [
818
+ # {
819
+ # "o": "26949.89",
820
+ # "h": "26957.64",
821
+ # "l": "26948.24",
822
+ # "c": "26950.00",
823
+ # "v": "0.0670",
824
+ # "t": 1687237080000
825
+ # },
826
+ # ],
827
+ # "instrument_name": "BTC_USD"
828
+ # }
829
+ # }
830
+ #
831
+ result = self.safe_value(response, 'result', {})
832
+ data = self.safe_list(result, 'data', [])
833
+ return self.parse_ohlcvs(data, market, timeframe, since, limit)
834
+
835
+ async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
836
+ """
837
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
838
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-book
839
+ :param str symbol: unified symbol of the market to fetch the order book for
840
+ :param int [limit]: the number of order book entries to return, max 50
841
+ :param dict [params]: extra parameters specific to the exchange API endpoint
842
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
843
+ """
844
+ await self.load_markets()
845
+ market = self.market(symbol)
846
+ request: dict = {
847
+ 'instrument_name': market['id'],
848
+ }
849
+ if limit:
850
+ request['depth'] = limit
851
+ response = await self.v1PublicGetPublicGetBook(self.extend(request, params))
852
+ #
853
+ # {
854
+ # "id": -1,
855
+ # "method": "public/get-book",
856
+ # "code": 0,
857
+ # "result": {
858
+ # "depth": 3,
859
+ # "data": [
860
+ # {
861
+ # "bids": [["30025.00", "0.00004", "1"], ["30020.15", "0.02498", "1"], ["30020.00", "0.00004", "1"]],
862
+ # "asks": [["30025.01", "0.04090", "1"], ["30025.70", "0.01000", "1"], ["30026.94", "0.02681", "1"]],
863
+ # "t": 1687491287380
864
+ # }
865
+ # ],
866
+ # "instrument_name": "BTC_USD"
867
+ # }
868
+ # }
869
+ #
870
+ result = self.safe_value(response, 'result', {})
871
+ data = self.safe_value(result, 'data', [])
872
+ orderBook = self.safe_value(data, 0)
873
+ timestamp = self.safe_integer(orderBook, 't')
874
+ return self.parse_order_book(orderBook, symbol, timestamp)
875
+
876
+ def parse_balance(self, response) -> Balances:
877
+ responseResult = self.safe_value(response, 'result', {})
878
+ data = self.safe_value(responseResult, 'data', [])
879
+ positionBalances = self.safe_value(data[0], 'position_balances', [])
880
+ result: dict = {'info': response}
881
+ for i in range(0, len(positionBalances)):
882
+ balance = positionBalances[i]
883
+ currencyId = self.safe_string(balance, 'instrument_name')
884
+ code = self.safe_currency_code(currencyId)
885
+ account = self.account()
886
+ account['total'] = self.safe_string(balance, 'quantity')
887
+ account['used'] = self.safe_string(balance, 'reserved_qty')
888
+ result[code] = account
889
+ return self.safe_balance(result)
890
+
891
+ async def fetch_balance(self, params={}) -> Balances:
892
+ """
893
+ query for balance and get the amount of funds available for trading or funds locked in orders
894
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-user-balance
895
+ :param dict [params]: extra parameters specific to the exchange API endpoint
896
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
897
+ """
898
+ await self.load_markets()
899
+ response = await self.v1PrivatePostPrivateUserBalance(params)
900
+ #
901
+ # {
902
+ # "id": 1687300499018,
903
+ # "method": "private/user-balance",
904
+ # "code": 0,
905
+ # "result": {
906
+ # "data": [
907
+ # {
908
+ # "total_available_balance": "5.84684368",
909
+ # "total_margin_balance": "5.84684368",
910
+ # "total_initial_margin": "0",
911
+ # "total_maintenance_margin": "0",
912
+ # "total_position_cost": "0",
913
+ # "total_cash_balance": "6.44412101",
914
+ # "total_collateral_value": "5.846843685",
915
+ # "total_session_unrealized_pnl": "0",
916
+ # "instrument_name": "USD",
917
+ # "total_session_realized_pnl": "0",
918
+ # "position_balances": [
919
+ # {
920
+ # "quantity": "0.0002119875",
921
+ # "reserved_qty": "0",
922
+ # "collateral_weight": "0.9",
923
+ # "collateral_amount": "5.37549592",
924
+ # "market_value": "5.97277325",
925
+ # "max_withdrawal_balance": "0.00021198",
926
+ # "instrument_name": "BTC",
927
+ # "hourly_interest_rate": "0"
928
+ # },
929
+ # ],
930
+ # "total_effective_leverage": "0",
931
+ # "position_limit": "3000000",
932
+ # "used_position_limit": "0",
933
+ # "total_borrow": "0",
934
+ # "margin_score": "0",
935
+ # "is_liquidating": False,
936
+ # "has_risk": False,
937
+ # "terminatable": True
938
+ # }
939
+ # ]
940
+ # }
941
+ # }
942
+ #
943
+ return self.parse_balance(response)
944
+
945
+ async def fetch_order(self, id: str, symbol: Str = None, params={}):
946
+ """
947
+ fetches information on an order made by the user
948
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-order-detail
949
+ :param str symbol: unified symbol of the market the order was made in
950
+ :param dict [params]: extra parameters specific to the exchange API endpoint
951
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
952
+ """
953
+ await self.load_markets()
954
+ market = None
955
+ if symbol is not None:
956
+ market = self.market(symbol)
957
+ request: dict = {
958
+ 'order_id': id,
959
+ }
960
+ response = await self.v1PrivatePostPrivateGetOrderDetail(self.extend(request, params))
961
+ #
962
+ # {
963
+ # "id": 1686872583882,
964
+ # "method": "private/get-order-detail",
965
+ # "code": 0,
966
+ # "result": {
967
+ # "account_id": "ae075bef-1234-4321-bd6g-bb9007252a63",
968
+ # "order_id": "6142909895025252686",
969
+ # "client_oid": "CCXT_c2d2152cc32d40a3ae7fbf",
970
+ # "order_type": "LIMIT",
971
+ # "time_in_force": "GOOD_TILL_CANCEL",
972
+ # "side": "BUY",
973
+ # "exec_inst": [],
974
+ # "quantity": "0.00020",
975
+ # "limit_price": "20000.00",
976
+ # "order_value": "4",
977
+ # "avg_price": "0",
978
+ # "trigger_price": "0",
979
+ # "ref_price": "0",
980
+ # "cumulative_quantity": "0",
981
+ # "cumulative_value": "0",
982
+ # "cumulative_fee": "0",
983
+ # "status": "ACTIVE",
984
+ # "update_user_id": "ae075bef-1234-4321-bd6g-bb9007252a63",
985
+ # "order_date": "2023-06-15",
986
+ # "instrument_name": "BTC_USD",
987
+ # "fee_instrument_name": "BTC",
988
+ # "create_time": 1686870220684,
989
+ # "create_time_ns": "1686870220684239675",
990
+ # "update_time": 1686870220684
991
+ # }
992
+ # }
993
+ #
994
+ order = self.safe_dict(response, 'result', {})
995
+ return self.parse_order(order, market)
996
+
997
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
998
+ market = self.market(symbol)
999
+ uppercaseType = type.upper()
1000
+ request: dict = {
1001
+ 'instrument_name': market['id'],
1002
+ 'side': side.upper(),
1003
+ 'quantity': self.amount_to_precision(symbol, amount),
1004
+ }
1005
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1006
+ request['price'] = self.price_to_precision(symbol, price)
1007
+ broker = self.safe_string(self.options, 'broker', 'CCXT')
1008
+ request['broker_id'] = broker
1009
+ marketType = None
1010
+ marginMode = None
1011
+ marketType, params = self.handle_market_type_and_params('createOrder', market, params)
1012
+ marginMode, params = self.custom_handle_margin_mode_and_params('createOrder', params)
1013
+ if (marketType == 'margin') or (marginMode is not None):
1014
+ request['spot_margin'] = 'MARGIN'
1015
+ elif marketType == 'spot':
1016
+ request['spot_margin'] = 'SPOT'
1017
+ timeInForce = self.safe_string_upper_2(params, 'timeInForce', 'time_in_force')
1018
+ if timeInForce is not None:
1019
+ if timeInForce == 'GTC':
1020
+ request['time_in_force'] = 'GOOD_TILL_CANCEL'
1021
+ elif timeInForce == 'IOC':
1022
+ request['time_in_force'] = 'IMMEDIATE_OR_CANCEL'
1023
+ elif timeInForce == 'FOK':
1024
+ request['time_in_force'] = 'FILL_OR_KILL'
1025
+ else:
1026
+ request['time_in_force'] = timeInForce
1027
+ postOnly = self.safe_bool(params, 'postOnly', False)
1028
+ if (postOnly) or (timeInForce == 'PO'):
1029
+ request['exec_inst'] = ['POST_ONLY']
1030
+ request['time_in_force'] = 'GOOD_TILL_CANCEL'
1031
+ triggerPrice = self.safe_string_n(params, ['stopPrice', 'triggerPrice', 'ref_price'])
1032
+ stopLossPrice = self.safe_number(params, 'stopLossPrice')
1033
+ takeProfitPrice = self.safe_number(params, 'takeProfitPrice')
1034
+ isTrigger = (triggerPrice is not None)
1035
+ isStopLossTrigger = (stopLossPrice is not None)
1036
+ isTakeProfitTrigger = (takeProfitPrice is not None)
1037
+ if isTrigger:
1038
+ request['ref_price'] = self.price_to_precision(symbol, triggerPrice)
1039
+ priceString = self.number_to_string(price)
1040
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1041
+ if side == 'buy':
1042
+ if Precise.string_lt(priceString, triggerPrice):
1043
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1044
+ else:
1045
+ request['type'] = 'STOP_LIMIT'
1046
+ else:
1047
+ if Precise.string_lt(priceString, triggerPrice):
1048
+ request['type'] = 'STOP_LIMIT'
1049
+ else:
1050
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1051
+ else:
1052
+ if side == 'buy':
1053
+ if Precise.string_lt(priceString, triggerPrice):
1054
+ request['type'] = 'TAKE_PROFIT'
1055
+ else:
1056
+ request['type'] = 'STOP_LOSS'
1057
+ else:
1058
+ if Precise.string_lt(priceString, triggerPrice):
1059
+ request['type'] = 'STOP_LOSS'
1060
+ else:
1061
+ request['type'] = 'TAKE_PROFIT'
1062
+ elif isStopLossTrigger:
1063
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT'):
1064
+ request['type'] = 'STOP_LIMIT'
1065
+ else:
1066
+ request['type'] = 'STOP_LOSS'
1067
+ request['ref_price'] = self.price_to_precision(symbol, stopLossPrice)
1068
+ elif isTakeProfitTrigger:
1069
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1070
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1071
+ else:
1072
+ request['type'] = 'TAKE_PROFIT'
1073
+ request['ref_price'] = self.price_to_precision(symbol, takeProfitPrice)
1074
+ else:
1075
+ request['type'] = uppercaseType
1076
+ params = self.omit(params, ['postOnly', 'clientOrderId', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1077
+ return self.extend(request, params)
1078
+
1079
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1080
+ """
1081
+ create a trade order
1082
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order
1083
+ :param str symbol: unified symbol of the market to create an order in
1084
+ :param str type: 'market', 'limit', 'stop_loss', 'stop_limit', 'take_profit', 'take_profit_limit'
1085
+ :param str side: 'buy' or 'sell'
1086
+ :param float amount: how much you want to trade in units of base currency
1087
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1088
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1089
+ :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK' or 'PO'
1090
+ :param str [params.ref_price_type]: 'MARK_PRICE', 'INDEX_PRICE', 'LAST_PRICE' which trigger price type to use, default is MARK_PRICE
1091
+ :param float [params.stopPrice]: price to trigger a stop order
1092
+ :param float [params.stopLossPrice]: price to trigger a stop-loss trigger order
1093
+ :param float [params.takeProfitPrice]: price to trigger a take-profit trigger order
1094
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1095
+ """
1096
+ await self.load_markets()
1097
+ market = self.market(symbol)
1098
+ request = self.create_order_request(symbol, type, side, amount, price, params)
1099
+ response = await self.v1PrivatePostPrivateCreateOrder(request)
1100
+ #
1101
+ # {
1102
+ # "id": 1686804664362,
1103
+ # "method": "private/create-order",
1104
+ # "code" : 0,
1105
+ # "result": {
1106
+ # "order_id": "6540219377766741832",
1107
+ # "client_oid": "CCXT_d6ef7c3db6c1495aa8b757"
1108
+ # }
1109
+ # }
1110
+ #
1111
+ result = self.safe_dict(response, 'result', {})
1112
+ return self.parse_order(result, market)
1113
+
1114
+ async def create_orders(self, orders: List[OrderRequest], params={}):
1115
+ """
1116
+ create a list of trade orders
1117
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-list
1118
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-oco
1119
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1120
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1121
+ """
1122
+ await self.load_markets()
1123
+ ordersRequests = []
1124
+ for i in range(0, len(orders)):
1125
+ rawOrder = orders[i]
1126
+ marketId = self.safe_string(rawOrder, 'symbol')
1127
+ type = self.safe_string(rawOrder, 'type')
1128
+ side = self.safe_string(rawOrder, 'side')
1129
+ amount = self.safe_value(rawOrder, 'amount')
1130
+ price = self.safe_value(rawOrder, 'price')
1131
+ orderParams = self.safe_value(rawOrder, 'params', {})
1132
+ orderRequest = self.create_advanced_order_request(marketId, type, side, amount, price, orderParams)
1133
+ ordersRequests.append(orderRequest)
1134
+ contigency = self.safe_string(params, 'contingency_type', 'LIST')
1135
+ request: dict = {
1136
+ 'contingency_type': contigency, # or OCO
1137
+ 'order_list': ordersRequests,
1138
+ }
1139
+ response = await self.v1PrivatePostPrivateCreateOrderList(self.extend(request, params))
1140
+ #
1141
+ # {
1142
+ # "id": 12,
1143
+ # "method": "private/create-order-list",
1144
+ # "code": 10001,
1145
+ # "result": {
1146
+ # "result_list": [
1147
+ # {
1148
+ # "index": 0,
1149
+ # "code": 0,
1150
+ # "order_id": "2015106383706015873",
1151
+ # "client_oid": "my_order_0001"
1152
+ # },
1153
+ # {
1154
+ # "index": 1,
1155
+ # "code": 20007,
1156
+ # "message": "INVALID_REQUEST",
1157
+ # "client_oid": "my_order_0002"
1158
+ # }
1159
+ # ]
1160
+ # }
1161
+ # }
1162
+ #
1163
+ # {
1164
+ # "id" : 1698068111133,
1165
+ # "method" : "private/create-order-list",
1166
+ # "code" : 0,
1167
+ # "result" : [{
1168
+ # "code" : 0,
1169
+ # "index" : 0,
1170
+ # "client_oid" : "1698068111133_0",
1171
+ # "order_id" : "6142909896519488206"
1172
+ # }, {
1173
+ # "code" : 306,
1174
+ # "index" : 1,
1175
+ # "client_oid" : "1698068111133_1",
1176
+ # "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
1177
+ # "order_id" : "6142909896519488207"
1178
+ # }]
1179
+ # }
1180
+ #
1181
+ result = self.safe_value(response, 'result', [])
1182
+ listId = self.safe_string(result, 'list_id')
1183
+ if listId is not None:
1184
+ ocoOrders = [{'order_id': listId}]
1185
+ return self.parse_orders(ocoOrders)
1186
+ return self.parse_orders(result)
1187
+
1188
+ def create_advanced_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1189
+ # differs slightly from createOrderRequest
1190
+ # since the advanced order endpoint requires a different set of parameters
1191
+ # namely here we don't support ref_price or spot_margin
1192
+ # and market-buy orders need to send notional instead of quantity
1193
+ market = self.market(symbol)
1194
+ uppercaseType = type.upper()
1195
+ request: dict = {
1196
+ 'instrument_name': market['id'],
1197
+ 'side': side.upper(),
1198
+ }
1199
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1200
+ request['price'] = self.price_to_precision(symbol, price)
1201
+ broker = self.safe_string(self.options, 'broker', 'CCXT')
1202
+ request['broker_id'] = broker
1203
+ timeInForce = self.safe_string_upper_2(params, 'timeInForce', 'time_in_force')
1204
+ if timeInForce is not None:
1205
+ if timeInForce == 'GTC':
1206
+ request['time_in_force'] = 'GOOD_TILL_CANCEL'
1207
+ elif timeInForce == 'IOC':
1208
+ request['time_in_force'] = 'IMMEDIATE_OR_CANCEL'
1209
+ elif timeInForce == 'FOK':
1210
+ request['time_in_force'] = 'FILL_OR_KILL'
1211
+ else:
1212
+ request['time_in_force'] = timeInForce
1213
+ postOnly = self.safe_bool(params, 'postOnly', False)
1214
+ if (postOnly) or (timeInForce == 'PO'):
1215
+ request['exec_inst'] = ['POST_ONLY']
1216
+ request['time_in_force'] = 'GOOD_TILL_CANCEL'
1217
+ triggerPrice = self.safe_string_n(params, ['stopPrice', 'triggerPrice', 'ref_price'])
1218
+ stopLossPrice = self.safe_number(params, 'stopLossPrice')
1219
+ takeProfitPrice = self.safe_number(params, 'takeProfitPrice')
1220
+ isTrigger = (triggerPrice is not None)
1221
+ isStopLossTrigger = (stopLossPrice is not None)
1222
+ isTakeProfitTrigger = (takeProfitPrice is not None)
1223
+ if isTrigger:
1224
+ priceString = self.number_to_string(price)
1225
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1226
+ if side == 'buy':
1227
+ if Precise.string_lt(priceString, triggerPrice):
1228
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1229
+ else:
1230
+ request['type'] = 'STOP_LIMIT'
1231
+ else:
1232
+ if Precise.string_lt(priceString, triggerPrice):
1233
+ request['type'] = 'STOP_LIMIT'
1234
+ else:
1235
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1236
+ else:
1237
+ if side == 'buy':
1238
+ if Precise.string_lt(priceString, triggerPrice):
1239
+ request['type'] = 'TAKE_PROFIT'
1240
+ else:
1241
+ request['type'] = 'STOP_LOSS'
1242
+ else:
1243
+ if Precise.string_lt(priceString, triggerPrice):
1244
+ request['type'] = 'STOP_LOSS'
1245
+ else:
1246
+ request['type'] = 'TAKE_PROFIT'
1247
+ elif isStopLossTrigger:
1248
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'STOP_LIMIT'):
1249
+ request['type'] = 'STOP_LIMIT'
1250
+ else:
1251
+ request['type'] = 'STOP_LOSS'
1252
+ elif isTakeProfitTrigger:
1253
+ if (uppercaseType == 'LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1254
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1255
+ else:
1256
+ request['type'] = 'TAKE_PROFIT'
1257
+ else:
1258
+ request['type'] = uppercaseType
1259
+ if (side == 'buy') and ((uppercaseType == 'MARKET') or (uppercaseType == 'STOP_LOSS') or (uppercaseType == 'TAKE_PROFIT')):
1260
+ # use createmarketBuy logic here
1261
+ quoteAmount = None
1262
+ createMarketBuyOrderRequiresPrice = True
1263
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1264
+ cost = self.safe_number_2(params, 'cost', 'notional')
1265
+ params = self.omit(params, 'cost')
1266
+ if cost is not None:
1267
+ quoteAmount = self.cost_to_precision(symbol, cost)
1268
+ elif createMarketBuyOrderRequiresPrice:
1269
+ if price is None:
1270
+ raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1271
+ else:
1272
+ amountString = self.number_to_string(amount)
1273
+ priceString = self.number_to_string(price)
1274
+ costRequest = Precise.string_mul(amountString, priceString)
1275
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1276
+ else:
1277
+ quoteAmount = self.cost_to_precision(symbol, amount)
1278
+ request['notional'] = quoteAmount
1279
+ else:
1280
+ request['quantity'] = self.amount_to_precision(symbol, amount)
1281
+ params = self.omit(params, ['postOnly', 'clientOrderId', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1282
+ return self.extend(request, params)
1283
+
1284
+ async def cancel_all_orders(self, symbol: Str = None, params={}):
1285
+ """
1286
+ cancel all open orders
1287
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-cancel-all-orders
1288
+ :param str symbol: unified market symbol of the orders to cancel
1289
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1290
+ :returns dict} Returns exchange raw message{@link https://docs.ccxt.com/#/?id=order-structure:
1291
+ """
1292
+ await self.load_markets()
1293
+ market = None
1294
+ request: dict = {}
1295
+ if symbol is not None:
1296
+ market = self.market(symbol)
1297
+ request['instrument_name'] = market['id']
1298
+ return await self.v1PrivatePostPrivateCancelAllOrders(self.extend(request, params))
1299
+
1300
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
1301
+ """
1302
+ cancels an open order
1303
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-cancel-order
1304
+ :param str id: the order id of the order to cancel
1305
+ :param str [symbol]: unified symbol of the market the order was made in
1306
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1307
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1308
+ """
1309
+ await self.load_markets()
1310
+ market = None
1311
+ if symbol is not None:
1312
+ market = self.market(symbol)
1313
+ request: dict = {
1314
+ 'order_id': id,
1315
+ }
1316
+ response = await self.v1PrivatePostPrivateCancelOrder(self.extend(request, params))
1317
+ #
1318
+ # {
1319
+ # "id": 1686882846638,
1320
+ # "method": "private/cancel-order",
1321
+ # "code": 0,
1322
+ # "message": "NO_ERROR",
1323
+ # "result": {
1324
+ # "client_oid": "CCXT_c2d2152cc32d40a3ae7fbf",
1325
+ # "order_id": "6142909895025252686"
1326
+ # }
1327
+ # }
1328
+ #
1329
+ result = self.safe_dict(response, 'result', {})
1330
+ return self.parse_order(result, market)
1331
+
1332
+ async def cancel_orders(self, ids, symbol: Str = None, params={}):
1333
+ """
1334
+ cancel multiple orders
1335
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-cancel-order-list-list
1336
+ :param str[] ids: order ids
1337
+ :param str symbol: unified market symbol
1338
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1339
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1340
+ """
1341
+ if symbol is None:
1342
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
1343
+ await self.load_markets()
1344
+ market = self.market(symbol)
1345
+ orderRequests = []
1346
+ for i in range(0, len(ids)):
1347
+ id = ids[i]
1348
+ order: dict = {
1349
+ 'instrument_name': market['id'],
1350
+ 'order_id': str(id),
1351
+ }
1352
+ orderRequests.append(order)
1353
+ request: dict = {
1354
+ 'contingency_type': 'LIST',
1355
+ 'order_list': orderRequests,
1356
+ }
1357
+ response = await self.v1PrivatePostPrivateCancelOrderList(self.extend(request, params))
1358
+ result = self.safe_list(response, 'result', [])
1359
+ return self.parse_orders(result, market, None, None, params)
1360
+
1361
+ async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
1362
+ """
1363
+ cancel multiple orders for multiple symbols
1364
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-cancel-order-list-list
1365
+ :param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol
1366
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1367
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1368
+ """
1369
+ await self.load_markets()
1370
+ orderRequests = []
1371
+ for i in range(0, len(orders)):
1372
+ order = orders[i]
1373
+ id = self.safe_string(order, 'id')
1374
+ symbol = self.safe_string(order, 'symbol')
1375
+ market = self.market(symbol)
1376
+ orderItem: dict = {
1377
+ 'instrument_name': market['id'],
1378
+ 'order_id': str(id),
1379
+ }
1380
+ orderRequests.append(orderItem)
1381
+ request: dict = {
1382
+ 'contingency_type': 'LIST',
1383
+ 'order_list': orderRequests,
1384
+ }
1385
+ response = await self.v1PrivatePostPrivateCancelOrderList(self.extend(request, params))
1386
+ result = self.safe_list(response, 'result', [])
1387
+ return self.parse_orders(result, None, None, None, params)
1388
+
1389
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1390
+ """
1391
+ fetch all unfilled currently open orders
1392
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-open-orders
1393
+ :param str symbol: unified market symbol
1394
+ :param int [since]: the earliest time in ms to fetch open orders for
1395
+ :param int [limit]: the maximum number of open order structures to retrieve
1396
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1397
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1398
+ """
1399
+ await self.load_markets()
1400
+ market = None
1401
+ request: dict = {}
1402
+ if symbol is not None:
1403
+ market = self.market(symbol)
1404
+ request['instrument_name'] = market['id']
1405
+ response = await self.v1PrivatePostPrivateGetOpenOrders(self.extend(request, params))
1406
+ #
1407
+ # {
1408
+ # "id": 1686806134961,
1409
+ # "method": "private/get-open-orders",
1410
+ # "code": 0,
1411
+ # "result": {
1412
+ # "data": [
1413
+ # {
1414
+ # "account_id": "ce075bef-1234-4321-bd6g-ff9007252e63",
1415
+ # "order_id": "6530219477767564494",
1416
+ # "client_oid": "CCXT_7ce730f0388441df9bc218",
1417
+ # "order_type": "LIMIT",
1418
+ # "time_in_force": "GOOD_TILL_CANCEL",
1419
+ # "side": "BUY",
1420
+ # "exec_inst": [],
1421
+ # "quantity": "0.00020",
1422
+ # "limit_price": "20000.00",
1423
+ # "order_value": "4",
1424
+ # "avg_price": "0",
1425
+ # "trigger_price": "0",
1426
+ # "ref_price": "0",
1427
+ # "cumulative_quantity": "0",
1428
+ # "cumulative_value": "0",
1429
+ # "cumulative_fee": "0",
1430
+ # "status": "ACTIVE",
1431
+ # "update_user_id": "ce075bef-1234-4321-bd6g-gg9007252e63",
1432
+ # "order_date": "2023-06-15",
1433
+ # "instrument_name": "BTC_USD",
1434
+ # "fee_instrument_name": "BTC",
1435
+ # "create_time": 1686806053992,
1436
+ # "create_time_ns": "1686806053992921880",
1437
+ # "update_time": 1686806053993
1438
+ # }
1439
+ # ]
1440
+ # }
1441
+ # }
1442
+ #
1443
+ data = self.safe_value(response, 'result', {})
1444
+ orders = self.safe_list(data, 'data', [])
1445
+ return self.parse_orders(orders, market, since, limit)
1446
+
1447
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1448
+ """
1449
+ fetch all trades made by the user
1450
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-trades
1451
+ :param str symbol: unified market symbol
1452
+ :param int [since]: the earliest time in ms to fetch trades for, maximum date range is one day
1453
+ :param int [limit]: the maximum number of trade structures to retrieve
1454
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1455
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
1456
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1457
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1458
+ """
1459
+ await self.load_markets()
1460
+ paginate = False
1461
+ paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
1462
+ if paginate:
1463
+ return await self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
1464
+ request: dict = {}
1465
+ market = None
1466
+ if symbol is not None:
1467
+ market = self.market(symbol)
1468
+ request['instrument_name'] = market['id']
1469
+ if since is not None:
1470
+ request['start_time'] = since
1471
+ if limit is not None:
1472
+ request['limit'] = limit
1473
+ until = self.safe_integer(params, 'until')
1474
+ params = self.omit(params, ['until'])
1475
+ if until is not None:
1476
+ request['end_time'] = until
1477
+ response = await self.v1PrivatePostPrivateGetTrades(self.extend(request, params))
1478
+ #
1479
+ # {
1480
+ # "id": 1686942003520,
1481
+ # "method": "private/get-trades",
1482
+ # "code": 0,
1483
+ # "result": {
1484
+ # "data": [
1485
+ # {
1486
+ # "account_id": "ds075abc-1234-4321-bd6g-ff9007252r63",
1487
+ # "event_date": "2023-06-16",
1488
+ # "journal_type": "TRADING",
1489
+ # "side": "BUY",
1490
+ # "instrument_name": "BTC_USD",
1491
+ # "fees": "-0.0000000525",
1492
+ # "trade_id": "6142909898247428343",
1493
+ # "trade_match_id": "4611686018455978480",
1494
+ # "create_time": 1686941992887,
1495
+ # "traded_price": "26347.16",
1496
+ # "traded_quantity": "0.00021",
1497
+ # "fee_instrument_name": "BTC",
1498
+ # "client_oid": "d1c70a60-810e-4c92-b2a0-72b931cb31e0",
1499
+ # "taker_side": "TAKER",
1500
+ # "order_id": "6142909895036331486",
1501
+ # "create_time_ns": "1686941992887207066"
1502
+ # }
1503
+ # ]
1504
+ # }
1505
+ # }
1506
+ #
1507
+ result = self.safe_value(response, 'result', {})
1508
+ trades = self.safe_list(result, 'data', [])
1509
+ return self.parse_trades(trades, market, since, limit)
1510
+
1511
+ def parse_address(self, addressString):
1512
+ address = None
1513
+ tag = None
1514
+ rawTag = None
1515
+ if addressString.find('?') > 0:
1516
+ address, rawTag = addressString.split('?')
1517
+ splitted = rawTag.split('=')
1518
+ tag = splitted[1]
1519
+ else:
1520
+ address = addressString
1521
+ return [address, tag]
1522
+
1523
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
1524
+ """
1525
+ make a withdrawal
1526
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-withdrawal
1527
+ :param str code: unified currency code
1528
+ :param float amount: the amount to withdraw
1529
+ :param str address: the address to withdraw to
1530
+ :param str tag:
1531
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1532
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1533
+ """
1534
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
1535
+ await self.load_markets()
1536
+ currency = self.safe_currency(code) # for instance, USDC is not inferred from markets but it's still available
1537
+ request: dict = {
1538
+ 'currency': currency['id'],
1539
+ 'amount': amount,
1540
+ 'address': address,
1541
+ }
1542
+ if tag is not None:
1543
+ request['address_tag'] = tag
1544
+ networkCode = None
1545
+ networkCode, params = self.handle_network_code_and_params(params)
1546
+ networkId = self.network_code_to_id(networkCode)
1547
+ if networkId is not None:
1548
+ request['network_id'] = networkId
1549
+ response = await self.v1PrivatePostPrivateCreateWithdrawal(self.extend(request, params))
1550
+ #
1551
+ # {
1552
+ # "id":-1,
1553
+ # "method":"private/create-withdrawal",
1554
+ # "code":0,
1555
+ # "result": {
1556
+ # "id": 2220,
1557
+ # "amount": 1,
1558
+ # "fee": 0.0004,
1559
+ # "symbol": "BTC",
1560
+ # "address": "2NBqqD5GRJ8wHy1PYyCXTe9ke5226FhavBf",
1561
+ # "client_wid": "my_withdrawal_002",
1562
+ # "create_time":1607063412000
1563
+ # }
1564
+ # }
1565
+ #
1566
+ result = self.safe_dict(response, 'result')
1567
+ return self.parse_transaction(result, currency)
1568
+
1569
+ async def fetch_deposit_addresses_by_network(self, code: str, params={}):
1570
+ """
1571
+ fetch a dictionary of addresses for a currency, indexed by network
1572
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-deposit-address
1573
+ :param str code: unified currency code of the currency for the deposit address
1574
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1575
+ :returns dict: a dictionary of `address structures <https://docs.ccxt.com/#/?id=address-structure>` indexed by the network
1576
+ """
1577
+ await self.load_markets()
1578
+ currency = self.safe_currency(code)
1579
+ request: dict = {
1580
+ 'currency': currency['id'],
1581
+ }
1582
+ response = await self.v1PrivatePostPrivateGetDepositAddress(self.extend(request, params))
1583
+ #
1584
+ # {
1585
+ # "id": 1234555011221,
1586
+ # "method": "private/get-deposit-address",
1587
+ # "code": 0,
1588
+ # "result": {
1589
+ # "deposit_address_list": [
1590
+ # {
1591
+ # "currency": "BTC",
1592
+ # "create_time": 1686730755000,
1593
+ # "id": "3737377",
1594
+ # "address": "3N9afggxTSmJ3H4jaMQuWyEiLBzZdAbK6d",
1595
+ # "status":"1",
1596
+ # "network": "BTC"
1597
+ # },
1598
+ # ]
1599
+ # }
1600
+ # }
1601
+ #
1602
+ data = self.safe_value(response, 'result', {})
1603
+ addresses = self.safe_value(data, 'deposit_address_list', [])
1604
+ addressesLength = len(addresses)
1605
+ if addressesLength == 0:
1606
+ raise ExchangeError(self.id + ' fetchDepositAddressesByNetwork() generating address...')
1607
+ result: dict = {}
1608
+ for i in range(0, addressesLength):
1609
+ value = self.safe_value(addresses, i)
1610
+ addressString = self.safe_string(value, 'address')
1611
+ currencyId = self.safe_string(value, 'currency')
1612
+ responseCode = self.safe_currency_code(currencyId)
1613
+ address, tag = self.parse_address(addressString)
1614
+ self.check_address(address)
1615
+ networkId = self.safe_string(value, 'network')
1616
+ network = self.network_id_to_code(networkId, responseCode)
1617
+ result[network] = {
1618
+ 'info': value,
1619
+ 'currency': responseCode,
1620
+ 'address': address,
1621
+ 'tag': tag,
1622
+ 'network': network,
1623
+ }
1624
+ return result
1625
+
1626
+ async def fetch_deposit_address(self, code: str, params={}):
1627
+ """
1628
+ fetch the deposit address for a currency associated with self account
1629
+ :param str code: unified currency code
1630
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1631
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1632
+ """
1633
+ network = self.safe_string_upper(params, 'network')
1634
+ params = self.omit(params, ['network'])
1635
+ depositAddresses = await self.fetch_deposit_addresses_by_network(code, params)
1636
+ if network in depositAddresses:
1637
+ return depositAddresses[network]
1638
+ else:
1639
+ keys = list(depositAddresses.keys())
1640
+ return depositAddresses[keys[0]]
1641
+
1642
+ def safe_network(self, networkId):
1643
+ networksById: dict = {
1644
+ 'BTC': 'BTC',
1645
+ 'ETH': 'ETH',
1646
+ 'SOL': 'SOL',
1647
+ 'BNB': 'BNB',
1648
+ 'CRONOS': 'CRONOS',
1649
+ 'MATIC': 'MATIC',
1650
+ 'OP': 'OP',
1651
+ }
1652
+ return self.safe_string(networksById, networkId, networkId)
1653
+
1654
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1655
+ """
1656
+ fetch all deposits made to an account
1657
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-deposit-history
1658
+ :param str code: unified currency code
1659
+ :param int [since]: the earliest time in ms to fetch deposits for
1660
+ :param int [limit]: the maximum number of deposits structures to retrieve
1661
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1662
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
1663
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1664
+ """
1665
+ await self.load_markets()
1666
+ currency = None
1667
+ request: dict = {}
1668
+ if code is not None:
1669
+ currency = self.safe_currency(code)
1670
+ request['currency'] = currency['id']
1671
+ if since is not None:
1672
+ # 90 days date range
1673
+ request['start_ts'] = since
1674
+ if limit is not None:
1675
+ request['page_size'] = limit
1676
+ until = self.safe_integer(params, 'until')
1677
+ params = self.omit(params, ['until'])
1678
+ if until is not None:
1679
+ request['end_ts'] = until
1680
+ response = await self.v1PrivatePostPrivateGetDepositHistory(self.extend(request, params))
1681
+ #
1682
+ # {
1683
+ # "id": 1688701375714,
1684
+ # "method": "private/get-deposit-history",
1685
+ # "code": 0,
1686
+ # "result": {
1687
+ # "deposit_list": [
1688
+ # {
1689
+ # "currency": "BTC",
1690
+ # "fee": 0,
1691
+ # "create_time": 1688023659000,
1692
+ # "id": "6201135",
1693
+ # "update_time": 1688178509000,
1694
+ # "amount": 0.00114571,
1695
+ # "address": "1234fggxTSmJ3H4jaMQuWyEiLBzZdAbK6d",
1696
+ # "status": "1",
1697
+ # "txid": "f0ae4202b76eb999c301eccdde44dc639bee42d1fdd5974105286ca3393f6065/2"
1698
+ # },
1699
+ # ]
1700
+ # }
1701
+ # }
1702
+ #
1703
+ data = self.safe_value(response, 'result', {})
1704
+ depositList = self.safe_list(data, 'deposit_list', [])
1705
+ return self.parse_transactions(depositList, currency, since, limit)
1706
+
1707
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1708
+ """
1709
+ fetch all withdrawals made from an account
1710
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-withdrawal-history
1711
+ :param str code: unified currency code
1712
+ :param int [since]: the earliest time in ms to fetch withdrawals for
1713
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
1714
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1715
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
1716
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1717
+ """
1718
+ await self.load_markets()
1719
+ currency = None
1720
+ request: dict = {}
1721
+ if code is not None:
1722
+ currency = self.safe_currency(code)
1723
+ request['currency'] = currency['id']
1724
+ if since is not None:
1725
+ # 90 days date range
1726
+ request['start_ts'] = since
1727
+ if limit is not None:
1728
+ request['page_size'] = limit
1729
+ until = self.safe_integer(params, 'until')
1730
+ params = self.omit(params, ['until'])
1731
+ if until is not None:
1732
+ request['end_ts'] = until
1733
+ response = await self.v1PrivatePostPrivateGetWithdrawalHistory(self.extend(request, params))
1734
+ #
1735
+ # {
1736
+ # "id": 1688613879534,
1737
+ # "method": "private/get-withdrawal-history",
1738
+ # "code": 0,
1739
+ # "result": {
1740
+ # "withdrawal_list": [
1741
+ # {
1742
+ # "currency": "BTC",
1743
+ # "client_wid": "",
1744
+ # "fee": 0.0005,
1745
+ # "create_time": 1688613850000,
1746
+ # "id": "5275977",
1747
+ # "update_time": 1688613850000,
1748
+ # "amount": 0.0005,
1749
+ # "address": "1234NMEWbiF8ZkwUMxmfzMxi2A1MQ44bMn",
1750
+ # "status": "1",
1751
+ # "txid": "",
1752
+ # "network_id": "BTC"
1753
+ # }
1754
+ # ]
1755
+ # }
1756
+ # }
1757
+ #
1758
+ data = self.safe_value(response, 'result', {})
1759
+ withdrawalList = self.safe_list(data, 'withdrawal_list', [])
1760
+ return self.parse_transactions(withdrawalList, currency, since, limit)
1761
+
1762
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1763
+ #
1764
+ # fetchTicker
1765
+ #
1766
+ # {
1767
+ # "i": "BTC_USD",
1768
+ # "h": "30821.45",
1769
+ # "l": "28685.11",
1770
+ # "a": "30446.00",
1771
+ # "v": "1767.8734",
1772
+ # "vv": "52436726.42",
1773
+ # "c": "0.0583",
1774
+ # "b": "30442.00",
1775
+ # "k": "30447.66",
1776
+ # "t": 1687403045415
1777
+ # }
1778
+ #
1779
+ # fetchTickers
1780
+ #
1781
+ # {
1782
+ # "i": "AVAXUSD-PERP",
1783
+ # "h": "13.209",
1784
+ # "l": "12.148",
1785
+ # "a": "13.209",
1786
+ # "v": "1109.8",
1787
+ # "vv": "14017.33",
1788
+ # "c": "0.0732",
1789
+ # "b": "13.210",
1790
+ # "k": "13.230",
1791
+ # "oi": "10888.9",
1792
+ # "t": 1687402657575
1793
+ # }
1794
+ #
1795
+ timestamp = self.safe_integer(ticker, 't')
1796
+ marketId = self.safe_string(ticker, 'i')
1797
+ market = self.safe_market(marketId, market, '_')
1798
+ quote = self.safe_string(market, 'quote')
1799
+ last = self.safe_string(ticker, 'a')
1800
+ return self.safe_ticker({
1801
+ 'symbol': market['symbol'],
1802
+ 'timestamp': timestamp,
1803
+ 'datetime': self.iso8601(timestamp),
1804
+ 'high': self.safe_number(ticker, 'h'),
1805
+ 'low': self.safe_number(ticker, 'l'),
1806
+ 'bid': self.safe_number(ticker, 'b'),
1807
+ 'bidVolume': None,
1808
+ 'ask': self.safe_number(ticker, 'k'),
1809
+ 'askVolume': None,
1810
+ 'vwap': None,
1811
+ 'open': None,
1812
+ 'close': last,
1813
+ 'last': last,
1814
+ 'previousClose': None,
1815
+ 'change': None,
1816
+ 'percentage': self.safe_string(ticker, 'c'),
1817
+ 'average': None,
1818
+ 'baseVolume': self.safe_string(ticker, 'v'),
1819
+ 'quoteVolume': self.safe_string(ticker, 'vv') if (quote == 'USD') else None,
1820
+ 'info': ticker,
1821
+ }, market)
1822
+
1823
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1824
+ #
1825
+ # fetchTrades
1826
+ #
1827
+ # {
1828
+ # "s": "sell",
1829
+ # "p": "26386.00",
1830
+ # "q": "0.00453",
1831
+ # "tn": 1686944282062,
1832
+ # "tn": 1704476468851524373,
1833
+ # "d": "4611686018455979970",
1834
+ # "i": "BTC_USD"
1835
+ # }
1836
+ #
1837
+ # fetchMyTrades
1838
+ #
1839
+ # {
1840
+ # "account_id": "ds075abc-1234-4321-bd6g-ff9007252r63",
1841
+ # "event_date": "2023-06-16",
1842
+ # "journal_type": "TRADING",
1843
+ # "side": "BUY",
1844
+ # "instrument_name": "BTC_USD",
1845
+ # "fees": "-0.0000000525",
1846
+ # "trade_id": "6142909898247428343",
1847
+ # "trade_match_id": "4611686018455978480",
1848
+ # "create_time": 1686941992887,
1849
+ # "traded_price": "26347.16",
1850
+ # "traded_quantity": "0.00021",
1851
+ # "fee_instrument_name": "BTC",
1852
+ # "client_oid": "d1c70a60-1234-4c92-b2a0-72b931cb31e0",
1853
+ # "taker_side": "TAKER",
1854
+ # "order_id": "6142909895036331486",
1855
+ # "create_time_ns": "1686941992887207066"
1856
+ # }
1857
+ #
1858
+ timestamp = self.safe_integer_2(trade, 't', 'create_time')
1859
+ marketId = self.safe_string_2(trade, 'i', 'instrument_name')
1860
+ market = self.safe_market(marketId, market, '_')
1861
+ feeCurrency = self.safe_string(trade, 'fee_instrument_name')
1862
+ feeCostString = self.safe_string(trade, 'fees')
1863
+ return self.safe_trade({
1864
+ 'info': trade,
1865
+ 'id': self.safe_string_2(trade, 'd', 'trade_id'),
1866
+ 'timestamp': timestamp,
1867
+ 'datetime': self.iso8601(timestamp),
1868
+ 'symbol': market['symbol'],
1869
+ 'order': self.safe_string(trade, 'order_id'),
1870
+ 'side': self.safe_string_lower_2(trade, 's', 'side'),
1871
+ 'takerOrMaker': self.safe_string_lower(trade, 'taker_side'),
1872
+ 'price': self.safe_number_2(trade, 'p', 'traded_price'),
1873
+ 'amount': self.safe_number_2(trade, 'q', 'traded_quantity'),
1874
+ 'cost': None,
1875
+ 'type': None,
1876
+ 'fee': {
1877
+ 'currency': self.safe_currency_code(feeCurrency),
1878
+ 'cost': self.parse_number(Precise.string_neg(feeCostString)),
1879
+ },
1880
+ }, market)
1881
+
1882
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1883
+ #
1884
+ # {
1885
+ # "o": "26949.89",
1886
+ # "h": "26957.64",
1887
+ # "l": "26948.24",
1888
+ # "c": "26950.00",
1889
+ # "v": "0.0670",
1890
+ # "t": 1687237080000
1891
+ # }
1892
+ #
1893
+ return [
1894
+ self.safe_integer(ohlcv, 't'),
1895
+ self.safe_number(ohlcv, 'o'),
1896
+ self.safe_number(ohlcv, 'h'),
1897
+ self.safe_number(ohlcv, 'l'),
1898
+ self.safe_number(ohlcv, 'c'),
1899
+ self.safe_number(ohlcv, 'v'),
1900
+ ]
1901
+
1902
+ def parse_order_status(self, status: Str):
1903
+ statuses: dict = {
1904
+ 'ACTIVE': 'open',
1905
+ 'CANCELED': 'canceled',
1906
+ 'FILLED': 'closed',
1907
+ 'REJECTED': 'rejected',
1908
+ 'EXPIRED': 'expired',
1909
+ }
1910
+ return self.safe_string(statuses, status, status)
1911
+
1912
+ def parse_time_in_force(self, timeInForce: Str):
1913
+ timeInForces: dict = {
1914
+ 'GOOD_TILL_CANCEL': 'GTC',
1915
+ 'IMMEDIATE_OR_CANCEL': 'IOC',
1916
+ 'FILL_OR_KILL': 'FOK',
1917
+ }
1918
+ return self.safe_string(timeInForces, timeInForce, timeInForce)
1919
+
1920
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1921
+ #
1922
+ # createOrder, cancelOrder
1923
+ #
1924
+ # {
1925
+ # "order_id": "6540219377766741832",
1926
+ # "client_oid": "CCXT_d6ef7c3db6c1495aa8b757"
1927
+ # }
1928
+ #
1929
+ # fetchOpenOrders, fetchOrder, fetchOrders
1930
+ #
1931
+ # {
1932
+ # "account_id": "ce075bef-1234-4321-bd6g-ff9007252e63",
1933
+ # "order_id": "6530219477767564494",
1934
+ # "client_oid": "CCXT_7ce730f0388441df9bc218",
1935
+ # "order_type": "LIMIT",
1936
+ # "time_in_force": "GOOD_TILL_CANCEL",
1937
+ # "side": "BUY",
1938
+ # "exec_inst": [],
1939
+ # "quantity": "0.00020",
1940
+ # "limit_price": "20000.00",
1941
+ # "order_value": "4",
1942
+ # "avg_price": "0",
1943
+ # "trigger_price": "0",
1944
+ # "ref_price": "0",
1945
+ # "cumulative_quantity": "0",
1946
+ # "cumulative_value": "0",
1947
+ # "cumulative_fee": "0",
1948
+ # "status": "ACTIVE",
1949
+ # "update_user_id": "ce075bef-1234-4321-bd6g-gg9007252e63",
1950
+ # "order_date": "2023-06-15",
1951
+ # "instrument_name": "BTC_USD",
1952
+ # "fee_instrument_name": "BTC",
1953
+ # "create_time": 1686806053992,
1954
+ # "create_time_ns": "1686806053992921880",
1955
+ # "update_time": 1686806053993
1956
+ # }
1957
+ #
1958
+ # createOrders
1959
+ # {
1960
+ # "code" : 306,
1961
+ # "index" : 1,
1962
+ # "client_oid" : "1698068111133_1",
1963
+ # "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
1964
+ # "order_id" : "6142909896519488207"
1965
+ # }
1966
+ #
1967
+ code = self.safe_integer(order, 'code')
1968
+ if (code is not None) and (code != 0):
1969
+ return self.safe_order({
1970
+ 'id': self.safe_string(order, 'order_id'),
1971
+ 'clientOrderId': self.safe_string(order, 'client_oid'),
1972
+ 'info': order,
1973
+ 'status': 'rejected',
1974
+ })
1975
+ created = self.safe_integer(order, 'create_time')
1976
+ marketId = self.safe_string(order, 'instrument_name')
1977
+ symbol = self.safe_symbol(marketId, market)
1978
+ execInst = self.safe_value(order, 'exec_inst')
1979
+ postOnly = None
1980
+ if execInst is not None:
1981
+ postOnly = False
1982
+ for i in range(0, len(execInst)):
1983
+ inst = execInst[i]
1984
+ if inst == 'POST_ONLY':
1985
+ postOnly = True
1986
+ break
1987
+ feeCurrency = self.safe_string(order, 'fee_instrument_name')
1988
+ return self.safe_order({
1989
+ 'info': order,
1990
+ 'id': self.safe_string(order, 'order_id'),
1991
+ 'clientOrderId': self.safe_string(order, 'client_oid'),
1992
+ 'timestamp': created,
1993
+ 'datetime': self.iso8601(created),
1994
+ 'lastTradeTimestamp': self.safe_integer(order, 'update_time'),
1995
+ 'status': self.parse_order_status(self.safe_string(order, 'status')),
1996
+ 'symbol': symbol,
1997
+ 'type': self.safe_string_lower(order, 'order_type'),
1998
+ 'timeInForce': self.parse_time_in_force(self.safe_string(order, 'time_in_force')),
1999
+ 'postOnly': postOnly,
2000
+ 'side': self.safe_string_lower(order, 'side'),
2001
+ 'price': self.safe_number(order, 'limit_price'),
2002
+ 'amount': self.safe_number(order, 'quantity'),
2003
+ 'filled': self.safe_number(order, 'cumulative_quantity'),
2004
+ 'remaining': None,
2005
+ 'average': self.safe_number(order, 'avg_price'),
2006
+ 'cost': self.safe_number(order, 'cumulative_value'),
2007
+ 'fee': {
2008
+ 'currency': self.safe_currency_code(feeCurrency),
2009
+ 'cost': self.safe_number(order, 'cumulative_fee'),
2010
+ },
2011
+ 'trades': [],
2012
+ }, market)
2013
+
2014
+ def parse_deposit_status(self, status):
2015
+ statuses: dict = {
2016
+ '0': 'pending',
2017
+ '1': 'ok',
2018
+ '2': 'failed',
2019
+ '3': 'pending',
2020
+ }
2021
+ return self.safe_string(statuses, status, status)
2022
+
2023
+ def parse_withdrawal_status(self, status):
2024
+ statuses: dict = {
2025
+ '0': 'pending',
2026
+ '1': 'pending',
2027
+ '2': 'failed',
2028
+ '3': 'pending',
2029
+ '4': 'failed',
2030
+ '5': 'ok',
2031
+ '6': 'canceled',
2032
+ }
2033
+ return self.safe_string(statuses, status, status)
2034
+
2035
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2036
+ #
2037
+ # fetchDeposits
2038
+ #
2039
+ # {
2040
+ # "currency": "BTC",
2041
+ # "fee": 0,
2042
+ # "create_time": 1688023659000,
2043
+ # "id": "6201135",
2044
+ # "update_time": 1688178509000,
2045
+ # "amount": 0.00114571,
2046
+ # "address": "1234fggxTSmJ3H4jaMQuWyEiLBzZdAbK6d",
2047
+ # "status": "1",
2048
+ # "txid": "f0ae4202b76eb999c301eccdde44dc639bee42d1fdd5974105286ca3393f6065/2"
2049
+ # }
2050
+ #
2051
+ # fetchWithdrawals
2052
+ #
2053
+ # {
2054
+ # "currency": "BTC",
2055
+ # "client_wid": "",
2056
+ # "fee": 0.0005,
2057
+ # "create_time": 1688613850000,
2058
+ # "id": "5775977",
2059
+ # "update_time": 1688613850000,
2060
+ # "amount": 0.0005,
2061
+ # "address": "1234NMEWbiF8ZkwUMxmfzMxi2A1MQ44bMn",
2062
+ # "status": "1",
2063
+ # "txid": "",
2064
+ # "network_id": "BTC"
2065
+ # }
2066
+ #
2067
+ # withdraw
2068
+ #
2069
+ # {
2070
+ # "id": 2220,
2071
+ # "amount": 1,
2072
+ # "fee": 0.0004,
2073
+ # "symbol": "BTC",
2074
+ # "address": "2NBqqD5GRJ8wHy1PYyCXTe9ke5226FhavBf",
2075
+ # "client_wid": "my_withdrawal_002",
2076
+ # "create_time":1607063412000
2077
+ # }
2078
+ #
2079
+ type = None
2080
+ rawStatus = self.safe_string(transaction, 'status')
2081
+ status = None
2082
+ if 'client_wid' in transaction:
2083
+ type = 'withdrawal'
2084
+ status = self.parse_withdrawal_status(rawStatus)
2085
+ else:
2086
+ type = 'deposit'
2087
+ status = self.parse_deposit_status(rawStatus)
2088
+ addressString = self.safe_string(transaction, 'address')
2089
+ address, tag = self.parse_address(addressString)
2090
+ currencyId = self.safe_string(transaction, 'currency')
2091
+ code = self.safe_currency_code(currencyId, currency)
2092
+ timestamp = self.safe_integer(transaction, 'create_time')
2093
+ feeCost = self.safe_number(transaction, 'fee')
2094
+ fee = None
2095
+ if feeCost is not None:
2096
+ fee = {'currency': code, 'cost': feeCost}
2097
+ return {
2098
+ 'info': transaction,
2099
+ 'id': self.safe_string(transaction, 'id'),
2100
+ 'txid': self.safe_string(transaction, 'txid'),
2101
+ 'timestamp': timestamp,
2102
+ 'datetime': self.iso8601(timestamp),
2103
+ 'network': None,
2104
+ 'address': address,
2105
+ 'addressTo': address,
2106
+ 'addressFrom': None,
2107
+ 'tag': tag,
2108
+ 'tagTo': tag,
2109
+ 'tagFrom': None,
2110
+ 'type': type,
2111
+ 'amount': self.safe_number(transaction, 'amount'),
2112
+ 'currency': code,
2113
+ 'status': status,
2114
+ 'updated': self.safe_integer(transaction, 'update_time'),
2115
+ 'internal': None,
2116
+ 'comment': self.safe_string(transaction, 'client_wid'),
2117
+ 'fee': fee,
2118
+ }
2119
+
2120
+ def custom_handle_margin_mode_and_params(self, methodName, params={}):
2121
+ """
2122
+ * @ignore
2123
+ marginMode specified by params["marginMode"], self.options["marginMode"], self.options["defaultMarginMode"], params["margin"] = True or self.options["defaultType"] = 'margin'
2124
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2125
+ :returns Array: the marginMode in lowercase
2126
+ """
2127
+ defaultType = self.safe_string(self.options, 'defaultType')
2128
+ isMargin = self.safe_bool(params, 'margin', False)
2129
+ params = self.omit(params, 'margin')
2130
+ marginMode = None
2131
+ marginMode, params = self.handle_margin_mode_and_params(methodName, params)
2132
+ if marginMode is not None:
2133
+ if marginMode != 'cross':
2134
+ raise NotSupported(self.id + ' only cross margin is supported')
2135
+ else:
2136
+ if (defaultType == 'margin') or (isMargin is True):
2137
+ marginMode = 'cross'
2138
+ return [marginMode, params]
2139
+
2140
+ def parse_deposit_withdraw_fee(self, fee, currency: Currency = None):
2141
+ #
2142
+ # {
2143
+ # "full_name": "Alchemix",
2144
+ # "default_network": "ETH",
2145
+ # "network_list": [
2146
+ # {
2147
+ # "network_id": "ETH",
2148
+ # "withdrawal_fee": "0.25000000",
2149
+ # "withdraw_enabled": True,
2150
+ # "min_withdrawal_amount": "0.5",
2151
+ # "deposit_enabled": True,
2152
+ # "confirmation_required": "0"
2153
+ # }
2154
+ # ]
2155
+ # }
2156
+ #
2157
+ networkList = self.safe_value(fee, 'network_list')
2158
+ networkListLength = len(networkList)
2159
+ result: dict = {
2160
+ 'info': fee,
2161
+ 'withdraw': {
2162
+ 'fee': None,
2163
+ 'percentage': None,
2164
+ },
2165
+ 'deposit': {
2166
+ 'fee': None,
2167
+ 'percentage': None,
2168
+ },
2169
+ 'networks': {},
2170
+ }
2171
+ if networkList is not None:
2172
+ for i in range(0, networkListLength):
2173
+ networkInfo = networkList[i]
2174
+ networkId = self.safe_string(networkInfo, 'network_id')
2175
+ currencyCode = self.safe_string(currency, 'code')
2176
+ networkCode = self.network_id_to_code(networkId, currencyCode)
2177
+ result['networks'][networkCode] = {
2178
+ 'deposit': {'fee': None, 'percentage': None},
2179
+ 'withdraw': {'fee': self.safe_number(networkInfo, 'withdrawal_fee'), 'percentage': False},
2180
+ }
2181
+ if networkListLength == 1:
2182
+ result['withdraw']['fee'] = self.safe_number(networkInfo, 'withdrawal_fee')
2183
+ result['withdraw']['percentage'] = False
2184
+ return result
2185
+
2186
+ async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
2187
+ """
2188
+ fetch deposit and withdraw fees
2189
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-currency-networks
2190
+ :param str[]|None codes: list of unified currency codes
2191
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2192
+ :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
2193
+ """
2194
+ await self.load_markets()
2195
+ response = await self.v1PrivatePostPrivateGetCurrencyNetworks(params)
2196
+ data = self.safe_value(response, 'result')
2197
+ currencyMap = self.safe_list(data, 'currency_map')
2198
+ return self.parse_deposit_withdraw_fees(currencyMap, codes, 'full_name')
2199
+
2200
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
2201
+ """
2202
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
2203
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-transactions
2204
+ :param str code: unified currency code
2205
+ :param int [since]: timestamp in ms of the earliest ledger entry
2206
+ :param int [limit]: max number of ledger entries to return
2207
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2208
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
2209
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
2210
+ """
2211
+ await self.load_markets()
2212
+ request: dict = {}
2213
+ currency = None
2214
+ if code is not None:
2215
+ currency = self.safe_currency(code)
2216
+ if since is not None:
2217
+ request['start_time'] = since
2218
+ if limit is not None:
2219
+ request['limit'] = limit
2220
+ until = self.safe_integer(params, 'until')
2221
+ params = self.omit(params, ['until'])
2222
+ if until is not None:
2223
+ request['end_time'] = until
2224
+ response = await self.v1PrivatePostPrivateGetTransactions(self.extend(request, params))
2225
+ #
2226
+ # {
2227
+ # "id": 1686813195698,
2228
+ # "method": "private/get-transactions",
2229
+ # "code": 0,
2230
+ # "result": {
2231
+ # "data": [
2232
+ # {
2233
+ # "account_id": "ce075cef-1234-4321-bd6e-gf9007351e64",
2234
+ # "event_date": "2023-06-15",
2235
+ # "journal_type": "TRADING",
2236
+ # "journal_id": "6530219460124075091",
2237
+ # "transaction_qty": "6.0091224",
2238
+ # "transaction_cost": "6.0091224",
2239
+ # "realized_pnl": "0",
2240
+ # "order_id": "6530219477766741833",
2241
+ # "trade_id": "6530219495775954765",
2242
+ # "trade_match_id": "4611686018455865176",
2243
+ # "event_timestamp_ms": 1686804665013,
2244
+ # "event_timestamp_ns": "1686804665013642422",
2245
+ # "client_oid": "CCXT_d6ea7c5db6c1495aa8b758",
2246
+ # "taker_side": "",
2247
+ # "side": "BUY",
2248
+ # "instrument_name": "USD"
2249
+ # },
2250
+ # ]
2251
+ # }
2252
+ # }
2253
+ #
2254
+ result = self.safe_value(response, 'result', {})
2255
+ ledger = self.safe_value(result, 'data', [])
2256
+ return self.parse_ledger(ledger, currency, since, limit)
2257
+
2258
+ def parse_ledger_entry(self, item: dict, currency: Currency = None):
2259
+ #
2260
+ # {
2261
+ # "account_id": "ce075cef-1234-4321-bd6e-gf9007351e64",
2262
+ # "event_date": "2023-06-15",
2263
+ # "journal_type": "TRADING",
2264
+ # "journal_id": "6530219460124075091",
2265
+ # "transaction_qty": "6.0091224",
2266
+ # "transaction_cost": "6.0091224",
2267
+ # "realized_pnl": "0",
2268
+ # "order_id": "6530219477766741833",
2269
+ # "trade_id": "6530219495775954765",
2270
+ # "trade_match_id": "4611686018455865176",
2271
+ # "event_timestamp_ms": 1686804665013,
2272
+ # "event_timestamp_ns": "1686804665013642422",
2273
+ # "client_oid": "CCXT_d6ea7c5db6c1495aa8b758",
2274
+ # "taker_side": "",
2275
+ # "side": "BUY",
2276
+ # "instrument_name": "USD"
2277
+ # }
2278
+ #
2279
+ timestamp = self.safe_integer(item, 'event_timestamp_ms')
2280
+ currencyId = self.safe_string(item, 'instrument_name')
2281
+ amount = self.safe_string(item, 'transaction_qty')
2282
+ direction = None
2283
+ if Precise.string_lt(amount, '0'):
2284
+ direction = 'out'
2285
+ amount = Precise.string_abs(amount)
2286
+ else:
2287
+ direction = 'in'
2288
+ return {
2289
+ 'id': self.safe_string(item, 'order_id'),
2290
+ 'direction': direction,
2291
+ 'account': self.safe_string(item, 'account_id'),
2292
+ 'referenceId': self.safe_string(item, 'trade_id'),
2293
+ 'referenceAccount': self.safe_string(item, 'trade_match_id'),
2294
+ 'type': self.parse_ledger_entry_type(self.safe_string(item, 'journal_type')),
2295
+ 'currency': self.safe_currency_code(currencyId, currency),
2296
+ 'amount': self.parse_number(amount),
2297
+ 'timestamp': timestamp,
2298
+ 'datetime': self.iso8601(timestamp),
2299
+ 'before': None,
2300
+ 'after': None,
2301
+ 'status': None,
2302
+ 'fee': {
2303
+ 'currency': None,
2304
+ 'cost': None,
2305
+ },
2306
+ 'info': item,
2307
+ }
2308
+
2309
+ def parse_ledger_entry_type(self, type):
2310
+ ledgerType: dict = {
2311
+ 'TRADING': 'trade',
2312
+ 'TRADE_FEE': 'fee',
2313
+ 'WITHDRAW_FEE': 'fee',
2314
+ 'WITHDRAW': 'withdrawal',
2315
+ 'DEPOSIT': 'deposit',
2316
+ 'ROLLBACK_WITHDRAW': 'rollback',
2317
+ 'ROLLBACK_DEPOSIT': 'rollback',
2318
+ 'FUNDING': 'fee',
2319
+ 'REALIZED_PNL': 'trade',
2320
+ 'INSURANCE_FUND': 'insurance',
2321
+ 'SOCIALIZED_LOSS': 'trade',
2322
+ 'LIQUIDATION_FEE': 'fee',
2323
+ 'SESSION_RESET': 'reset',
2324
+ 'ADJUSTMENT': 'adjustment',
2325
+ 'SESSION_SETTLE': 'settlement',
2326
+ 'UNCOVERED_LOSS': 'trade',
2327
+ 'ADMIN_ADJUSTMENT': 'adjustment',
2328
+ 'DELIST': 'delist',
2329
+ 'SETTLEMENT_FEE': 'fee',
2330
+ 'AUTO_CONVERSION': 'conversion',
2331
+ 'MANUAL_CONVERSION': 'conversion',
2332
+ }
2333
+ return self.safe_string(ledgerType, type, type)
2334
+
2335
+ async def fetch_accounts(self, params={}) -> List[Account]:
2336
+ """
2337
+ fetch all the accounts associated with a profile
2338
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-accounts
2339
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2340
+ :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
2341
+ """
2342
+ await self.load_markets()
2343
+ response = await self.v1PrivatePostPrivateGetAccounts(params)
2344
+ #
2345
+ # {
2346
+ # "id": 1234567894321,
2347
+ # "method": "private/get-accounts",
2348
+ # "code": 0,
2349
+ # "result": {
2350
+ # "master_account": {
2351
+ # "uuid": "a1234abc-1234-4321-q5r7-b1ab0a0b12b",
2352
+ # "user_uuid": "a1234abc-1234-4321-q5r7-b1ab0a0b12b",
2353
+ # "enabled": True,
2354
+ # "tradable": True,
2355
+ # "name": "YOUR_NAME",
2356
+ # "country_code": "CAN",
2357
+ # "phone_country_code": "CAN",
2358
+ # "incorp_country_code": "",
2359
+ # "margin_access": "DEFAULT",
2360
+ # "derivatives_access": "DEFAULT",
2361
+ # "create_time": 1656445188000,
2362
+ # "update_time": 1660794567262,
2363
+ # "two_fa_enabled": True,
2364
+ # "kyc_level": "ADVANCED",
2365
+ # "suspended": False,
2366
+ # "terminated": False,
2367
+ # "spot_enabled": False,
2368
+ # "margin_enabled": False,
2369
+ # "derivatives_enabled": False
2370
+ # },
2371
+ # "sub_account_list": []
2372
+ # }
2373
+ # }
2374
+ #
2375
+ result = self.safe_value(response, 'result', {})
2376
+ masterAccount = self.safe_value(result, 'master_account', {})
2377
+ accounts = self.safe_value(result, 'sub_account_list', [])
2378
+ accounts.append(masterAccount)
2379
+ return self.parse_accounts(accounts, params)
2380
+
2381
+ def parse_account(self, account):
2382
+ #
2383
+ # {
2384
+ # "uuid": "a1234abc-1234-4321-q5r7-b1ab0a0b12b",
2385
+ # "user_uuid": "a1234abc-1234-4321-q5r7-b1ab0a0b12b",
2386
+ # "master_account_uuid": "a1234abc-1234-4321-q5r7-b1ab0a0b12b",
2387
+ # "label": "FORMER_MASTER_MARGIN",
2388
+ # "enabled": True,
2389
+ # "tradable": True,
2390
+ # "name": "YOUR_NAME",
2391
+ # "country_code": "YOUR_COUNTRY_CODE",
2392
+ # "incorp_country_code": "",
2393
+ # "margin_access": "DEFAULT",
2394
+ # "derivatives_access": "DEFAULT",
2395
+ # "create_time": 1656481992000,
2396
+ # "update_time": 1667272884594,
2397
+ # "two_fa_enabled": False,
2398
+ # "kyc_level": "ADVANCED",
2399
+ # "suspended": False,
2400
+ # "terminated": False,
2401
+ # "spot_enabled": False,
2402
+ # "margin_enabled": False,
2403
+ # "derivatives_enabled": False,
2404
+ # "system_label": "FORMER_MASTER_MARGIN"
2405
+ # }
2406
+ #
2407
+ return {
2408
+ 'id': self.safe_string(account, 'uuid'),
2409
+ 'type': self.safe_string(account, 'label'),
2410
+ 'code': None,
2411
+ 'info': account,
2412
+ }
2413
+
2414
+ async def fetch_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2415
+ """
2416
+ fetches historical settlement records
2417
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-expired-settlement-price
2418
+ :param str symbol: unified market symbol of the settlement history
2419
+ :param int [since]: timestamp in ms
2420
+ :param int [limit]: number of records
2421
+ :param dict [params]: exchange specific params
2422
+ :param int [params.type]: 'future', 'option'
2423
+ :returns dict[]: a list of `settlement history objects <https://docs.ccxt.com/#/?id=settlement-history-structure>`
2424
+ """
2425
+ await self.load_markets()
2426
+ market = None
2427
+ if symbol is not None:
2428
+ market = self.market(symbol)
2429
+ type = None
2430
+ type, params = self.handle_market_type_and_params('fetchSettlementHistory', market, params)
2431
+ self.check_required_argument('fetchSettlementHistory', type, 'type', ['future', 'option', 'WARRANT', 'FUTURE'])
2432
+ if type == 'option':
2433
+ type = 'WARRANT'
2434
+ request: dict = {
2435
+ 'instrument_type': type.upper(),
2436
+ }
2437
+ response = await self.v1PublicGetPublicGetExpiredSettlementPrice(self.extend(request, params))
2438
+ #
2439
+ # {
2440
+ # "id": -1,
2441
+ # "method": "public/get-expired-settlement-price",
2442
+ # "code": 0,
2443
+ # "result": {
2444
+ # "data": [
2445
+ # {
2446
+ # "i": "BTCUSD-230526",
2447
+ # "x": 1685088000000,
2448
+ # "v": "26464.1",
2449
+ # "t": 1685087999500
2450
+ # }
2451
+ # ]
2452
+ # }
2453
+ # }
2454
+ #
2455
+ result = self.safe_value(response, 'result', {})
2456
+ data = self.safe_value(result, 'data', [])
2457
+ settlements = self.parse_settlements(data, market)
2458
+ sorted = self.sort_by(settlements, 'timestamp')
2459
+ return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
2460
+
2461
+ def parse_settlement(self, settlement, market):
2462
+ #
2463
+ # {
2464
+ # "i": "BTCUSD-230526",
2465
+ # "x": 1685088000000,
2466
+ # "v": "26464.1",
2467
+ # "t": 1685087999500
2468
+ # }
2469
+ #
2470
+ timestamp = self.safe_integer(settlement, 'x')
2471
+ marketId = self.safe_string(settlement, 'i')
2472
+ return {
2473
+ 'info': settlement,
2474
+ 'symbol': self.safe_symbol(marketId, market),
2475
+ 'price': self.safe_number(settlement, 'v'),
2476
+ 'timestamp': timestamp,
2477
+ 'datetime': self.iso8601(timestamp),
2478
+ }
2479
+
2480
+ def parse_settlements(self, settlements, market):
2481
+ #
2482
+ # [
2483
+ # {
2484
+ # "i": "BTCUSD-230526",
2485
+ # "x": 1685088000000,
2486
+ # "v": "26464.1",
2487
+ # "t": 1685087999500
2488
+ # }
2489
+ # ]
2490
+ #
2491
+ result = []
2492
+ for i in range(0, len(settlements)):
2493
+ result.append(self.parse_settlement(settlements[i], market))
2494
+ return result
2495
+
2496
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2497
+ """
2498
+ fetches historical funding rates
2499
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-valuations
2500
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2501
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
2502
+ :param int [limit]: the maximum amount of [funding rate structures] to fetch
2503
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2504
+ :param int [params.until]: timestamp in ms for the ending date filter, default is the current time
2505
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2506
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2507
+ """
2508
+ if symbol is None:
2509
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
2510
+ await self.load_markets()
2511
+ paginate = False
2512
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2513
+ if paginate:
2514
+ return await self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params)
2515
+ market = self.market(symbol)
2516
+ if not market['swap']:
2517
+ raise BadSymbol(self.id + ' fetchFundingRateHistory() supports swap contracts only')
2518
+ request: dict = {
2519
+ 'instrument_name': market['id'],
2520
+ 'valuation_type': 'funding_hist',
2521
+ }
2522
+ if since is not None:
2523
+ request['start_ts'] = since
2524
+ if limit is not None:
2525
+ request['count'] = limit
2526
+ until = self.safe_integer(params, 'until')
2527
+ params = self.omit(params, ['until'])
2528
+ if until is not None:
2529
+ request['end_ts'] = until
2530
+ response = await self.v1PublicGetPublicGetValuations(self.extend(request, params))
2531
+ #
2532
+ # {
2533
+ # "id": -1,
2534
+ # "method": "public/get-valuations",
2535
+ # "code": 0,
2536
+ # "result": {
2537
+ # "data": [
2538
+ # {
2539
+ # "v": "-0.000001884",
2540
+ # "t": 1687892400000
2541
+ # },
2542
+ # ],
2543
+ # "instrument_name": "BTCUSD-PERP"
2544
+ # }
2545
+ # }
2546
+ #
2547
+ result = self.safe_value(response, 'result', {})
2548
+ data = self.safe_value(result, 'data', [])
2549
+ marketId = self.safe_string(result, 'instrument_name')
2550
+ rates = []
2551
+ for i in range(0, len(data)):
2552
+ entry = data[i]
2553
+ timestamp = self.safe_integer(entry, 't')
2554
+ rates.append({
2555
+ 'info': entry,
2556
+ 'symbol': self.safe_symbol(marketId, market),
2557
+ 'fundingRate': self.safe_number(entry, 'v'),
2558
+ 'timestamp': timestamp,
2559
+ 'datetime': self.iso8601(timestamp),
2560
+ })
2561
+ sorted = self.sort_by(rates, 'timestamp')
2562
+ return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
2563
+
2564
+ async def fetch_position(self, symbol: str, params={}):
2565
+ """
2566
+ fetch data on a single open contract trade position
2567
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-positions
2568
+ :param str symbol: unified market symbol of the market the position is held in
2569
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2570
+ :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2571
+ """
2572
+ await self.load_markets()
2573
+ market = self.market(symbol)
2574
+ request: dict = {
2575
+ 'instrument_name': market['id'],
2576
+ }
2577
+ response = await self.v1PrivatePostPrivateGetPositions(self.extend(request, params))
2578
+ #
2579
+ # {
2580
+ # "id": 1688015952050,
2581
+ # "method": "private/get-positions",
2582
+ # "code": 0,
2583
+ # "result": {
2584
+ # "data": [
2585
+ # {
2586
+ # "account_id": "ce075bef-b600-4277-bd6e-ff9007251e63",
2587
+ # "quantity": "0.0001",
2588
+ # "cost": "3.02392",
2589
+ # "open_pos_cost": "3.02392",
2590
+ # "open_position_pnl": "-0.0010281328",
2591
+ # "session_pnl": "-0.0010281328",
2592
+ # "update_timestamp_ms": 1688015919091,
2593
+ # "instrument_name": "BTCUSD-PERP",
2594
+ # "type": "PERPETUAL_SWAP"
2595
+ # }
2596
+ # ]
2597
+ # }
2598
+ # }
2599
+ #
2600
+ result = self.safe_dict(response, 'result', {})
2601
+ data = self.safe_list(result, 'data', [])
2602
+ return self.parse_position(self.safe_dict(data, 0), market)
2603
+
2604
+ async def fetch_positions(self, symbols: Strings = None, params={}):
2605
+ """
2606
+ fetch all open positions
2607
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-positions
2608
+ :param str[]|None symbols: list of unified market symbols
2609
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2610
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2611
+ """
2612
+ await self.load_markets()
2613
+ symbols = self.market_symbols(symbols)
2614
+ request: dict = {}
2615
+ market = None
2616
+ if symbols is not None:
2617
+ symbol = None
2618
+ if isinstance(symbols, list):
2619
+ symbolsLength = len(symbols)
2620
+ if symbolsLength > 1:
2621
+ raise BadRequest(self.id + ' fetchPositions() symbols argument cannot contain more than 1 symbol')
2622
+ symbol = symbols[0]
2623
+ else:
2624
+ symbol = symbols
2625
+ market = self.market(symbol)
2626
+ request['instrument_name'] = market['id']
2627
+ response = await self.v1PrivatePostPrivateGetPositions(self.extend(request, params))
2628
+ #
2629
+ # {
2630
+ # "id": 1688015952050,
2631
+ # "method": "private/get-positions",
2632
+ # "code": 0,
2633
+ # "result": {
2634
+ # "data": [
2635
+ # {
2636
+ # "account_id": "ce075bef-b600-4277-bd6e-ff9007251e63",
2637
+ # "quantity": "0.0001",
2638
+ # "cost": "3.02392",
2639
+ # "open_pos_cost": "3.02392",
2640
+ # "open_position_pnl": "-0.0010281328",
2641
+ # "session_pnl": "-0.0010281328",
2642
+ # "update_timestamp_ms": 1688015919091,
2643
+ # "instrument_name": "BTCUSD-PERP",
2644
+ # "type": "PERPETUAL_SWAP"
2645
+ # }
2646
+ # ]
2647
+ # }
2648
+ # }
2649
+ #
2650
+ responseResult = self.safe_value(response, 'result', {})
2651
+ positions = self.safe_value(responseResult, 'data', [])
2652
+ result = []
2653
+ for i in range(0, len(positions)):
2654
+ entry = positions[i]
2655
+ marketId = self.safe_string(entry, 'instrument_name')
2656
+ marketInner = self.safe_market(marketId, None, None, 'contract')
2657
+ result.append(self.parse_position(entry, marketInner))
2658
+ return self.filter_by_array_positions(result, 'symbol', None, False)
2659
+
2660
+ def parse_position(self, position: dict, market: Market = None):
2661
+ #
2662
+ # {
2663
+ # "account_id": "ce075bef-b600-4277-bd6e-ff9007251e63",
2664
+ # "quantity": "0.0001",
2665
+ # "cost": "3.02392",
2666
+ # "open_pos_cost": "3.02392",
2667
+ # "open_position_pnl": "-0.0010281328",
2668
+ # "session_pnl": "-0.0010281328",
2669
+ # "update_timestamp_ms": 1688015919091,
2670
+ # "instrument_name": "BTCUSD-PERP",
2671
+ # "type": "PERPETUAL_SWAP"
2672
+ # }
2673
+ #
2674
+ marketId = self.safe_string(position, 'instrument_name')
2675
+ market = self.safe_market(marketId, market, None, 'contract')
2676
+ symbol = self.safe_symbol(marketId, market, None, 'contract')
2677
+ timestamp = self.safe_integer(position, 'update_timestamp_ms')
2678
+ amount = self.safe_string(position, 'quantity')
2679
+ return self.safe_position({
2680
+ 'info': position,
2681
+ 'id': None,
2682
+ 'symbol': symbol,
2683
+ 'timestamp': timestamp,
2684
+ 'datetime': self.iso8601(timestamp),
2685
+ 'hedged': None,
2686
+ 'side': 'buy' if Precise.string_gt(amount, '0') else 'sell',
2687
+ 'contracts': Precise.string_abs(amount),
2688
+ 'contractSize': market['contractSize'],
2689
+ 'entryPrice': None,
2690
+ 'markPrice': None,
2691
+ 'notional': None,
2692
+ 'leverage': None,
2693
+ 'collateral': self.safe_number(position, 'open_pos_cost'),
2694
+ 'initialMargin': self.safe_number(position, 'cost'),
2695
+ 'maintenanceMargin': None,
2696
+ 'initialMarginPercentage': None,
2697
+ 'maintenanceMarginPercentage': None,
2698
+ 'unrealizedPnl': self.safe_number(position, 'open_position_pnl'),
2699
+ 'liquidationPrice': None,
2700
+ 'marginMode': None,
2701
+ 'percentage': None,
2702
+ 'marginRatio': None,
2703
+ 'stopLossPrice': None,
2704
+ 'takeProfitPrice': None,
2705
+ })
2706
+
2707
+ def nonce(self):
2708
+ return self.milliseconds()
2709
+
2710
+ def params_to_string(self, object, level):
2711
+ maxLevel = 3
2712
+ if level >= maxLevel:
2713
+ return str(object)
2714
+ if isinstance(object, str):
2715
+ return object
2716
+ returnString = ''
2717
+ paramsKeys = None
2718
+ if isinstance(object, list):
2719
+ paramsKeys = object
2720
+ else:
2721
+ sorted = self.keysort(object)
2722
+ paramsKeys = list(sorted.keys())
2723
+ for i in range(0, len(paramsKeys)):
2724
+ key = paramsKeys[i]
2725
+ returnString += key
2726
+ value = object[key]
2727
+ if value == 'None':
2728
+ returnString += 'None'
2729
+ elif isinstance(value, list):
2730
+ for j in range(0, len(value)):
2731
+ returnString += self.params_to_string(value[j], level + 1)
2732
+ else:
2733
+ returnString += str(value)
2734
+ return returnString
2735
+
2736
+ async def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
2737
+ """
2738
+ closes open positions for a market
2739
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-close-position
2740
+ :param str symbol: Unified CCXT market symbol
2741
+ :param str [marginMode]: not used by cryptocom.closePositions
2742
+ :param str [side]: not used by cryptocom.closePositions
2743
+ :param dict [params]: extra parameters specific to the okx api endpoint
2744
+ *
2745
+ * EXCHANGE SPECIFIC PARAMETERS
2746
+ :param str [params.type]: LIMIT or MARKET
2747
+ :param number [params.price]: for limit orders only
2748
+ :returns dict[]: `A list of position structures <https://docs.ccxt.com/#/?id=position-structure>`
2749
+ """
2750
+ await self.load_markets()
2751
+ market = self.market(symbol)
2752
+ request: dict = {
2753
+ 'instrument_name': market['id'],
2754
+ 'type': 'MARKET',
2755
+ }
2756
+ type = self.safe_string_upper(params, 'type')
2757
+ price = self.safe_string(params, 'price')
2758
+ if type is not None:
2759
+ request['type'] = type
2760
+ if price is not None:
2761
+ request['price'] = self.price_to_precision(market['symbol'], price)
2762
+ response = await self.v1PrivatePostPrivateClosePosition(self.extend(request, params))
2763
+ #
2764
+ # {
2765
+ # "id" : 1700830813298,
2766
+ # "method" : "private/close-position",
2767
+ # "code" : 0,
2768
+ # "result" : {
2769
+ # "client_oid" : "179a909d-5614-655b-0d0e-9e85c9a25c85",
2770
+ # "order_id" : "6142909897021751347"
2771
+ # }
2772
+ # }
2773
+ #
2774
+ result = self.safe_dict(response, 'result')
2775
+ return self.parse_order(result, market)
2776
+
2777
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2778
+ type = self.safe_string(api, 0)
2779
+ access = self.safe_string(api, 1)
2780
+ url = self.urls['api'][type] + '/' + path
2781
+ query = self.omit(params, self.extract_params(path))
2782
+ if access == 'public':
2783
+ if query:
2784
+ url += '?' + self.urlencode(query)
2785
+ else:
2786
+ self.check_required_credentials()
2787
+ nonce = str(self.nonce())
2788
+ requestParams = self.extend({}, params)
2789
+ paramsKeys = list(requestParams.keys())
2790
+ strSortKey = self.params_to_string(requestParams, 0)
2791
+ payload = path + nonce + self.apiKey + strSortKey + nonce
2792
+ signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256)
2793
+ paramsKeysLength = len(paramsKeys)
2794
+ body = self.json({
2795
+ 'id': nonce,
2796
+ 'method': path,
2797
+ 'params': params,
2798
+ 'api_key': self.apiKey,
2799
+ 'sig': signature,
2800
+ 'nonce': nonce,
2801
+ })
2802
+ # fix issue https://github.com/ccxt/ccxt/issues/11179
2803
+ # php always encodes dictionaries
2804
+ # if an array is empty, php will put it in square brackets
2805
+ # python and js will put it in curly brackets
2806
+ # the code below checks and replaces those brackets in empty requests
2807
+ if paramsKeysLength == 0:
2808
+ paramsString = '{}'
2809
+ arrayString = '[]'
2810
+ body = body.replace(arrayString, paramsString)
2811
+ headers = {
2812
+ 'Content-Type': 'application/json',
2813
+ }
2814
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
2815
+
2816
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2817
+ errorCode = self.safe_string(response, 'code')
2818
+ if errorCode != '0':
2819
+ feedback = self.id + ' ' + body
2820
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
2821
+ raise ExchangeError(self.id + ' ' + body)
2822
+ return None