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
ccxt/hashkey.py ADDED
@@ -0,0 +1,4150 @@
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.base.exchange import Exchange
7
+ from ccxt.abstract.hashkey import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Account, Balances, Bool, Currencies, Currency, DepositAddress, Int, LastPrice, LastPrices, LedgerEntry, Leverage, LeverageTier, LeverageTiers, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
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 AccountSuspended
16
+ from ccxt.base.errors import ArgumentsRequired
17
+ from ccxt.base.errors import BadRequest
18
+ from ccxt.base.errors import BadSymbol
19
+ from ccxt.base.errors import OperationRejected
20
+ from ccxt.base.errors import InsufficientFunds
21
+ from ccxt.base.errors import InvalidAddress
22
+ from ccxt.base.errors import InvalidOrder
23
+ from ccxt.base.errors import OrderNotFound
24
+ from ccxt.base.errors import OrderImmediatelyFillable
25
+ from ccxt.base.errors import OrderNotFillable
26
+ from ccxt.base.errors import DuplicateOrderId
27
+ from ccxt.base.errors import ContractUnavailable
28
+ from ccxt.base.errors import NotSupported
29
+ from ccxt.base.errors import OperationFailed
30
+ from ccxt.base.errors import DDoSProtection
31
+ from ccxt.base.errors import RateLimitExceeded
32
+ from ccxt.base.errors import ExchangeNotAvailable
33
+ from ccxt.base.errors import InvalidNonce
34
+ from ccxt.base.errors import RequestTimeout
35
+ from ccxt.base.decimal_to_precision import TICK_SIZE
36
+ from ccxt.base.precise import Precise
37
+
38
+
39
+ class hashkey(Exchange, ImplicitAPI):
40
+
41
+ def describe(self):
42
+ return self.deep_extend(super(hashkey, self).describe(), {
43
+ 'id': 'hashkey',
44
+ 'name': 'HashKey Global',
45
+ 'countries': ['BM'], # Bermuda
46
+ 'rateLimit': 100,
47
+ 'version': 'v1',
48
+ 'certified': True,
49
+ 'pro': True,
50
+ 'has': {
51
+ 'CORS': None,
52
+ 'spot': True,
53
+ 'margin': False,
54
+ 'swap': False,
55
+ 'future': False,
56
+ 'option': False,
57
+ 'addMargin': False,
58
+ 'cancelAllOrders': True,
59
+ 'cancelAllOrdersAfter': False,
60
+ 'cancelOrder': True,
61
+ 'cancelOrders': True,
62
+ 'cancelWithdraw': False,
63
+ 'closePosition': False,
64
+ 'createConvertTrade': False,
65
+ 'createDepositAddress': False,
66
+ 'createMarketBuyOrderWithCost': True,
67
+ 'createMarketOrder': True,
68
+ 'createMarketOrderWithCost': False,
69
+ 'createMarketSellOrderWithCost': False,
70
+ 'createOrder': True,
71
+ 'createOrderWithTakeProfitAndStopLoss': False,
72
+ 'createReduceOnlyOrder': True,
73
+ 'createStopLimitOrder': True,
74
+ 'createStopLossOrder': False,
75
+ 'createStopMarketOrder': True,
76
+ 'createStopOrder': True,
77
+ 'createTakeProfitOrder': False,
78
+ 'createTrailingAmountOrder': False,
79
+ 'createTrailingPercentOrder': False,
80
+ 'createTriggerOrder': True,
81
+ 'fetchAccounts': True,
82
+ 'fetchBalance': True,
83
+ 'fetchCanceledAndClosedOrders': True,
84
+ 'fetchCanceledOrders': True,
85
+ 'fetchClosedOrder': True,
86
+ 'fetchClosedOrders': False,
87
+ 'fetchConvertCurrencies': False,
88
+ 'fetchConvertQuote': False,
89
+ 'fetchConvertTrade': False,
90
+ 'fetchConvertTradeHistory': False,
91
+ 'fetchCurrencies': True,
92
+ 'fetchDepositAddress': True,
93
+ 'fetchDepositAddresses': False,
94
+ 'fetchDepositAddressesByNetwork': False,
95
+ 'fetchDeposits': True,
96
+ 'fetchDepositsWithdrawals': False,
97
+ 'fetchFundingHistory': False,
98
+ 'fetchFundingRate': True,
99
+ 'fetchFundingRateHistory': True,
100
+ 'fetchFundingRates': True,
101
+ 'fetchIndexOHLCV': False,
102
+ 'fetchLedger': True,
103
+ 'fetchLeverage': True,
104
+ 'fetchLeverageTiers': True,
105
+ 'fetchMarginAdjustmentHistory': False,
106
+ 'fetchMarginMode': False,
107
+ 'fetchMarketLeverageTiers': 'emulated',
108
+ 'fetchMarkets': True,
109
+ 'fetchMarkOHLCV': False,
110
+ 'fetchMyTrades': True,
111
+ 'fetchOHLCV': True,
112
+ 'fetchOpenInterestHistory': False,
113
+ 'fetchOpenOrder': False,
114
+ 'fetchOpenOrders': True,
115
+ 'fetchOrder': True,
116
+ 'fetchOrderBook': True,
117
+ 'fetchOrders': False,
118
+ 'fetchOrderTrades': False,
119
+ 'fetchPosition': False,
120
+ 'fetchPositionHistory': False,
121
+ 'fetchPositionMode': False,
122
+ 'fetchPositions': True,
123
+ 'fetchPositionsForSymbol': True,
124
+ 'fetchPositionsHistory': False,
125
+ 'fetchPremiumIndexOHLCV': False,
126
+ 'fetchStatus': True,
127
+ 'fetchTicker': True,
128
+ 'fetchTickers': True,
129
+ 'fetchTime': True,
130
+ 'fetchTrades': True,
131
+ 'fetchTradingFee': True, # emulated for spot markets
132
+ 'fetchTradingFees': True, # for spot markets only
133
+ 'fetchTransactions': False,
134
+ 'fetchTransfers': False,
135
+ 'fetchWithdrawals': True,
136
+ 'reduceMargin': False,
137
+ 'sandbox': False,
138
+ 'setLeverage': True,
139
+ 'setMargin': False,
140
+ 'setPositionMode': False,
141
+ 'transfer': True,
142
+ 'withdraw': True,
143
+ },
144
+ 'timeframes': {
145
+ '1m': '1m',
146
+ '3m': '3m',
147
+ '5m': '5m',
148
+ '15m': '15m',
149
+ '30m': '30m',
150
+ '1h': '1h',
151
+ '2h': '2h',
152
+ '4h': '4h',
153
+ '6h': '6h',
154
+ '8h': '8h',
155
+ '12h': '12h',
156
+ '1d': '1d',
157
+ '1w': '1w',
158
+ '1M': '1M',
159
+ },
160
+ 'urls': {
161
+ 'logo': 'https://github.com/user-attachments/assets/6dd6127b-cc19-4a13-9b29-a98d81f80e98',
162
+ 'api': {
163
+ 'public': 'https://api-glb.hashkey.com',
164
+ 'private': 'https://api-glb.hashkey.com',
165
+ },
166
+ 'test': {
167
+ 'public': 'https://api-glb.sim.hashkeydev.com',
168
+ 'private': 'https://api-glb.sim.hashkeydev.com',
169
+ },
170
+ 'www': 'https://global.hashkey.com/',
171
+ 'doc': 'https://hashkeyglobal-apidoc.readme.io/',
172
+ 'fees': 'https://support.global.hashkey.com/hc/en-us/articles/13199900083612-HashKey-Global-Fee-Structure',
173
+ 'referral': 'https://global.hashkey.com/en-US/register/invite?invite_code=82FQUN',
174
+ },
175
+ 'api': {
176
+ 'public': {
177
+ 'get': {
178
+ 'api/v1/exchangeInfo': 5,
179
+ 'quote/v1/depth': 1,
180
+ 'quote/v1/trades': 1,
181
+ 'quote/v1/klines': 1,
182
+ 'quote/v1/ticker/24hr': 1,
183
+ 'quote/v1/ticker/price': 1,
184
+ 'quote/v1/ticker/bookTicker': 1, # not unified
185
+ 'quote/v1/depth/merged': 1,
186
+ 'quote/v1/markPrice': 1,
187
+ 'quote/v1/index': 1,
188
+ 'api/v1/futures/fundingRate': 1,
189
+ 'api/v1/futures/historyFundingRate': 1,
190
+ 'api/v1/ping': 1,
191
+ 'api/v1/time': 1,
192
+ },
193
+ },
194
+ 'private': {
195
+ 'get': {
196
+ 'api/v1/spot/order': 1,
197
+ 'api/v1/spot/openOrders': 1,
198
+ 'api/v1/spot/tradeOrders': 5,
199
+ 'api/v1/futures/leverage': 1,
200
+ 'api/v1/futures/order': 1,
201
+ 'api/v1/futures/openOrders': 1,
202
+ 'api/v1/futures/userTrades': 1,
203
+ 'api/v1/futures/positions': 1,
204
+ 'api/v1/futures/historyOrders': 1,
205
+ 'api/v1/futures/balance': 1,
206
+ 'api/v1/futures/liquidationAssignStatus': 1,
207
+ 'api/v1/futures/riskLimit': 1,
208
+ 'api/v1/futures/commissionRate': 1,
209
+ 'api/v1/futures/getBestOrder': 1,
210
+ 'api/v1/account/vipInfo': 1,
211
+ 'api/v1/account': 1,
212
+ 'api/v1/account/trades': 5,
213
+ 'api/v1/account/type': 5,
214
+ 'api/v1/account/checkApiKey': 1,
215
+ 'api/v1/account/balanceFlow': 5,
216
+ 'api/v1/spot/subAccount/openOrders': 1,
217
+ 'api/v1/spot/subAccount/tradeOrders': 1,
218
+ 'api/v1/subAccount/trades': 1,
219
+ 'api/v1/futures/subAccount/openOrders': 1,
220
+ 'api/v1/futures/subAccount/historyOrders': 1,
221
+ 'api/v1/futures/subAccount/userTrades': 1,
222
+ 'api/v1/account/deposit/address': 1,
223
+ 'api/v1/account/depositOrders': 1,
224
+ 'api/v1/account/withdrawOrders': 1,
225
+ },
226
+ 'post': {
227
+ 'api/v1/userDataStream': 1,
228
+ 'api/v1/spot/orderTest': 1,
229
+ 'api/v1/spot/order': 1,
230
+ 'api/v1.1/spot/order': 1,
231
+ 'api/v1/spot/batchOrders': 5,
232
+ 'api/v1/futures/leverage': 1,
233
+ 'api/v1/futures/order': 1,
234
+ 'api/v1/futures/position/trading-stop': 3,
235
+ 'api/v1/futures/batchOrders': 5,
236
+ 'api/v1/account/assetTransfer': 1,
237
+ 'api/v1/account/authAddress': 1,
238
+ 'api/v1/account/withdraw': 1,
239
+ },
240
+ 'put': {
241
+ 'api/v1/userDataStream': 1,
242
+ },
243
+ 'delete': {
244
+ 'api/v1/spot/order': 1,
245
+ 'api/v1/spot/openOrders': 5,
246
+ 'api/v1/spot/cancelOrderByIds': 5,
247
+ 'api/v1/futures/order': 1,
248
+ 'api/v1/futures/batchOrders': 1,
249
+ 'api/v1/futures/cancelOrderByIds': 1,
250
+ 'api/v1/userDataStream': 1,
251
+ },
252
+ },
253
+ },
254
+ 'fees': {
255
+ 'trading': {
256
+ 'spot': {
257
+ 'tierBased': True,
258
+ 'percentage': True,
259
+ 'feeSide': 'get',
260
+ 'maker': self.parse_number('0.0012'),
261
+ 'taker': self.parse_number('0.0012'),
262
+ 'tiers': {
263
+ 'maker': [
264
+ [self.parse_number('0'), self.parse_number('0.0012')],
265
+ [self.parse_number('1000000'), self.parse_number('0.00080')],
266
+ [self.parse_number('5000000'), self.parse_number('0.00070')],
267
+ [self.parse_number('10000000'), self.parse_number('0.00060')],
268
+ [self.parse_number('50000000'), self.parse_number('0.00040')],
269
+ [self.parse_number('200000000'), self.parse_number('0.00030')],
270
+ [self.parse_number('400000000'), self.parse_number('0.00010')],
271
+ [self.parse_number('800000000'), self.parse_number('0.00')],
272
+ ],
273
+ 'taker': [
274
+ [self.parse_number('0'), self.parse_number('0.0012')],
275
+ [self.parse_number('1000000'), self.parse_number('0.00090')],
276
+ [self.parse_number('5000000'), self.parse_number('0.00085')],
277
+ [self.parse_number('10000000'), self.parse_number('0.00075')],
278
+ [self.parse_number('50000000'), self.parse_number('0.00065')],
279
+ [self.parse_number('200000000'), self.parse_number('0.00045')],
280
+ [self.parse_number('400000000'), self.parse_number('0.00040')],
281
+ [self.parse_number('800000000'), self.parse_number('0.00035')],
282
+ ],
283
+ },
284
+ },
285
+ 'swap': {
286
+ 'tierBased': True,
287
+ 'percentage': True,
288
+ 'feeSide': 'get',
289
+ 'maker': self.parse_number('0.00025'),
290
+ 'taker': self.parse_number('0.00060'),
291
+ 'tiers': {
292
+ 'maker': [
293
+ [self.parse_number('0'), self.parse_number('0.00025')],
294
+ [self.parse_number('1000000'), self.parse_number('0.00016')],
295
+ [self.parse_number('5000000'), self.parse_number('0.00014')],
296
+ [self.parse_number('10000000'), self.parse_number('0.00012')],
297
+ [self.parse_number('50000000'), self.parse_number('0.000080')],
298
+ [self.parse_number('200000000'), self.parse_number('0.000060')],
299
+ [self.parse_number('400000000'), self.parse_number('0.000020')],
300
+ [self.parse_number('800000000'), self.parse_number('0.00')],
301
+ ],
302
+ 'taker': [
303
+ [self.parse_number('0'), self.parse_number('0.00060')],
304
+ [self.parse_number('1000000'), self.parse_number('0.00050')],
305
+ [self.parse_number('5000000'), self.parse_number('0.00045')],
306
+ [self.parse_number('10000000'), self.parse_number('0.00040')],
307
+ [self.parse_number('50000000'), self.parse_number('0.00035')],
308
+ [self.parse_number('200000000'), self.parse_number('0.00030')],
309
+ [self.parse_number('400000000'), self.parse_number('0.00025')],
310
+ [self.parse_number('800000000'), self.parse_number('0.00020')],
311
+ ],
312
+ },
313
+ },
314
+ },
315
+ },
316
+ 'options': {
317
+ 'broker': '10000700011',
318
+ 'recvWindow': None,
319
+ 'sandboxMode': False,
320
+ 'networks': {
321
+ 'BTC': 'BTC',
322
+ 'ERC20': 'ETH',
323
+ 'AVAX': 'AvalancheC',
324
+ 'SOL': 'Solana',
325
+ 'MATIC': 'Polygon',
326
+ 'ATOM': 'Cosmos',
327
+ 'DOT': 'Polkadot',
328
+ 'LTC': 'LTC',
329
+ 'OPTIMISM': 'Optimism',
330
+ 'ARB': 'Arbitrum',
331
+ 'DOGE': 'Dogecoin',
332
+ 'TRC20': 'Tron',
333
+ 'ZKSYNC': 'zkSync',
334
+ 'TON': 'TON',
335
+ 'KLAYTN': 'Klaytn',
336
+ 'MERLINCHAIN': 'Merlin Chain',
337
+ },
338
+ 'networksById': {
339
+ 'BTC': 'BTC',
340
+ 'Bitcoin': 'BTC',
341
+ 'ETH': 'ERC20',
342
+ 'ERC20': 'ERC20',
343
+ 'AvalancheC': 'AVAX',
344
+ 'AVAX C-Chain': 'AVAX',
345
+ 'Solana': 'SOL',
346
+ 'Cosmos': 'ATOM',
347
+ 'Arbitrum': 'ARB',
348
+ 'Polygon': 'MATIC',
349
+ 'Optimism': 'OPTIMISM',
350
+ 'Polkadot': 'DOT',
351
+ 'LTC': 'LTC',
352
+ 'Litecoin': 'LTC',
353
+ 'Dogecoin': 'DOGE',
354
+ 'Merlin Chain': 'MERLINCHAIN',
355
+ 'zkSync': 'ZKSYNC',
356
+ 'TRC20': 'TRC20',
357
+ 'Tron': 'TRC20',
358
+ 'TON': 'TON',
359
+ 'BSC(BEP20)': 'BSC',
360
+ 'Klaytn': 'KLAYTN',
361
+ },
362
+ 'defaultNetwork': 'ERC20',
363
+ },
364
+ 'commonCurrencies': {},
365
+ 'exceptions': {
366
+ 'exact': {
367
+ '0001': BadRequest, # Required field '%s' missing or invalid.
368
+ '0002': AuthenticationError, # Incorrect signature
369
+ '0003': RateLimitExceeded, # Rate limit exceeded
370
+ '0102': AuthenticationError, # Invalid APIKey
371
+ '0103': AuthenticationError, # APIKey expired
372
+ '0104': PermissionDenied, # The accountId defined is not permissible
373
+ '0201': ExchangeError, # Instrument not found
374
+ '0202': PermissionDenied, # Invalid IP
375
+ '0206': BadRequest, # Unsupported order type
376
+ '0207': BadRequest, # Invalid price
377
+ '0209': BadRequest, # Invalid price precision
378
+ '0210': BadRequest, # Price outside of allowed range
379
+ '0211': OrderNotFound, # Order not found
380
+ '0401': InsufficientFunds, # Insufficient asset
381
+ '0402': BadRequest, # Invalid asset
382
+ '-1000': ExchangeError, # An unknown error occurred while processing the request
383
+ '-1001': ExchangeError, # Internal error
384
+ '-100010': BadSymbol, # Invalid Symbols!
385
+ '-100012': BadSymbol, # Parameter symbol [str] missing!
386
+ '-1002': AuthenticationError, # Unauthorized operation
387
+ '-1004': BadRequest, # Bad request
388
+ '-1005': PermissionDenied, # No permission
389
+ '-1006': ExchangeError, # Execution status unknown
390
+ '-1007': RequestTimeout, # Timeout waiting for response from server
391
+ '-1014': InvalidOrder, # Unsupported order combination
392
+ '-1015': InvalidOrder, # Too many new orders
393
+ '-1020': OperationRejected, # Unsupported operation
394
+ '-1021': InvalidNonce, # Timestamp for self request is outside of the recvWindow
395
+ '-1024': BadRequest, # Duplicate request
396
+ '-1101': ExchangeNotAvailable, # Feature has been offline
397
+ '-1115': InvalidOrder, # Invalid timeInForce
398
+ '-1117': InvalidOrder, # Invalid order side
399
+ '-1123': InvalidOrder, # Invalid client order id
400
+ '-1124': InvalidOrder, # Invalid price
401
+ '-1126': InvalidOrder, # Invalid quantity
402
+ '-1129': BadRequest, # Invalid parameters, quantity and amount are not allowed to be sent at the same time.
403
+ '-1130': BadRequest, # Illegal parameter '%s'
404
+ '-1132': BadRequest, # Order price greater than the maximum
405
+ '-1133': BadRequest, # Order price lower than the minimum
406
+ '-1135': BadRequest, # Order quantity greater than the maximum
407
+ '-1136': BadRequest, # Order quantity lower than the minimum
408
+ '-1138': InvalidOrder, # Order has been partially cancelled
409
+ '-1137': InvalidOrder, # Order quantity precision too large
410
+ '-1139': OrderImmediatelyFillable, # Order has been filled
411
+ '-1140': InvalidOrder, # Order amount lower than the minimum
412
+ '-1141': DuplicateOrderId, # Duplicate order
413
+ '-1142': OrderNotFillable, # Order has been cancelled
414
+ '-1143': OrderNotFound, # Order not found on order book
415
+ '-1144': OperationRejected, # Order has been locked
416
+ '-1145': NotSupported, # Cancellation on self order type not supported
417
+ '-1146': RequestTimeout, # Order creation timeout
418
+ '-1147': RequestTimeout, # Order cancellation timeout
419
+ '-1148': InvalidOrder, # Order amount precision too large
420
+ '-1149': OperationRejected, # Order creation failed
421
+ '-1150': OperationFailed, # Order cancellation failed
422
+ '-1151': OperationRejected, # The trading pair is not open yet
423
+ '-1152': AccountNotEnabled, # User does not exist
424
+ '-1153': InvalidOrder, # Invalid price type
425
+ '-1154': InvalidOrder, # Invalid position side
426
+ '-1155': OperationRejected, # The trading pair is not available for api trading
427
+ '-1156': OperationFailed, # Limit maker order creation failed
428
+ '-1157': OperationFailed, # Modify futures margin failed
429
+ '-1158': OperationFailed, # Reduce margin is forbidden
430
+ '-1159': AccountNotEnabled, # Finance account already exists
431
+ '-1160': AccountNotEnabled, # Account does not exist
432
+ '-1161': OperationFailed, # Balance transfer failed
433
+ '-1162': ContractUnavailable, # Unsupport contract address
434
+ '-1163': InvalidAddress, # Illegal withdrawal address
435
+ '-1164': OperationFailed, # Withdraw failed
436
+ '-1165': ArgumentsRequired, # Withdrawal amount cannot be null
437
+ '-1166': OperationRejected, # Withdrawal amount exceeds the daily limit
438
+ '-1167': BadRequest, # Withdrawal amount less than the minimum
439
+ '-1168': BadRequest, # Illegal withdrawal amount
440
+ '-1169': PermissionDenied, # Withdraw not allowed
441
+ '-1170': PermissionDenied, # Deposit not allowed
442
+ '-1171': PermissionDenied, # Withdrawal address not in whitelist
443
+ '-1172': BadRequest, # Invalid from account id
444
+ '-1173': BadRequest, # Invalid to account i
445
+ '-1174': PermissionDenied, # Transfer not allowed between the same account
446
+ '-1175': BadRequest, # Invalid fiat deposit status
447
+ '-1176': BadRequest, # Invalid fiat withdrawal status
448
+ '-1177': InvalidOrder, # Invalid fiat order type
449
+ '-1178': AccountNotEnabled, # Brokerage account does not exist
450
+ '-1179': AccountSuspended, # Address owner is not True
451
+ '-1181': ExchangeError, # System error
452
+ '-1193': OperationRejected, # Order creation count exceeds the limit
453
+ '-1194': OperationRejected, # Market order creation forbidden
454
+ '-1195': BadRequest, # Market order long position cannot exceed %s above the market price
455
+ '-1196': BadRequest, # Market order short position cannot be below %s of the market price
456
+ '-1200': BadRequest, # Order buy quantity too small
457
+ '-1201': BadRequest, # Order buy quantity too large
458
+ '-1202': BadRequest, # Order sell quantity too small
459
+ '-1203': BadRequest, # Order sell quantity too large
460
+ '-1204': BadRequest, # From account must be a main account
461
+ '-1205': AccountNotEnabled, # Account not authorized
462
+ '-1206': BadRequest, # Order amount greater than the maximum
463
+ '-1207': BadRequest, # The status of deposit is invalid
464
+ '-1208': BadRequest, # The orderType of fiat is invalid
465
+ '-1209': BadRequest, # The status of withdraw is invalid
466
+ '-2001': ExchangeNotAvailable, # Platform is yet to open trading
467
+ '-2002': OperationFailed, # The number of open orders exceeds the limit 300
468
+ '-2003': OperationFailed, # Position size cannot meet target leverage
469
+ '-2004': OperationFailed, # Adjust leverage fail
470
+ '-2005': RequestTimeout, # Adjust leverage timeout
471
+ '-2010': OperationRejected, # New order rejected
472
+ '-2011': OperationRejected, # Order cancellation rejected
473
+ '-2016': OperationRejected, # API key creation exceeds the limit
474
+ '-2017': OperationRejected, # Open orders exceeds the limit of the trading pair
475
+ '-2018': OperationRejected, # Trade user creation exceeds the limit
476
+ '-2019': PermissionDenied, # Trader and omnibus user not allowed to login app
477
+ '-2020': PermissionDenied, # Not allowed to trade self trading pair
478
+ '-2021': PermissionDenied, # Not allowed to trade self trading pair
479
+ '-2022': OperationRejected, # Order batch size exceeds the limit
480
+ '-2023': AuthenticationError, # Need to pass KYC verification
481
+ '-2024': AccountNotEnabled, # Fiat account does not exist
482
+ '-2025': AccountNotEnabled, # Custody account not exist
483
+ '-2026': BadRequest, # Invalid type
484
+ '-2027': OperationRejected, # Exceed maximum time range of 30 days
485
+ '-2028': OperationRejected, # The search is limited to data within the last one month
486
+ '-2029': OperationRejected, # The search is limited to data within the last three months
487
+ '-2030': InsufficientFunds, # Insufficient margin
488
+ '-2031': NotSupported, # Leverage reduction is not supported in Isolated Margin Mode with open positions
489
+ '-2032': OperationRejected, # After the transaction, your %s position will account for %s of the total position, which poses concentration risk. Do you want to continue with the transaction?
490
+ '-2033': OperationFailed, # Order creation failed. Please verify if the order parameters comply with the trading rules
491
+ '-2034': InsufficientFunds, # Trade account holding limit is zero
492
+ '-2035': OperationRejected, # The sub account has been frozen and cannot transfer
493
+ '-2036': NotSupported, # We do not support queries for records exceeding 30 days
494
+ '-2037': ExchangeError, # Position and order data error
495
+ '-2038': InsufficientFunds, # Insufficient margin
496
+ '-2039': NotSupported, # Leverage reduction is not supported in Isolated Margin Mode with open positions
497
+ '-2040': ExchangeNotAvailable, # There is a request being processed. Please try again later
498
+ '-2041': BadRequest, # Token does not exist
499
+ '-2042': OperationRejected, # You have passed the trade limit, please pay attention to the risks
500
+ '-2043': OperationRejected, # Maximum allowed leverage reached, please lower your leverage
501
+ '-2044': BadRequest, # This order price is unreasonable to exceed(or be lower than) the liquidation price
502
+ '-2045': BadRequest, # Price too low, please order again!
503
+ '-2046': BadRequest, # Price too high, please order again!
504
+ '-2048': BadRequest, # Exceed the maximum number of conditional orders of %s
505
+ '-2049': BadRequest, # Create stop order buy price too big
506
+ '-2050': BadRequest, # Create stop order sell price too small
507
+ '-2051': OperationRejected, # Create order rejected
508
+ '-2052': OperationRejected, # Create stop profit-loss plan order reject
509
+ '-2053': OperationRejected, # Position not enough
510
+ '-2054': BadRequest, # Invalid long stop profit price
511
+ '-2055': BadRequest, # Invalid long stop loss price
512
+ '-2056': BadRequest, # Invalid short stop profit price
513
+ '-2057': BadRequest, # Invalid short stop loss price
514
+ '-3117': PermissionDenied, # Invalid permission
515
+ '-3143': PermissionDenied, # According to KYC and risk assessment, your trading account has exceeded the limit.
516
+ '-3144': PermissionDenied, # Currently, your trading account has exceeded its limit and is temporarily unable to perform transfers
517
+ '-3145': DDoSProtection, # Please DO NOT submit request too frequently
518
+ '-4001': BadRequest, # Invalid asset
519
+ '-4002': BadRequest, # Withdrawal amount less than Minimum Withdrawal Amount
520
+ '-4003': InsufficientFunds, # Insufficient Balance
521
+ '-4004': BadRequest, # Invalid bank account number
522
+ '-4005': BadRequest, # Assets are not listed
523
+ '-4006': AccountNotEnabled, # KYC is not certified
524
+ '-4007': NotSupported, # Withdrawal channels are not supported
525
+ '-4008': AccountNotEnabled, # This currency does not support self customer type
526
+ '-4009': PermissionDenied, # No withdrawal permission
527
+ '-4010': PermissionDenied, # Withdrawals on the same day exceed the maximum limit for a single day
528
+ '-4011': ExchangeError, # System error
529
+ '-4012': ExchangeError, # Parameter error
530
+ '-4013': OperationFailed, # Withdraw repeatly
531
+ },
532
+ 'broad': {},
533
+ },
534
+ 'precisionMode': TICK_SIZE,
535
+ })
536
+
537
+ def fetch_time(self, params={}) -> Int:
538
+ """
539
+ fetches the current integer timestamp in milliseconds from the exchange server
540
+
541
+ https://hashkeyglobal-apidoc.readme.io/reference/check-server-time
542
+
543
+ :param dict [params]: extra parameters specific to the exchange API endpoint
544
+ :returns int: the current integer timestamp in milliseconds from the exchange server
545
+ """
546
+ response = self.publicGetApiV1Time(params)
547
+ #
548
+ # {
549
+ # "serverTime": 1721661553214
550
+ # }
551
+ #
552
+ return self.safe_integer(response, 'serverTime')
553
+
554
+ def fetch_status(self, params={}):
555
+ """
556
+ the latest known information on the availability of the exchange API
557
+
558
+ https://hashkeyglobal-apidoc.readme.io/reference/test-connectivity
559
+
560
+ :param dict [params]: extra parameters specific to the exchange API endpoint
561
+ :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
562
+ """
563
+ response = self.publicGetApiV1Ping(params)
564
+ #
565
+ # {}
566
+ #
567
+ return {
568
+ 'status': 'ok',
569
+ 'updated': None,
570
+ 'eta': None,
571
+ 'url': None,
572
+ 'info': response,
573
+ }
574
+
575
+ def fetch_markets(self, params={}) -> List[Market]:
576
+ """
577
+ retrieves data on all markets for the exchange
578
+
579
+ https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
580
+
581
+ :param dict [params]: extra parameters specific to the exchange API endpoint
582
+ :param str [params.symbol]: the id of the market to fetch
583
+ :returns dict[]: an array of objects representing market data
584
+ """
585
+ symbol: Str = None
586
+ request: dict = {}
587
+ symbol, params = self.handle_option_and_params(params, 'fetchMarkets', 'symbol')
588
+ if symbol is not None:
589
+ request['symbol'] = symbol
590
+ response = self.publicGetApiV1ExchangeInfo(self.extend(request, params))
591
+ #
592
+ # {
593
+ # "timezone": "UTC",
594
+ # "serverTime": "1721661653952",
595
+ # "brokerFilters": [],
596
+ # "symbols": [
597
+ # {
598
+ # "symbol": "BTCUSDT",
599
+ # "symbolName": "BTCUSDT",
600
+ # "status": "TRADING",
601
+ # "baseAsset": "BTC",
602
+ # "baseAssetName": "BTC",
603
+ # "baseAssetPrecision": "0.00001",
604
+ # "quoteAsset": "USDT",
605
+ # "quoteAssetName": "USDT",
606
+ # "quotePrecision": "0.0000001",
607
+ # "retailAllowed": True,
608
+ # "piAllowed": True,
609
+ # "corporateAllowed": True,
610
+ # "omnibusAllowed": True,
611
+ # "icebergAllowed": False,
612
+ # "isAggregate": False,
613
+ # "allowMargin": False,
614
+ # "filters": [
615
+ # {
616
+ # "minPrice": "0.01",
617
+ # "maxPrice": "100000.00000000",
618
+ # "tickSize": "0.01",
619
+ # "filterType": "PRICE_FILTER"
620
+ # },
621
+ # {
622
+ # "minQty": "0.00001",
623
+ # "maxQty": "8",
624
+ # "stepSize": "0.00001",
625
+ # "marketOrderMinQty": "0.00001",
626
+ # "marketOrderMaxQty": "4",
627
+ # "filterType": "LOT_SIZE"
628
+ # },
629
+ # {
630
+ # "minNotional": "1",
631
+ # "filterType": "MIN_NOTIONAL"
632
+ # },
633
+ # {
634
+ # "minAmount": "1",
635
+ # "maxAmount": "400000",
636
+ # "minBuyPrice": "0",
637
+ # "marketOrderMinAmount": "1",
638
+ # "marketOrderMaxAmount": "200000",
639
+ # "filterType": "TRADE_AMOUNT"
640
+ # },
641
+ # {
642
+ # "maxSellPrice": "0",
643
+ # "buyPriceUpRate": "0.1",
644
+ # "sellPriceDownRate": "0.1",
645
+ # "filterType": "LIMIT_TRADING"
646
+ # },
647
+ # {
648
+ # "buyPriceUpRate": "0.1",
649
+ # "sellPriceDownRate": "0.1",
650
+ # "filterType": "MARKET_TRADING"
651
+ # },
652
+ # {
653
+ # "noAllowMarketStartTime": "1710485700000",
654
+ # "noAllowMarketEndTime": "1710486000000",
655
+ # "limitOrderStartTime": "0",
656
+ # "limitOrderEndTime": "0",
657
+ # "limitMinPrice": "0",
658
+ # "limitMaxPrice": "0",
659
+ # "filterType": "OPEN_QUOTE"
660
+ # }
661
+ # ]
662
+ # }
663
+ # ],
664
+ # "options": [],
665
+ # "contracts": [
666
+ # {
667
+ # "filters": [
668
+ # {
669
+ # "minPrice": "0.1",
670
+ # "maxPrice": "100000.00000000",
671
+ # "tickSize": "0.1",
672
+ # "filterType": "PRICE_FILTER"
673
+ # },
674
+ # {
675
+ # "minQty": "0.001",
676
+ # "maxQty": "10",
677
+ # "stepSize": "0.001",
678
+ # "marketOrderMinQty": "0",
679
+ # "marketOrderMaxQty": "0",
680
+ # "filterType": "LOT_SIZE"
681
+ # },
682
+ # {
683
+ # "minNotional": "0",
684
+ # "filterType": "MIN_NOTIONAL"
685
+ # },
686
+ # {
687
+ # "maxSellPrice": "999999",
688
+ # "buyPriceUpRate": "0.05",
689
+ # "sellPriceDownRate": "0.05",
690
+ # "maxEntrustNum": 200,
691
+ # "maxConditionNum": 200,
692
+ # "filterType": "LIMIT_TRADING"
693
+ # },
694
+ # {
695
+ # "buyPriceUpRate": "0.05",
696
+ # "sellPriceDownRate": "0.05",
697
+ # "filterType": "MARKET_TRADING"
698
+ # },
699
+ # {
700
+ # "noAllowMarketStartTime": "0",
701
+ # "noAllowMarketEndTime": "0",
702
+ # "limitOrderStartTime": "0",
703
+ # "limitOrderEndTime": "0",
704
+ # "limitMinPrice": "0",
705
+ # "limitMaxPrice": "0",
706
+ # "filterType": "OPEN_QUOTE"
707
+ # }
708
+ # ],
709
+ # "exchangeId": "301",
710
+ # "symbol": "BTCUSDT-PERPETUAL",
711
+ # "symbolName": "BTCUSDT-PERPETUAL",
712
+ # "status": "TRADING",
713
+ # "baseAsset": "BTCUSDT-PERPETUAL",
714
+ # "baseAssetPrecision": "0.001",
715
+ # "quoteAsset": "USDT",
716
+ # "quoteAssetPrecision": "0.1",
717
+ # "icebergAllowed": False,
718
+ # "inverse": False,
719
+ # "index": "USDT",
720
+ # "marginToken": "USDT",
721
+ # "marginPrecision": "0.0001",
722
+ # "contractMultiplier": "0.001",
723
+ # "underlying": "BTC",
724
+ # "riskLimits": [
725
+ # {
726
+ # "riskLimitId": "200000722",
727
+ # "quantity": "1000.00",
728
+ # "initialMargin": "0.10",
729
+ # "maintMargin": "0.005",
730
+ # "isWhite": False
731
+ # },
732
+ # {
733
+ # "riskLimitId": "200000723",
734
+ # "quantity": "2000.00",
735
+ # "initialMargin": "0.10",
736
+ # "maintMargin": "0.01",
737
+ # "isWhite": False
738
+ # }
739
+ # ]
740
+ # }
741
+ # ],
742
+ # "coins": [
743
+ # {
744
+ # "orgId": "9001",
745
+ # "coinId": "BTC",
746
+ # "coinName": "BTC",
747
+ # "coinFullName": "Bitcoin",
748
+ # "allowWithdraw": True,
749
+ # "allowDeposit": True,
750
+ # "tokenType": "CHAIN_TOKEN",
751
+ # "chainTypes": [
752
+ # {
753
+ # "chainType": "Bitcoin",
754
+ # "withdrawFee": "0",
755
+ # "minWithdrawQuantity": "0.002",
756
+ # "maxWithdrawQuantity": "0",
757
+ # "minDepositQuantity": "0.0005",
758
+ # "allowDeposit": True,
759
+ # "allowWithdraw": True
760
+ # }
761
+ # ]
762
+ # }
763
+ # ]
764
+ # }
765
+ #
766
+ spotMarkets = self.safe_list(response, 'symbols', [])
767
+ swapMarkets = self.safe_list(response, 'contracts', [])
768
+ markets = self.array_concat(spotMarkets, swapMarkets)
769
+ if self.is_empty(markets):
770
+ markets = [response] # if user provides params.symbol the exchange returns a single object insted of list of objects
771
+ return self.parse_markets(markets)
772
+
773
+ def parse_market(self, market: dict) -> Market:
774
+ # spot
775
+ # {
776
+ # "symbol": "BTCUSDT",
777
+ # "symbolName": "BTCUSDT",
778
+ # "status": "TRADING",
779
+ # "baseAsset": "BTC",
780
+ # "baseAssetName": "BTC",
781
+ # "baseAssetPrecision": "0.00001",
782
+ # "quoteAsset": "USDT",
783
+ # "quoteAssetName": "USDT",
784
+ # "quotePrecision": "0.0000001",
785
+ # "retailAllowed": True,
786
+ # "piAllowed": True,
787
+ # "corporateAllowed": True,
788
+ # "omnibusAllowed": True,
789
+ # "icebergAllowed": False,
790
+ # "isAggregate": False,
791
+ # "allowMargin": False,
792
+ # "filters": [
793
+ # {
794
+ # "minPrice": "0.01",
795
+ # "maxPrice": "100000.00000000",
796
+ # "tickSize": "0.01",
797
+ # "filterType": "PRICE_FILTER"
798
+ # },
799
+ # {
800
+ # "minQty": "0.00001",
801
+ # "maxQty": "8",
802
+ # "stepSize": "0.00001",
803
+ # "marketOrderMinQty": "0.00001",
804
+ # "marketOrderMaxQty": "4",
805
+ # "filterType": "LOT_SIZE"
806
+ # },
807
+ # {
808
+ # "minNotional": "1",
809
+ # "filterType": "MIN_NOTIONAL"
810
+ # },
811
+ # {
812
+ # "minAmount": "1",
813
+ # "maxAmount": "400000",
814
+ # "minBuyPrice": "0",
815
+ # "marketOrderMinAmount": "1",
816
+ # "marketOrderMaxAmount": "200000",
817
+ # "filterType": "TRADE_AMOUNT"
818
+ # },
819
+ # {
820
+ # "maxSellPrice": "0",
821
+ # "buyPriceUpRate": "0.1",
822
+ # "sellPriceDownRate": "0.1",
823
+ # "filterType": "LIMIT_TRADING"
824
+ # },
825
+ # {
826
+ # "buyPriceUpRate": "0.1",
827
+ # "sellPriceDownRate": "0.1",
828
+ # "filterType": "MARKET_TRADING"
829
+ # },
830
+ # {
831
+ # "noAllowMarketStartTime": "1710485700000",
832
+ # "noAllowMarketEndTime": "1710486000000",
833
+ # "limitOrderStartTime": "0",
834
+ # "limitOrderEndTime": "0",
835
+ # "limitMinPrice": "0",
836
+ # "limitMaxPrice": "0",
837
+ # "filterType": "OPEN_QUOTE"
838
+ # }
839
+ # ]
840
+ # }
841
+ #
842
+ # swap
843
+ # {
844
+ # "filters": [
845
+ # {
846
+ # "minPrice": "0.1",
847
+ # "maxPrice": "100000.00000000",
848
+ # "tickSize": "0.1",
849
+ # "filterType": "PRICE_FILTER"
850
+ # },
851
+ # {
852
+ # "minQty": "0.001",
853
+ # "maxQty": "10",
854
+ # "stepSize": "0.001",
855
+ # "marketOrderMinQty": "0",
856
+ # "marketOrderMaxQty": "0",
857
+ # "filterType": "LOT_SIZE"
858
+ # },
859
+ # {
860
+ # "minNotional": "0",
861
+ # "filterType": "MIN_NOTIONAL"
862
+ # },
863
+ # {
864
+ # "maxSellPrice": "999999",
865
+ # "buyPriceUpRate": "0.05",
866
+ # "sellPriceDownRate": "0.05",
867
+ # "maxEntrustNum": 200,
868
+ # "maxConditionNum": 200,
869
+ # "filterType": "LIMIT_TRADING"
870
+ # },
871
+ # {
872
+ # "buyPriceUpRate": "0.05",
873
+ # "sellPriceDownRate": "0.05",
874
+ # "filterType": "MARKET_TRADING"
875
+ # },
876
+ # {
877
+ # "noAllowMarketStartTime": "0",
878
+ # "noAllowMarketEndTime": "0",
879
+ # "limitOrderStartTime": "0",
880
+ # "limitOrderEndTime": "0",
881
+ # "limitMinPrice": "0",
882
+ # "limitMaxPrice": "0",
883
+ # "filterType": "OPEN_QUOTE"
884
+ # }
885
+ # ],
886
+ # "exchangeId": "301",
887
+ # "symbol": "BTCUSDT-PERPETUAL",
888
+ # "symbolName": "BTCUSDT-PERPETUAL",
889
+ # "status": "TRADING",
890
+ # "baseAsset": "BTCUSDT-PERPETUAL",
891
+ # "baseAssetPrecision": "0.001",
892
+ # "quoteAsset": "USDT",
893
+ # "quoteAssetPrecision": "0.1",
894
+ # "icebergAllowed": False,
895
+ # "inverse": False,
896
+ # "index": "USDT",
897
+ # "marginToken": "USDT",
898
+ # "marginPrecision": "0.0001",
899
+ # "contractMultiplier": "0.001",
900
+ # "underlying": "BTC",
901
+ # "riskLimits": [
902
+ # {
903
+ # "riskLimitId": "200000722",
904
+ # "quantity": "1000.00",
905
+ # "initialMargin": "0.10",
906
+ # "maintMargin": "0.005",
907
+ # "isWhite": False
908
+ # },
909
+ # {
910
+ # "riskLimitId": "200000723",
911
+ # "quantity": "2000.00",
912
+ # "initialMargin": "0.10",
913
+ # "maintMargin": "0.01",
914
+ # "isWhite": False
915
+ # }
916
+ # ]
917
+ # }
918
+ #
919
+ marketId = self.safe_string(market, 'symbol')
920
+ quoteId = self.safe_string(market, 'quoteAsset')
921
+ quote = self.safe_currency_code(quoteId)
922
+ settleId = self.safe_string(market, 'marginToken')
923
+ settle = self.safe_currency_code(settleId)
924
+ baseId = self.safe_string(market, 'baseAsset')
925
+ marketType = 'spot'
926
+ isSpot = True
927
+ isSwap = False
928
+ suffix = ''
929
+ parts = marketId.split('-')
930
+ secondPart = self.safe_string(parts, 1)
931
+ if secondPart == 'PERPETUAL':
932
+ marketType = 'swap'
933
+ isSpot = False
934
+ isSwap = True
935
+ baseId = self.safe_string(market, 'underlying')
936
+ suffix += ':' + settleId
937
+ base = self.safe_currency_code(baseId)
938
+ symbol = base + '/' + quote + suffix
939
+ status = self.safe_string(market, 'status')
940
+ active = status == 'TRADING'
941
+ isLinear: Bool = None
942
+ subType = None
943
+ isInverse = self.safe_bool(market, 'inverse')
944
+ if isInverse is not None:
945
+ if isInverse:
946
+ isLinear = False
947
+ subType = 'inverse'
948
+ else:
949
+ isLinear = True
950
+ subType = 'linear'
951
+ filtersList = self.safe_list(market, 'filters', [])
952
+ filters = self.index_by(filtersList, 'filterType')
953
+ priceFilter = self.safe_dict(filters, 'PRICE_FILTER', {})
954
+ amountFilter = self.safe_dict(filters, 'LOT_SIZE', {})
955
+ costFilter = self.safe_dict(filters, 'MIN_NOTIONAL', {})
956
+ minCostString = self.omit_zero(self.safe_string(costFilter, 'min_notional'))
957
+ contractSizeString = self.safe_string(market, 'contractMultiplier')
958
+ amountPrecisionString = self.safe_string(amountFilter, 'stepSize')
959
+ amountMinLimitString = self.safe_string(amountFilter, 'minQty')
960
+ amountMaxLimitString = self.safe_string(amountFilter, 'maxQty')
961
+ minLeverage: Int = None
962
+ maxLeverage: Int = None
963
+ if isSwap:
964
+ amountPrecisionString = Precise.string_div(amountPrecisionString, contractSizeString)
965
+ amountMinLimitString = Precise.string_div(amountMinLimitString, contractSizeString)
966
+ amountMaxLimitString = Precise.string_div(amountMaxLimitString, contractSizeString)
967
+ riskLimits = self.safe_list(market, 'riskLimits')
968
+ if riskLimits is not None:
969
+ first = self.safe_dict(riskLimits, 0)
970
+ arrayLength = len(riskLimits)
971
+ last = self.safe_dict(riskLimits, arrayLength - 1)
972
+ minInitialMargin = self.safe_string(first, 'initialMargin')
973
+ maxInitialMargin = self.safe_string(last, 'initialMargin')
974
+ if Precise.string_gt(minInitialMargin, maxInitialMargin):
975
+ minInitialMargin, maxInitialMargin = [maxInitialMargin, minInitialMargin]
976
+ minLeverage = self.parse_to_int(Precise.string_div('1', maxInitialMargin))
977
+ maxLeverage = self.parse_to_int(Precise.string_div('1', minInitialMargin))
978
+ tradingFees = self.safe_dict(self.fees, 'trading')
979
+ fees = self.safe_dict(tradingFees, 'spot') if isSpot else self.safe_dict(tradingFees, 'swap')
980
+ return self.safe_market_structure({
981
+ 'id': marketId,
982
+ 'symbol': symbol,
983
+ 'base': base,
984
+ 'quote': quote,
985
+ 'baseId': baseId,
986
+ 'quoteId': quoteId,
987
+ 'active': active,
988
+ 'type': marketType,
989
+ 'subType': subType,
990
+ 'spot': isSpot,
991
+ 'margin': self.safe_bool(market, 'allowMargin'),
992
+ 'swap': isSwap,
993
+ 'future': False,
994
+ 'option': False,
995
+ 'contract': isSwap,
996
+ 'settle': settle,
997
+ 'settleId': settleId,
998
+ 'contractSize': self.parse_number(contractSizeString),
999
+ 'linear': isLinear,
1000
+ 'inverse': isInverse,
1001
+ 'taker': self.safe_number(fees, 'taker'),
1002
+ 'maker': self.safe_number(fees, 'maker'),
1003
+ 'percentage': self.safe_bool(fees, 'percentage'),
1004
+ 'tierBased': self.safe_bool(fees, 'tierBased'),
1005
+ 'feeSide': self.safe_string(fees, 'feeSide'),
1006
+ 'expiry': None,
1007
+ 'expiryDatetime': None,
1008
+ 'strike': None,
1009
+ 'optionType': None,
1010
+ 'precision': {
1011
+ 'amount': self.parse_number(amountPrecisionString),
1012
+ 'price': self.safe_number(priceFilter, 'tickSize'),
1013
+ },
1014
+ 'limits': {
1015
+ 'amount': {
1016
+ 'min': self.parse_number(amountMinLimitString),
1017
+ 'max': self.parse_number(amountMaxLimitString),
1018
+ },
1019
+ 'price': {
1020
+ 'min': self.safe_number(priceFilter, 'minPrice'),
1021
+ 'max': self.safe_number(priceFilter, 'maxPrice'),
1022
+ },
1023
+ 'leverage': {
1024
+ 'min': minLeverage,
1025
+ 'max': maxLeverage,
1026
+ },
1027
+ 'cost': {
1028
+ 'min': self.parse_number(minCostString),
1029
+ 'max': None,
1030
+ },
1031
+ },
1032
+ 'created': None,
1033
+ 'info': market,
1034
+ })
1035
+
1036
+ def fetch_currencies(self, params={}) -> Currencies:
1037
+ """
1038
+ fetches all available currencies on an exchange
1039
+
1040
+ https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
1041
+
1042
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1043
+ :returns dict: an associative dictionary of currencies
1044
+ """
1045
+ response = self.publicGetApiV1ExchangeInfo(params)
1046
+ coins = self.safe_list(response, 'coins')
1047
+ #
1048
+ # {
1049
+ # ...
1050
+ # "coins": [
1051
+ # {
1052
+ # "orgId": "9001",
1053
+ # "coinId": "BTC",
1054
+ # "coinName": "BTC",
1055
+ # "coinFullName": "Bitcoin",
1056
+ # "allowWithdraw": True,
1057
+ # "allowDeposit": True,
1058
+ # "tokenType": "CHAIN_TOKEN",
1059
+ # "chainTypes": [
1060
+ # {
1061
+ # "chainType": "Bitcoin",
1062
+ # "withdrawFee": "0",
1063
+ # "minWithdrawQuantity": "0.002",
1064
+ # "maxWithdrawQuantity": "0",
1065
+ # "minDepositQuantity": "0.0005",
1066
+ # "allowDeposit": True,
1067
+ # "allowWithdraw": True
1068
+ # }
1069
+ # ]
1070
+ # }
1071
+ # ]
1072
+ # }
1073
+ #
1074
+ result: dict = {}
1075
+ for i in range(0, len(coins)):
1076
+ currecy = coins[i]
1077
+ currencyId = self.safe_string(currecy, 'coinId')
1078
+ code = self.safe_currency_code(currencyId)
1079
+ allowWithdraw = self.safe_bool(currecy, 'allowWithdraw')
1080
+ allowDeposit = self.safe_bool(currecy, 'allowDeposit')
1081
+ networks = self.safe_list(currecy, 'chainTypes')
1082
+ networksById = self.safe_dict(self.options, 'networksById')
1083
+ parsedNetworks: dict = {}
1084
+ for j in range(0, len(networks)):
1085
+ network = networks[j]
1086
+ networkId = self.safe_string(network, 'chainType')
1087
+ networkName = self.safe_string(networksById, networkId, networkId)
1088
+ maxWithdrawQuantity = self.omit_zero(self.safe_string(network, 'maxWithdrawQuantity'))
1089
+ networkDeposit = self.safe_bool(network, 'allowDeposit')
1090
+ networkWithdraw = self.safe_bool(network, 'allowWithdraw')
1091
+ parsedNetworks[networkName] = {
1092
+ 'id': networkId,
1093
+ 'network': networkName,
1094
+ 'limits': {
1095
+ 'withdraw': {
1096
+ 'min': self.safe_number(network, 'minWithdrawQuantity'),
1097
+ 'max': self.parse_number(maxWithdrawQuantity),
1098
+ },
1099
+ 'deposit': {
1100
+ 'min': self.safe_number(network, 'minDepositQuantity'),
1101
+ 'max': None,
1102
+ },
1103
+ },
1104
+ 'active': networkDeposit and networkWithdraw,
1105
+ 'deposit': networkDeposit,
1106
+ 'withdraw': networkWithdraw,
1107
+ 'fee': self.safe_number(network, 'withdrawFee'),
1108
+ 'precision': None,
1109
+ 'info': network,
1110
+ }
1111
+ result[code] = {
1112
+ 'id': currencyId,
1113
+ 'code': code,
1114
+ 'precision': None,
1115
+ 'type': self.parse_currency_type(self.safe_string(currecy, 'tokenType')),
1116
+ 'name': self.safe_string(currecy, 'coinFullName'),
1117
+ 'active': allowWithdraw and allowDeposit,
1118
+ 'deposit': allowDeposit,
1119
+ 'withdraw': allowWithdraw,
1120
+ 'fee': None,
1121
+ 'limits': {
1122
+ 'deposit': {
1123
+ 'min': None,
1124
+ 'max': None,
1125
+ },
1126
+ 'withdraw': {
1127
+ 'min': None,
1128
+ 'max': None,
1129
+ },
1130
+ },
1131
+ 'networks': parsedNetworks,
1132
+ 'info': currecy,
1133
+ }
1134
+ return result
1135
+
1136
+ def parse_currency_type(self, type):
1137
+ types = {
1138
+ 'CHAIN_TOKEN': 'crypto',
1139
+ 'ERC20_TOKEN': 'crypto',
1140
+ 'BSC_TOKEN': 'crypto',
1141
+ 'REAL_MONEY': 'fiat',
1142
+ }
1143
+ return self.safe_string(types, type)
1144
+
1145
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1146
+ """
1147
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1148
+
1149
+ https://hashkeyglobal-apidoc.readme.io/reference/get-order-book
1150
+
1151
+ :param str symbol: unified symbol of the market to fetch the order book for
1152
+ :param int [limit]: the maximum amount of order book entries to return(maximum value is 200)
1153
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1154
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1155
+ """
1156
+ self.load_markets()
1157
+ market = self.market(symbol)
1158
+ request: dict = {
1159
+ 'symbol': market['id'],
1160
+ }
1161
+ if limit is not None:
1162
+ request['limit'] = limit
1163
+ response = self.publicGetQuoteV1Depth(self.extend(request, params))
1164
+ #
1165
+ # {
1166
+ # "t": 1721681436393,
1167
+ # "b": [
1168
+ # ["67902.49", "0.00112"],
1169
+ # ["67901.08", "0.01014"]
1170
+ # ...
1171
+ # ],
1172
+ # "a": [
1173
+ # ["67905.99", "0.87134"],
1174
+ # ["67906", "0.57361"]
1175
+ # ...
1176
+ # ]
1177
+ # }
1178
+ #
1179
+ timestamp = self.safe_integer(response, 't')
1180
+ return self.parse_order_book(response, symbol, timestamp, 'b', 'a')
1181
+
1182
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1183
+ """
1184
+ get the list of most recent trades for a particular symbol
1185
+
1186
+ https://hashkeyglobal-apidoc.readme.io/reference/get-recent-trade-list
1187
+
1188
+ :param str symbol: unified symbol of the market to fetch trades for
1189
+ :param int [since]: timestamp in ms of the earliest trade to fetch
1190
+ :param int [limit]: the maximum amount of trades to fetch(maximum value is 100)
1191
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1192
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1193
+ """
1194
+ self.load_markets()
1195
+ market = self.market(symbol)
1196
+ request: dict = {
1197
+ 'symbol': market['id'],
1198
+ }
1199
+ if limit is not None:
1200
+ request['limit'] = limit
1201
+ response = self.publicGetQuoteV1Trades(self.extend(request, params))
1202
+ #
1203
+ # [
1204
+ # {
1205
+ # "t": 1721682745779,
1206
+ # "p": "67835.99",
1207
+ # "q": "0.00017",
1208
+ # "ibm": True
1209
+ # },
1210
+ # ...
1211
+ # ]
1212
+ #
1213
+ return self.parse_trades(response, market, since, limit)
1214
+
1215
+ def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1216
+ """
1217
+ fetch all trades made by the user
1218
+
1219
+ https://hashkeyglobal-apidoc.readme.io/reference/get-account-trade-list
1220
+ https://hashkeyglobal-apidoc.readme.io/reference/query-futures-trades
1221
+ https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-user
1222
+
1223
+ :param str symbol: *is mandatory for swap markets* unified market symbol
1224
+ :param int [since]: the earliest time in ms to fetch trades for
1225
+ :param int [limit]: the maximum amount of trades to fetch(default 200, max 500)
1226
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1227
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch trades for(default 'spot')
1228
+ :param int [params.until]: the latest time in ms to fetch trades for, only supports the last 30 days timeframe
1229
+ :param str [params.fromId]: srarting trade id
1230
+ :param str [params.toId]: ending trade id
1231
+ :param str [params.clientOrderId]: *spot markets only* filter trades by orderId
1232
+ :param str [params.accountId]: account id to fetch the orders from
1233
+ :returns Trade[]: a list of `trade structures <https://github.com/ccxt/ccxt/wiki/Manual#trade-structure>`
1234
+ """
1235
+ methodName = 'fetchMyTrades'
1236
+ self.load_markets()
1237
+ request: dict = {}
1238
+ market: Market = None
1239
+ if symbol is not None:
1240
+ market = self.market(symbol)
1241
+ marketType = 'spot'
1242
+ marketType, params = self.handle_market_type_and_params(methodName, market, params)
1243
+ if since is not None:
1244
+ request['startTime'] = since
1245
+ if limit is not None:
1246
+ request['limit'] = limit
1247
+ until: Int = None
1248
+ until, params = self.handle_option_and_params(params, methodName, 'until')
1249
+ if until is not None:
1250
+ request['endTime'] = until
1251
+ accountId: Str = None
1252
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
1253
+ response = None
1254
+ if marketType == 'spot':
1255
+ if market is not None:
1256
+ request['symbol'] = market['id']
1257
+ clientOrderId: Str = None
1258
+ clientOrderId, params = self.handle_option_and_params(params, methodName, 'clientOrderId')
1259
+ if clientOrderId is not None:
1260
+ request['clientOrderId'] = clientOrderId
1261
+ if accountId is not None:
1262
+ request['accountId'] = accountId
1263
+ response = self.privateGetApiV1AccountTrades(self.extend(request, params))
1264
+ #
1265
+ # [
1266
+ # {
1267
+ # "id": "1739352552862964736",
1268
+ # "clientOrderId": "1722082982086472",
1269
+ # "ticketId": "1739352552795029504",
1270
+ # "symbol": "ETHUSDT",
1271
+ # "symbolName": "ETHUSDT",
1272
+ # "orderId": "1739352552762301440",
1273
+ # "matchOrderId": "0",
1274
+ # "price": "3289.96",
1275
+ # "qty": "0.001",
1276
+ # "commission": "0.0000012",
1277
+ # "commissionAsset": "ETH",
1278
+ # "time": "1722082982097",
1279
+ # "isBuyer": True,
1280
+ # "isMaker": False,
1281
+ # "fee": {
1282
+ # "feeCoinId": "ETH",
1283
+ # "feeCoinName": "ETH",
1284
+ # "fee": "0.0000012"
1285
+ # },
1286
+ # "feeCoinId": "ETH",
1287
+ # "feeAmount": "0.0000012",
1288
+ # "makerRebate": "0"
1289
+ # },
1290
+ # ...
1291
+ # ]
1292
+ #
1293
+ elif marketType == 'swap':
1294
+ if symbol is None:
1295
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a symbol argument for swap markets')
1296
+ request['symbol'] = market['id']
1297
+ if accountId is not None:
1298
+ request['subAccountId'] = accountId
1299
+ response = self.privateGetApiV1FuturesSubAccountUserTrades(self.extend(request, params))
1300
+ else:
1301
+ response = self.privateGetApiV1FuturesUserTrades(self.extend(request, params))
1302
+ #
1303
+ # [
1304
+ # {
1305
+ # "time": "1722429951648",
1306
+ # "tradeId": "1742263144691139328",
1307
+ # "orderId": "1742263144028363776",
1308
+ # "symbol": "ETHUSDT-PERPETUAL",
1309
+ # "price": "3327.54",
1310
+ # "quantity": "4",
1311
+ # "commissionAsset": "USDT",
1312
+ # "commission": "0.00798609",
1313
+ # "makerRebate": "0",
1314
+ # "type": "LIMIT",
1315
+ # "side": "BUY_OPEN",
1316
+ # "realizedPnl": "0",
1317
+ # "isMarker": False
1318
+ # }
1319
+ # ]
1320
+ #
1321
+ else:
1322
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
1323
+ return self.parse_trades(response, market, since, limit)
1324
+
1325
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1326
+ #
1327
+ # fetchTrades
1328
+ #
1329
+ # {
1330
+ # "t": 1721682745779,
1331
+ # "p": "67835.99",
1332
+ # "q": "0.00017",
1333
+ # "ibm": True
1334
+ # }
1335
+ #
1336
+ # fetchMyTrades spot
1337
+ #
1338
+ # {
1339
+ # "id": "1739352552862964736",
1340
+ # "clientOrderId": "1722082982086472",
1341
+ # "ticketId": "1739352552795029504",
1342
+ # "symbol": "ETHUSDT",
1343
+ # "symbolName": "ETHUSDT",
1344
+ # "orderId": "1739352552762301440",
1345
+ # "matchOrderId": "0",
1346
+ # "price": "3289.96",
1347
+ # "qty": "0.001",
1348
+ # "commission": "0.0000012",
1349
+ # "commissionAsset": "ETH",
1350
+ # "time": "1722082982097",
1351
+ # "isBuyer": True,
1352
+ # "isMaker": False,
1353
+ # "fee": {
1354
+ # "feeCoinId": "ETH",
1355
+ # "feeCoinName": "ETH",
1356
+ # "fee": "0.0000012"
1357
+ # },
1358
+ # "feeCoinId": "ETH",
1359
+ # "feeAmount": "0.0000012",
1360
+ # "makerRebate": "0"
1361
+ # }
1362
+ #
1363
+ # fetchMyTrades swap
1364
+ # {
1365
+ # "time": "1722429951648",
1366
+ # "tradeId": "1742263144691139328",
1367
+ # "orderId": "1742263144028363776",
1368
+ # "symbol": "ETHUSDT-PERPETUAL",
1369
+ # "price": "3327.54",
1370
+ # "quantity": "4",
1371
+ # "commissionAsset": "USDT",
1372
+ # "commission": "0.00798609",
1373
+ # "makerRebate": "0",
1374
+ # "type": "LIMIT",
1375
+ # "side": "BUY_OPEN",
1376
+ # "realizedPnl": "0",
1377
+ # "isMarker": False
1378
+ # }
1379
+ timestamp = self.safe_integer_2(trade, 't', 'time')
1380
+ marketId = self.safe_string(trade, 'symbol')
1381
+ market = self.safe_market(marketId, market)
1382
+ side = self.safe_string_lower(trade, 'side') # swap trades have side param
1383
+ if side is not None:
1384
+ side = self.safe_string(side.split('_'), 0)
1385
+ isBuyer = self.safe_bool(trade, 'isBuyer')
1386
+ if isBuyer is not None:
1387
+ side = 'buy' if isBuyer else 'sell'
1388
+ takerOrMaker = None
1389
+ isMaker = self.safe_bool_n(trade, ['isMaker', 'isMarker', 'ibm'])
1390
+ if isMaker is not None:
1391
+ takerOrMaker = 'maker' if isMaker else 'taker'
1392
+ feeCost = self.safe_string(trade, 'commission')
1393
+ feeCurrncyId = self.safe_string(trade, 'commissionAsset')
1394
+ feeInfo = self.safe_dict(trade, 'fee')
1395
+ fee = None
1396
+ if feeInfo is not None:
1397
+ feeCost = self.safe_string(feeInfo, 'fee')
1398
+ feeCurrncyId = self.safe_string(feeInfo, 'feeCoinId')
1399
+ if feeCost is not None:
1400
+ fee = {
1401
+ 'cost': self.parse_number(feeCost),
1402
+ 'currency': self.safe_currency_code(feeCurrncyId),
1403
+ }
1404
+ return self.safe_trade({
1405
+ 'id': self.safe_string_2(trade, 'id', 'tradeId'),
1406
+ 'timestamp': timestamp,
1407
+ 'datetime': self.iso8601(timestamp),
1408
+ 'symbol': market['symbol'],
1409
+ 'side': side,
1410
+ 'price': self.safe_string_2(trade, 'p', 'price'),
1411
+ 'amount': self.safe_string_n(trade, ['q', 'qty', 'quantity']),
1412
+ 'cost': None,
1413
+ 'takerOrMaker': takerOrMaker,
1414
+ 'type': None,
1415
+ 'order': self.safe_string(trade, 'orderId'),
1416
+ 'fee': fee,
1417
+ 'info': trade,
1418
+ }, market)
1419
+
1420
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1421
+ """
1422
+
1423
+ https://hashkeyglobal-apidoc.readme.io/reference/get-kline
1424
+
1425
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1426
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1427
+ :param str timeframe: the length of time each candle represents
1428
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1429
+ :param int [limit]: the maximum amount of candles to fetch
1430
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1431
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
1432
+ :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)
1433
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1434
+ """
1435
+ methodName = 'fetchOHLCV'
1436
+ self.load_markets()
1437
+ paginate = False
1438
+ paginate, params = self.handle_option_and_params(params, methodName, 'paginate')
1439
+ if paginate:
1440
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000)
1441
+ market = self.market(symbol)
1442
+ timeframe = self.safe_string(self.timeframes, timeframe, timeframe)
1443
+ request: dict = {
1444
+ 'symbol': market['id'],
1445
+ 'interval': timeframe,
1446
+ }
1447
+ if since is not None:
1448
+ request['startTime'] = since
1449
+ if limit is not None:
1450
+ request['limit'] = limit
1451
+ until: Int = None
1452
+ until, params = self.handle_option_and_params(params, methodName, 'until')
1453
+ if until is not None:
1454
+ request['endTime'] = until
1455
+ response = self.publicGetQuoteV1Klines(self.extend(request, params))
1456
+ #
1457
+ # [
1458
+ # [
1459
+ # 1721684280000,
1460
+ # "67832.49",
1461
+ # "67862.5",
1462
+ # "67832.49",
1463
+ # "67861.44",
1464
+ # "0.01122",0,
1465
+ # "761.2763533",68,
1466
+ # "0.00561",
1467
+ # "380.640643"
1468
+ # ],
1469
+ # ...
1470
+ # ]
1471
+ #
1472
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)
1473
+
1474
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1475
+ #
1476
+ # [
1477
+ # 1721684280000,
1478
+ # "67832.49",
1479
+ # "67862.5",
1480
+ # "67832.49",
1481
+ # "67861.44",
1482
+ # "0.01122",0,
1483
+ # "761.2763533",68,
1484
+ # "0.00561",
1485
+ # "380.640643"
1486
+ # ]
1487
+ #
1488
+ return [
1489
+ self.safe_integer(ohlcv, 0),
1490
+ self.safe_number(ohlcv, 1),
1491
+ self.safe_number(ohlcv, 2),
1492
+ self.safe_number(ohlcv, 3),
1493
+ self.safe_number(ohlcv, 4),
1494
+ self.safe_number(ohlcv, 5),
1495
+ ]
1496
+
1497
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1498
+ """
1499
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1500
+
1501
+ https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
1502
+
1503
+ :param str symbol: unified symbol of the market to fetch the ticker for
1504
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1505
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1506
+ """
1507
+ self.load_markets()
1508
+ market = self.market(symbol)
1509
+ request: dict = {
1510
+ 'symbol': market['id'],
1511
+ }
1512
+ response = self.publicGetQuoteV1Ticker24hr(self.extend(request, params))
1513
+ #
1514
+ # [
1515
+ # {
1516
+ # "t": 1721685896846,
1517
+ # "s": "BTCUSDT-PERPETUAL",
1518
+ # "c": "67756.7",
1519
+ # "h": "68479.9",
1520
+ # "l": "66594.3",
1521
+ # "o": "68279.7",
1522
+ # "b": "67756.6",
1523
+ # "a": "67756.7",
1524
+ # "v": "1604722",
1525
+ # "qv": "108827258.7761"
1526
+ # }
1527
+ # ]
1528
+ #
1529
+ ticker = self.safe_dict(response, 0, {})
1530
+ return self.parse_ticker(ticker, market)
1531
+
1532
+ def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1533
+ """
1534
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1535
+
1536
+ https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
1537
+
1538
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1539
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1540
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1541
+ """
1542
+ self.load_markets()
1543
+ symbols = self.market_symbols(symbols)
1544
+ response = self.publicGetQuoteV1Ticker24hr(params)
1545
+ return self.parse_tickers(response, symbols)
1546
+
1547
+ def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1548
+ #
1549
+ # {
1550
+ # "t": 1721685896846,
1551
+ # "s": "BTCUSDT-PERPETUAL",
1552
+ # "c": "67756.7",
1553
+ # "h": "68479.9",
1554
+ # "l": "66594.3",
1555
+ # "o": "68279.7",
1556
+ # "b": "67756.6",
1557
+ # "a": "67756.7",
1558
+ # "v": "1604722",
1559
+ # "qv": "108827258.7761"
1560
+ # }
1561
+ #
1562
+ timestamp = self.safe_integer(ticker, 't')
1563
+ marketId = self.safe_string(ticker, 's')
1564
+ market = self.safe_market(marketId, market)
1565
+ symbol = market['symbol']
1566
+ last = self.safe_string(ticker, 'c')
1567
+ return self.safe_ticker({
1568
+ 'symbol': symbol,
1569
+ 'timestamp': timestamp,
1570
+ 'datetime': self.iso8601(timestamp),
1571
+ 'high': self.safe_string(ticker, 'h'),
1572
+ 'low': self.safe_string(ticker, 'l'),
1573
+ 'bid': self.safe_string(ticker, 'b'),
1574
+ 'bidVolume': None,
1575
+ 'ask': self.safe_string(ticker, 'a'),
1576
+ 'askVolume': None,
1577
+ 'vwap': None,
1578
+ 'open': self.safe_string(ticker, 'o'),
1579
+ 'close': last,
1580
+ 'last': last,
1581
+ 'previousClose': None,
1582
+ 'change': None,
1583
+ 'percentage': None,
1584
+ 'average': None,
1585
+ 'baseVolume': self.safe_string(ticker, 'v'),
1586
+ 'quoteVolume': self.safe_string(ticker, 'qv'),
1587
+ 'info': ticker,
1588
+ }, market)
1589
+
1590
+ def fetch_last_prices(self, symbols: Strings = None, params={}) -> LastPrices:
1591
+ """
1592
+ fetches the last price for multiple markets
1593
+
1594
+ https://hashkeyglobal-apidoc.readme.io/reference/get-symbol-price-ticker
1595
+
1596
+ :param str[] [symbols]: unified symbols of the markets to fetch the last prices
1597
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1598
+ :param str [params.symbol]: the id of the market to fetch last price for
1599
+ :returns dict: a dictionary of lastprices structures
1600
+ """
1601
+ self.load_markets()
1602
+ symbols = self.market_symbols(symbols)
1603
+ request: dict = {}
1604
+ symbol: Str = None
1605
+ symbol, params = self.handle_option_and_params(params, 'fetchLastPrices', 'symbol')
1606
+ if symbol is not None:
1607
+ request['symbol'] = symbol
1608
+ response = self.publicGetQuoteV1TickerPrice(self.extend(request, params))
1609
+ #
1610
+ # [
1611
+ # {
1612
+ # "s": "BTCUSDT-PERPETUAL",
1613
+ # "p": "64871"
1614
+ # },
1615
+ # ...
1616
+ # ]
1617
+ #
1618
+ return self.parse_last_prices(response, symbols)
1619
+
1620
+ def parse_last_price(self, entry, market: Market = None) -> LastPrice:
1621
+ marketId = self.safe_string(entry, 's')
1622
+ market = self.safe_market(marketId, market)
1623
+ return {
1624
+ 'symbol': market['symbol'],
1625
+ 'timestamp': None,
1626
+ 'datetime': None,
1627
+ 'price': self.safe_number(entry, 'p'),
1628
+ 'side': None,
1629
+ 'info': entry,
1630
+ }
1631
+
1632
+ def fetch_balance(self, params={}) -> Balances:
1633
+ """
1634
+ query for balance and get the amount of funds available for trading or funds locked in orders
1635
+
1636
+ https://hashkeyglobal-apidoc.readme.io/reference/get-account-information
1637
+
1638
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1639
+ :param str [params.accountId]: account ID, for Master Key only
1640
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch balance for(default 'spot')
1641
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1642
+ """
1643
+ self.load_markets()
1644
+ request: dict = {}
1645
+ methodName = 'fetchBalance'
1646
+ marketType = 'spot'
1647
+ marketType, params = self.handle_market_type_and_params(methodName, None, params, marketType)
1648
+ if marketType == 'swap':
1649
+ response = self.privateGetApiV1FuturesBalance(params)
1650
+ #
1651
+ # [
1652
+ # {
1653
+ # "balance": "30.63364672",
1654
+ # "availableBalance": "28.85635534",
1655
+ # "positionMargin": "4.3421",
1656
+ # "orderMargin": "0",
1657
+ # "asset": "USDT",
1658
+ # "crossUnRealizedPnl": "2.5649"
1659
+ # }
1660
+ # ]
1661
+ #
1662
+ balance = self.safe_dict(response, 0, {})
1663
+ return self.parse_swap_balance(balance)
1664
+ elif marketType == 'spot':
1665
+ accountId: Str = None
1666
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
1667
+ if accountId is not None:
1668
+ request['accountId'] = accountId
1669
+ response = self.privateGetApiV1Account(self.extend(request, params))
1670
+ #
1671
+ # {
1672
+ # "balances": [
1673
+ # {
1674
+ # "asset":"USDT",
1675
+ # "assetId":"USDT",
1676
+ # "assetName":"USDT",
1677
+ # "total":"40",
1678
+ # "free":"40",
1679
+ # "locked":"0"
1680
+ # },
1681
+ # ...
1682
+ # ],
1683
+ # "userId": "1732885739572845312"
1684
+ # }
1685
+ #
1686
+ return self.parse_balance(response)
1687
+ else:
1688
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
1689
+
1690
+ def parse_balance(self, balance) -> Balances:
1691
+ #
1692
+ # {
1693
+ # "balances": [
1694
+ # {
1695
+ # "asset":"USDT",
1696
+ # "assetId":"USDT",
1697
+ # "assetName":"USDT",
1698
+ # "total":"40",
1699
+ # "free":"40",
1700
+ # "locked":"0"
1701
+ # },
1702
+ # ...
1703
+ # ],
1704
+ # "userId": "1732885739572845312"
1705
+ # }
1706
+ #
1707
+ result: dict = {
1708
+ 'info': balance,
1709
+ }
1710
+ balances = self.safe_list(balance, 'balances', [])
1711
+ for i in range(0, len(balances)):
1712
+ balanceEntry = balances[i]
1713
+ currencyId = self.safe_string(balanceEntry, 'asset')
1714
+ code = self.safe_currency_code(currencyId)
1715
+ account = self.account()
1716
+ account['total'] = self.safe_string(balanceEntry, 'total')
1717
+ account['free'] = self.safe_string(balanceEntry, 'free')
1718
+ account['used'] = self.safe_string(balanceEntry, 'locked')
1719
+ result[code] = account
1720
+ return self.safe_balance(result)
1721
+
1722
+ def parse_swap_balance(self, balance) -> Balances:
1723
+ #
1724
+ # {
1725
+ # "balance": "30.63364672",
1726
+ # "availableBalance": "28.85635534",
1727
+ # "positionMargin": "4.3421",
1728
+ # "orderMargin": "0",
1729
+ # "asset": "USDT",
1730
+ # "crossUnRealizedPnl": "2.5649"
1731
+ # }
1732
+ #
1733
+ currencyId = self.safe_string(balance, 'asset')
1734
+ code = self.safe_currency_code(currencyId)
1735
+ account = self.account()
1736
+ account['total'] = self.safe_string(balance, 'balance')
1737
+ positionMargin = self.safe_string(balance, 'positionMargin')
1738
+ orderMargin = self.safe_string(balance, 'orderMargin')
1739
+ account['used'] = Precise.string_add(positionMargin, orderMargin)
1740
+ result: dict = {
1741
+ 'info': balance,
1742
+ }
1743
+ result[code] = account
1744
+ return self.safe_balance(result)
1745
+
1746
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1747
+ """
1748
+ fetch the deposit address for a currency associated with self account
1749
+
1750
+ https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-address
1751
+
1752
+ :param str code: unified currency code(default is 'USDT')
1753
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1754
+ :param str [params.network]: network for fetch deposit address(default is 'ETH')
1755
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1756
+ """
1757
+ self.load_markets()
1758
+ currency = self.currency(code)
1759
+ request: dict = {
1760
+ 'coin': currency['id'],
1761
+ }
1762
+ networkCode: Str = None
1763
+ networkCode, params = self.handle_network_code_and_params(params)
1764
+ if networkCode is None:
1765
+ networkCode = self.default_network_code(code)
1766
+ request['chainType'] = self.network_code_to_id(networkCode, code)
1767
+ response = self.privateGetApiV1AccountDepositAddress(self.extend(request, params))
1768
+ #
1769
+ # {
1770
+ # "canDeposit": True,
1771
+ # "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
1772
+ # "addressExt": "",
1773
+ # "minQuantity": "1",
1774
+ # "needAddressTag": False,
1775
+ # "requiredConfirmTimes": 64,
1776
+ # "canWithdrawConfirmTimes": 64,
1777
+ # "coinType": "ERC20_TOKEN"
1778
+ # }
1779
+ #
1780
+ depositAddress = self.parse_deposit_address(response, currency)
1781
+ depositAddress['network'] = networkCode
1782
+ return depositAddress
1783
+
1784
+ def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
1785
+ #
1786
+ # {
1787
+ # "canDeposit": True,
1788
+ # "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
1789
+ # "addressExt": "",
1790
+ # "minQuantity": "1",
1791
+ # "needAddressTag": False,
1792
+ # "requiredConfirmTimes": 64,
1793
+ # "canWithdrawConfirmTimes": 64,
1794
+ # "coinType": "ERC20_TOKEN"
1795
+ # }
1796
+ #
1797
+ address = self.safe_string(depositAddress, 'address')
1798
+ self.check_address(address)
1799
+ tag = self.safe_string(depositAddress, 'addressExt')
1800
+ if tag == '':
1801
+ tag = None
1802
+ return {
1803
+ 'info': depositAddress,
1804
+ 'currency': currency['code'],
1805
+ 'network': None,
1806
+ 'address': address,
1807
+ 'tag': tag,
1808
+ }
1809
+
1810
+ def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1811
+ """
1812
+ fetch all deposits made to an account
1813
+
1814
+ https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-history
1815
+
1816
+ :param str code: unified currency code of the currency transferred
1817
+ :param int [since]: the earliest time in ms to fetch transfers for(default 24 hours ago)
1818
+ :param int [limit]: the maximum number of transfer structures to retrieve(default 50, max 200)
1819
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1820
+ :param int [params.until]: the latest time in ms to fetch transfers for(default time now)
1821
+ :param int [params.fromId]: starting ID(To be released)
1822
+ :returns dict[]: a list of `transfer structures <https://docs.ccxt.com/#/?id=transfer-structure>`
1823
+ """
1824
+ methodName = 'fetchDeposits'
1825
+ self.load_markets()
1826
+ request: dict = {}
1827
+ currency: Currency = None
1828
+ if code is not None:
1829
+ currency = self.currency(code)
1830
+ request['coin'] = currency['id']
1831
+ if since is not None:
1832
+ request['startTime'] = since
1833
+ if limit is not None:
1834
+ request['limit'] = limit
1835
+ until: Int = None
1836
+ until, params = self.handle_option_and_params(params, methodName, 'until')
1837
+ if until is not None:
1838
+ request['endTime'] = until
1839
+ response = self.privateGetApiV1AccountDepositOrders(self.extend(request, params))
1840
+ #
1841
+ # [
1842
+ # {
1843
+ # "time": "1721641082163",
1844
+ # "coin": "TRXUSDT",
1845
+ # "coinName": "TRXUSDT",
1846
+ # "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
1847
+ # "quantity": "86.00000000000000000000",
1848
+ # "status": 4,
1849
+ # "statusCode": "4",
1850
+ # "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
1851
+ # }
1852
+ # ]
1853
+ #
1854
+ return self.parse_transactions(response, currency, since, limit, {'type': 'deposit'})
1855
+
1856
+ def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1857
+ """
1858
+ fetch all withdrawals made from an account
1859
+
1860
+ https://hashkeyglobal-apidoc.readme.io/reference/withdrawal-records
1861
+
1862
+ :param str code: unified currency code of the currency transferred
1863
+ :param int [since]: the earliest time in ms to fetch transfers for(default 24 hours ago)
1864
+ :param int [limit]: the maximum number of transfer structures to retrieve(default 50, max 200)
1865
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1866
+ :param int [params.until]: the latest time in ms to fetch transfers for(default time now)
1867
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1868
+ """
1869
+ methodName = 'fetchWithdrawals'
1870
+ self.load_markets()
1871
+ request: dict = {}
1872
+ currency: Currency = None
1873
+ if code is not None:
1874
+ currency = self.currency(code)
1875
+ request['coin'] = currency['id']
1876
+ if since is not None:
1877
+ request['startTime'] = since
1878
+ if limit is not None:
1879
+ request['limit'] = limit
1880
+ until: Int = None
1881
+ until, params = self.handle_option_and_params(params, methodName, 'until')
1882
+ if until is not None:
1883
+ request['endTime'] = until
1884
+ response = self.privateGetApiV1AccountWithdrawOrders(self.extend(request, params))
1885
+ #
1886
+ # [
1887
+ # {
1888
+ # "time": "1723545505366",
1889
+ # "id": "W611267400947572736",
1890
+ # "coin": "USDT",
1891
+ # "coinId": "USDT",
1892
+ # "coinName": "USDT",
1893
+ # "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1894
+ # "quantity": "2.00000000",
1895
+ # "arriveQuantity": "2.00000000",
1896
+ # "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
1897
+ # "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1898
+ # "feeCoinId": "USDT",
1899
+ # "feeCoinName": "USDT",
1900
+ # "fee": "1.00000000",
1901
+ # "remark": "",
1902
+ # "platform": ""
1903
+ # }
1904
+ # ]
1905
+ #
1906
+ return self.parse_transactions(response, currency, since, limit, {'type': 'withdrawal'})
1907
+
1908
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
1909
+ """
1910
+ make a withdrawal
1911
+
1912
+ https://hashkeyglobal-apidoc.readme.io/reference/withdraw
1913
+
1914
+ :param str code: unified currency code
1915
+ :param float amount: the amount to withdraw
1916
+ :param str address: the address to withdraw to
1917
+ :param str tag:
1918
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1919
+ :param str [params.network]: network for withdraw
1920
+ :param str [params.clientOrderId]: client order id
1921
+ :param str [params.platform]: the platform to withdraw to(hashkey, HashKey HK)
1922
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1923
+ """
1924
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
1925
+ self.load_markets()
1926
+ currency = self.currency(code)
1927
+ request: dict = {
1928
+ 'coin': currency['id'],
1929
+ 'address': address,
1930
+ 'quantity': amount,
1931
+ }
1932
+ if tag is not None:
1933
+ request['addressExt'] = tag
1934
+ clientOrderId: Str = None
1935
+ clientOrderId, params = self.handle_option_and_params(params, 'withdraw', 'clientOrderId')
1936
+ if clientOrderId is not None:
1937
+ request['clientOrderId'] = clientOrderId
1938
+ networkCode: Str = None
1939
+ networkCode, params = self.handle_network_code_and_params(params)
1940
+ if networkCode is not None:
1941
+ request['chainType'] = self.network_code_to_id(networkCode)
1942
+ platform: Str = None
1943
+ platform, params = self.handle_option_and_params(params, 'withdraw', 'platform')
1944
+ if platform is not None:
1945
+ request['platform'] = platform
1946
+ response = self.privatePostApiV1AccountWithdraw(self.extend(request, params))
1947
+ #
1948
+ # {
1949
+ # "success": True,
1950
+ # "id": "0",
1951
+ # "orderId": "W611267400947572736",
1952
+ # "accountId": "1732885739589466115"
1953
+ # }
1954
+ #
1955
+ return self.parse_transaction(response, currency)
1956
+
1957
+ def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
1958
+ #
1959
+ # fetchDeposits
1960
+ # {
1961
+ # "time": "1721641082163",
1962
+ # "coin": "TRXUSDT", # todo how to parse it?
1963
+ # "coinName": "TRXUSDT",
1964
+ # "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
1965
+ # "quantity": "86.00000000000000000000",
1966
+ # "status": 4,
1967
+ # "statusCode": "4",
1968
+ # "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
1969
+ # }
1970
+ #
1971
+ # fetchWithdrawals
1972
+ # {
1973
+ # "time": "1723545505366",
1974
+ # "id": "W611267400947572736",
1975
+ # "coin": "USDT",
1976
+ # "coinId": "USDT",
1977
+ # "coinName": "USDT",
1978
+ # "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1979
+ # "quantity": "2.00000000",
1980
+ # "arriveQuantity": "2.00000000",
1981
+ # "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
1982
+ # "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1983
+ # "feeCoinId": "USDT",
1984
+ # "feeCoinName": "USDT",
1985
+ # "fee": "1.00000000",
1986
+ # "remark": "",
1987
+ # "platform": ""
1988
+ # }
1989
+ #
1990
+ # withdraw
1991
+ # {
1992
+ # "success": True,
1993
+ # "id": "0",
1994
+ # "orderId": "W611267400947572736",
1995
+ # "accountId": "1732885739589466115"
1996
+ # }
1997
+ #
1998
+ id = self.safe_string_2(transaction, 'id', 'orderId')
1999
+ address = self.safe_string(transaction, 'address')
2000
+ status = self.safe_string(transaction, 'status') # for fetchDeposits
2001
+ if status is None:
2002
+ success = self.safe_bool(transaction, 'success', False) # for withdraw
2003
+ if success:
2004
+ status = 'ok'
2005
+ else:
2006
+ addressUrl = self.safe_string(transaction, 'addressUrl') # for fetchWithdrawals
2007
+ if addressUrl is not None:
2008
+ status = 'ok'
2009
+ txid = self.safe_string(transaction, 'txId')
2010
+ coin = self.safe_string(transaction, 'coin')
2011
+ code = self.safe_currency_code(coin, currency)
2012
+ timestamp = self.safe_integer(transaction, 'time')
2013
+ amount = self.safe_number(transaction, 'quantity')
2014
+ feeCost = self.safe_number(transaction, 'fee')
2015
+ fee = None
2016
+ if feeCost is not None:
2017
+ fee = {
2018
+ 'cost': feeCost,
2019
+ 'currency': code,
2020
+ }
2021
+ return {
2022
+ 'info': transaction,
2023
+ 'id': id,
2024
+ 'txid': txid,
2025
+ 'timestamp': timestamp,
2026
+ 'datetime': self.iso8601(timestamp),
2027
+ 'network': None,
2028
+ 'address': address,
2029
+ 'addressTo': None,
2030
+ 'addressFrom': None,
2031
+ 'tag': None,
2032
+ 'tagTo': None,
2033
+ 'tagFrom': None,
2034
+ 'type': None,
2035
+ 'amount': amount,
2036
+ 'currency': code,
2037
+ 'status': self.parse_transaction_status(status),
2038
+ 'updated': None,
2039
+ 'internal': None,
2040
+ 'comment': None,
2041
+ 'fee': fee,
2042
+ }
2043
+
2044
+ def parse_transaction_status(self, status):
2045
+ statuses: dict = {
2046
+ '1': 'pending',
2047
+ '2': 'pending',
2048
+ '3': 'failed',
2049
+ '4': 'ok',
2050
+ '5': 'pending',
2051
+ '6': 'ok',
2052
+ '7': 'failed',
2053
+ '8': 'cancelled',
2054
+ '9': 'failed',
2055
+ '10': 'failed',
2056
+ 'successful': 'ok',
2057
+ 'success': 'ok',
2058
+ }
2059
+ return self.safe_string(statuses, status, status)
2060
+
2061
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2062
+ """
2063
+ transfer currency internally between wallets on the same account
2064
+
2065
+ https://hashkeyglobal-apidoc.readme.io/reference/new-account-transfer
2066
+
2067
+ :param str code: unified currency code
2068
+ :param float amount: amount to transfer
2069
+ :param str fromAccount: account id to transfer from
2070
+ :param str toAccount: account id to transfer to
2071
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2072
+ :param str [params.clientOrderId]: a unique id for the transfer
2073
+ :param str [params.remark]: a note for the transfer
2074
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2075
+ """
2076
+ self.load_markets()
2077
+ currency = self.currency(code)
2078
+ request: dict = {
2079
+ 'coin': currency['id'],
2080
+ 'quantity': self.currency_to_precision(code, amount),
2081
+ 'fromAccountId': fromAccount,
2082
+ 'toAccountId': toAccount,
2083
+ }
2084
+ clientOrderId: Str = None
2085
+ clientOrderId, params = self.handle_option_and_params(params, 'transfer', 'clientOrderId')
2086
+ if clientOrderId is not None:
2087
+ request['clientOrderId'] = clientOrderId
2088
+ remark: Str = None
2089
+ remark, params = self.handle_option_and_params(params, 'transfer', 'remark')
2090
+ if remark is not None:
2091
+ request['remark'] = remark
2092
+ response = self.privatePostApiV1AccountAssetTransfer(self.extend(request, params))
2093
+ #
2094
+ # {
2095
+ # "success": True,
2096
+ # "timestamp": 1722260230773,
2097
+ # "clientOrderId": "",
2098
+ # "orderId": "1740839420695806720"
2099
+ # }
2100
+ #
2101
+ return self.parse_transfer(response, currency)
2102
+
2103
+ def parse_transfer(self, transfer, currency: Currency = None):
2104
+ timestamp = self.safe_integer(transfer, 'timestamp')
2105
+ currencyId = self.safe_string(currency, 'id')
2106
+ status: Str = None
2107
+ success = self.safe_bool(transfer, 'success', False)
2108
+ if success:
2109
+ status = 'ok'
2110
+ return {
2111
+ 'id': self.safe_string(transfer, 'orderId'),
2112
+ 'timestamp': timestamp,
2113
+ 'datetime': self.iso8601(timestamp),
2114
+ 'currency': self.safe_currency_code(currencyId, currency),
2115
+ 'amount': None,
2116
+ 'fromAccount': None,
2117
+ 'toAccount': None,
2118
+ 'status': status,
2119
+ 'info': transfer,
2120
+ }
2121
+
2122
+ def fetch_accounts(self, params={}) -> List[Account]:
2123
+ """
2124
+ fetch all the accounts associated with a profile
2125
+
2126
+ https://hashkeyglobal-apidoc.readme.io/reference/query-sub-account
2127
+
2128
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2129
+ :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
2130
+ """
2131
+ self.load_markets()
2132
+ response = self.privateGetApiV1AccountType(params)
2133
+ #
2134
+ # [
2135
+ # {
2136
+ # "accountId": "1732885739589466112",
2137
+ # "accountLabel": "Main Trading Account",
2138
+ # "accountType": 1,
2139
+ # "accountIndex": 0
2140
+ # },
2141
+ # ...
2142
+ # ]
2143
+ #
2144
+ return self.parse_accounts(response, params)
2145
+
2146
+ def parse_account(self, account):
2147
+ accountLabel = self.safe_string(account, 'accountLabel')
2148
+ label = ''
2149
+ if accountLabel == 'Main Trading Account' or accountLabel == 'Main Future Account':
2150
+ label = 'main'
2151
+ elif accountLabel == 'Sub Main Trading Account' or accountLabel == 'Sub Main Future Account':
2152
+ label = 'sub'
2153
+ accountType = self.parse_account_type(self.safe_string(account, 'accountType'))
2154
+ type = label + ' ' + accountType
2155
+ return {
2156
+ 'id': self.safe_string(account, 'accountId'),
2157
+ 'type': type,
2158
+ 'code': None,
2159
+ 'info': account,
2160
+ }
2161
+
2162
+ def parse_account_type(self, type):
2163
+ types: dict = {
2164
+ '1': 'spot account',
2165
+ '3': 'swap account',
2166
+ '5': 'custody account',
2167
+ '6': 'fiat account',
2168
+ }
2169
+ return self.safe_string(types, type, type)
2170
+
2171
+ def encode_account_type(self, type):
2172
+ types = {
2173
+ 'spot': '1',
2174
+ 'swap': '3',
2175
+ 'custody': '5',
2176
+ }
2177
+ return self.safe_integer(types, type, type)
2178
+
2179
+ def encode_flow_type(self, type):
2180
+ types = {
2181
+ 'trade': '1',
2182
+ 'fee': '3',
2183
+ 'transfer': '51',
2184
+ 'deposit': '900',
2185
+ 'withdraw': '904',
2186
+ }
2187
+ return self.safe_integer(types, type, type)
2188
+
2189
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
2190
+ """
2191
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
2192
+
2193
+ https://hashkeyglobal-apidoc.readme.io/reference/get-account-transaction-list
2194
+
2195
+ :param str [code]: unified currency code, default is None(not used)
2196
+ :param int [since]: timestamp in ms of the earliest ledger entry, default is None
2197
+ :param int [limit]: max number of ledger entries to return, default is None
2198
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2199
+ :param int [params.until]: the latest time in ms to fetch entries for
2200
+ :param int [params.flowType]: trade, fee, transfer, deposit, withdrawal
2201
+ :param int [params.accountType]: spot, swap, custody
2202
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
2203
+ """
2204
+ methodName = 'fetchLedger'
2205
+ if since is None:
2206
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a since argument')
2207
+ until: Int = None
2208
+ until, params = self.handle_option_and_params(params, methodName, 'until')
2209
+ if until is None:
2210
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires an until argument')
2211
+ self.load_markets()
2212
+ currency = self.currency(code)
2213
+ request = {}
2214
+ request['startTime'] = since
2215
+ if limit is not None:
2216
+ request['limit'] = limit
2217
+ request['endTime'] = until
2218
+ flowType = None
2219
+ flowType, params = self.handle_option_and_params(params, methodName, 'flowType')
2220
+ if flowType is not None:
2221
+ request['flowType'] = self.encode_flow_type(flowType)
2222
+ accountType = None
2223
+ accountType, params = self.handle_option_and_params(params, methodName, 'accountType')
2224
+ if accountType is not None:
2225
+ request['accountType'] = self.encode_account_type(accountType)
2226
+ response = self.privateGetApiV1AccountBalanceFlow(self.extend(request, params))
2227
+ #
2228
+ # [
2229
+ # {
2230
+ # "id": "1740844413612065537",
2231
+ # "accountId": "1732885739589466112",
2232
+ # "coin": "USDT",
2233
+ # "coinId": "USDT",
2234
+ # "coinName": "USDT",
2235
+ # "flowTypeValue": 51,
2236
+ # "flowType": "USER_ACCOUNT_TRANSFER",
2237
+ # "flowName": "",
2238
+ # "change": "-1",
2239
+ # "total": "8.015680088",
2240
+ # "created": "1722260825765"
2241
+ # },
2242
+ # ...
2243
+ # ]
2244
+ #
2245
+ return self.parse_ledger(response, currency, since, limit)
2246
+
2247
+ def parse_ledger_entry_type(self, type):
2248
+ types: dict = {
2249
+ '1': 'trade', # transfer
2250
+ '2': 'fee', # trade
2251
+ '51': 'transfer',
2252
+ '900': 'deposit',
2253
+ '904': 'withdraw',
2254
+ }
2255
+ return self.safe_string(types, type, type)
2256
+
2257
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
2258
+ #
2259
+ # {
2260
+ # "id": "1740844413612065537",
2261
+ # "accountId": "1732885739589466112",
2262
+ # "coin": "USDT",
2263
+ # "coinId": "USDT",
2264
+ # "coinName": "USDT",
2265
+ # "flowTypeValue": 51,
2266
+ # "flowType": "USER_ACCOUNT_TRANSFER",
2267
+ # "flowName": "",
2268
+ # "change": "-1",
2269
+ # "total": "8.015680088",
2270
+ # "created": "1722260825765"
2271
+ # }
2272
+ #
2273
+ id = self.safe_string(item, 'id')
2274
+ account = self.safe_string(item, 'accountId')
2275
+ timestamp = self.safe_integer(item, 'created')
2276
+ type = self.parse_ledger_entry_type(self.safe_string(item, 'flowTypeValue'))
2277
+ currencyId = self.safe_string(item, 'coin')
2278
+ code = self.safe_currency_code(currencyId, currency)
2279
+ currency = self.safe_currency(currencyId, currency)
2280
+ amountString = self.safe_string(item, 'change')
2281
+ amount = self.parse_number(amountString)
2282
+ direction = 'in'
2283
+ if amountString.find('-') >= 0:
2284
+ direction = 'out'
2285
+ afterString = self.safe_string(item, 'total')
2286
+ after = self.parse_number(afterString)
2287
+ status = 'ok'
2288
+ return self.safe_ledger_entry({
2289
+ 'info': item,
2290
+ 'id': id,
2291
+ 'timestamp': timestamp,
2292
+ 'datetime': self.iso8601(timestamp),
2293
+ 'account': account,
2294
+ 'direction': direction,
2295
+ 'referenceId': None,
2296
+ 'referenceAccount': None,
2297
+ 'type': type,
2298
+ 'currency': code,
2299
+ 'symbol': None,
2300
+ 'amount': amount,
2301
+ 'before': None,
2302
+ 'after': after,
2303
+ 'status': status,
2304
+ 'fee': None,
2305
+ }, currency)
2306
+
2307
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
2308
+ """
2309
+ create a trade order
2310
+
2311
+ https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
2312
+ https://hashkeyglobal-apidoc.readme.io/reference/create-order
2313
+ https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
2314
+
2315
+ :param str symbol: unified symbol of the market to create an order in
2316
+ :param str type: 'market' or 'limit' or 'LIMIT_MAKER' for spot, 'market' or 'limit' or 'STOP' for swap
2317
+ :param str side: 'buy' or 'sell'
2318
+ :param float amount: how much of you want to trade in units of the base currency
2319
+ :param float [price]: the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2320
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2321
+ :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
2322
+ :param boolean [params.test]: *spot markets only* whether to use the test endpoint or not, default is False
2323
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2324
+ :param str [params.timeInForce]: "GTC" or "IOC" or "PO" for spot, 'GTC' or 'FOK' or 'IOC' or 'LIMIT_MAKER' or 'PO' for swap
2325
+ :param str [params.clientOrderId]: a unique id for the order - is mandatory for swap
2326
+ :param float [params.triggerPrice]: *swap markets only* The price at which a trigger order is triggered at
2327
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2328
+ """
2329
+ self.load_markets()
2330
+ market = self.market(symbol)
2331
+ if market['spot']:
2332
+ return self.create_spot_order(symbol, type, side, amount, price, params)
2333
+ elif market['swap']:
2334
+ return self.create_swap_order(symbol, type, side, amount, price, params)
2335
+ else:
2336
+ raise NotSupported(self.id + ' createOrder() is not supported for ' + market['type'] + ' type of markets')
2337
+
2338
+ def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
2339
+ """
2340
+ create a market buy order by providing the symbol and cost
2341
+ :param str symbol: unified symbol of the market to create an order in
2342
+ :param float cost: how much you want to trade in units of the quote currency
2343
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2344
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2345
+ """
2346
+ self.load_markets()
2347
+ market = self.market(symbol)
2348
+ if not market['spot']:
2349
+ raise NotSupported(self.id + ' createMarketBuyOrderWithCost() is supported for spot markets only')
2350
+ params['cost'] = cost
2351
+ return self.create_order(symbol, 'market', 'buy', cost, None, params)
2352
+
2353
+ def create_spot_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
2354
+ """
2355
+ create a trade order on spot market
2356
+
2357
+ https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
2358
+ https://hashkeyglobal-apidoc.readme.io/reference/create-order
2359
+
2360
+ :param str symbol: unified symbol of the market to create an order in
2361
+ :param str type: 'market' or 'limit' or 'LIMIT_MAKER'
2362
+ :param str side: 'buy' or 'sell'
2363
+ :param float amount: how much of you want to trade in units of the base currency
2364
+ :param float [price]: the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2365
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2366
+ :param float [params.cost]: *market buy only* the quote quantity that can be used alternative for the amount
2367
+ :param bool [params.test]: whether to use the test endpoint or not, default is False
2368
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2369
+ :param str [params.timeInForce]: 'GTC', 'IOC', or 'PO'
2370
+ :param str [params.clientOrderId]: a unique id for the order
2371
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2372
+ """
2373
+ triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
2374
+ if triggerPrice is not None:
2375
+ raise NotSupported(self.id + ' trigger orders are not supported for spot markets')
2376
+ self.load_markets()
2377
+ market = self.market(symbol)
2378
+ isMarketBuy = (type == 'market') and (side == 'buy')
2379
+ cost = self.safe_string(params, 'cost')
2380
+ if (not isMarketBuy) and (cost is not None):
2381
+ raise NotSupported(self.id + ' createOrder() supports cost parameter for spot market buy orders only')
2382
+ request: dict = self.create_spot_order_request(symbol, type, side, amount, price, params)
2383
+ response: dict = {}
2384
+ test = self.safe_bool(params, 'test')
2385
+ if test:
2386
+ params = self.omit(params, 'test')
2387
+ response = self.privatePostApiV1SpotOrderTest(request)
2388
+ elif isMarketBuy and (cost is None):
2389
+ response = self.privatePostApiV11SpotOrder(request) # the endpoint for market buy orders by amount
2390
+ #
2391
+ # {
2392
+ # "accountId": "1732885739589466112",
2393
+ # "symbol": "ETHUSDT",
2394
+ # "symbolName": "ETHUSDT",
2395
+ # "clientOrderId": "1722005792096557",
2396
+ # "orderId": "1738705036219839744",
2397
+ # "transactTime": "1722005792106",
2398
+ # "price": "0",
2399
+ # "origQty": "0.006",
2400
+ # "executedQty": "0.0059",
2401
+ # "status": "FILLED",
2402
+ # "timeInForce": "IOC",
2403
+ # "type": "MARKET",
2404
+ # "side": "BUY",
2405
+ # "reqAmount": "0",
2406
+ # "concentration": ""
2407
+ # }
2408
+ #
2409
+ else:
2410
+ response = self.privatePostApiV1SpotOrder(request) # the endpoint for market buy orders by cost and other orders
2411
+ #
2412
+ # market buy
2413
+ # {
2414
+ # "accountId": "1732885739589466112",
2415
+ # "symbol": "ETHUSDT",
2416
+ # "symbolName": "ETHUSDT",
2417
+ # "clientOrderId": "1722004623170558",
2418
+ # "orderId": "1738695230608169984",
2419
+ # "transactTime": "1722004623186",
2420
+ # "price": "0",
2421
+ # "origQty": "0",
2422
+ # "executedQty": "0.0061",
2423
+ # "status": "FILLED",
2424
+ # "timeInForce": "IOC",
2425
+ # "type": "MARKET",
2426
+ # "side": "BUY",
2427
+ # "reqAmount": "20",
2428
+ # "concentration": ""
2429
+ # }
2430
+ #
2431
+ # market sell
2432
+ # {
2433
+ # "accountId": "1732885739589466112",
2434
+ # "symbol": "ETHUSDT",
2435
+ # "symbolName": "ETHUSDT",
2436
+ # "clientOrderId": "1722005654516362",
2437
+ # "orderId": "1738703882140316928",
2438
+ # "transactTime": "1722005654529",
2439
+ # "price": "0",
2440
+ # "origQty": "0.006",
2441
+ # "executedQty": "0.006",
2442
+ # "status": "FILLED",
2443
+ # "timeInForce": "IOC",
2444
+ # "type": "MARKET",
2445
+ # "side": "SELL",
2446
+ # "reqAmount": "0",
2447
+ # "concentration": ""
2448
+ # }
2449
+ #
2450
+ # limit
2451
+ # {
2452
+ # "accountId": "1732885739589466112",
2453
+ # "symbol": "ETHUSDT",
2454
+ # "symbolName": "ETHUSDT",
2455
+ # "clientOrderId": "1722006209978370",
2456
+ # "orderId": "1738708541676585728",
2457
+ # "transactTime": "1722006209989",
2458
+ # "price": "5000",
2459
+ # "origQty": "0.005",
2460
+ # "executedQty": "0",
2461
+ # "status": "NEW",
2462
+ # "timeInForce": "GTC",
2463
+ # "type": "LIMIT_MAKER",
2464
+ # "side": "SELL",
2465
+ # "reqAmount": "0",
2466
+ # "concentration": ""
2467
+ # }
2468
+ #
2469
+ return self.parse_order(response, market)
2470
+
2471
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> dict:
2472
+ market = self.market(symbol)
2473
+ if market['spot']:
2474
+ return self.create_spot_order_request(symbol, type, side, amount, price, params)
2475
+ elif market['swap']:
2476
+ return self.create_swap_order_request(symbol, type, side, amount, price, params)
2477
+ else:
2478
+ raise NotSupported(self.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets')
2479
+
2480
+ def create_spot_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> dict:
2481
+ """
2482
+ @ignore
2483
+ helper function to build request
2484
+ :param str symbol: unified symbol of the market to create an order in
2485
+ :param str type: 'market' or 'limit' or 'LIMIT_MAKER'
2486
+ :param str side: 'buy' or 'sell'
2487
+ :param float amount: how much of you want to trade in units of the base currency
2488
+ :param float [price]: the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2489
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2490
+ :param float [params.cost]: *market buy only* the quote quantity that can be used alternative for the amount
2491
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2492
+ :param str [params.timeInForce]: "GTC", "IOC", or "PO"
2493
+ :param str [params.clientOrderId]: a unique id for the order
2494
+ :returns dict: request to be sent to the exchange
2495
+ """
2496
+ market = self.market(symbol)
2497
+ type = type.upper()
2498
+ request: dict = {
2499
+ 'symbol': market['id'],
2500
+ 'side': side.upper(),
2501
+ 'type': type,
2502
+ }
2503
+ if amount is not None:
2504
+ request['quantity'] = self.amount_to_precision(symbol, amount)
2505
+ cost: Str = None
2506
+ cost, params = self.handle_param_string(params, 'cost')
2507
+ if cost is not None:
2508
+ request['quantity'] = self.cost_to_precision(symbol, cost)
2509
+ if price is not None:
2510
+ request['price'] = self.price_to_precision(symbol, price)
2511
+ isMarketOrder = type == 'MARKET'
2512
+ postOnly = False
2513
+ postOnly, params = self.handle_post_only(isMarketOrder, type == 'LIMIT_MAKER', params)
2514
+ if postOnly and (type == 'LIMIT'):
2515
+ request['type'] = 'LIMIT_MAKER'
2516
+ clientOrderId: Str = None
2517
+ clientOrderId, params = self.handle_param_string(params, 'clientOrderId')
2518
+ if clientOrderId is not None:
2519
+ params['newClientOrderId'] = clientOrderId
2520
+ return self.extend(request, params)
2521
+
2522
+ def create_swap_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> dict:
2523
+ """
2524
+ @ignore
2525
+ helper function to build request
2526
+ :param str symbol: unified symbol of the market to create an order in
2527
+ :param str type: 'market' or 'limit' or 'STOP'
2528
+ :param str side: 'buy' or 'sell'
2529
+ :param float amount: how much of you want to trade in units of the base currency
2530
+ :param float [price]: the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2531
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2532
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2533
+ :param bool [params.reduceOnly]: True or False whether the order is reduce only
2534
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
2535
+ :param str [params.timeInForce]: 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
2536
+ :param str [params.clientOrderId]: a unique id for the order
2537
+ :returns dict: request to be sent to the exchange
2538
+ """
2539
+ market = self.market(symbol)
2540
+ request: dict = {
2541
+ 'symbol': market['id'],
2542
+ 'type': 'LIMIT',
2543
+ 'quantity': self.amount_to_precision(symbol, amount),
2544
+ }
2545
+ isMarketOrder = type == 'market'
2546
+ if isMarketOrder:
2547
+ request['priceType'] = 'MARKET'
2548
+ if price is not None:
2549
+ request['price'] = self.price_to_precision(symbol, price)
2550
+ request['priceType'] = 'INPUT'
2551
+ reduceOnly = False
2552
+ reduceOnly, params = self.handle_param_bool(params, 'reduceOnly', reduceOnly)
2553
+ suffix = '_OPEN'
2554
+ if reduceOnly:
2555
+ suffix = '_CLOSE'
2556
+ request['side'] = side.upper() + suffix
2557
+ timeInForce: Str = None
2558
+ timeInForce, params = self.handle_param_string(params, 'timeInForce')
2559
+ postOnly = False
2560
+ postOnly, params = self.handle_post_only(isMarketOrder, timeInForce == 'LIMIT_MAKER', params)
2561
+ if postOnly:
2562
+ timeInForce = 'LIMIT_MAKER'
2563
+ if timeInForce is not None:
2564
+ request['timeInForce'] = timeInForce
2565
+ clientOrderId = self.safe_string(params, 'clientOrderId')
2566
+ if clientOrderId is None:
2567
+ request['clientOrderId'] = self.uuid()
2568
+ triggerPrice = self.safe_string(params, 'triggerPrice')
2569
+ if triggerPrice is not None:
2570
+ request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
2571
+ request['type'] = 'STOP'
2572
+ params = self.omit(params, 'triggerPrice')
2573
+ return self.extend(request, params)
2574
+
2575
+ def create_swap_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
2576
+ """
2577
+ create a trade order on swap market
2578
+
2579
+ https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
2580
+
2581
+ :param str symbol: unified symbol of the market to create an order in
2582
+ :param str type: 'market' or 'limit' or 'STOP'
2583
+ :param str side: 'buy' or 'sell'
2584
+ :param float amount: how much of you want to trade in units of the base currency
2585
+ :param float [price]: the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2586
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2587
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2588
+ :param bool [params.reduceOnly]: True or False whether the order is reduce only
2589
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
2590
+ :param str [params.timeInForce]: 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
2591
+ :param str [params.clientOrderId]: a unique id for the order
2592
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2593
+ """
2594
+ self.load_markets()
2595
+ market = self.market(symbol)
2596
+ request = self.create_swap_order_request(symbol, type, side, amount, price, params)
2597
+ response = self.privatePostApiV1FuturesOrder(self.extend(request, params))
2598
+ #
2599
+ # {
2600
+ # "time": "1722429951611",
2601
+ # "updateTime": "1722429951648",
2602
+ # "orderId": "1742263144028363776",
2603
+ # "clientOrderId": "1722429950315",
2604
+ # "symbol": "ETHUSDT-PERPETUAL",
2605
+ # "price": "3460.62",
2606
+ # "leverage": "5",
2607
+ # "origQty": "10",
2608
+ # "executedQty": "10",
2609
+ # "avgPrice": "0",
2610
+ # "marginLocked": "6.9212",
2611
+ # "type": "LIMIT",
2612
+ # "side": "BUY_OPEN",
2613
+ # "timeInForce": "IOC",
2614
+ # "status": "FILLED",
2615
+ # "priceType": "MARKET",
2616
+ # "contractMultiplier": "0.00100000"
2617
+ # }
2618
+ #
2619
+ return self.parse_order(response, market)
2620
+
2621
+ def create_orders(self, orders: List[OrderRequest], params={}):
2622
+ """
2623
+ create a list of trade orders(all orders should be of the same symbol)
2624
+
2625
+ https://hashkeyglobal-apidoc.readme.io/reference/create-multiple-orders
2626
+ https://hashkeyglobal-apidoc.readme.io/reference/batch-create-new-futures-order
2627
+
2628
+ :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
2629
+ :param dict [params]: extra parameters specific to the api endpoint
2630
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2631
+ """
2632
+ self.load_markets()
2633
+ ordersRequests = []
2634
+ for i in range(0, len(orders)):
2635
+ rawOrder = orders[i]
2636
+ symbol = self.safe_string(rawOrder, 'symbol')
2637
+ type = self.safe_string(rawOrder, 'type')
2638
+ side = self.safe_string(rawOrder, 'side')
2639
+ amount = self.safe_number(rawOrder, 'amount')
2640
+ price = self.safe_number(rawOrder, 'price')
2641
+ orderParams = self.safe_dict(rawOrder, 'params', {})
2642
+ orderRequest = self.create_order_request(symbol, type, side, amount, price, orderParams)
2643
+ clientOrderId = self.safe_string(orderRequest, 'clientOrderId')
2644
+ if clientOrderId is None:
2645
+ orderRequest['clientOrderId'] = self.uuid() # both spot and swap endpoints require clientOrderId
2646
+ ordersRequests.append(orderRequest)
2647
+ firstOrder = ordersRequests[0]
2648
+ firstSymbol = self.safe_string(firstOrder, 'symbol')
2649
+ market = self.market(firstSymbol)
2650
+ request: dict = {
2651
+ 'orders': ordersRequests,
2652
+ }
2653
+ response = None
2654
+ if market['spot']:
2655
+ response = self.privatePostApiV1SpotBatchOrders(self.extend(request, params))
2656
+ #
2657
+ # {
2658
+ # "code": 0,
2659
+ # "result": [
2660
+ # {
2661
+ # "code": "0000",
2662
+ # "order": {
2663
+ # "accountId": "1732885739589466112",
2664
+ # "symbol": "ETHUSDT",
2665
+ # "symbolName": "ETHUSDT",
2666
+ # "clientOrderId": "1722701490163000",
2667
+ # "orderId": "1744540984757258752",
2668
+ # "transactTime": "1722701491385",
2669
+ # "price": "1500",
2670
+ # "origQty": "0.001",
2671
+ # "executedQty": "0",
2672
+ # "status": "NEW",
2673
+ # "timeInForce": "GTC",
2674
+ # "type": "LIMIT",
2675
+ # "side": "BUY",
2676
+ # "reqAmount": "0"
2677
+ # }
2678
+ # }
2679
+ # ],
2680
+ # "concentration": ""
2681
+ # }
2682
+ #
2683
+ elif market['swap']:
2684
+ response = self.privatePostApiV1FuturesBatchOrders(self.extend(request, params))
2685
+ #
2686
+ # {
2687
+ # "code": "0000",
2688
+ # "result": [
2689
+ # {
2690
+ # "code": "0000",
2691
+ # "order": {
2692
+ # "time": "1722704251911",
2693
+ # "updateTime": "1722704251918",
2694
+ # "orderId": "1744564141727808768",
2695
+ # "clientOrderId": "1722704250648000",
2696
+ # "symbol": "ETHUSDT-PERPETUAL",
2697
+ # "price": "1500",
2698
+ # "leverage": "4",
2699
+ # "origQty": "1",
2700
+ # "executedQty": "0",
2701
+ # "avgPrice": "0",
2702
+ # "marginLocked": "0.375",
2703
+ # "type": "LIMIT",
2704
+ # "side": "BUY_OPEN",
2705
+ # "timeInForce": "GTC",
2706
+ # "status": "NEW",
2707
+ # "priceType": "INPUT",
2708
+ # "isLiquidationOrder": False,
2709
+ # "indexPrice": "0",
2710
+ # "liquidationType": ""
2711
+ # }
2712
+ # },
2713
+ # {
2714
+ # "code": "0207",
2715
+ # "msg": "Create limit order sell price too low"
2716
+ # }
2717
+ # ]
2718
+ # }
2719
+ #
2720
+ else:
2721
+ raise NotSupported(self.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets')
2722
+ result = self.safe_list(response, 'result', [])
2723
+ responseOrders = []
2724
+ for i in range(0, len(result)):
2725
+ responseEntry = self.safe_dict(result, i, {})
2726
+ responseOrder = self.safe_dict(responseEntry, 'order', {})
2727
+ responseOrders.append(responseOrder)
2728
+ return self.parse_orders(responseOrders)
2729
+
2730
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
2731
+ """
2732
+ cancels an open order
2733
+
2734
+ https://hashkeyglobal-apidoc.readme.io/reference/cancel-order
2735
+ https://hashkeyglobal-apidoc.readme.io/reference/cancel-futures-order
2736
+
2737
+ :param str id: order id
2738
+ :param str symbol: unified symbol of the market the order was made in
2739
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2740
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch entry for(default 'spot')
2741
+ :param str [params.clientOrderId]: a unique id for the order that can be used alternative for the id
2742
+ :param bool [params.trigger]: *swap markets only* True for canceling a trigger order(default False)
2743
+ :param bool [params.stop]: *swap markets only* an alternative for trigger param
2744
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2745
+ """
2746
+ methodName = 'cancelOrder'
2747
+ self.check_type_param(methodName, params)
2748
+ self.load_markets()
2749
+ request: dict = {}
2750
+ clientOrderId = self.safe_string(params, 'clientOrderId')
2751
+ if clientOrderId is None:
2752
+ request['orderId'] = id
2753
+ market: Market = None
2754
+ if symbol is not None:
2755
+ market = self.market(symbol)
2756
+ marketType = 'spot'
2757
+ marketType, params = self.handle_market_type_and_params(methodName, market, params, marketType)
2758
+ response = None
2759
+ if marketType == 'spot':
2760
+ response = self.privateDeleteApiV1SpotOrder(self.extend(request, params))
2761
+ #
2762
+ # {
2763
+ # "accountId": "1732885739589466112",
2764
+ # "symbol": "ETHUSDT",
2765
+ # "clientOrderId": "1722006209978370",
2766
+ # "orderId": "1738708541676585728",
2767
+ # "transactTime": "1722006209989",
2768
+ # "price": "5000",
2769
+ # "origQty": "0.005",
2770
+ # "executedQty": "0",
2771
+ # "status": "NEW",
2772
+ # "timeInForce": "GTC",
2773
+ # "type": "LIMIT_MAKER",
2774
+ # "side": "SELL"
2775
+ # }
2776
+ #
2777
+ elif marketType == 'swap':
2778
+ isTrigger = False
2779
+ isTrigger, params = self.handle_trigger_option_and_params(params, methodName, isTrigger)
2780
+ if isTrigger:
2781
+ request['type'] = 'STOP'
2782
+ else:
2783
+ request['type'] = 'LIMIT'
2784
+ if market is not None:
2785
+ request['symbol'] = market['id']
2786
+ response = self.privateDeleteApiV1FuturesOrder(self.extend(request, params))
2787
+ #
2788
+ # {
2789
+ # "time": "1722432302919",
2790
+ # "updateTime": "1722432302925",
2791
+ # "orderId": "1742282868229463040",
2792
+ # "clientOrderId": "1722432301670",
2793
+ # "symbol": "ETHUSDT-PERPETUAL",
2794
+ # "price": "4000",
2795
+ # "leverage": "5",
2796
+ # "origQty": "10",
2797
+ # "executedQty": "0",
2798
+ # "avgPrice": "0",
2799
+ # "marginLocked": "0",
2800
+ # "type": "LIMIT_MAKER",
2801
+ # "side": "SELL_CLOSE",
2802
+ # "timeInForce": "GTC",
2803
+ # "status": "NEW",
2804
+ # "priceType": "INPUT",
2805
+ # "isLiquidationOrder": False,
2806
+ # "indexPrice": "0",
2807
+ # "liquidationType": ""
2808
+ # }
2809
+ #
2810
+ else:
2811
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
2812
+ return self.parse_order(response)
2813
+
2814
+ def cancel_all_orders(self, symbol: Str = None, params={}):
2815
+ """
2816
+ cancel all open orders
2817
+
2818
+ https://hashkeyglobal-apidoc.readme.io/reference/cancel-all-open-orders
2819
+ https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order
2820
+
2821
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
2822
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2823
+ :param str [params.side]: 'buy' or 'sell'
2824
+ :returns dict: response from exchange
2825
+ """
2826
+ # Does not cancel trigger orders. For canceling trigger order use cancelOrder() or cancelOrders()
2827
+ methodName = 'cancelAllOrders'
2828
+ if symbol is None:
2829
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a symbol argument')
2830
+ self.load_markets()
2831
+ market = self.market(symbol)
2832
+ request: dict = {
2833
+ 'symbol': market['id'],
2834
+ }
2835
+ side = self.safe_string(params, 'side')
2836
+ if side is not None:
2837
+ request['side'] = side
2838
+ response = None
2839
+ if market['spot']:
2840
+ response = self.privateDeleteApiV1SpotOpenOrders(self.extend(request, params))
2841
+ #
2842
+ # {"success": True}
2843
+ #
2844
+ elif market['swap']:
2845
+ response = self.privateDeleteApiV1FuturesBatchOrders(self.extend(request, params))
2846
+ #
2847
+ # {"message": "success", "timestamp": "1723127222198", "code": "0000"}
2848
+ #
2849
+ else:
2850
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets')
2851
+ order = self.safe_order(response)
2852
+ order['info'] = response
2853
+ return [order]
2854
+
2855
+ def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
2856
+ """
2857
+ cancel multiple orders
2858
+
2859
+ https://hashkeyglobal-apidoc.readme.io/reference/cancel-multiple-orders
2860
+ https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order-by-order-id
2861
+
2862
+ :param str[] ids: order ids
2863
+ :param str [symbol]: unified market symbol(not used by hashkey)
2864
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2865
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch entry for(default 'spot')
2866
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2867
+ """
2868
+ methodName = 'cancelOrders'
2869
+ self.load_markets()
2870
+ request = {}
2871
+ orderIds = ','.join(ids)
2872
+ request['ids'] = orderIds
2873
+ market: Market = None
2874
+ if symbol is not None:
2875
+ market = self.market(symbol)
2876
+ marketType = 'spot'
2877
+ marketType, params = self.handle_market_type_and_params(methodName, market, params, marketType)
2878
+ response = None
2879
+ if marketType == 'spot':
2880
+ response = self.privateDeleteApiV1SpotCancelOrderByIds(self.extend(request))
2881
+ #
2882
+ # {
2883
+ # "code": "0000",
2884
+ # "result": []
2885
+ # }
2886
+ #
2887
+ elif marketType == 'swap':
2888
+ response = self.privateDeleteApiV1FuturesCancelOrderByIds(self.extend(request))
2889
+ else:
2890
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
2891
+ order = self.safe_order(response)
2892
+ order['info'] = response
2893
+ return [order]
2894
+
2895
+ def fetch_order(self, id: str, symbol: Str = None, params={}) -> Order:
2896
+ """
2897
+ fetches information on an order made by the user
2898
+
2899
+ https://hashkeyglobal-apidoc.readme.io/reference/query-order
2900
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-order
2901
+
2902
+ :param str id: the order id
2903
+ :param str symbol: unified symbol of the market the order was made in
2904
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2905
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch entry for(default 'spot')
2906
+ :param str [params.clientOrderId]: a unique id for the order that can be used alternative for the id
2907
+ :param str [params.accountId]: *spot markets only* account id to fetch the order from
2908
+ :param bool [params.trigger]: *swap markets only* True for fetching a trigger order(default False)
2909
+ :param bool [params.stop]: *swap markets only* an alternative for trigger param
2910
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2911
+ """
2912
+ methodName = 'fetchOrder'
2913
+ self.check_type_param(methodName, params)
2914
+ self.load_markets()
2915
+ request: dict = {}
2916
+ clientOrderId: Str = None
2917
+ clientOrderId, params = self.handle_param_string(params, 'clientOrderId')
2918
+ if clientOrderId is None:
2919
+ request['orderId'] = id
2920
+ market: Market = None
2921
+ if symbol is not None:
2922
+ market = self.market(symbol)
2923
+ marketType = 'spot'
2924
+ marketType, params = self.handle_market_type_and_params(methodName, market, params, marketType)
2925
+ response = None
2926
+ if marketType == 'spot':
2927
+ if clientOrderId is not None:
2928
+ request['origClientOrderId'] = clientOrderId
2929
+ accountId: Str = None
2930
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
2931
+ if accountId is not None:
2932
+ request['accountId'] = accountId
2933
+ response = self.privateGetApiV1SpotOrder(self.extend(request, params))
2934
+ #
2935
+ # {
2936
+ # "accountId": "1732885739589466112",
2937
+ # "exchangeId": "301",
2938
+ # "symbol": "ETHUSDT",
2939
+ # "symbolName": "ETHUSDT",
2940
+ # "clientOrderId": "1722004623170558",
2941
+ # "orderId": "1738695230608169984",
2942
+ # "price": "0",
2943
+ # "origQty": "0",
2944
+ # "executedQty": "0.0061",
2945
+ # "cummulativeQuoteQty": "19.736489",
2946
+ # "cumulativeQuoteQty": "19.736489",
2947
+ # "avgPrice": "3235.49",
2948
+ # "status": "FILLED",
2949
+ # "timeInForce": "IOC",
2950
+ # "type": "MARKET",
2951
+ # "side": "BUY",
2952
+ # "stopPrice": "0.0",
2953
+ # "icebergQty": "0.0",
2954
+ # "time": "1722004623186",
2955
+ # "updateTime": "1722004623406",
2956
+ # "isWorking": True,
2957
+ # "reqAmount": "20",
2958
+ # "feeCoin": "",
2959
+ # "feeAmount": "0",
2960
+ # "sumFeeAmount": "0"
2961
+ # }
2962
+ #
2963
+ elif marketType == 'swap':
2964
+ isTrigger = False
2965
+ isTrigger, params = self.handle_trigger_option_and_params(params, methodName, isTrigger)
2966
+ if isTrigger:
2967
+ request['type'] = 'STOP'
2968
+ response = self.privateGetApiV1FuturesOrder(self.extend(request, params))
2969
+ #
2970
+ # {
2971
+ # "time": "1722429951611",
2972
+ # "updateTime": "1722429951700",
2973
+ # "orderId": "1742263144028363776",
2974
+ # "clientOrderId": "1722429950315",
2975
+ # "symbol": "ETHUSDT-PERPETUAL",
2976
+ # "price": "3460.62",
2977
+ # "leverage": "5",
2978
+ # "origQty": "10",
2979
+ # "executedQty": "10",
2980
+ # "avgPrice": "3327.52",
2981
+ # "marginLocked": "0",
2982
+ # "type": "LIMIT",
2983
+ # "side": "BUY_OPEN",
2984
+ # "timeInForce": "IOC",
2985
+ # "status": "FILLED",
2986
+ # "priceType": "MARKET",
2987
+ # "isLiquidationOrder": False,
2988
+ # "indexPrice": "0",
2989
+ # "liquidationType": ""
2990
+ # }
2991
+ #
2992
+ else:
2993
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
2994
+ return self.parse_order(response)
2995
+
2996
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2997
+ """
2998
+ fetch all unfilled currently open orders
2999
+
3000
+ https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
3001
+ https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
3002
+ https://hashkeyglobal-apidoc.readme.io/reference/sub
3003
+ https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
3004
+
3005
+ :param str [symbol]: unified market symbol of the market orders were made in - is mandatory for swap markets
3006
+ :param int [since]: the earliest time in ms to fetch orders for
3007
+ :param int [limit]: the maximum number of order structures to retrieve - default 500, maximum 1000
3008
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3009
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch entries for(default 'spot')
3010
+ :param str [params.orderId]: *spot markets only* the id of the order to fetch
3011
+ :param str [params.side]: *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
3012
+ :param str [params.fromOrderId]: *swap markets only* the id of the order to start from
3013
+ :param bool [params.trigger]: *swap markets only* True for fetching trigger orders(default False)
3014
+ :param bool [params.stop]: *swap markets only* an alternative for trigger param
3015
+ :param str [params.accountId]: account id to fetch the orders from
3016
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3017
+ """
3018
+ methodName = 'fetchOpenOrders'
3019
+ self.check_type_param(methodName, params)
3020
+ self.load_markets()
3021
+ market: Market = None
3022
+ if symbol is not None:
3023
+ market = self.market(symbol)
3024
+ marketType = 'spot'
3025
+ marketType, params = self.handle_market_type_and_params(methodName, market, params, marketType)
3026
+ params = self.extend({'methodName': methodName}, params)
3027
+ if marketType == 'spot':
3028
+ return self.fetch_open_spot_orders(symbol, since, limit, params)
3029
+ elif marketType == 'swap':
3030
+ return self.fetch_open_swap_orders(symbol, since, limit, params)
3031
+ else:
3032
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
3033
+
3034
+ def fetch_open_spot_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3035
+ """
3036
+ @ignore
3037
+ fetch all unfilled currently open orders for spot markets
3038
+
3039
+ https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
3040
+ https://hashkeyglobal-apidoc.readme.io/reference/sub
3041
+
3042
+ :param str [symbol]: unified market symbol of the market orders were made in
3043
+ :param int [since]: the earliest time in ms to fetch orders for
3044
+ :param int [limit]: the maximum number of order structures to retrieve - default 500, maximum 1000
3045
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3046
+ :param str [params.orderId]: the id of the order to fetch
3047
+ :param str [params.side]: 'buy' or 'sell' - the side of the orders to fetch
3048
+ :param str [params.accountId]: account id to fetch the orders from
3049
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3050
+ """
3051
+ self.load_markets()
3052
+ methodName = 'fetchOpenSpotOrders'
3053
+ methodName, params = self.handle_param_string(params, 'methodName', methodName)
3054
+ market: Market = None
3055
+ request: dict = {}
3056
+ response = None
3057
+ accountId: Str = None
3058
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
3059
+ if accountId is not None:
3060
+ request['subAccountId'] = accountId
3061
+ response = self.privateGetApiV1SpotSubAccountOpenOrders(self.extend(request, params))
3062
+ else:
3063
+ if symbol is not None:
3064
+ market = self.market(symbol)
3065
+ request['symbol'] = market['id']
3066
+ if limit is not None:
3067
+ request['limit'] = limit
3068
+ orderId: Str = None
3069
+ orderId, params = self.handle_option_and_params(params, methodName, 'orderId')
3070
+ if orderId is not None:
3071
+ request['orderId'] = orderId
3072
+ side: Str = None
3073
+ side, params = self.handle_option_and_params(params, methodName, 'side')
3074
+ if side is not None:
3075
+ request['side'] = side.upper()
3076
+ response = self.privateGetApiV1SpotOpenOrders(self.extend(request, params))
3077
+ #
3078
+ # [
3079
+ # {
3080
+ # "accountId": "1732885739589466112",
3081
+ # "exchangeId": "301",
3082
+ # "symbol": "ETHUSDT",
3083
+ # "symbolName": "ETHUSDT",
3084
+ # "clientOrderId": "1",
3085
+ # "orderId": "1739491435386897152",
3086
+ # "price": "2000",
3087
+ # "origQty": "0.001",
3088
+ # "executedQty": "0",
3089
+ # "cummulativeQuoteQty": "0",
3090
+ # "cumulativeQuoteQty": "0",
3091
+ # "avgPrice": "0",
3092
+ # "status": "NEW",
3093
+ # "timeInForce": "GTC",
3094
+ # "type": "LIMIT",
3095
+ # "side": "BUY",
3096
+ # "stopPrice": "0.0",
3097
+ # "icebergQty": "0.0",
3098
+ # "time": "1722099538193",
3099
+ # "updateTime": "1722099538197",
3100
+ # "isWorking": True,
3101
+ # "reqAmount": "0"
3102
+ # }
3103
+ # ]
3104
+ #
3105
+ return self.parse_orders(response, market, since, limit)
3106
+
3107
+ def fetch_open_swap_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3108
+ """
3109
+ @ignore
3110
+ fetch all unfilled currently open orders for swap markets
3111
+
3112
+ https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
3113
+ https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
3114
+
3115
+ :param str symbol: *is mandatory* unified market symbol of the market orders were made in
3116
+ :param int [since]: the earliest time in ms to fetch orders for
3117
+ :param int [limit]: the maximum number of order structures to retrieve - maximum 500
3118
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3119
+ :param str [params.fromOrderId]: the id of the order to start from
3120
+ :param bool [params.trigger]: True for fetching trigger orders(default False)
3121
+ :param bool [params.stop]: an alternative for trigger param
3122
+ :param str [params.accountId]: account id to fetch the orders from
3123
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3124
+ """
3125
+ methodName = 'fetchOpenSwapOrders'
3126
+ methodName, params = self.handle_param_string(params, 'methodName', methodName)
3127
+ if symbol is None:
3128
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a symbol argument for swap market orders')
3129
+ market = self.market(symbol)
3130
+ request: dict = {
3131
+ 'symbol': market['id'],
3132
+ }
3133
+ isTrigger = False
3134
+ isTrigger, params = self.handle_trigger_option_and_params(params, methodName, isTrigger)
3135
+ if isTrigger:
3136
+ request['type'] = 'STOP'
3137
+ else:
3138
+ request['type'] = 'LIMIT'
3139
+ if limit is not None:
3140
+ request['limit'] = limit
3141
+ fromOrderId: Str = None
3142
+ fromOrderId, params = self.handle_option_and_params(params, methodName, 'fromOrderId')
3143
+ if fromOrderId is not None:
3144
+ request['fromOrderId'] = fromOrderId
3145
+ response = None
3146
+ accountId: Str = None
3147
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
3148
+ if accountId is not None:
3149
+ request['subAccountId'] = accountId
3150
+ response = self.privateGetApiV1FuturesSubAccountOpenOrders(self.extend(request, params))
3151
+ else:
3152
+ response = self.privateGetApiV1FuturesOpenOrders(self.extend(request, params))
3153
+ # 'LIMIT'
3154
+ # [
3155
+ # {
3156
+ # "time": "1722432302919",
3157
+ # "updateTime": "1722432302925",
3158
+ # "orderId": "1742282868229463040",
3159
+ # "clientOrderId": "1722432301670",
3160
+ # "symbol": "ETHUSDT-PERPETUAL",
3161
+ # "price": "4000",
3162
+ # "leverage": "5",
3163
+ # "origQty": "10",
3164
+ # "executedQty": "0",
3165
+ # "avgPrice": "0",
3166
+ # "marginLocked": "0",
3167
+ # "type": "LIMIT_MAKER",
3168
+ # "side": "SELL_CLOSE",
3169
+ # "timeInForce": "GTC",
3170
+ # "status": "NEW",
3171
+ # "priceType": "INPUT",
3172
+ # "isLiquidationOrder": False,
3173
+ # "indexPrice": "0",
3174
+ # "liquidationType": ""
3175
+ # }
3176
+ # ]
3177
+ #
3178
+ # 'STOP'
3179
+ # [
3180
+ # {
3181
+ # "time": "1722433095688",
3182
+ # "updateTime": "1722433095688",
3183
+ # "orderId": "1742289518466225664",
3184
+ # "accountId": "1735619524953226496",
3185
+ # "clientOrderId": "1722433094438",
3186
+ # "symbol": "ETHUSDT-PERPETUAL",
3187
+ # "price": "3700",
3188
+ # "leverage": "0",
3189
+ # "origQty": "10",
3190
+ # "type": "STOP",
3191
+ # "side": "SELL_CLOSE",
3192
+ # "status": "ORDER_NEW",
3193
+ # "stopPrice": "3600"
3194
+ # }
3195
+ # ]
3196
+ return self.parse_orders(response, market, since, limit)
3197
+
3198
+ def fetch_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3199
+ """
3200
+ fetches information on multiple canceled and closed orders made by the user
3201
+
3202
+ https://hashkeyglobal-apidoc.readme.io/reference/get-all-orders
3203
+ https://hashkeyglobal-apidoc.readme.io/reference/query-futures-history-orders
3204
+ https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-history-orders
3205
+
3206
+ :param str symbol: *is mandatory for swap markets* unified market symbol of the market orders were made in
3207
+ :param int [since]: the earliest time in ms to fetch orders for
3208
+ :param int [limit]: the maximum number of order structures to retrieve - default 500, maximum 1000
3209
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3210
+ :param int [params.until]: the latest time in ms to fetch entries for - only supports the last 90 days timeframe
3211
+ :param str [params.type]: 'spot' or 'swap' - the type of the market to fetch entries for(default 'spot')
3212
+ :param str [params.orderId]: *spot markets only* the id of the order to fetch
3213
+ :param str [params.side]: *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
3214
+ :param str [params.fromOrderId]: *swap markets only* the id of the order to start from
3215
+ :param bool [params.trigger]: *swap markets only* the id of the order to start from True for fetching trigger orders(default False)
3216
+ :param bool [params.stop]: *swap markets only* the id of the order to start from an alternative for trigger param
3217
+ :param str [params.accountId]: account id to fetch the orders from
3218
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3219
+ """
3220
+ methodName = 'fetchCanceledAndClosedOrders'
3221
+ self.check_type_param(methodName, params)
3222
+ self.load_markets()
3223
+ request: dict = {}
3224
+ if limit is not None:
3225
+ request['limit'] = limit
3226
+ if since is not None:
3227
+ request['startTime'] = since
3228
+ until: Int = None
3229
+ until, params = self.handle_option_and_params(params, methodName, 'until')
3230
+ if until is not None:
3231
+ request['endTime'] = until
3232
+ accountId: Str = None
3233
+ accountId, params = self.handle_option_and_params(params, methodName, 'accountId')
3234
+ market: Market = None
3235
+ if symbol is not None:
3236
+ market = self.market(symbol)
3237
+ marketType = 'spot'
3238
+ marketType, params = self.handle_market_type_and_params(methodName, market, params, marketType)
3239
+ response = None
3240
+ if marketType == 'spot':
3241
+ if market is not None:
3242
+ request['symbol'] = market['id']
3243
+ orderId: Str = None
3244
+ orderId, params = self.handle_option_and_params(params, methodName, 'orderId')
3245
+ if orderId is not None:
3246
+ request['orderId'] = orderId
3247
+ side: Str = None
3248
+ side, params = self.handle_option_and_params(params, methodName, 'side')
3249
+ if side is not None:
3250
+ request['side'] = side.upper()
3251
+ if accountId is not None:
3252
+ request['accountId'] = accountId
3253
+ response = self.privateGetApiV1SpotTradeOrders(self.extend(request, params))
3254
+ #
3255
+ # [
3256
+ # {
3257
+ # "accountId": "1732885739589466112",
3258
+ # "exchangeId": "301",
3259
+ # "symbol": "ETHUSDT",
3260
+ # "symbolName": "ETHUSDT",
3261
+ # "clientOrderId": "1722082982086472",
3262
+ # "orderId": "1739352552762301440",
3263
+ # "price": "0",
3264
+ # "origQty": "0.001",
3265
+ # "executedQty": "0.001",
3266
+ # "cummulativeQuoteQty": "3.28996",
3267
+ # "cumulativeQuoteQty": "3.28996",
3268
+ # "avgPrice": "3289.96",
3269
+ # "status": "FILLED",
3270
+ # "timeInForce": "IOC",
3271
+ # "type": "MARKET",
3272
+ # "side": "BUY",
3273
+ # "stopPrice": "0.0",
3274
+ # "icebergQty": "0.0",
3275
+ # "time": "1722082982093",
3276
+ # "updateTime": "1722082982097",
3277
+ # "isWorking": True,
3278
+ # "reqAmount": "0"
3279
+ # },
3280
+ # ...
3281
+ # ]
3282
+ #
3283
+ elif marketType == 'swap':
3284
+ if symbol is None:
3285
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a symbol argument for swap markets')
3286
+ request['symbol'] = market['id']
3287
+ isTrigger = False
3288
+ isTrigger, params = self.handle_trigger_option_and_params(params, methodName, isTrigger)
3289
+ if isTrigger:
3290
+ request['type'] = 'STOP'
3291
+ else:
3292
+ request['type'] = 'LIMIT'
3293
+ fromOrderId: Str = None
3294
+ fromOrderId, params = self.handle_option_and_params(params, methodName, 'fromOrderId')
3295
+ if fromOrderId is not None:
3296
+ request['fromOrderId'] = fromOrderId
3297
+ if accountId is not None:
3298
+ request['subAccountId'] = accountId
3299
+ response = self.privateGetApiV1FuturesSubAccountHistoryOrders(self.extend(request, params))
3300
+ else:
3301
+ response = self.privateGetApiV1FuturesHistoryOrders(self.extend(request, params))
3302
+ #
3303
+ # [
3304
+ # {
3305
+ # "time": "1722429951611",
3306
+ # "updateTime": "1722429951700",
3307
+ # "orderId": "1742263144028363776",
3308
+ # "clientOrderId": "1722429950315",
3309
+ # "symbol": "ETHUSDT-PERPETUAL",
3310
+ # "price": "3460.62",
3311
+ # "leverage": "5",
3312
+ # "origQty": "10",
3313
+ # "executedQty": "10",
3314
+ # "avgPrice": "3327.52",
3315
+ # "marginLocked": "0",
3316
+ # "type": "LIMIT",
3317
+ # "side": "BUY_OPEN",
3318
+ # "timeInForce": "IOC",
3319
+ # "status": "FILLED",
3320
+ # "priceType": "MARKET",
3321
+ # "isLiquidationOrder": False,
3322
+ # "indexPrice": "0",
3323
+ # "liquidationType": ""
3324
+ # }
3325
+ # ]
3326
+ #
3327
+ else:
3328
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets')
3329
+ return self.parse_orders(response, market, since, limit)
3330
+
3331
+ def check_type_param(self, methodName, params):
3332
+ # some hashkey endpoints have a type param for swap markets that defines the type of an order
3333
+ # type param is reserved in ccxt for defining the type of the market
3334
+ # current method warns user if he provides the exchange specific value in type parameter
3335
+ paramsType = self.safe_string(params, 'type')
3336
+ if (paramsType is not None) and (paramsType != 'spot') and (paramsType != 'swap'):
3337
+ raise BadRequest(self.id + ' ' + methodName + '() type parameter can not be "' + paramsType + '". It should define the type of the market("spot" or "swap"). To define the type of an order use the trigger parameter(True for trigger orders)')
3338
+
3339
+ def handle_trigger_option_and_params(self, params: object, methodName: str, defaultValue=None):
3340
+ isStop = defaultValue
3341
+ isStop, params = self.handle_option_and_params(params, methodName, 'stop', isStop)
3342
+ isTrigger = isStop
3343
+ isTrigger, params = self.handle_option_and_params(params, methodName, 'trigger', isTrigger)
3344
+ return [isTrigger, params]
3345
+
3346
+ def parse_order(self, order: dict, market: Market = None) -> Order:
3347
+ #
3348
+ # createOrder spot
3349
+ # {
3350
+ # "accountId": "1732885739589466112",
3351
+ # "symbol": "ETHUSDT",
3352
+ # "symbolName": "ETHUSDT",
3353
+ # "clientOrderId": "1722004623170558",
3354
+ # "orderId": "1738695230608169984",
3355
+ # "transactTime": "1722004623186",
3356
+ # "price": "0",
3357
+ # "origQty": "0",
3358
+ # "executedQty": "0.0061",
3359
+ # "status": "FILLED",
3360
+ # "timeInForce": "IOC",
3361
+ # "type": "MARKET",
3362
+ # "side": "BUY",
3363
+ # "reqAmount": "20",
3364
+ # "concentration": ""
3365
+ # }
3366
+ #
3367
+ # fetchOrder spot
3368
+ # {
3369
+ # "accountId": "1732885739589466112",
3370
+ # "exchangeId": "301",
3371
+ # "symbol": "ETHUSDT",
3372
+ # "symbolName": "ETHUSDT",
3373
+ # "clientOrderId": "1722004623170558",
3374
+ # "orderId": "1738695230608169984",
3375
+ # "price": "0",
3376
+ # "origQty": "0",
3377
+ # "executedQty": "0.0061",
3378
+ # "cummulativeQuoteQty": "19.736489",
3379
+ # "cumulativeQuoteQty": "19.736489",
3380
+ # "avgPrice": "3235.49",
3381
+ # "status": "FILLED",
3382
+ # "timeInForce": "IOC",
3383
+ # "type": "MARKET",
3384
+ # "side": "BUY",
3385
+ # "stopPrice": "0.0",
3386
+ # "icebergQty": "0.0",
3387
+ # "time": "1722004623186",
3388
+ # "updateTime": "1722004623406",
3389
+ # "isWorking": True,
3390
+ # "reqAmount": "20",
3391
+ # "feeCoin": "",
3392
+ # "feeAmount": "0",
3393
+ # "sumFeeAmount": "0"
3394
+ # }
3395
+ #
3396
+ # cancelOrder
3397
+ # {
3398
+ # "accountId": "1732885739589466112",
3399
+ # "symbol": "ETHUSDT",
3400
+ # "clientOrderId": "1722006209978370",
3401
+ # "orderId": "1738708541676585728",
3402
+ # "transactTime": "1722006209989",
3403
+ # "price": "5000",
3404
+ # "origQty": "0.005",
3405
+ # "executedQty": "0",
3406
+ # "status": "NEW",
3407
+ # "timeInForce": "GTC",
3408
+ # "type": "LIMIT_MAKER",
3409
+ # "side": "SELL"
3410
+ # }
3411
+ #
3412
+ # createOrder swap
3413
+ # {
3414
+ # "time": "1722429951611",
3415
+ # "updateTime": "1722429951648",
3416
+ # "orderId": "1742263144028363776",
3417
+ # "clientOrderId": "1722429950315",
3418
+ # "symbol": "ETHUSDT-PERPETUAL",
3419
+ # "price": "3460.62",
3420
+ # "leverage": "5",
3421
+ # "origQty": "10",
3422
+ # "executedQty": "10",
3423
+ # "avgPrice": "0",
3424
+ # "marginLocked": "6.9212",
3425
+ # "type": "LIMIT",
3426
+ # "side": "BUY_OPEN",
3427
+ # "timeInForce": "IOC",
3428
+ # "status": "FILLED",
3429
+ # "priceType": "MARKET",
3430
+ # "contractMultiplier": "0.00100000"
3431
+ # }
3432
+ #
3433
+ # fetchOrder swap
3434
+ # {
3435
+ # "time": "1722429951611",
3436
+ # "updateTime": "1722429951700",
3437
+ # "orderId": "1742263144028363776",
3438
+ # "clientOrderId": "1722429950315",
3439
+ # "symbol": "ETHUSDT-PERPETUAL",
3440
+ # "price": "3460.62",
3441
+ # "leverage": "5",
3442
+ # "origQty": "10",
3443
+ # "executedQty": "10",
3444
+ # "avgPrice": "3327.52",
3445
+ # "marginLocked": "0",
3446
+ # "type": "LIMIT",
3447
+ # "side": "BUY_OPEN",
3448
+ # "timeInForce": "IOC",
3449
+ # "status": "FILLED",
3450
+ # "priceType": "MARKET",
3451
+ # "isLiquidationOrder": False,
3452
+ # "indexPrice": "0",
3453
+ # "liquidationType": ""
3454
+ # }
3455
+ #
3456
+ marketId = self.safe_string(order, 'symbol')
3457
+ market = self.safe_market(marketId, market)
3458
+ timestamp = self.safe_integer_2(order, 'transactTime', 'time')
3459
+ status = self.safe_string(order, 'status')
3460
+ type = self.safe_string(order, 'type')
3461
+ priceType = self.safe_string(order, 'priceType')
3462
+ if priceType == 'MARKET':
3463
+ type = 'market'
3464
+ price = self.omit_zero(self.safe_string(order, 'price'))
3465
+ if type == 'STOP':
3466
+ if price is None:
3467
+ type = 'market'
3468
+ else:
3469
+ type = 'limit'
3470
+ timeInForce = self.safe_string(order, 'timeInForce')
3471
+ postOnly: Bool = None
3472
+ type, timeInForce, postOnly = self.parse_order_type_time_in_force_and_post_only(type, timeInForce)
3473
+ average = self.omit_zero(self.safe_string(order, 'avgPrice'))
3474
+ if price is None:
3475
+ price = average
3476
+ side = self.safe_string_lower(order, 'side')
3477
+ reduceOnly: Bool = None
3478
+ side, reduceOnly = self.parse_order_side_and_reduce_only(side)
3479
+ feeCurrncyId = self.safe_string(order, 'feeCoin')
3480
+ if feeCurrncyId == '':
3481
+ feeCurrncyId = None
3482
+ triggerPrice = self.omit_zero(self.safe_string(order, 'stopPrice'))
3483
+ return self.safe_order({
3484
+ 'id': self.safe_string(order, 'orderId'),
3485
+ 'clientOrderId': self.safe_string(order, 'clientOrderId'),
3486
+ 'datetime': self.iso8601(timestamp),
3487
+ 'timestamp': timestamp,
3488
+ 'lastTradeTimestamp': None,
3489
+ 'lastUpdateTimestamp': self.safe_integer(order, 'updateTime'),
3490
+ 'status': self.parse_order_status(status),
3491
+ 'symbol': market['symbol'],
3492
+ 'type': type,
3493
+ 'timeInForce': timeInForce,
3494
+ 'side': side,
3495
+ 'price': price,
3496
+ 'average': average,
3497
+ 'amount': self.omit_zero(self.safe_string(order, 'origQty')),
3498
+ 'filled': self.safe_string(order, 'executedQty'),
3499
+ 'remaining': None,
3500
+ 'stopPrice': triggerPrice,
3501
+ 'triggerPrice': triggerPrice,
3502
+ 'takeProfitPrice': None,
3503
+ 'stopLossPrice': None,
3504
+ 'cost': self.omit_zero(self.safe_string_2(order, 'cumulativeQuoteQty', 'cummulativeQuoteQty')),
3505
+ 'trades': None,
3506
+ 'fee': {
3507
+ 'currency': self.safe_currency_code(feeCurrncyId),
3508
+ 'amount': self.omit_zero(self.safe_string(order, 'feeAmount')),
3509
+ },
3510
+ 'reduceOnly': reduceOnly,
3511
+ 'postOnly': postOnly,
3512
+ 'info': order,
3513
+ }, market)
3514
+
3515
+ def parse_order_side_and_reduce_only(self, unparsed):
3516
+ parts = unparsed.split('_')
3517
+ side = parts[0]
3518
+ reduceOnly: Bool = None
3519
+ secondPart = self.safe_string(parts, 1)
3520
+ if secondPart is not None:
3521
+ if secondPart == 'open':
3522
+ reduceOnly = False
3523
+ elif (secondPart == 'close'):
3524
+ reduceOnly = True
3525
+ return [side, reduceOnly]
3526
+
3527
+ def parse_order_status(self, status):
3528
+ statuses = {
3529
+ 'NEW': 'open',
3530
+ 'PARTIALLY_FILLED': 'open',
3531
+ 'PARTIALLY_CANCELED': 'canceled',
3532
+ 'FILLED': 'closed',
3533
+ 'CANCELED': 'canceled',
3534
+ 'ORDER_CANCELED': 'canceled',
3535
+ 'PENDING_CANCEL': 'canceled',
3536
+ 'REJECTED': 'rejected',
3537
+ 'ORDER_NEW': 'open',
3538
+ }
3539
+ return self.safe_string(statuses, status, status)
3540
+
3541
+ def parse_order_type_time_in_force_and_post_only(self, type, timeInForce):
3542
+ postOnly: Bool = None
3543
+ if type == 'LIMIT_MAKER':
3544
+ postOnly = True
3545
+ elif (timeInForce == 'LIMIT_MAKER') or (timeInForce == 'MAKER'):
3546
+ postOnly = True
3547
+ timeInForce = 'PO'
3548
+ type = self.parse_order_type(type)
3549
+ return [type, timeInForce, postOnly]
3550
+
3551
+ def parse_order_type(self, type):
3552
+ types = {
3553
+ 'MARKET': 'market',
3554
+ 'LIMIT': 'limit',
3555
+ 'LIMIT_MAKER': 'limit',
3556
+ 'MARKET_OF_BASE': 'market',
3557
+ }
3558
+ return self.safe_string(types, type, type)
3559
+
3560
+ def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
3561
+ """
3562
+ fetch the current funding rate
3563
+
3564
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
3565
+
3566
+ :param str symbol: unified market symbol
3567
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3568
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3569
+ """
3570
+ self.load_markets()
3571
+ market = self.market(symbol)
3572
+ request: dict = {
3573
+ 'symbol': market['id'],
3574
+ 'timestamp': self.milliseconds(),
3575
+ }
3576
+ response = self.publicGetApiV1FuturesFundingRate(self.extend(request, params))
3577
+ #
3578
+ # [
3579
+ # {"symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000"}
3580
+ # ]
3581
+ #
3582
+ rate = self.safe_dict(response, 0, {})
3583
+ return self.parse_funding_rate(rate, market)
3584
+
3585
+ def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
3586
+ """
3587
+ fetch the funding rate for multiple markets
3588
+
3589
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
3590
+
3591
+ :param str[]|None symbols: list of unified market symbols
3592
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3593
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexed by market symbols
3594
+ """
3595
+ self.load_markets()
3596
+ symbols = self.market_symbols(symbols)
3597
+ request: dict = {
3598
+ 'timestamp': self.milliseconds(),
3599
+ }
3600
+ response = self.publicGetApiV1FuturesFundingRate(self.extend(request, params))
3601
+ #
3602
+ # [
3603
+ # {"symbol": "BTCUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000"},
3604
+ # {"symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000"}
3605
+ # ]
3606
+ #
3607
+ fundingRates = self.parse_funding_rates(response)
3608
+ return self.filter_by_array(fundingRates, 'symbol', symbols)
3609
+
3610
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
3611
+ #
3612
+ # {
3613
+ # "symbol": "ETHUSDT-PERPETUAL",
3614
+ # "rate": "0.0001",
3615
+ # "nextSettleTime": "1722297600000"
3616
+ # }
3617
+ #
3618
+ marketId = self.safe_string(contract, 'symbol')
3619
+ market = self.safe_market(marketId, market, None, 'swap')
3620
+ fundingRate = self.safe_number(contract, 'rate')
3621
+ fundingTimestamp = self.safe_integer(contract, 'nextSettleTime')
3622
+ return {
3623
+ 'info': contract,
3624
+ 'symbol': market['symbol'],
3625
+ 'markPrice': None,
3626
+ 'indexPrice': None,
3627
+ 'interestRate': None,
3628
+ 'estimatedSettlePrice': None,
3629
+ 'timestamp': None,
3630
+ 'datetime': None,
3631
+ 'fundingRate': fundingRate,
3632
+ 'fundingTimestamp': None,
3633
+ 'fundingDatetime': None,
3634
+ 'nextFundingRate': None,
3635
+ 'nextFundingTimestamp': fundingTimestamp,
3636
+ 'nextFundingDatetime': self.iso8601(fundingTimestamp),
3637
+ 'previousFundingRate': None,
3638
+ 'previousFundingTimestamp': None,
3639
+ 'previousFundingDatetime': None,
3640
+ 'interval': None,
3641
+ }
3642
+
3643
+ def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3644
+ """
3645
+ fetches historical funding rate prices
3646
+
3647
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-history-funding-rate
3648
+
3649
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
3650
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
3651
+ :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
3652
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3653
+ :param int [params.fromId]: the id of the entry to start from
3654
+ :param int [params.endId]: the id of the entry to end with
3655
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
3656
+ """
3657
+ self.load_markets()
3658
+ if symbol is None:
3659
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
3660
+ market = self.market(symbol)
3661
+ request: dict = {
3662
+ 'symbol': market['id'],
3663
+ }
3664
+ if limit is not None:
3665
+ request['limit'] = limit
3666
+ response = self.publicGetApiV1FuturesHistoryFundingRate(self.extend(request, params))
3667
+ #
3668
+ # [
3669
+ # {
3670
+ # "id": "10698",
3671
+ # "symbol": "ETHUSDT-PERPETUAL",
3672
+ # "settleTime": "1722268800000",
3673
+ # "settleRate": "0.0001"
3674
+ # },
3675
+ # ...
3676
+ # ]
3677
+ #
3678
+ rates = []
3679
+ for i in range(0, len(response)):
3680
+ entry = response[i]
3681
+ timestamp = self.safe_integer(entry, 'settleTime')
3682
+ rates.append({
3683
+ 'info': entry,
3684
+ 'symbol': self.safe_symbol(self.safe_string(entry, 'symbol'), market, None, 'swap'),
3685
+ 'fundingRate': self.safe_number(entry, 'settleRate'),
3686
+ 'timestamp': timestamp,
3687
+ 'datetime': self.iso8601(timestamp),
3688
+ })
3689
+ sorted = self.sort_by(rates, 'timestamp')
3690
+ return self.filter_by_since_limit(sorted, since, limit)
3691
+
3692
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3693
+ """
3694
+ fetch open positions for a market
3695
+
3696
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
3697
+
3698
+ fetch all open positions
3699
+ :param str[]|None symbols: list of unified market symbols
3700
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3701
+ :param str [params.side]: 'LONG' or 'SHORT' - the direction of the position(if not provided, positions for both sides will be returned)
3702
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3703
+ """
3704
+ methodName = 'fetchPositions'
3705
+ if (symbols is None):
3706
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a symbol argument with one single market symbol')
3707
+ else:
3708
+ symbolsLength = len(symbols)
3709
+ if symbolsLength != 1:
3710
+ raise NotSupported(self.id + ' ' + methodName + '() is supported for a symbol argument with one single market symbol only')
3711
+ self.load_markets()
3712
+ return self.fetch_positions_for_symbol(symbols[0], self.extend({'methodName': 'fetchPositions'}, params))
3713
+
3714
+ def fetch_positions_for_symbol(self, symbol: str, params={}) -> List[Position]:
3715
+ """
3716
+ fetch open positions for a single market
3717
+
3718
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
3719
+
3720
+ fetch all open positions for specific symbol
3721
+ :param str symbol: unified market symbol
3722
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3723
+ :param str [params.side]: 'LONG' or 'SHORT' - the direction of the position(if not provided, positions for both sides will be returned)
3724
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3725
+ """
3726
+ self.load_markets()
3727
+ market = self.market(symbol)
3728
+ methodName = 'fetchPosition'
3729
+ methodName, params = self.handle_param_string(params, 'methodName', methodName)
3730
+ if not market['swap']:
3731
+ raise NotSupported(self.id + ' ' + methodName + '() supports swap markets only')
3732
+ request: dict = {
3733
+ 'symbol': market['id'],
3734
+ }
3735
+ side: Str = None
3736
+ side, params = self.handle_option_and_params(params, methodName, 'side')
3737
+ if side is not None:
3738
+ request['side'] = side.upper()
3739
+ response = self.privateGetApiV1FuturesPositions(self.extend(request, params))
3740
+ #
3741
+ # [
3742
+ # {
3743
+ # "symbol": "ETHUSDT-PERPETUAL",
3744
+ # "side": "LONG",
3745
+ # "avgPrice": "3327.52",
3746
+ # "position": "10",
3747
+ # "available": "0",
3748
+ # "leverage": "5",
3749
+ # "lastPrice": "3324.44",
3750
+ # "positionValue": "33.2752",
3751
+ # "liquidationPrice": "-953.83",
3752
+ # "margin": "6.9012",
3753
+ # "marginRate": "",
3754
+ # "unrealizedPnL": "-0.0288",
3755
+ # "profitRate": "-0.0041",
3756
+ # "realizedPnL": "-0.0199",
3757
+ # "minMargin": "0.2173"
3758
+ # }
3759
+ # ]
3760
+ #
3761
+ return self.parse_positions(response, [symbol])
3762
+
3763
+ def parse_position(self, position: dict, market: Market = None):
3764
+ marketId = self.safe_string(position, 'symbol')
3765
+ market = self.safe_market(marketId, market)
3766
+ symbol = market['symbol']
3767
+ return self.safe_position({
3768
+ 'symbol': symbol,
3769
+ 'id': None,
3770
+ 'timestamp': None,
3771
+ 'datetime': None,
3772
+ 'contracts': self.safe_number(position, 'position'),
3773
+ 'contractSize': None,
3774
+ 'side': self.safe_string_lower(position, 'side'),
3775
+ 'notional': self.safe_number(position, 'positionValue'),
3776
+ 'leverage': self.safe_integer(position, 'leverage'),
3777
+ 'unrealizedPnl': self.safe_number(position, 'unrealizedPnL'),
3778
+ 'realizedPnl': self.safe_number(position, 'realizedPnL'),
3779
+ 'collateral': None,
3780
+ 'entryPrice': self.safe_number(position, 'avgPrice'),
3781
+ 'markPrice': None,
3782
+ 'liquidationPrice': self.safe_number(position, 'liquidationPrice'),
3783
+ 'marginMode': 'cross',
3784
+ 'hedged': True,
3785
+ 'maintenanceMargin': self.safe_number(position, 'minMargin'),
3786
+ 'maintenanceMarginPercentage': None,
3787
+ 'initialMargin': self.safe_number(position, 'margin'),
3788
+ 'initialMarginPercentage': None,
3789
+ 'marginRatio': None,
3790
+ 'lastUpdateTimestamp': None,
3791
+ 'lastPrice': self.safe_number(position, 'lastPrice'),
3792
+ 'stopLossPrice': None,
3793
+ 'takeProfitPrice': None,
3794
+ 'percentage': None,
3795
+ 'info': position,
3796
+ })
3797
+
3798
+ def fetch_leverage(self, symbol: str, params={}) -> Leverage:
3799
+ """
3800
+ fetch the set leverage for a market
3801
+
3802
+ https://hashkeyglobal-apidoc.readme.io/reference/query-futures-leverage-trade
3803
+
3804
+ :param str symbol: unified market symbol
3805
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3806
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
3807
+ """
3808
+ self.load_markets()
3809
+ market = self.market(symbol)
3810
+ request: dict = {
3811
+ 'symbol': market['id'],
3812
+ }
3813
+ response = self.privateGetApiV1FuturesLeverage(self.extend(request, params))
3814
+ #
3815
+ # [
3816
+ # {
3817
+ # "symbolId": "ETHUSDT-PERPETUAL",
3818
+ # "leverage": "5",
3819
+ # "marginType": "CROSS"
3820
+ # }
3821
+ # ]
3822
+ #
3823
+ leverage = self.safe_dict(response, 0, {})
3824
+ return self.parse_leverage(leverage, market)
3825
+
3826
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
3827
+ marginMode = self.safe_string_lower(leverage, 'marginType')
3828
+ leverageValue = self.safe_number(leverage, 'leverage')
3829
+ return {
3830
+ 'info': leverage,
3831
+ 'symbol': market['symbol'],
3832
+ 'marginMode': marginMode,
3833
+ 'longLeverage': leverageValue,
3834
+ 'shortLeverage': leverageValue,
3835
+ }
3836
+
3837
+ def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
3838
+ """
3839
+ set the level of leverage for a market
3840
+
3841
+ https://hashkeyglobal-apidoc.readme.io/reference/change-futures-leverage-trade
3842
+
3843
+ :param float leverage: the rate of leverage
3844
+ :param str symbol: unified market symbol
3845
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3846
+ :returns dict: response from the exchange
3847
+ """
3848
+ if symbol is None:
3849
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
3850
+ self.load_markets()
3851
+ request: dict = {
3852
+ 'leverage': leverage,
3853
+ }
3854
+ market = self.market(symbol)
3855
+ request['symbol'] = market['id']
3856
+ response = self.privatePostApiV1FuturesLeverage(self.extend(request, params))
3857
+ #
3858
+ # {
3859
+ # "code": "0000",
3860
+ # "symbolId": "ETHUSDT-PERPETUAL",
3861
+ # "leverage": "3"
3862
+ # }
3863
+ #
3864
+ return self.parse_leverage(response, market)
3865
+
3866
+ def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
3867
+ """
3868
+ retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
3869
+
3870
+ https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
3871
+
3872
+ :param str[]|None symbols: list of unified market symbols
3873
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3874
+ :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
3875
+ """
3876
+ self.load_markets()
3877
+ response = self.publicGetApiV1ExchangeInfo(params)
3878
+ # response is the same fetchMarkets()
3879
+ data = self.safe_list(response, 'contracts', [])
3880
+ symbols = self.market_symbols(symbols)
3881
+ return self.parse_leverage_tiers(data, symbols, 'symbol')
3882
+
3883
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
3884
+ #
3885
+ # {
3886
+ # "filters": [
3887
+ # {
3888
+ # "minPrice": "0.1",
3889
+ # "maxPrice": "100000.00000000",
3890
+ # "tickSize": "0.1",
3891
+ # "filterType": "PRICE_FILTER"
3892
+ # },
3893
+ # {
3894
+ # "minQty": "0.001",
3895
+ # "maxQty": "10",
3896
+ # "stepSize": "0.001",
3897
+ # "marketOrderMinQty": "0",
3898
+ # "marketOrderMaxQty": "0",
3899
+ # "filterType": "LOT_SIZE"
3900
+ # },
3901
+ # {
3902
+ # "minNotional": "0",
3903
+ # "filterType": "MIN_NOTIONAL"
3904
+ # },
3905
+ # {
3906
+ # "maxSellPrice": "999999",
3907
+ # "buyPriceUpRate": "0.05",
3908
+ # "sellPriceDownRate": "0.05",
3909
+ # "maxEntrustNum": 200,
3910
+ # "maxConditionNum": 200,
3911
+ # "filterType": "LIMIT_TRADING"
3912
+ # },
3913
+ # {
3914
+ # "buyPriceUpRate": "0.05",
3915
+ # "sellPriceDownRate": "0.05",
3916
+ # "filterType": "MARKET_TRADING"
3917
+ # },
3918
+ # {
3919
+ # "noAllowMarketStartTime": "0",
3920
+ # "noAllowMarketEndTime": "0",
3921
+ # "limitOrderStartTime": "0",
3922
+ # "limitOrderEndTime": "0",
3923
+ # "limitMinPrice": "0",
3924
+ # "limitMaxPrice": "0",
3925
+ # "filterType": "OPEN_QUOTE"
3926
+ # }
3927
+ # ],
3928
+ # "exchangeId": "301",
3929
+ # "symbol": "BTCUSDT-PERPETUAL",
3930
+ # "symbolName": "BTCUSDT-PERPETUAL",
3931
+ # "status": "TRADING",
3932
+ # "baseAsset": "BTCUSDT-PERPETUAL",
3933
+ # "baseAssetPrecision": "0.001",
3934
+ # "quoteAsset": "USDT",
3935
+ # "quoteAssetPrecision": "0.1",
3936
+ # "icebergAllowed": False,
3937
+ # "inverse": False,
3938
+ # "index": "USDT",
3939
+ # "marginToken": "USDT",
3940
+ # "marginPrecision": "0.0001",
3941
+ # "contractMultiplier": "0.001",
3942
+ # "underlying": "BTC",
3943
+ # "riskLimits": [
3944
+ # {
3945
+ # "riskLimitId": "200000722",
3946
+ # "quantity": "1000.00",
3947
+ # "initialMargin": "0.10",
3948
+ # "maintMargin": "0.005",
3949
+ # "isWhite": False
3950
+ # },
3951
+ # {
3952
+ # "riskLimitId": "200000723",
3953
+ # "quantity": "2000.00",
3954
+ # "initialMargin": "0.10",
3955
+ # "maintMargin": "0.01",
3956
+ # "isWhite": False
3957
+ # }
3958
+ # ]
3959
+ # }
3960
+ #
3961
+ riskLimits = self.safe_list(info, 'riskLimits', [])
3962
+ marketId = self.safe_string(info, 'symbol')
3963
+ market = self.safe_market(marketId, market)
3964
+ tiers = []
3965
+ for i in range(0, len(riskLimits)):
3966
+ tier = riskLimits[i]
3967
+ initialMarginRate = self.safe_string(tier, 'initialMargin')
3968
+ tiers.append({
3969
+ 'tier': self.sum(i, 1),
3970
+ 'symbol': self.safe_symbol(marketId, market),
3971
+ 'currency': market['settle'],
3972
+ 'minNotional': None,
3973
+ 'maxNotional': self.safe_number(tier, 'quantity'),
3974
+ 'maintenanceMarginRate': self.safe_number(tier, 'maintMargin'),
3975
+ 'maxLeverage': self.parse_number(Precise.string_div('1', initialMarginRate)),
3976
+ 'info': tier,
3977
+ })
3978
+ return tiers
3979
+
3980
+ def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
3981
+ """
3982
+ fetch the trading fees for a market
3983
+
3984
+ https://developers.binance.com/docs/wallet/asset/trade-fee # spot
3985
+ https://hashkeyglobal-apidoc.readme.io/reference/get-futures-commission-rate-request-weight # swap
3986
+
3987
+ :param str symbol: unified market symbol
3988
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3989
+ :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
3990
+ """
3991
+ self.load_markets()
3992
+ market = self.market(symbol)
3993
+ methodName = 'fetchTradingFee'
3994
+ response = None
3995
+ if market['spot']:
3996
+ response = self.fetch_trading_fees(params)
3997
+ return self.safe_dict(response, symbol)
3998
+ elif market['swap']:
3999
+ response = self.privateGetApiV1FuturesCommissionRate(self.extend({'symbol': market['id']}, params))
4000
+ return self.parse_trading_fee(response, market)
4001
+ #
4002
+ # {
4003
+ # "openMakerFee": "0.00025",
4004
+ # "openTakerFee": "0.0006",
4005
+ # "closeMakerFee": "0.00025",
4006
+ # "closeTakerFee": "0.0006"
4007
+ # }
4008
+ #
4009
+ else:
4010
+ raise NotSupported(self.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets')
4011
+
4012
+ def fetch_trading_fees(self, params={}) -> TradingFees:
4013
+ """
4014
+ *for spot markets only* fetch the trading fees for multiple markets
4015
+
4016
+ https://developers.binance.com/docs/wallet/asset/trade-fee
4017
+
4018
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4019
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
4020
+ """
4021
+ self.load_markets()
4022
+ response = self.privateGetApiV1AccountVipInfo(params)
4023
+ #
4024
+ # {
4025
+ # "code": 0,
4026
+ # "vipLevel": "0",
4027
+ # "tradeVol30Day": "67",
4028
+ # "totalAssetBal": "0",
4029
+ # "data": [
4030
+ # {
4031
+ # "symbol": "UXLINKUSDT",
4032
+ # "productType": "Token-Token",
4033
+ # "buyMakerFeeCurrency": "UXLINK",
4034
+ # "buyTakerFeeCurrency": "UXLINK",
4035
+ # "sellMakerFeeCurrency": "USDT",
4036
+ # "sellTakerFeeCurrency": "USDT",
4037
+ # "actualMakerRate": "0.0012",
4038
+ # "actualTakerRate": "0.0012"
4039
+ # },
4040
+ # ...
4041
+ # ],
4042
+ # "updateTimestamp": "1722320137809"
4043
+ # }
4044
+ #
4045
+ data = self.safe_list(response, 'data', [])
4046
+ result: dict = {}
4047
+ for i in range(0, len(data)):
4048
+ fee = self.safe_dict(data, i, {})
4049
+ parsedFee = self.parse_trading_fee(fee)
4050
+ result[parsedFee['symbol']] = parsedFee
4051
+ return result
4052
+
4053
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
4054
+ #
4055
+ # spot
4056
+ # {
4057
+ # "symbol": "UXLINKUSDT",
4058
+ # "productType": "Token-Token",
4059
+ # "buyMakerFeeCurrency": "UXLINK",
4060
+ # "buyTakerFeeCurrency": "UXLINK",
4061
+ # "sellMakerFeeCurrency": "USDT",
4062
+ # "sellTakerFeeCurrency": "USDT",
4063
+ # "actualMakerRate": "0.0012",
4064
+ # "actualTakerRate": "0.0012"
4065
+ # }
4066
+ #
4067
+ # swap
4068
+ # {
4069
+ # "openMakerFee": "0.00025",
4070
+ # "openTakerFee": "0.0006",
4071
+ # "closeMakerFee": "0.00025",
4072
+ # "closeTakerFee": "0.0006"
4073
+ # }
4074
+ #
4075
+ marketId = self.safe_string(fee, 'symbol')
4076
+ market = self.safe_market(marketId, market)
4077
+ return {
4078
+ 'info': fee,
4079
+ 'symbol': market['symbol'],
4080
+ 'maker': self.safe_number_2(fee, 'openMakerFee', 'actualMakerRate'),
4081
+ 'taker': self.safe_number_2(fee, 'openTakerFee', 'actualTakerRate'),
4082
+ 'percentage': True,
4083
+ 'tierBased': True,
4084
+ }
4085
+
4086
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4087
+ url = self.urls['api'][api] + '/' + path
4088
+ query: Str = None
4089
+ if api == 'private':
4090
+ self.check_required_credentials()
4091
+ timestamp = self.milliseconds()
4092
+ additionalParams = {
4093
+ 'timestamp': timestamp,
4094
+ }
4095
+ recvWindow = self.safe_integer(self.options, 'recvWindow')
4096
+ if recvWindow is not None:
4097
+ additionalParams['recvWindow'] = recvWindow
4098
+ headers = {
4099
+ 'X-HK-APIKEY': self.apiKey,
4100
+ 'Content-Type': 'application/x-www-form-urlencoded',
4101
+ }
4102
+ signature: Str = None
4103
+ if (method == 'POST') and ((path == 'api/v1/spot/batchOrders') or (path == 'api/v1/futures/batchOrders')):
4104
+ headers['Content-Type'] = 'application/json'
4105
+ body = self.json(self.safe_list(params, 'orders'))
4106
+ signature = self.hmac(self.encode(self.custom_urlencode(additionalParams)), self.encode(self.secret), hashlib.sha256)
4107
+ query = self.custom_urlencode(self.extend(additionalParams, {'signature': signature}))
4108
+ url += '?' + query
4109
+ else:
4110
+ totalParams = self.extend(additionalParams, params)
4111
+ signature = self.hmac(self.encode(self.custom_urlencode(totalParams)), self.encode(self.secret), hashlib.sha256)
4112
+ totalParams['signature'] = signature
4113
+ query = self.custom_urlencode(totalParams)
4114
+ if method == 'GET':
4115
+ url += '?' + query
4116
+ else:
4117
+ body = query
4118
+ headers['INPUT-SOURCE'] = self.safe_string(self.options, 'broker', '10000700011')
4119
+ headers['broker_sign'] = signature
4120
+ else:
4121
+ query = self.urlencode(params)
4122
+ if len(query) != 0:
4123
+ url += '?' + query
4124
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
4125
+
4126
+ def custom_urlencode(self, params: dict = {}) -> Str:
4127
+ result = self.urlencode(params)
4128
+ result = result.replace('%2C', ',')
4129
+ return result
4130
+
4131
+ def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
4132
+ if response is None:
4133
+ return None
4134
+ errorInArray = False
4135
+ responseCodeString = self.safe_string(response, 'code', None)
4136
+ responseCodeInteger = self.safe_integer(response, 'code', None) # some codes in response are returned as '0000' others
4137
+ if responseCodeInteger == 0:
4138
+ result = self.safe_list(response, 'result', []) # for batch methods
4139
+ for i in range(0, len(result)):
4140
+ entry = self.safe_dict(result, i)
4141
+ entryCodeInteger = self.safe_integer(entry, 'code')
4142
+ if entryCodeInteger != 0:
4143
+ errorInArray = True
4144
+ responseCodeString = self.safe_string(entry, 'code')
4145
+ if (code != 200) or errorInArray:
4146
+ feedback = self.id + ' ' + body
4147
+ self.throw_broadly_matched_exception(self.exceptions['broad'], responseCodeString, feedback)
4148
+ self.throw_exactly_matched_exception(self.exceptions['exact'], responseCodeString, feedback)
4149
+ raise ExchangeError(feedback)
4150
+ return None