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

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