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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2431 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.hyperliquid import ImplicitAPI
8
+ import asyncio
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Trade, Transaction, TransferEntry
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import ArgumentsRequired
13
+ from ccxt.base.errors import BadRequest
14
+ from ccxt.base.errors import InvalidOrder
15
+ from ccxt.base.errors import OrderNotFound
16
+ from ccxt.base.errors import NotSupported
17
+ from ccxt.base.decimal_to_precision import ROUND
18
+ from ccxt.base.decimal_to_precision import DECIMAL_PLACES
19
+ from ccxt.base.decimal_to_precision import SIGNIFICANT_DIGITS
20
+ from ccxt.base.decimal_to_precision import TICK_SIZE
21
+ from ccxt.base.precise import Precise
22
+
23
+
24
+ class hyperliquid(Exchange, ImplicitAPI):
25
+
26
+ def describe(self):
27
+ return self.deep_extend(super(hyperliquid, self).describe(), {
28
+ 'id': 'hyperliquid',
29
+ 'name': 'Hyperliquid',
30
+ 'countries': [],
31
+ 'version': 'v1',
32
+ 'rateLimit': 50, # 1200 requests per minute, 20 request per second
33
+ 'certified': False,
34
+ 'pro': True,
35
+ 'dex': True,
36
+ 'has': {
37
+ 'CORS': None,
38
+ 'spot': True,
39
+ 'margin': False,
40
+ 'swap': True,
41
+ 'future': True,
42
+ 'option': False,
43
+ 'addMargin': True,
44
+ 'borrowCrossMargin': False,
45
+ 'borrowIsolatedMargin': False,
46
+ 'cancelAllOrders': False,
47
+ 'cancelAllOrdersAfter': True,
48
+ 'cancelOrder': True,
49
+ 'cancelOrders': True,
50
+ 'cancelOrdersForSymbols': True,
51
+ 'closeAllPositions': False,
52
+ 'closePosition': False,
53
+ 'createMarketBuyOrderWithCost': False,
54
+ 'createMarketOrderWithCost': False,
55
+ 'createMarketSellOrderWithCost': False,
56
+ 'createOrder': True,
57
+ 'createOrders': True,
58
+ 'createReduceOnlyOrder': True,
59
+ 'editOrder': True,
60
+ 'fetchAccounts': False,
61
+ 'fetchBalance': True,
62
+ 'fetchBorrowInterest': False,
63
+ 'fetchBorrowRateHistories': False,
64
+ 'fetchBorrowRateHistory': False,
65
+ 'fetchCanceledOrders': False,
66
+ 'fetchClosedOrders': True,
67
+ 'fetchCrossBorrowRate': False,
68
+ 'fetchCrossBorrowRates': False,
69
+ 'fetchCurrencies': True,
70
+ 'fetchDepositAddress': False,
71
+ 'fetchDepositAddresses': False,
72
+ 'fetchDeposits': False,
73
+ 'fetchDepositWithdrawFee': 'emulated',
74
+ 'fetchDepositWithdrawFees': False,
75
+ 'fetchFundingHistory': False,
76
+ 'fetchFundingRate': False,
77
+ 'fetchFundingRateHistory': True,
78
+ 'fetchFundingRates': False,
79
+ 'fetchIndexOHLCV': False,
80
+ 'fetchIsolatedBorrowRate': False,
81
+ 'fetchIsolatedBorrowRates': False,
82
+ 'fetchLedger': False,
83
+ 'fetchLeverage': False,
84
+ 'fetchLeverageTiers': False,
85
+ 'fetchLiquidations': False,
86
+ 'fetchMarginMode': None,
87
+ 'fetchMarketLeverageTiers': False,
88
+ 'fetchMarkets': True,
89
+ 'fetchMarkOHLCV': False,
90
+ 'fetchMyLiquidations': False,
91
+ 'fetchMyTrades': True,
92
+ 'fetchOHLCV': True,
93
+ 'fetchOpenInterest': False,
94
+ 'fetchOpenInterestHistory': False,
95
+ 'fetchOpenOrders': True,
96
+ 'fetchOrder': True,
97
+ 'fetchOrderBook': True,
98
+ 'fetchOrders': False,
99
+ 'fetchOrderTrades': False,
100
+ 'fetchPosition': True,
101
+ 'fetchPositionMode': False,
102
+ 'fetchPositions': True,
103
+ 'fetchPositionsRisk': False,
104
+ 'fetchPremiumIndexOHLCV': False,
105
+ 'fetchTicker': False,
106
+ 'fetchTickers': False,
107
+ 'fetchTime': False,
108
+ 'fetchTrades': True,
109
+ 'fetchTradingFee': False,
110
+ 'fetchTradingFees': False,
111
+ 'fetchTransfer': False,
112
+ 'fetchTransfers': False,
113
+ 'fetchWithdrawal': False,
114
+ 'fetchWithdrawals': False,
115
+ 'reduceMargin': True,
116
+ 'repayCrossMargin': False,
117
+ 'repayIsolatedMargin': False,
118
+ 'sandbox': True,
119
+ 'setLeverage': True,
120
+ 'setMarginMode': True,
121
+ 'setPositionMode': False,
122
+ 'transfer': True,
123
+ 'withdraw': True,
124
+ },
125
+ 'timeframes': {
126
+ '1m': '1m',
127
+ '3m': '3m',
128
+ '5m': '5m',
129
+ '15m': '15m',
130
+ '30m': '30m',
131
+ '1h': '1h',
132
+ '2h': '2h',
133
+ '4h': '4h',
134
+ '6h': '6h',
135
+ '12h': '12h',
136
+ '1d': '1d',
137
+ '3d': '3d',
138
+ '1w': '1w',
139
+ '1M': '1m',
140
+ },
141
+ 'hostname': 'hyperliquid.xyz',
142
+ 'urls': {
143
+ 'logo': 'https://github.com/ccxt/ccxt/assets/43336371/b371bc6c-4a8c-489f-87f4-20a913dd8d4b',
144
+ 'api': {
145
+ 'public': 'https://api.{hostname}',
146
+ 'private': 'https://api.{hostname}',
147
+ },
148
+ 'test': {
149
+ 'public': 'https://api.hyperliquid-testnet.xyz',
150
+ 'private': 'https://api.hyperliquid-testnet.xyz',
151
+ },
152
+ 'www': 'https://hyperliquid.xyz',
153
+ 'doc': 'https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api',
154
+ 'fees': 'https://hyperliquid.gitbook.io/hyperliquid-docs/trading/fees',
155
+ 'referral': 'https://app.hyperliquid.xyz/',
156
+ },
157
+ 'api': {
158
+ 'public': {
159
+ 'post': {
160
+ 'info': 1,
161
+ },
162
+ },
163
+ 'private': {
164
+ 'post': {
165
+ 'exchange': 1,
166
+ },
167
+ },
168
+ },
169
+ 'fees': {
170
+ 'swap': {
171
+ 'taker': self.parse_number('0.00035'),
172
+ 'maker': self.parse_number('0.0001'),
173
+ },
174
+ 'spot': {
175
+ 'taker': self.parse_number('0.00035'),
176
+ 'maker': self.parse_number('0.0001'),
177
+ },
178
+ },
179
+ 'requiredCredentials': {
180
+ 'apiKey': False,
181
+ 'secret': False,
182
+ 'walletAddress': True,
183
+ 'privateKey': True,
184
+ },
185
+ 'exceptions': {
186
+ 'exact': {
187
+ },
188
+ 'broad': {
189
+ 'Price must be divisible by tick size.': InvalidOrder,
190
+ 'Order must have minimum value of $10': InvalidOrder,
191
+ 'Insufficient margin to place order.': InvalidOrder,
192
+ 'Reduce only order would increase position.': InvalidOrder,
193
+ 'Post only order would have immediately matched,': InvalidOrder,
194
+ 'Order could not immediately match against any resting orders.': InvalidOrder,
195
+ 'Invalid TP/SL price.': InvalidOrder,
196
+ 'No liquidity available for market order.': InvalidOrder,
197
+ 'Order was never placed, already canceled, or filled.': OrderNotFound,
198
+ 'User or API Wallet ': InvalidOrder,
199
+ },
200
+ },
201
+ 'precisionMode': TICK_SIZE,
202
+ 'commonCurrencies': {
203
+ },
204
+ 'options': {
205
+ 'defaultType': 'swap',
206
+ 'sandboxMode': False,
207
+ 'defaultSlippage': 0.05,
208
+ 'zeroAddress': '0x0000000000000000000000000000000000000000',
209
+ },
210
+ })
211
+
212
+ def set_sandbox_mode(self, enabled):
213
+ super(hyperliquid, self).set_sandbox_mode(enabled)
214
+ self.options['sandboxMode'] = enabled
215
+
216
+ async def fetch_currencies(self, params={}) -> Currencies:
217
+ """
218
+ fetches all available currencies on an exchange
219
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-exchange-metadata
220
+ :param dict [params]: extra parameters specific to the exchange API endpoint
221
+ :returns dict: an associative dictionary of currencies
222
+ """
223
+ request: dict = {
224
+ 'type': 'meta',
225
+ }
226
+ response = await self.publicPostInfo(self.extend(request, params))
227
+ #
228
+ # [
229
+ # {
230
+ # "universe": [
231
+ # {
232
+ # "maxLeverage": 50,
233
+ # "name": "SOL",
234
+ # "onlyIsolated": False,
235
+ # "szDecimals": 2
236
+ # }
237
+ # ]
238
+ # }
239
+ # ]
240
+ #
241
+ meta = self.safe_list(response, 'universe', [])
242
+ result: dict = {}
243
+ for i in range(0, len(meta)):
244
+ data = self.safe_dict(meta, i, {})
245
+ id = i
246
+ name = self.safe_string(data, 'name')
247
+ code = self.safe_currency_code(name)
248
+ result[code] = {
249
+ 'id': id,
250
+ 'name': name,
251
+ 'code': code,
252
+ 'precision': None,
253
+ 'info': data,
254
+ 'active': None,
255
+ 'deposit': None,
256
+ 'withdraw': None,
257
+ 'networks': None,
258
+ 'fee': None,
259
+ # 'fees': fees,
260
+ 'limits': None,
261
+ }
262
+ return result
263
+
264
+ async def fetch_markets(self, params={}) -> List[Market]:
265
+ """
266
+ retrieves data on all markets for hyperliquid
267
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
268
+ :param dict [params]: extra parameters specific to the exchange API endpoint
269
+ :returns dict[]: an array of objects representing market data
270
+ """
271
+ rawPromises = [
272
+ self.fetch_swap_markets(params),
273
+ self.fetch_spot_markets(params),
274
+ ]
275
+ promises = await asyncio.gather(*rawPromises)
276
+ swapMarkets = promises[0]
277
+ spotMarkets = promises[1]
278
+ return self.array_concat(swapMarkets, spotMarkets)
279
+
280
+ async def fetch_swap_markets(self, params={}) -> List[Market]:
281
+ """
282
+ retrieves data on all swap markets for hyperliquid
283
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
284
+ :param dict [params]: extra parameters specific to the exchange API endpoint
285
+ :returns dict[]: an array of objects representing market data
286
+ """
287
+ request: dict = {
288
+ 'type': 'metaAndAssetCtxs',
289
+ }
290
+ response = await self.publicPostInfo(self.extend(request, params))
291
+ #
292
+ # [
293
+ # {
294
+ # "universe": [
295
+ # {
296
+ # "maxLeverage": 50,
297
+ # "name": "SOL",
298
+ # "onlyIsolated": False,
299
+ # "szDecimals": 2
300
+ # }
301
+ # ]
302
+ # },
303
+ # [
304
+ # {
305
+ # "dayNtlVlm": "9450588.2273",
306
+ # "funding": "0.0000198",
307
+ # "impactPxs": [
308
+ # "108.04",
309
+ # "108.06"
310
+ # ],
311
+ # "markPx": "108.04",
312
+ # "midPx": "108.05",
313
+ # "openInterest": "10764.48",
314
+ # "oraclePx": "107.99",
315
+ # "premium": "0.00055561",
316
+ # "prevDayPx": "111.81"
317
+ # }
318
+ # ]
319
+ # ]
320
+ #
321
+ #
322
+ meta = self.safe_dict(response, 0, {})
323
+ meta = self.safe_list(meta, 'universe', [])
324
+ assetCtxs = self.safe_dict(response, 1, {})
325
+ result = []
326
+ for i in range(0, len(meta)):
327
+ data = self.extend(
328
+ self.safe_dict(meta, i, {}),
329
+ self.safe_dict(assetCtxs, i, {})
330
+ )
331
+ data['baseId'] = i
332
+ result.append(data)
333
+ return self.parse_markets(result)
334
+
335
+ async def fetch_spot_markets(self, params={}) -> List[Market]:
336
+ """
337
+ retrieves data on all spot markets for hyperliquid
338
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
339
+ :param dict [params]: extra parameters specific to the exchange API endpoint
340
+ :returns dict[]: an array of objects representing market data
341
+ """
342
+ request: dict = {
343
+ 'type': 'spotMetaAndAssetCtxs',
344
+ }
345
+ response = await self.publicPostInfo(self.extend(request, params))
346
+ #
347
+ # [
348
+ # {
349
+ # 'tokens': [
350
+ # {
351
+ # 'name': 'USDC',
352
+ # 'szDecimals': '8',
353
+ # 'weiDecimals': '8',
354
+ # },
355
+ # {
356
+ # 'name': 'PURR',
357
+ # 'szDecimals': '0',
358
+ # 'weiDecimals': '5',
359
+ # },
360
+ # ],
361
+ # 'universe': [
362
+ # {
363
+ # 'name': 'PURR/USDC',
364
+ # 'tokens': [
365
+ # 1,
366
+ # 0,
367
+ # ],
368
+ # },
369
+ # ],
370
+ # },
371
+ # [
372
+ # {
373
+ # 'dayNtlVlm': '264250385.14640012',
374
+ # 'markPx': '0.018314',
375
+ # 'midPx': '0.0182235',
376
+ # 'prevDayPx': '0.017427',
377
+ # },
378
+ # ],
379
+ # ]
380
+ # mainnet
381
+ # [
382
+ # {
383
+ # "canonical_tokens2":[
384
+ # 0,
385
+ # 1
386
+ # ],
387
+ # "spot_infos":[
388
+ # {
389
+ # "name":"PURR/USDC",
390
+ # "tokens":[
391
+ # 1,
392
+ # 0
393
+ # ]
394
+ # }
395
+ # ],
396
+ # "token_id_to_token":[
397
+ # [
398
+ # "0x6d1e7cde53ba9467b783cb7c530ce054",
399
+ # 0
400
+ # ],
401
+ # [
402
+ # "0xc1fb593aeffbeb02f85e0308e9956a90",
403
+ # 1
404
+ # ]
405
+ # ],
406
+ # "token_infos":[
407
+ # {
408
+ # "deployer":null,
409
+ # "spec":{
410
+ # "name":"USDC",
411
+ # "szDecimals":"8",
412
+ # "weiDecimals":"8"
413
+ # },
414
+ # "spots":[
415
+ # ]
416
+ # },
417
+ # {
418
+ # "deployer":null,
419
+ # "spec":{
420
+ # "name":"PURR",
421
+ # "szDecimals":"0",
422
+ # "weiDecimals":"5"
423
+ # },
424
+ # "spots":[
425
+ # 0
426
+ # ]
427
+ # }
428
+ # ]
429
+ # },
430
+ # [
431
+ # {
432
+ # "dayNtlVlm":"35001170.16631",
433
+ # "markPx":"0.15743",
434
+ # "midPx":"0.157555",
435
+ # "prevDayPx":"0.158"
436
+ # }
437
+ # ]
438
+ # ]
439
+ #
440
+ # response differs depending on the environment(mainnet vs sandbox)
441
+ first = self.safe_dict(response, 0, {})
442
+ meta = self.safe_list_2(first, 'universe', 'spot_infos', [])
443
+ tokens = self.safe_list_2(first, 'tokens', 'token_infos', [])
444
+ markets = []
445
+ for i in range(0, len(meta)):
446
+ market = self.safe_dict(meta, i, {})
447
+ marketName = self.safe_string(market, 'name')
448
+ if marketName.find('/') < 0:
449
+ # there are some weird spot markets in testnet, eg @2
450
+ continue
451
+ marketParts = marketName.split('/')
452
+ baseName = self.safe_string(marketParts, 0)
453
+ quoteId = self.safe_string(marketParts, 1)
454
+ base = self.safe_currency_code(baseName)
455
+ quote = self.safe_currency_code(quoteId)
456
+ symbol = base + '/' + quote
457
+ fees = self.safe_dict(self.fees, 'spot', {})
458
+ taker = self.safe_number(fees, 'taker')
459
+ maker = self.safe_number(fees, 'maker')
460
+ tokensPos = self.safe_list(market, 'tokens', [])
461
+ baseTokenPos = self.safe_integer(tokensPos, 0)
462
+ # quoteTokenPos = self.safe_integer(tokensPos, 1)
463
+ baseTokenInfo = self.safe_dict(tokens, baseTokenPos, {})
464
+ # quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
465
+ innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
466
+ # innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
467
+ amountPrecision = self.parse_number(self.parse_precision(self.safe_string(innerBaseTokenInfo, 'szDecimals')))
468
+ # quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
469
+ baseId = self.number_to_string(i + 10000)
470
+ markets.append(self.safe_market_structure({
471
+ 'id': marketName,
472
+ 'symbol': symbol,
473
+ 'base': base,
474
+ 'quote': quote,
475
+ 'settle': None,
476
+ 'baseId': baseId,
477
+ 'quoteId': quoteId,
478
+ 'settleId': None,
479
+ 'type': 'spot',
480
+ 'spot': True,
481
+ 'subType': None,
482
+ 'margin': None,
483
+ 'swap': False,
484
+ 'future': False,
485
+ 'option': False,
486
+ 'active': True,
487
+ 'contract': False,
488
+ 'linear': None,
489
+ 'inverse': None,
490
+ 'taker': taker,
491
+ 'maker': maker,
492
+ 'contractSize': None,
493
+ 'expiry': None,
494
+ 'expiryDatetime': None,
495
+ 'strike': None,
496
+ 'optionType': None,
497
+ 'precision': {
498
+ 'amount': amountPrecision, # decimal places
499
+ 'price': 5, # significant digits
500
+ },
501
+ 'limits': {
502
+ 'leverage': {
503
+ 'min': None,
504
+ 'max': None,
505
+ },
506
+ 'amount': {
507
+ 'min': None,
508
+ 'max': None,
509
+ },
510
+ 'price': {
511
+ 'min': None,
512
+ 'max': None,
513
+ },
514
+ 'cost': {
515
+ 'min': None,
516
+ 'max': None,
517
+ },
518
+ },
519
+ 'created': None,
520
+ 'info': market,
521
+ }))
522
+ return markets
523
+
524
+ def parse_market(self, market: dict) -> Market:
525
+ #
526
+ # {
527
+ # "maxLeverage": "50",
528
+ # "name": "ETH",
529
+ # "onlyIsolated": False,
530
+ # "szDecimals": "4",
531
+ # "dayNtlVlm": "1709813.11535",
532
+ # "funding": "0.00004807",
533
+ # "impactPxs": [
534
+ # "2369.3",
535
+ # "2369.6"
536
+ # ],
537
+ # "markPx": "2369.6",
538
+ # "midPx": "2369.45",
539
+ # "openInterest": "1815.4712",
540
+ # "oraclePx": "2367.3",
541
+ # "premium": "0.00090821",
542
+ # "prevDayPx": "2381.5"
543
+ # }
544
+ #
545
+ quoteId = 'USDC'
546
+ base = self.safe_string(market, 'name')
547
+ quote = self.safe_currency_code(quoteId)
548
+ baseId = self.safe_string(market, 'baseId')
549
+ settleId = 'USDC'
550
+ settle = self.safe_currency_code(settleId)
551
+ symbol = base + '/' + quote
552
+ contract = True
553
+ swap = True
554
+ if contract:
555
+ if swap:
556
+ symbol = symbol + ':' + settle
557
+ fees = self.safe_dict(self.fees, 'swap', {})
558
+ taker = self.safe_number(fees, 'taker')
559
+ maker = self.safe_number(fees, 'maker')
560
+ return {
561
+ 'id': baseId,
562
+ 'symbol': symbol,
563
+ 'base': base,
564
+ 'quote': quote,
565
+ 'settle': settle,
566
+ 'baseId': baseId,
567
+ 'quoteId': quoteId,
568
+ 'settleId': settleId,
569
+ 'type': 'swap',
570
+ 'spot': False,
571
+ 'margin': None,
572
+ 'swap': swap,
573
+ 'future': False,
574
+ 'option': False,
575
+ 'active': True,
576
+ 'contract': contract,
577
+ 'linear': True,
578
+ 'inverse': False,
579
+ 'taker': taker,
580
+ 'maker': maker,
581
+ 'contractSize': self.parse_number('1'),
582
+ 'expiry': None,
583
+ 'expiryDatetime': None,
584
+ 'strike': None,
585
+ 'optionType': None,
586
+ 'precision': {
587
+ 'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'szDecimals'))), # decimal places
588
+ 'price': 5, # significant digits
589
+ },
590
+ 'limits': {
591
+ 'leverage': {
592
+ 'min': None,
593
+ 'max': None,
594
+ },
595
+ 'amount': {
596
+ 'min': None,
597
+ 'max': None,
598
+ },
599
+ 'price': {
600
+ 'min': None,
601
+ 'max': None,
602
+ },
603
+ 'cost': {
604
+ 'min': None,
605
+ 'max': None,
606
+ },
607
+ },
608
+ 'created': None,
609
+ 'info': market,
610
+ }
611
+
612
+ async def fetch_balance(self, params={}) -> Balances:
613
+ """
614
+ query for balance and get the amount of funds available for trading or funds locked in orders
615
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
616
+ :param dict [params]: extra parameters specific to the exchange API endpoint
617
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
618
+ :param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
619
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
620
+ """
621
+ userAddress = None
622
+ userAddress, params = self.handle_public_address('fetchBalance', params)
623
+ type = None
624
+ type, params = self.handle_market_type_and_params('fetchBalance', None, params)
625
+ isSpot = (type == 'spot')
626
+ reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
627
+ request: dict = {
628
+ 'type': reqType,
629
+ 'user': userAddress,
630
+ }
631
+ response = await self.publicPostInfo(self.extend(request, params))
632
+ #
633
+ # {
634
+ # "assetPositions": [],
635
+ # "crossMaintenanceMarginUsed": "0.0",
636
+ # "crossMarginSummary": {
637
+ # "accountValue": "100.0",
638
+ # "totalMarginUsed": "0.0",
639
+ # "totalNtlPos": "0.0",
640
+ # "totalRawUsd": "100.0"
641
+ # },
642
+ # "marginSummary": {
643
+ # "accountValue": "100.0",
644
+ # "totalMarginUsed": "0.0",
645
+ # "totalNtlPos": "0.0",
646
+ # "totalRawUsd": "100.0"
647
+ # },
648
+ # "time": "1704261007014",
649
+ # "withdrawable": "100.0"
650
+ # }
651
+ # spot
652
+ #
653
+ # {
654
+ # "balances":[
655
+ # {
656
+ # "coin":"USDC",
657
+ # "hold":"0.0",
658
+ # "total":"1481.844"
659
+ # },
660
+ # {
661
+ # "coin":"PURR",
662
+ # "hold":"0.0",
663
+ # "total":"999.65004"
664
+ # }
665
+ # }
666
+ #
667
+ balances = self.safe_list(response, 'balances')
668
+ if balances is not None:
669
+ spotBalances: dict = {'info': response}
670
+ for i in range(0, len(balances)):
671
+ balance = balances[i]
672
+ code = self.safe_currency_code(self.safe_string(balance, 'coin'))
673
+ account = self.account()
674
+ total = self.safe_string(balance, 'total')
675
+ free = self.safe_string(balance, 'hold')
676
+ account['total'] = total
677
+ account['free'] = free
678
+ spotBalances[code] = account
679
+ return self.safe_balance(spotBalances)
680
+ data = self.safe_dict(response, 'marginSummary', {})
681
+ result: dict = {
682
+ 'info': response,
683
+ 'USDC': {
684
+ 'total': self.safe_float(data, 'accountValue'),
685
+ 'used': self.safe_float(data, 'totalMarginUsed'),
686
+ },
687
+ }
688
+ timestamp = self.safe_integer(response, 'time')
689
+ result['timestamp'] = timestamp
690
+ result['datetime'] = self.iso8601(timestamp)
691
+ return self.safe_balance(result)
692
+
693
+ async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
694
+ """
695
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
696
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info
697
+ :param str symbol: unified symbol of the market to fetch the order book for
698
+ :param int [limit]: the maximum amount of order book entries to return
699
+ :param dict [params]: extra parameters specific to the exchange API endpoint
700
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
701
+ """
702
+ await self.load_markets()
703
+ market = self.market(symbol)
704
+ request: dict = {
705
+ 'type': 'l2Book',
706
+ 'coin': market['base'] if market['swap'] else market['id'],
707
+ }
708
+ response = await self.publicPostInfo(self.extend(request, params))
709
+ #
710
+ # {
711
+ # "coin": "ETH",
712
+ # "levels": [
713
+ # [
714
+ # {
715
+ # "n": "2",
716
+ # "px": "2216.2",
717
+ # "sz": "74.0637"
718
+ # }
719
+ # ],
720
+ # [
721
+ # {
722
+ # "n": "2",
723
+ # "px": "2216.5",
724
+ # "sz": "70.5893"
725
+ # }
726
+ # ]
727
+ # ],
728
+ # "time": "1704290104840"
729
+ # }
730
+ #
731
+ data = self.safe_list(response, 'levels', [])
732
+ result: dict = {
733
+ 'bids': self.safe_list(data, 0, []),
734
+ 'asks': self.safe_list(data, 1, []),
735
+ }
736
+ timestamp = self.safe_integer(response, 'time')
737
+ return self.parse_order_book(result, market['symbol'], timestamp, 'bids', 'asks', 'px', 'sz')
738
+
739
+ async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
740
+ """
741
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
742
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info-1
743
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
744
+ :param str timeframe: the length of time each candle represents, support '1m', '15m', '1h', '1d'
745
+ :param int [since]: timestamp in ms of the earliest candle to fetch
746
+ :param int [limit]: the maximum amount of candles to fetch
747
+ :param dict [params]: extra parameters specific to the exchange API endpoint
748
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
749
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
750
+ """
751
+ await self.load_markets()
752
+ market = self.market(symbol)
753
+ until = self.safe_integer(params, 'until', self.milliseconds())
754
+ if since is None:
755
+ since = 0
756
+ if limit is None:
757
+ limit = 500
758
+ params = self.omit(params, ['until'])
759
+ request: dict = {
760
+ 'type': 'candleSnapshot',
761
+ 'req': {
762
+ 'coin': market['base'] if market['swap'] else market['id'],
763
+ 'interval': timeframe,
764
+ 'startTime': since,
765
+ 'endTime': until,
766
+ },
767
+ }
768
+ response = await self.publicPostInfo(self.extend(request, params))
769
+ #
770
+ # [
771
+ # {
772
+ # "T": 1704287699999,
773
+ # "c": "2226.4",
774
+ # "h": "2247.9",
775
+ # "i": "15m",
776
+ # "l": "2224.6",
777
+ # "n": 46,
778
+ # "o": "2247.9",
779
+ # "s": "ETH",
780
+ # "t": 1704286800000,
781
+ # "v": "591.6427"
782
+ # }
783
+ # ]
784
+ #
785
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)
786
+
787
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
788
+ #
789
+ # {
790
+ # "T": 1704287699999,
791
+ # "c": "2226.4",
792
+ # "h": "2247.9",
793
+ # "i": "15m",
794
+ # "l": "2224.6",
795
+ # "n": 46,
796
+ # "o": "2247.9",
797
+ # "s": "ETH",
798
+ # "t": 1704286800000,
799
+ # "v": "591.6427"
800
+ # }
801
+ #
802
+ return [
803
+ self.safe_integer(ohlcv, 't'),
804
+ self.safe_number(ohlcv, 'o'),
805
+ self.safe_number(ohlcv, 'h'),
806
+ self.safe_number(ohlcv, 'l'),
807
+ self.safe_number(ohlcv, 'c'),
808
+ self.safe_number(ohlcv, 'v'),
809
+ ]
810
+
811
+ async def fetch_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
812
+ """
813
+ get the list of most recent trades for a particular symbol
814
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
815
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
816
+ :param str symbol: unified market symbol
817
+ :param int [since]: the earliest time in ms to fetch trades for
818
+ :param int [limit]: the maximum number of trades structures to retrieve
819
+ :param dict [params]: extra parameters specific to the exchange API endpoint
820
+ :param int [params.until]: timestamp in ms of the latest trade
821
+ :param str [params.address]: wallet address that made trades
822
+ :param str [params.user]: wallet address that made trades
823
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
824
+ """
825
+ userAddress = None
826
+ userAddress, params = self.handle_public_address('fetchTrades', params)
827
+ await self.load_markets()
828
+ market = self.safe_market(symbol)
829
+ request: dict = {
830
+ 'user': userAddress,
831
+ }
832
+ if since is not None:
833
+ request['type'] = 'userFillsByTime'
834
+ request['startTime'] = since
835
+ else:
836
+ request['type'] = 'userFills'
837
+ until = self.safe_integer(params, 'until')
838
+ params = self.omit(params, 'until')
839
+ if until is not None:
840
+ request['endTime'] = until
841
+ response = await self.publicPostInfo(self.extend(request, params))
842
+ #
843
+ # [
844
+ # {
845
+ # "closedPnl": "0.19343",
846
+ # "coin": "ETH",
847
+ # "crossed": True,
848
+ # "dir": "Close Long",
849
+ # "fee": "0.050062",
850
+ # "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
851
+ # "liquidationMarkPx": null,
852
+ # "oid": 3929354691,
853
+ # "px": "2381.1",
854
+ # "side": "A",
855
+ # "startPosition": "0.0841",
856
+ # "sz": "0.0841",
857
+ # "tid": 128423918764978,
858
+ # "time": 1704262888911
859
+ # }
860
+ # ]
861
+ #
862
+ return self.parse_trades(response, market, since, limit)
863
+
864
+ def amount_to_precision(self, symbol, amount):
865
+ market = self.market(symbol)
866
+ if market['spot']:
867
+ return super(hyperliquid, self).amount_to_precision(symbol, amount)
868
+ return self.decimal_to_precision(amount, ROUND, self.markets[symbol]['precision']['amount'], self.precisionMode)
869
+
870
+ def price_to_precision(self, symbol: str, price) -> str:
871
+ market = self.market(symbol)
872
+ result = self.decimal_to_precision(price, ROUND, market['precision']['price'], SIGNIFICANT_DIGITS, self.paddingMode)
873
+ decimalParsedResult = self.decimal_to_precision(result, ROUND, 6, DECIMAL_PLACES, self.paddingMode)
874
+ return decimalParsedResult
875
+
876
+ def hash_message(self, message):
877
+ return '0x' + self.hash(message, 'keccak', 'hex')
878
+
879
+ def sign_hash(self, hash, privateKey):
880
+ signature = self.ecdsa(hash[-64:], privateKey[-64:], 'secp256k1', None)
881
+ return {
882
+ 'r': '0x' + signature['r'],
883
+ 's': '0x' + signature['s'],
884
+ 'v': self.sum(27, signature['v']),
885
+ }
886
+
887
+ def sign_message(self, message, privateKey):
888
+ return self.sign_hash(self.hash_message(message), privateKey[-64:])
889
+
890
+ def construct_phantom_agent(self, hash, isTestnet=True):
891
+ source = 'b' if (isTestnet) else 'a'
892
+ return {
893
+ 'source': source,
894
+ 'connectionId': hash,
895
+ }
896
+
897
+ def action_hash(self, action, vaultAddress, nonce):
898
+ dataBinary = self.packb(action)
899
+ dataHex = self.binary_to_base16(dataBinary)
900
+ data = dataHex
901
+ data += '00000' + self.int_to_base16(nonce)
902
+ if vaultAddress is None:
903
+ data += '00'
904
+ else:
905
+ data += '01'
906
+ data += vaultAddress
907
+ return self.hash(self.base16_to_binary(data), 'keccak', 'binary')
908
+
909
+ def sign_l1_action(self, action, nonce, vaultAdress=None) -> object:
910
+ hash = self.action_hash(action, vaultAdress, nonce)
911
+ isTestnet = self.safe_bool(self.options, 'sandboxMode', False)
912
+ phantomAgent = self.construct_phantom_agent(hash, isTestnet)
913
+ # data: Dict = {
914
+ # 'domain': {
915
+ # 'chainId': 1337,
916
+ # 'name': 'Exchange',
917
+ # 'verifyingContract': '0x0000000000000000000000000000000000000000',
918
+ # 'version': '1',
919
+ # },
920
+ # 'types': {
921
+ # 'Agent': [
922
+ # {'name': 'source', 'type': 'string'},
923
+ # {'name': 'connectionId', 'type': 'bytes32'},
924
+ # ],
925
+ # 'EIP712Domain': [
926
+ # {'name': 'name', 'type': 'string'},
927
+ # {'name': 'version', 'type': 'string'},
928
+ # {'name': 'chainId', 'type': 'uint256'},
929
+ # {'name': 'verifyingContract', 'type': 'address'},
930
+ # ],
931
+ # },
932
+ # 'primaryType': 'Agent',
933
+ # 'message': phantomAgent,
934
+ # }
935
+ zeroAddress = self.safe_string(self.options, 'zeroAddress')
936
+ chainId = 1337 # check self out
937
+ domain: dict = {
938
+ 'chainId': chainId,
939
+ 'name': 'Exchange',
940
+ 'verifyingContract': zeroAddress,
941
+ 'version': '1',
942
+ }
943
+ messageTypes: dict = {
944
+ 'Agent': [
945
+ {'name': 'source', 'type': 'string'},
946
+ {'name': 'connectionId', 'type': 'bytes32'},
947
+ ],
948
+ }
949
+ msg = self.eth_encode_structured_data(domain, messageTypes, phantomAgent)
950
+ signature = self.sign_message(msg, self.privateKey)
951
+ return signature
952
+
953
+ def sign_user_signed_action(self, messageTypes, message):
954
+ zeroAddress = self.safe_string(self.options, 'zeroAddress')
955
+ chainId = 421614 # check self out
956
+ domain: dict = {
957
+ 'chainId': chainId,
958
+ 'name': 'HyperliquidSignTransaction',
959
+ 'verifyingContract': zeroAddress,
960
+ 'version': '1',
961
+ }
962
+ msg = self.eth_encode_structured_data(domain, messageTypes, message)
963
+ signature = self.sign_message(msg, self.privateKey)
964
+ return signature
965
+
966
+ def build_transfer_sig(self, message):
967
+ messageTypes: dict = {
968
+ 'HyperliquidTransaction:UsdSend': [
969
+ {'name': 'hyperliquidChain', 'type': 'string'},
970
+ {'name': 'destination', 'type': 'string'},
971
+ {'name': 'amount', 'type': 'string'},
972
+ {'name': 'time', 'type': 'uint64'},
973
+ ],
974
+ }
975
+ return self.sign_user_signed_action(messageTypes, message)
976
+
977
+ def build_withdraw_sig(self, message):
978
+ messageTypes: dict = {
979
+ 'HyperliquidTransaction:Withdraw': [
980
+ {'name': 'hyperliquidChain', 'type': 'string'},
981
+ {'name': 'destination', 'type': 'string'},
982
+ {'name': 'amount', 'type': 'string'},
983
+ {'name': 'time', 'type': 'uint64'},
984
+ ],
985
+ }
986
+ return self.sign_user_signed_action(messageTypes, message)
987
+
988
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
989
+ """
990
+ create a trade order
991
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
992
+ :param str symbol: unified symbol of the market to create an order in
993
+ :param str type: 'market' or 'limit'
994
+ :param str side: 'buy' or 'sell'
995
+ :param float amount: how much of currency you want to trade in units of base currency
996
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
997
+ :param dict [params]: extra parameters specific to the exchange API endpoint
998
+ :param str [params.timeInForce]: 'Gtc', 'Ioc', 'Alo'
999
+ :param bool [params.postOnly]: True or False whether the order is post-only
1000
+ :param bool [params.reduceOnly]: True or False whether the order is reduce-only
1001
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1002
+ :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1003
+ :param str [params.slippage]: the slippage for market order
1004
+ :param str [params.vaultAddress]: the vault address for order
1005
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1006
+ """
1007
+ await self.load_markets()
1008
+ market = self.market(symbol)
1009
+ vaultAddress = self.safe_string(params, 'vaultAddress')
1010
+ params = self.omit(params, 'vaultAddress')
1011
+ symbol = market['symbol']
1012
+ order = {
1013
+ 'symbol': symbol,
1014
+ 'type': type,
1015
+ 'side': side,
1016
+ 'amount': amount,
1017
+ 'price': price,
1018
+ 'params': params,
1019
+ }
1020
+ globalParams: dict = {}
1021
+ if vaultAddress is not None:
1022
+ globalParams['vaultAddress'] = vaultAddress
1023
+ response = await self.create_orders([order], globalParams)
1024
+ first = self.safe_dict(response, 0)
1025
+ return first
1026
+
1027
+ async def create_orders(self, orders: List[OrderRequest], params={}):
1028
+ """
1029
+ create a list of trade orders
1030
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
1031
+ :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
1032
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1033
+ """
1034
+ self.check_required_credentials()
1035
+ await self.load_markets()
1036
+ defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1037
+ defaultSlippage = self.safe_string(params, 'slippage', defaultSlippage)
1038
+ hasClientOrderId = False
1039
+ for i in range(0, len(orders)):
1040
+ rawOrder = orders[i]
1041
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1042
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1043
+ if clientOrderId is not None:
1044
+ hasClientOrderId = True
1045
+ if hasClientOrderId:
1046
+ for i in range(0, len(orders)):
1047
+ rawOrder = orders[i]
1048
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1049
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1050
+ if clientOrderId is None:
1051
+ raise ArgumentsRequired(self.id + ' createOrders() all orders must have clientOrderId if at least one has a clientOrderId')
1052
+ params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
1053
+ nonce = self.milliseconds()
1054
+ orderReq = []
1055
+ for i in range(0, len(orders)):
1056
+ rawOrder = orders[i]
1057
+ marketId = self.safe_string(rawOrder, 'symbol')
1058
+ market = self.market(marketId)
1059
+ symbol = market['symbol']
1060
+ type = self.safe_string_upper(rawOrder, 'type')
1061
+ isMarket = (type == 'MARKET')
1062
+ side = self.safe_string_upper(rawOrder, 'side')
1063
+ isBuy = (side == 'BUY')
1064
+ amount = self.safe_string(rawOrder, 'amount')
1065
+ price = self.safe_string(rawOrder, 'price')
1066
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1067
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1068
+ slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
1069
+ defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1070
+ postOnly = self.safe_bool(orderParams, 'postOnly', False)
1071
+ if postOnly:
1072
+ defaultTimeInForce = 'alo'
1073
+ timeInForce = self.safe_string_lower(orderParams, 'timeInForce', defaultTimeInForce)
1074
+ timeInForce = self.capitalize(timeInForce)
1075
+ triggerPrice = self.safe_string_2(orderParams, 'triggerPrice', 'stopPrice')
1076
+ stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
1077
+ takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
1078
+ isTrigger = (stopLossPrice or takeProfitPrice)
1079
+ px = None
1080
+ if isMarket:
1081
+ if price is None:
1082
+ raise ArgumentsRequired(self.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options(default is 5%).')
1083
+ px = Precise.string_mul(price, Precise.string_add('1', slippage)) if (isBuy) else Precise.string_mul(price, Precise.string_sub('1', slippage))
1084
+ px = self.price_to_precision(symbol, px) # round after adding slippage
1085
+ else:
1086
+ px = self.price_to_precision(symbol, price)
1087
+ sz = self.amount_to_precision(symbol, amount)
1088
+ reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
1089
+ orderType: dict = {}
1090
+ if isTrigger:
1091
+ isTp = False
1092
+ if takeProfitPrice is not None:
1093
+ triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1094
+ isTp = True
1095
+ else:
1096
+ triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1097
+ orderType['trigger'] = {
1098
+ 'isMarket': isMarket,
1099
+ 'triggerPx': triggerPrice,
1100
+ 'tpsl': 'tp' if (isTp) else 'sl',
1101
+ }
1102
+ else:
1103
+ orderType['limit'] = {
1104
+ 'tif': timeInForce,
1105
+ }
1106
+ orderParams = self.omit(orderParams, ['clientOrderId', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce', 'client_id', 'reduceOnly', 'postOnly'])
1107
+ orderObj: dict = {
1108
+ 'a': self.parse_to_int(market['baseId']),
1109
+ 'b': isBuy,
1110
+ 'p': px,
1111
+ 's': sz,
1112
+ 'r': reduceOnly,
1113
+ 't': orderType,
1114
+ # 'c': clientOrderId,
1115
+ }
1116
+ if clientOrderId is not None:
1117
+ orderObj['c'] = clientOrderId
1118
+ orderReq.append(self.extend(orderObj, orderParams))
1119
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1120
+ orderAction: dict = {
1121
+ 'type': 'order',
1122
+ 'orders': orderReq,
1123
+ 'grouping': 'na',
1124
+ # 'brokerCode': 1, # cant
1125
+ }
1126
+ if vaultAddress is None:
1127
+ orderAction['brokerCode'] = 1
1128
+ signature = self.sign_l1_action(orderAction, nonce, vaultAddress)
1129
+ request: dict = {
1130
+ 'action': orderAction,
1131
+ 'nonce': nonce,
1132
+ 'signature': signature,
1133
+ # 'vaultAddress': vaultAddress,
1134
+ }
1135
+ if vaultAddress is not None:
1136
+ params = self.omit(params, 'vaultAddress')
1137
+ request['vaultAddress'] = vaultAddress
1138
+ response = await self.privatePostExchange(self.extend(request, params))
1139
+ #
1140
+ # {
1141
+ # "status": "ok",
1142
+ # "response": {
1143
+ # "type": "order",
1144
+ # "data": {
1145
+ # "statuses": [
1146
+ # {
1147
+ # "resting": {
1148
+ # "oid": 5063830287
1149
+ # }
1150
+ # }
1151
+ # ]
1152
+ # }
1153
+ # }
1154
+ # }
1155
+ #
1156
+ responseObj = self.safe_dict(response, 'response', {})
1157
+ data = self.safe_dict(responseObj, 'data', {})
1158
+ statuses = self.safe_list(data, 'statuses', [])
1159
+ return self.parse_orders(statuses, None)
1160
+
1161
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
1162
+ """
1163
+ cancels an open order
1164
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
1165
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
1166
+ :param str id: order id
1167
+ :param str symbol: unified symbol of the market the order was made in
1168
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1169
+ :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1170
+ :param str [params.vaultAddress]: the vault address for order
1171
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1172
+ """
1173
+ return await self.cancel_orders([id], symbol, params)
1174
+
1175
+ async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
1176
+ """
1177
+ cancel multiple orders
1178
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
1179
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
1180
+ :param str[] ids: order ids
1181
+ :param str [symbol]: unified market symbol
1182
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1183
+ :param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1184
+ :param str [params.vaultAddress]: the vault address
1185
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1186
+ """
1187
+ self.check_required_credentials()
1188
+ if symbol is None:
1189
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
1190
+ await self.load_markets()
1191
+ market = self.market(symbol)
1192
+ clientOrderId = self.safe_value_2(params, 'clientOrderId', 'client_id')
1193
+ params = self.omit(params, ['clientOrderId', 'client_id'])
1194
+ nonce = self.milliseconds()
1195
+ request: dict = {
1196
+ 'nonce': nonce,
1197
+ # 'vaultAddress': vaultAddress,
1198
+ }
1199
+ cancelReq = []
1200
+ cancelAction: dict = {
1201
+ 'type': '',
1202
+ 'cancels': [],
1203
+ }
1204
+ baseId = self.parse_to_numeric(market['baseId'])
1205
+ if clientOrderId is not None:
1206
+ if not isinstance(clientOrderId, list):
1207
+ clientOrderId = [clientOrderId]
1208
+ cancelAction['type'] = 'cancelByCloid'
1209
+ for i in range(0, len(clientOrderId)):
1210
+ cancelReq.append({
1211
+ 'asset': baseId,
1212
+ 'cloid': clientOrderId[i],
1213
+ })
1214
+ else:
1215
+ cancelAction['type'] = 'cancel'
1216
+ for i in range(0, len(ids)):
1217
+ cancelReq.append({
1218
+ 'a': baseId,
1219
+ 'o': self.parse_to_numeric(ids[i]),
1220
+ })
1221
+ cancelAction['cancels'] = cancelReq
1222
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1223
+ signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1224
+ request['action'] = cancelAction
1225
+ request['signature'] = signature
1226
+ if vaultAddress is not None:
1227
+ params = self.omit(params, 'vaultAddress')
1228
+ request['vaultAddress'] = vaultAddress
1229
+ response = await self.privatePostExchange(self.extend(request, params))
1230
+ #
1231
+ # {
1232
+ # "status":"ok",
1233
+ # "response":{
1234
+ # "type":"cancel",
1235
+ # "data":{
1236
+ # "statuses":[
1237
+ # "success"
1238
+ # ]
1239
+ # }
1240
+ # }
1241
+ # }
1242
+ #
1243
+ return response
1244
+
1245
+ async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
1246
+ """
1247
+ cancel multiple orders for multiple symbols
1248
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
1249
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
1250
+ :param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol
1251
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1252
+ :param str [params.vaultAddress]: the vault address
1253
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1254
+ """
1255
+ self.check_required_credentials()
1256
+ await self.load_markets()
1257
+ nonce = self.milliseconds()
1258
+ request: dict = {
1259
+ 'nonce': nonce,
1260
+ # 'vaultAddress': vaultAddress,
1261
+ }
1262
+ cancelReq = []
1263
+ cancelAction: dict = {
1264
+ 'type': '',
1265
+ 'cancels': [],
1266
+ }
1267
+ cancelByCloid = False
1268
+ for i in range(0, len(orders)):
1269
+ order = orders[i]
1270
+ clientOrderId = self.safe_string(order, 'clientOrderId')
1271
+ if clientOrderId is not None:
1272
+ cancelByCloid = True
1273
+ id = self.safe_string(order, 'id')
1274
+ symbol = self.safe_string(order, 'symbol')
1275
+ if symbol is None:
1276
+ raise ArgumentsRequired(self.id + ' cancelOrdersForSymbols() requires a symbol argument in each order')
1277
+ if id is not None and cancelByCloid:
1278
+ raise BadRequest(self.id + ' cancelOrdersForSymbols() all orders must have either id or clientOrderId')
1279
+ assetKey = 'asset' if cancelByCloid else 'a'
1280
+ idKey = 'cloid' if cancelByCloid else 'o'
1281
+ market = self.market(symbol)
1282
+ cancelObj: dict = {}
1283
+ cancelObj[assetKey] = self.parse_to_numeric(market['baseId'])
1284
+ cancelObj[idKey] = clientOrderId if cancelByCloid else self.parse_to_numeric(id)
1285
+ cancelReq.append(cancelObj)
1286
+ cancelAction['type'] = 'cancelByCloid' if cancelByCloid else 'cancel'
1287
+ cancelAction['cancels'] = cancelReq
1288
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1289
+ signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1290
+ request['action'] = cancelAction
1291
+ request['signature'] = signature
1292
+ if vaultAddress is not None:
1293
+ params = self.omit(params, 'vaultAddress')
1294
+ request['vaultAddress'] = vaultAddress
1295
+ response = await self.privatePostExchange(self.extend(request, params))
1296
+ #
1297
+ # {
1298
+ # "status":"ok",
1299
+ # "response":{
1300
+ # "type":"cancel",
1301
+ # "data":{
1302
+ # "statuses":[
1303
+ # "success"
1304
+ # ]
1305
+ # }
1306
+ # }
1307
+ # }
1308
+ #
1309
+ return response
1310
+
1311
+ async def cancel_all_orders_after(self, timeout: Int, params={}):
1312
+ """
1313
+ dead man's switch, cancel all orders after the given timeout
1314
+ :param number timeout: time in milliseconds, 0 represents cancel the timer
1315
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1316
+ :param str [params.vaultAddress]: the vault address
1317
+ :returns dict: the api result
1318
+ """
1319
+ self.check_required_credentials()
1320
+ await self.load_markets()
1321
+ params = self.omit(params, ['clientOrderId', 'client_id'])
1322
+ nonce = self.milliseconds()
1323
+ request: dict = {
1324
+ 'nonce': nonce,
1325
+ # 'vaultAddress': vaultAddress,
1326
+ }
1327
+ cancelAction: dict = {
1328
+ 'type': 'scheduleCancel',
1329
+ 'time': nonce + timeout,
1330
+ }
1331
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1332
+ signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1333
+ request['action'] = cancelAction
1334
+ request['signature'] = signature
1335
+ if vaultAddress is not None:
1336
+ params = self.omit(params, 'vaultAddress')
1337
+ request['vaultAddress'] = vaultAddress
1338
+ response = await self.privatePostExchange(self.extend(request, params))
1339
+ #
1340
+ # {
1341
+ # "status":"err",
1342
+ # "response":"Cannot set scheduled cancel time until enough volume traded. Required: $1000000. Traded: $373.47205."
1343
+ # }
1344
+ #
1345
+ return response
1346
+
1347
+ async def edit_order(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
1348
+ """
1349
+ edit a trade order
1350
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
1351
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1352
+ :param str id: cancel order id
1353
+ :param str symbol: unified symbol of the market to create an order in
1354
+ :param str type: 'market' or 'limit'
1355
+ :param str side: 'buy' or 'sell'
1356
+ :param float amount: how much of currency you want to trade in units of base currency
1357
+ :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
1358
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1359
+ :param str [params.timeInForce]: 'Gtc', 'Ioc', 'Alo'
1360
+ :param bool [params.postOnly]: True or False whether the order is post-only
1361
+ :param bool [params.reduceOnly]: True or False whether the order is reduce-only
1362
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1363
+ :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1364
+ :param str [params.vaultAddress]: the vault address for order
1365
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1366
+ """
1367
+ self.check_required_credentials()
1368
+ if id is None:
1369
+ raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
1370
+ await self.load_markets()
1371
+ market = self.market(symbol)
1372
+ type = type.upper()
1373
+ isMarket = (type == 'MARKET')
1374
+ side = side.upper()
1375
+ isBuy = (side == 'BUY')
1376
+ defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1377
+ slippage = self.safe_string(params, 'slippage', defaultSlippage)
1378
+ defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1379
+ postOnly = self.safe_bool(params, 'postOnly', False)
1380
+ if postOnly:
1381
+ defaultTimeInForce = 'alo'
1382
+ timeInForce = self.safe_string_lower(params, 'timeInForce', defaultTimeInForce)
1383
+ timeInForce = self.capitalize(timeInForce)
1384
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_id')
1385
+ triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
1386
+ stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice)
1387
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1388
+ isTrigger = (stopLossPrice or takeProfitPrice)
1389
+ params = self.omit(params, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id'])
1390
+ px = str(price)
1391
+ if isMarket:
1392
+ px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
1393
+ else:
1394
+ px = self.price_to_precision(symbol, str(price))
1395
+ sz = self.amount_to_precision(symbol, amount)
1396
+ reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1397
+ orderType: dict = {}
1398
+ if isTrigger:
1399
+ isTp = False
1400
+ if takeProfitPrice is not None:
1401
+ triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1402
+ isTp = True
1403
+ else:
1404
+ triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1405
+ orderType['trigger'] = {
1406
+ 'isMarket': isMarket,
1407
+ 'triggerPx': triggerPrice,
1408
+ 'tpsl': 'tp' if (isTp) else 'sl',
1409
+ }
1410
+ else:
1411
+ orderType['limit'] = {
1412
+ 'tif': timeInForce,
1413
+ }
1414
+ if triggerPrice is None:
1415
+ triggerPrice = '0'
1416
+ nonce = self.milliseconds()
1417
+ orderReq: dict = {
1418
+ 'a': self.parse_to_int(market['baseId']),
1419
+ 'b': isBuy,
1420
+ 'p': px,
1421
+ 's': sz,
1422
+ 'r': reduceOnly,
1423
+ 't': orderType,
1424
+ # 'c': clientOrderId,
1425
+ }
1426
+ if clientOrderId is not None:
1427
+ orderReq['c'] = clientOrderId
1428
+ modifyReq: dict = {
1429
+ 'oid': self.parse_to_int(id),
1430
+ 'order': orderReq,
1431
+ }
1432
+ modifyAction: dict = {
1433
+ 'type': 'batchModify',
1434
+ 'modifies': [modifyReq],
1435
+ }
1436
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1437
+ signature = self.sign_l1_action(modifyAction, nonce, vaultAddress)
1438
+ request: dict = {
1439
+ 'action': modifyAction,
1440
+ 'nonce': nonce,
1441
+ 'signature': signature,
1442
+ # 'vaultAddress': vaultAddress,
1443
+ }
1444
+ if vaultAddress is not None:
1445
+ params = self.omit(params, 'vaultAddress')
1446
+ request['vaultAddress'] = vaultAddress
1447
+ response = await self.privatePostExchange(self.extend(request, params))
1448
+ #
1449
+ # {
1450
+ # "status": "ok",
1451
+ # "response": {
1452
+ # "type": "order",
1453
+ # "data": {
1454
+ # "statuses": [
1455
+ # {
1456
+ # "resting": {
1457
+ # "oid": 5063830287
1458
+ # }
1459
+ # }
1460
+ # ]
1461
+ # }
1462
+ # }
1463
+ # }
1464
+ # when the order is filled immediately
1465
+ # {
1466
+ # "status":"ok",
1467
+ # "response":{
1468
+ # "type":"order",
1469
+ # "data":{
1470
+ # "statuses":[
1471
+ # {
1472
+ # "filled":{
1473
+ # "totalSz":"0.1",
1474
+ # "avgPx":"100.84",
1475
+ # "oid":6195281425
1476
+ # }
1477
+ # }
1478
+ # ]
1479
+ # }
1480
+ # }
1481
+ # }
1482
+ #
1483
+ responseObject = self.safe_dict(response, 'response', {})
1484
+ dataObject = self.safe_dict(responseObject, 'data', {})
1485
+ statuses = self.safe_list(dataObject, 'statuses', [])
1486
+ first = self.safe_dict(statuses, 0, {})
1487
+ return self.parse_order(first, market)
1488
+
1489
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1490
+ """
1491
+ fetches historical funding rate prices
1492
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-historical-funding-rates
1493
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
1494
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
1495
+ :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
1496
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1497
+ :param int [params.until]: timestamp in ms of the latest funding rate
1498
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
1499
+ """
1500
+ await self.load_markets()
1501
+ market = self.market(symbol)
1502
+ request: dict = {
1503
+ 'type': 'fundingHistory',
1504
+ 'coin': market['base'],
1505
+ }
1506
+ if since is not None:
1507
+ request['startTime'] = since
1508
+ else:
1509
+ request['startTime'] = self.milliseconds() - 100 * 60 * 60 * 1000
1510
+ until = self.safe_integer(params, 'until')
1511
+ params = self.omit(params, 'until')
1512
+ if until is not None:
1513
+ request['endTime'] = until
1514
+ response = await self.publicPostInfo(self.extend(request, params))
1515
+ #
1516
+ # [
1517
+ # {
1518
+ # "coin": "ETH",
1519
+ # "fundingRate": "0.0000125",
1520
+ # "premium": "0.00057962",
1521
+ # "time": 1704290400031
1522
+ # }
1523
+ # ]
1524
+ #
1525
+ result = []
1526
+ for i in range(0, len(response)):
1527
+ entry = response[i]
1528
+ timestamp = self.safe_integer(entry, 'time')
1529
+ result.append({
1530
+ 'info': entry,
1531
+ 'symbol': self.safe_symbol(None, market),
1532
+ 'fundingRate': self.safe_number(entry, 'fundingRate'),
1533
+ 'timestamp': timestamp,
1534
+ 'datetime': self.iso8601(timestamp),
1535
+ })
1536
+ sorted = self.sort_by(result, 'timestamp')
1537
+ return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
1538
+
1539
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1540
+ """
1541
+ fetch all unfilled currently open orders
1542
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-open-orders
1543
+ :param str symbol: unified market symbol
1544
+ :param int [since]: the earliest time in ms to fetch open orders for
1545
+ :param int [limit]: the maximum number of open orders structures to retrieve
1546
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1547
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
1548
+ :param str [params.method]: 'openOrders' or 'frontendOpenOrders' default is 'frontendOpenOrders'
1549
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1550
+ """
1551
+ userAddress = None
1552
+ userAddress, params = self.handle_public_address('fetchOpenOrders', params)
1553
+ method = None
1554
+ method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'frontendOpenOrders')
1555
+ await self.load_markets()
1556
+ market = self.safe_market(symbol)
1557
+ request: dict = {
1558
+ 'type': method,
1559
+ 'user': userAddress,
1560
+ }
1561
+ response = await self.publicPostInfo(self.extend(request, params))
1562
+ #
1563
+ # [
1564
+ # {
1565
+ # "coin": "ETH",
1566
+ # "limitPx": "2000.0",
1567
+ # "oid": 3991946565,
1568
+ # "origSz": "0.1",
1569
+ # "side": "B",
1570
+ # "sz": "0.1",
1571
+ # "timestamp": 1704346468838
1572
+ # }
1573
+ # ]
1574
+ #
1575
+ return self.parse_orders(response, market, since, limit)
1576
+
1577
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1578
+ """
1579
+ fetch all unfilled currently closed orders
1580
+ :param str symbol: unified market symbol
1581
+ :param int [since]: the earliest time in ms to fetch open orders for
1582
+ :param int [limit]: the maximum number of open orders structures to retrieve
1583
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1584
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
1585
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1586
+ """
1587
+ userAddress = None
1588
+ userAddress, params = self.handle_public_address('fetchClosedOrders', params)
1589
+ await self.load_markets()
1590
+ market = self.safe_market(symbol)
1591
+ request: dict = {
1592
+ 'type': 'historicalOrders',
1593
+ 'user': userAddress,
1594
+ }
1595
+ response = await self.publicPostInfo(self.extend(request, params))
1596
+ #
1597
+ # [
1598
+ # {
1599
+ # "coin": "ETH",
1600
+ # "limitPx": "2000.0",
1601
+ # "oid": 3991946565,
1602
+ # "origSz": "0.1",
1603
+ # "side": "B",
1604
+ # "sz": "0.1",
1605
+ # "timestamp": 1704346468838
1606
+ # }
1607
+ # ]
1608
+ #
1609
+ return self.parse_orders(response, market, since, limit)
1610
+
1611
+ async def fetch_order(self, id: str, symbol: Str = None, params={}):
1612
+ """
1613
+ fetches information on an order made by the user
1614
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-order-status-by-oid-or-cloid
1615
+ :param str symbol: unified symbol of the market the order was made in
1616
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1617
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
1618
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1619
+ """
1620
+ userAddress = None
1621
+ userAddress, params = self.handle_public_address('fetchOrder', params)
1622
+ await self.load_markets()
1623
+ market = self.safe_market(symbol)
1624
+ request: dict = {
1625
+ 'type': 'orderStatus',
1626
+ 'oid': self.parse_to_numeric(id),
1627
+ 'user': userAddress,
1628
+ }
1629
+ response = await self.publicPostInfo(self.extend(request, params))
1630
+ #
1631
+ # {
1632
+ # "order": {
1633
+ # "order": {
1634
+ # "children": [],
1635
+ # "cloid": null,
1636
+ # "coin": "ETH",
1637
+ # "isPositionTpsl": False,
1638
+ # "isTrigger": False,
1639
+ # "limitPx": "2000.0",
1640
+ # "oid": "3991946565",
1641
+ # "orderType": "Limit",
1642
+ # "origSz": "0.1",
1643
+ # "reduceOnly": False,
1644
+ # "side": "B",
1645
+ # "sz": "0.1",
1646
+ # "tif": "Gtc",
1647
+ # "timestamp": "1704346468838",
1648
+ # "triggerCondition": "N/A",
1649
+ # "triggerPx": "0.0"
1650
+ # },
1651
+ # "status": "open",
1652
+ # "statusTimestamp": "1704346468838"
1653
+ # },
1654
+ # "status": "order"
1655
+ # }
1656
+ #
1657
+ data = self.safe_dict(response, 'order')
1658
+ return self.parse_order(data, market)
1659
+
1660
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1661
+ #
1662
+ # fetchOpenOrders
1663
+ #
1664
+ # {
1665
+ # "coin": "ETH",
1666
+ # "limitPx": "2000.0",
1667
+ # "oid": 3991946565,
1668
+ # "origSz": "0.1",
1669
+ # "side": "B",
1670
+ # "sz": "0.1",
1671
+ # "timestamp": 1704346468838
1672
+ # }
1673
+ # fetchClosedorders
1674
+ # {
1675
+ # "cloid": null,
1676
+ # "closedPnl": "0.0",
1677
+ # "coin": "SOL",
1678
+ # "crossed": True,
1679
+ # "dir": "Open Long",
1680
+ # "fee": "0.003879",
1681
+ # "hash": "0x4a2647998682b7f07bc5040ab531e1011400f9a51bfa0346a0b41ebe510e8875",
1682
+ # "liquidationMarkPx": null,
1683
+ # "oid": "6463280784",
1684
+ # "px": "110.83",
1685
+ # "side": "B",
1686
+ # "startPosition": "1.64",
1687
+ # "sz": "0.1",
1688
+ # "tid": "232174667018988",
1689
+ # "time": "1709142268394"
1690
+ # }
1691
+ #
1692
+ # fetchOrder
1693
+ #
1694
+ # {
1695
+ # "order": {
1696
+ # "children": [],
1697
+ # "cloid": null,
1698
+ # "coin": "ETH",
1699
+ # "isPositionTpsl": False,
1700
+ # "isTrigger": False,
1701
+ # "limitPx": "2000.0",
1702
+ # "oid": "3991946565",
1703
+ # "orderType": "Limit",
1704
+ # "origSz": "0.1",
1705
+ # "reduceOnly": False,
1706
+ # "side": "B",
1707
+ # "sz": "0.1",
1708
+ # "tif": "Gtc",
1709
+ # "timestamp": "1704346468838",
1710
+ # "triggerCondition": "N/A",
1711
+ # "triggerPx": "0.0"
1712
+ # },
1713
+ # "status": "open",
1714
+ # "statusTimestamp": "1704346468838"
1715
+ # }
1716
+ #
1717
+ # createOrder
1718
+ #
1719
+ # {
1720
+ # "resting": {
1721
+ # "oid": 5063830287
1722
+ # }
1723
+ # }
1724
+ #
1725
+ # {
1726
+ # "filled":{
1727
+ # "totalSz":"0.1",
1728
+ # "avgPx":"100.84",
1729
+ # "oid":6195281425
1730
+ # }
1731
+ # }
1732
+ # frontendOrder
1733
+ # {
1734
+ # "children": [],
1735
+ # "cloid": null,
1736
+ # "coin": "BLUR",
1737
+ # "isPositionTpsl": False,
1738
+ # "isTrigger": True,
1739
+ # "limitPx": "0.5",
1740
+ # "oid": 8670487141,
1741
+ # "orderType": "Stop Limit",
1742
+ # "origSz": "20.0",
1743
+ # "reduceOnly": False,
1744
+ # "side": "B",
1745
+ # "sz": "20.0",
1746
+ # "tif": null,
1747
+ # "timestamp": 1715523663687,
1748
+ # "triggerCondition": "Price above 0.6",
1749
+ # "triggerPx": "0.6"
1750
+ # }
1751
+ #
1752
+ entry = self.safe_dict_n(order, ['order', 'resting', 'filled'])
1753
+ if entry is None:
1754
+ entry = order
1755
+ coin = self.safe_string(entry, 'coin')
1756
+ marketId = None
1757
+ if coin is not None:
1758
+ if coin.find('/') > -1:
1759
+ marketId = coin
1760
+ else:
1761
+ marketId = coin + '/USDC:USDC'
1762
+ if self.safe_string(entry, 'id') is None:
1763
+ market = self.safe_market(marketId, None)
1764
+ else:
1765
+ market = self.safe_market(marketId, market)
1766
+ symbol = market['symbol']
1767
+ timestamp = self.safe_integer_2(order, 'timestamp', 'statusTimestamp')
1768
+ status = self.safe_string(order, 'status')
1769
+ side = self.safe_string(entry, 'side')
1770
+ if side is not None:
1771
+ side = 'sell' if (side == 'A') else 'buy'
1772
+ return self.safe_order({
1773
+ 'info': order,
1774
+ 'id': self.safe_string(entry, 'oid'),
1775
+ 'clientOrderId': self.safe_string(entry, 'cloid'),
1776
+ 'timestamp': timestamp,
1777
+ 'datetime': self.iso8601(timestamp),
1778
+ 'lastTradeTimestamp': None,
1779
+ 'lastUpdateTimestamp': None,
1780
+ 'symbol': symbol,
1781
+ 'type': self.parse_order_type(self.safe_string_lower(entry, 'orderType')),
1782
+ 'timeInForce': self.safe_string_upper(entry, 'tif'),
1783
+ 'postOnly': None,
1784
+ 'reduceOnly': self.safe_bool(entry, 'reduceOnly'),
1785
+ 'side': side,
1786
+ 'price': self.safe_number(entry, 'limitPx'),
1787
+ 'triggerPrice': self.safe_number(entry, 'triggerPx') if self.safe_bool(entry, 'isTrigger') else None,
1788
+ 'amount': self.safe_number_2(entry, 'sz', 'totalSz'),
1789
+ 'cost': None,
1790
+ 'average': self.safe_number(entry, 'avgPx'),
1791
+ 'filled': None,
1792
+ 'remaining': None,
1793
+ 'status': self.parse_order_status(status),
1794
+ 'fee': None,
1795
+ 'trades': None,
1796
+ }, market)
1797
+
1798
+ def parse_order_status(self, status: Str):
1799
+ statuses: dict = {
1800
+ 'triggered': 'open',
1801
+ 'filled': 'closed',
1802
+ }
1803
+ return self.safe_string(statuses, status, status)
1804
+
1805
+ def parse_order_type(self, status):
1806
+ statuses: dict = {
1807
+ 'stop limit': 'limit',
1808
+ 'stop market': 'market',
1809
+ }
1810
+ return self.safe_string(statuses, status, status)
1811
+
1812
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1813
+ """
1814
+ fetch all trades made by the user
1815
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
1816
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
1817
+ :param str symbol: unified market symbol
1818
+ :param int [since]: the earliest time in ms to fetch trades for
1819
+ :param int [limit]: the maximum number of trades structures to retrieve
1820
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1821
+ :param int [params.until]: timestamp in ms of the latest trade
1822
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1823
+ """
1824
+ userAddress = None
1825
+ userAddress, params = self.handle_public_address('fetchMyTrades', params)
1826
+ await self.load_markets()
1827
+ market = self.safe_market(symbol)
1828
+ request: dict = {
1829
+ 'user': userAddress,
1830
+ }
1831
+ if since is not None:
1832
+ request['type'] = 'userFillsByTime'
1833
+ request['startTime'] = since
1834
+ else:
1835
+ request['type'] = 'userFills'
1836
+ until = self.safe_integer(params, 'until')
1837
+ params = self.omit(params, 'until')
1838
+ if until is not None:
1839
+ request['endTime'] = until
1840
+ response = await self.publicPostInfo(self.extend(request, params))
1841
+ #
1842
+ # [
1843
+ # {
1844
+ # "closedPnl": "0.19343",
1845
+ # "coin": "ETH",
1846
+ # "crossed": True,
1847
+ # "dir": "Close Long",
1848
+ # "fee": "0.050062",
1849
+ # "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
1850
+ # "liquidationMarkPx": null,
1851
+ # "oid": 3929354691,
1852
+ # "px": "2381.1",
1853
+ # "side": "A",
1854
+ # "startPosition": "0.0841",
1855
+ # "sz": "0.0841",
1856
+ # "tid": 128423918764978,
1857
+ # "time": 1704262888911
1858
+ # }
1859
+ # ]
1860
+ #
1861
+ return self.parse_trades(response, market, since, limit)
1862
+
1863
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1864
+ #
1865
+ # {
1866
+ # "closedPnl": "0.19343",
1867
+ # "coin": "ETH",
1868
+ # "crossed": True,
1869
+ # "dir": "Close Long",
1870
+ # "fee": "0.050062",
1871
+ # "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
1872
+ # "liquidationMarkPx": null,
1873
+ # "oid": 3929354691,
1874
+ # "px": "2381.1",
1875
+ # "side": "A",
1876
+ # "startPosition": "0.0841",
1877
+ # "sz": "0.0841",
1878
+ # "tid": 128423918764978,
1879
+ # "time": 1704262888911
1880
+ # }
1881
+ #
1882
+ timestamp = self.safe_integer(trade, 'time')
1883
+ price = self.safe_string(trade, 'px')
1884
+ amount = self.safe_string(trade, 'sz')
1885
+ coin = self.safe_string(trade, 'coin')
1886
+ marketId = coin + '/USDC:USDC'
1887
+ market = self.safe_market(marketId, None)
1888
+ symbol = market['symbol']
1889
+ id = self.safe_string(trade, 'tid')
1890
+ side = self.safe_string(trade, 'side')
1891
+ if side is not None:
1892
+ side = 'sell' if (side == 'A') else 'buy'
1893
+ fee = self.safe_string(trade, 'fee')
1894
+ return self.safe_trade({
1895
+ 'info': trade,
1896
+ 'timestamp': timestamp,
1897
+ 'datetime': self.iso8601(timestamp),
1898
+ 'symbol': symbol,
1899
+ 'id': id,
1900
+ 'order': self.safe_string(trade, 'oid'),
1901
+ 'type': None,
1902
+ 'side': side,
1903
+ 'takerOrMaker': None,
1904
+ 'price': price,
1905
+ 'amount': amount,
1906
+ 'cost': None,
1907
+ 'fee': {'cost': fee, 'currency': 'USDC'},
1908
+ }, market)
1909
+
1910
+ async def fetch_position(self, symbol: str, params={}):
1911
+ """
1912
+ fetch data on an open position
1913
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
1914
+ :param str symbol: unified market symbol of the market the position is held in
1915
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1916
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
1917
+ :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
1918
+ """
1919
+ positions = await self.fetch_positions([symbol], params)
1920
+ return self.safe_dict(positions, 0, {})
1921
+
1922
+ async def fetch_positions(self, symbols: Strings = None, params={}):
1923
+ """
1924
+ fetch all open positions
1925
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
1926
+ :param str[] [symbols]: list of unified market symbols
1927
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1928
+ :param str [params.user]: user address, will default to self.walletAddress if not provided
1929
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
1930
+ """
1931
+ await self.load_markets()
1932
+ userAddress = None
1933
+ userAddress, params = self.handle_public_address('fetchPositions', params)
1934
+ symbols = self.market_symbols(symbols)
1935
+ request: dict = {
1936
+ 'type': 'clearinghouseState',
1937
+ 'user': userAddress,
1938
+ }
1939
+ response = await self.publicPostInfo(self.extend(request, params))
1940
+ #
1941
+ # {
1942
+ # "assetPositions": [
1943
+ # {
1944
+ # "position": {
1945
+ # "coin": "ETH",
1946
+ # "cumFunding": {
1947
+ # "allTime": "0.0",
1948
+ # "sinceChange": "0.0",
1949
+ # "sinceOpen": "0.0"
1950
+ # },
1951
+ # "entryPx": "2213.9",
1952
+ # "leverage": {
1953
+ # "rawUsd": "-475.23904",
1954
+ # "type": "isolated",
1955
+ # "value": "20"
1956
+ # },
1957
+ # "liquidationPx": "2125.00856238",
1958
+ # "marginUsed": "24.88097",
1959
+ # "maxLeverage": "50",
1960
+ # "positionValue": "500.12001",
1961
+ # "returnOnEquity": "0.0",
1962
+ # "szi": "0.2259",
1963
+ # "unrealizedPnl": "0.0"
1964
+ # },
1965
+ # "type": "oneWay"
1966
+ # }
1967
+ # ],
1968
+ # "crossMaintenanceMarginUsed": "0.0",
1969
+ # "crossMarginSummary": {
1970
+ # "accountValue": "100.0",
1971
+ # "totalMarginUsed": "0.0",
1972
+ # "totalNtlPos": "0.0",
1973
+ # "totalRawUsd": "100.0"
1974
+ # },
1975
+ # "marginSummary": {
1976
+ # "accountValue": "100.0",
1977
+ # "totalMarginUsed": "0.0",
1978
+ # "totalNtlPos": "0.0",
1979
+ # "totalRawUsd": "100.0"
1980
+ # },
1981
+ # "time": "1704261007014",
1982
+ # "withdrawable": "100.0"
1983
+ # }
1984
+ #
1985
+ data = self.safe_list(response, 'assetPositions', [])
1986
+ result = []
1987
+ for i in range(0, len(data)):
1988
+ result.append(self.parse_position(data[i], None))
1989
+ return self.filter_by_array_positions(result, 'symbol', symbols, False)
1990
+
1991
+ def parse_position(self, position: dict, market: Market = None):
1992
+ #
1993
+ # {
1994
+ # "position": {
1995
+ # "coin": "ETH",
1996
+ # "cumFunding": {
1997
+ # "allTime": "0.0",
1998
+ # "sinceChange": "0.0",
1999
+ # "sinceOpen": "0.0"
2000
+ # },
2001
+ # "entryPx": "2213.9",
2002
+ # "leverage": {
2003
+ # "rawUsd": "-475.23904",
2004
+ # "type": "isolated",
2005
+ # "value": "20"
2006
+ # },
2007
+ # "liquidationPx": "2125.00856238",
2008
+ # "marginUsed": "24.88097",
2009
+ # "maxLeverage": "50",
2010
+ # "positionValue": "500.12001",
2011
+ # "returnOnEquity": "0.0",
2012
+ # "szi": "0.2259",
2013
+ # "unrealizedPnl": "0.0"
2014
+ # },
2015
+ # "type": "oneWay"
2016
+ # }
2017
+ #
2018
+ entry = self.safe_dict(position, 'position', {})
2019
+ coin = self.safe_string(entry, 'coin')
2020
+ marketId = coin + '/USDC:USDC'
2021
+ market = self.safe_market(marketId, None)
2022
+ symbol = market['symbol']
2023
+ leverage = self.safe_dict(entry, 'leverage', {})
2024
+ isIsolated = (self.safe_string(leverage, 'type') == 'isolated')
2025
+ quantity = self.safe_number(leverage, 'rawUsd')
2026
+ side = None
2027
+ if quantity is not None:
2028
+ side = 'short' if (quantity > 0) else 'long'
2029
+ unrealizedPnl = self.safe_number(entry, 'unrealizedPnl')
2030
+ initialMargin = self.safe_number(entry, 'marginUsed')
2031
+ percentage = unrealizedPnl / initialMargin * 100
2032
+ return self.safe_position({
2033
+ 'info': position,
2034
+ 'id': None,
2035
+ 'symbol': symbol,
2036
+ 'timestamp': None,
2037
+ 'datetime': None,
2038
+ 'isolated': isIsolated,
2039
+ 'hedged': None,
2040
+ 'side': side,
2041
+ 'contracts': self.safe_number(entry, 'szi'),
2042
+ 'contractSize': None,
2043
+ 'entryPrice': self.safe_number(entry, 'entryPx'),
2044
+ 'markPrice': None,
2045
+ 'notional': self.safe_number(entry, 'positionValue'),
2046
+ 'leverage': self.safe_number(leverage, 'value'),
2047
+ 'collateral': None,
2048
+ 'initialMargin': initialMargin,
2049
+ 'maintenanceMargin': None,
2050
+ 'initialMarginPercentage': None,
2051
+ 'maintenanceMarginPercentage': None,
2052
+ 'unrealizedPnl': unrealizedPnl,
2053
+ 'liquidationPrice': self.safe_number(entry, 'liquidationPx'),
2054
+ 'marginMode': None,
2055
+ 'percentage': percentage,
2056
+ })
2057
+
2058
+ async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
2059
+ """
2060
+ set margin mode(symbol)
2061
+ :param str marginMode: margin mode must be either [isolated, cross]
2062
+ :param str symbol: unified market symbol of the market the position is held in, default is None
2063
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2064
+ :param str [params.leverage]: the rate of leverage, is required if setting trade mode(symbol)
2065
+ :returns dict: response from the exchange
2066
+ """
2067
+ if symbol is None:
2068
+ raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
2069
+ await self.load_markets()
2070
+ market = self.market(symbol)
2071
+ leverage = self.safe_integer(params, 'leverage')
2072
+ if leverage is None:
2073
+ raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter')
2074
+ asset = self.parse_to_int(market['baseId'])
2075
+ isCross = (marginMode == 'cross')
2076
+ nonce = self.milliseconds()
2077
+ params = self.omit(params, ['leverage'])
2078
+ updateAction: dict = {
2079
+ 'type': 'updateLeverage',
2080
+ 'asset': asset,
2081
+ 'isCross': isCross,
2082
+ 'leverage': leverage,
2083
+ }
2084
+ vaultAddress = self.safe_string(params, 'vaultAddress')
2085
+ if vaultAddress is not None:
2086
+ params = self.omit(params, 'vaultAddress')
2087
+ if vaultAddress.startswith('0x'):
2088
+ vaultAddress = vaultAddress.replace('0x', '')
2089
+ extendedAction = self.extend(updateAction, params)
2090
+ signature = self.sign_l1_action(extendedAction, nonce, vaultAddress)
2091
+ request: dict = {
2092
+ 'action': extendedAction,
2093
+ 'nonce': nonce,
2094
+ 'signature': signature,
2095
+ # 'vaultAddress': vaultAddress,
2096
+ }
2097
+ if vaultAddress is not None:
2098
+ request['vaultAddress'] = vaultAddress
2099
+ response = await self.privatePostExchange(request)
2100
+ #
2101
+ # {
2102
+ # 'response': {
2103
+ # 'type': 'default'
2104
+ # },
2105
+ # 'status': 'ok'
2106
+ # }
2107
+ #
2108
+ return response
2109
+
2110
+ async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2111
+ """
2112
+ set the level of leverage for a market
2113
+ :param float leverage: the rate of leverage
2114
+ :param str symbol: unified market symbol
2115
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2116
+ :param str [params.marginMode]: margin mode must be either [isolated, cross], default is cross
2117
+ :returns dict: response from the exchange
2118
+ """
2119
+ if symbol is None:
2120
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
2121
+ await self.load_markets()
2122
+ market = self.market(symbol)
2123
+ marginMode = self.safe_string(params, 'marginMode', 'cross')
2124
+ isCross = (marginMode == 'cross')
2125
+ asset = self.parse_to_int(market['baseId'])
2126
+ nonce = self.milliseconds()
2127
+ params = self.omit(params, 'marginMode')
2128
+ updateAction: dict = {
2129
+ 'type': 'updateLeverage',
2130
+ 'asset': asset,
2131
+ 'isCross': isCross,
2132
+ 'leverage': leverage,
2133
+ }
2134
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2135
+ signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2136
+ request: dict = {
2137
+ 'action': updateAction,
2138
+ 'nonce': nonce,
2139
+ 'signature': signature,
2140
+ # 'vaultAddress': vaultAddress,
2141
+ }
2142
+ if vaultAddress is not None:
2143
+ params = self.omit(params, 'vaultAddress')
2144
+ request['vaultAddress'] = vaultAddress
2145
+ response = await self.privatePostExchange(self.extend(request, params))
2146
+ #
2147
+ # {
2148
+ # 'response': {
2149
+ # 'type': 'default'
2150
+ # },
2151
+ # 'status': 'ok'
2152
+ # }
2153
+ #
2154
+ return response
2155
+
2156
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2157
+ """
2158
+ add margin
2159
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
2160
+ :param str symbol: unified market symbol
2161
+ :param float amount: amount of margin to add
2162
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2163
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
2164
+ """
2165
+ return await self.modify_margin_helper(symbol, amount, 'add', params)
2166
+
2167
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2168
+ """
2169
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
2170
+ remove margin from a position
2171
+ :param str symbol: unified market symbol
2172
+ :param float amount: the amount of margin to remove
2173
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2174
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
2175
+ """
2176
+ return await self.modify_margin_helper(symbol, amount, 'reduce', params)
2177
+
2178
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2179
+ await self.load_markets()
2180
+ market = self.market(symbol)
2181
+ asset = self.parse_to_int(market['baseId'])
2182
+ sz = self.parse_to_int(Precise.string_mul(self.amount_to_precision(symbol, amount), '1000000'))
2183
+ if type == 'reduce':
2184
+ sz = -sz
2185
+ nonce = self.milliseconds()
2186
+ updateAction: dict = {
2187
+ 'type': 'updateIsolatedMargin',
2188
+ 'asset': asset,
2189
+ 'isBuy': True,
2190
+ 'ntli': sz,
2191
+ }
2192
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2193
+ signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2194
+ request: dict = {
2195
+ 'action': updateAction,
2196
+ 'nonce': nonce,
2197
+ 'signature': signature,
2198
+ # 'vaultAddress': vaultAddress,
2199
+ }
2200
+ if vaultAddress is not None:
2201
+ params = self.omit(params, 'vaultAddress')
2202
+ request['vaultAddress'] = vaultAddress
2203
+ response = await self.privatePostExchange(self.extend(request, params))
2204
+ #
2205
+ # {
2206
+ # 'response': {
2207
+ # 'type': 'default'
2208
+ # },
2209
+ # 'status': 'ok'
2210
+ # }
2211
+ #
2212
+ return self.extend(self.parse_margin_modification(response, market), {
2213
+ 'code': self.safe_string(response, 'status'),
2214
+ })
2215
+
2216
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
2217
+ #
2218
+ # {
2219
+ # 'type': 'default'
2220
+ # }
2221
+ #
2222
+ return {
2223
+ 'info': data,
2224
+ 'symbol': self.safe_symbol(None, market),
2225
+ 'type': None,
2226
+ 'marginMode': 'isolated',
2227
+ 'amount': None,
2228
+ 'total': None,
2229
+ 'code': self.safe_string(market, 'settle'),
2230
+ 'status': None,
2231
+ 'timestamp': None,
2232
+ 'datetime': None,
2233
+ }
2234
+
2235
+ async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2236
+ """
2237
+ transfer currency internally between wallets on the same account
2238
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
2239
+ :param str code: unified currency code
2240
+ :param float amount: amount to transfer
2241
+ :param str fromAccount: account to transfer from *spot, swap*
2242
+ :param str toAccount: account to transfer to *swap, spot or address*
2243
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2244
+ :param str [params.vaultAddress]: the vault address for order
2245
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2246
+ """
2247
+ self.check_required_credentials()
2248
+ await self.load_markets()
2249
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
2250
+ nonce = self.milliseconds()
2251
+ if self.in_array(fromAccount, ['spot', 'swap', 'perp']):
2252
+ # handle swap <> spot account transfer
2253
+ if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
2254
+ raise NotSupported(self.id + 'transfer() only support spot <> swap transfer')
2255
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2256
+ params = self.omit(params, 'vaultAddress')
2257
+ toPerp = (toAccount == 'perp') or (toAccount == 'swap')
2258
+ action: dict = {
2259
+ 'type': 'spotUser',
2260
+ 'classTransfer': {
2261
+ 'usdc': amount,
2262
+ 'toPerp': toPerp,
2263
+ },
2264
+ }
2265
+ signature = self.sign_l1_action(action, nonce, vaultAddress)
2266
+ innerRequest: dict = {
2267
+ 'action': self.extend(action, params),
2268
+ 'nonce': nonce,
2269
+ 'signature': signature,
2270
+ }
2271
+ if vaultAddress is not None:
2272
+ innerRequest['vaultAddress'] = vaultAddress
2273
+ transferResponse = await self.privatePostExchange(innerRequest)
2274
+ return transferResponse
2275
+ # handle sub-account/different account transfer
2276
+ self.check_address(toAccount)
2277
+ if code is not None:
2278
+ code = code.upper()
2279
+ if code != 'USDC':
2280
+ raise NotSupported(self.id + 'transfer() only support USDC')
2281
+ payload: dict = {
2282
+ 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
2283
+ 'destination': toAccount,
2284
+ 'amount': self.number_to_string(amount),
2285
+ 'time': nonce,
2286
+ }
2287
+ sig = self.build_transfer_sig(payload)
2288
+ request: dict = {
2289
+ 'action': {
2290
+ 'hyperliquidChain': payload['hyperliquidChain'],
2291
+ 'signatureChainId': '0x66eee', # check self out
2292
+ 'destination': toAccount,
2293
+ 'amount': str(amount),
2294
+ 'time': nonce,
2295
+ 'type': 'usdSend',
2296
+ },
2297
+ 'nonce': nonce,
2298
+ 'signature': sig,
2299
+ }
2300
+ response = await self.privatePostExchange(self.extend(request, params))
2301
+ return response
2302
+
2303
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
2304
+ """
2305
+ make a withdrawal(only support USDC)
2306
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#initiate-a-withdrawal-request
2307
+ :param str code: unified currency code
2308
+ :param float amount: the amount to withdraw
2309
+ :param str address: the address to withdraw to
2310
+ :param str tag:
2311
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2312
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2313
+ """
2314
+ self.check_required_credentials()
2315
+ await self.load_markets()
2316
+ self.check_address(address)
2317
+ if code is not None:
2318
+ code = code.upper()
2319
+ if code != 'USDC':
2320
+ raise NotSupported(self.id + 'withdraw() only support USDC')
2321
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
2322
+ nonce = self.milliseconds()
2323
+ payload: dict = {
2324
+ 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
2325
+ 'destination': address,
2326
+ 'amount': str(amount),
2327
+ 'time': nonce,
2328
+ }
2329
+ sig = self.build_withdraw_sig(payload)
2330
+ request: dict = {
2331
+ 'action': {
2332
+ 'hyperliquidChain': payload['hyperliquidChain'],
2333
+ 'signatureChainId': '0x66eee', # check self out
2334
+ 'destination': address,
2335
+ 'amount': str(amount),
2336
+ 'time': nonce,
2337
+ 'type': 'withdraw3',
2338
+ },
2339
+ 'nonce': nonce,
2340
+ 'signature': sig,
2341
+ }
2342
+ response = await self.privatePostExchange(self.extend(request, params))
2343
+ return self.parse_transaction(response)
2344
+
2345
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2346
+ #
2347
+ # {status: 'ok', response: {type: 'default'}}
2348
+ #
2349
+ return {
2350
+ 'info': transaction,
2351
+ 'id': None,
2352
+ 'txid': None,
2353
+ 'timestamp': None,
2354
+ 'datetime': None,
2355
+ 'network': None,
2356
+ 'address': None,
2357
+ 'addressTo': None,
2358
+ 'addressFrom': None,
2359
+ 'tag': None,
2360
+ 'tagTo': None,
2361
+ 'tagFrom': None,
2362
+ 'type': None,
2363
+ 'amount': None,
2364
+ 'currency': None,
2365
+ 'status': self.safe_string(transaction, 'status'),
2366
+ 'updated': None,
2367
+ 'comment': None,
2368
+ 'internal': None,
2369
+ 'fee': None,
2370
+ }
2371
+
2372
+ def format_vault_address(self, address: Str = None):
2373
+ if address is None:
2374
+ return None
2375
+ if address.startswith('0x'):
2376
+ return address.replace('0x', '')
2377
+ return address
2378
+
2379
+ def handle_public_address(self, methodName: str, params: dict):
2380
+ userAux = None
2381
+ userAux, params = self.handle_option_and_params(params, methodName, 'user')
2382
+ user = userAux
2383
+ user, params = self.handle_option_and_params(params, methodName, 'address', userAux)
2384
+ if (user is not None) and (user != ''):
2385
+ return [user, params]
2386
+ if (self.walletAddress is not None) and (self.walletAddress != ''):
2387
+ return [self.walletAddress, params]
2388
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set')
2389
+
2390
+ def coin_to_market_id(self, coin: Str):
2391
+ if coin.find('/') > -1:
2392
+ return coin # spot
2393
+ return coin + '/USDC:USDC'
2394
+
2395
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2396
+ if not response:
2397
+ return None # fallback to default error handler
2398
+ # {"status":"err","response":"User or API Wallet 0xb8a6f8b26223de27c31938d56e470a5b832703a5 does not exist."}
2399
+ #
2400
+ # {
2401
+ # status: 'ok',
2402
+ # response: {type: 'order', data: {statuses: [{error: 'Insufficient margin to place order. asset=4'}]}}
2403
+ # }
2404
+ #
2405
+ status = self.safe_string(response, 'status', '')
2406
+ message = None
2407
+ if status == 'err':
2408
+ message = self.safe_string(response, 'response')
2409
+ else:
2410
+ responsePayload = self.safe_dict(response, 'response', {})
2411
+ data = self.safe_dict(responsePayload, 'data', {})
2412
+ statuses = self.safe_list(data, 'statuses', [])
2413
+ firstStatus = self.safe_dict(statuses, 0)
2414
+ message = self.safe_string(firstStatus, 'error')
2415
+ feedback = self.id + ' ' + body
2416
+ nonEmptyMessage = ((message is not None) and (message != ''))
2417
+ if nonEmptyMessage:
2418
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2419
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2420
+ if nonEmptyMessage:
2421
+ raise ExchangeError(feedback) # unknown message
2422
+ return None
2423
+
2424
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2425
+ url = self.implode_hostname(self.urls['api'][api]) + '/' + path
2426
+ if method == 'POST':
2427
+ headers = {
2428
+ 'Content-Type': 'application/json',
2429
+ }
2430
+ body = self.json(params)
2431
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}