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/pro/kraken.py ADDED
@@ -0,0 +1,1356 @@
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
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
8
+ from ccxt.base.types import Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.async_support.base.ws.client import Client
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import AccountSuspended
15
+ from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import BadSymbol
17
+ from ccxt.base.errors import InsufficientFunds
18
+ from ccxt.base.errors import InvalidOrder
19
+ from ccxt.base.errors import OrderNotFound
20
+ from ccxt.base.errors import NotSupported
21
+ from ccxt.base.errors import RateLimitExceeded
22
+ from ccxt.base.errors import ExchangeNotAvailable
23
+ from ccxt.base.errors import InvalidNonce
24
+ from ccxt.base.precise import Precise
25
+
26
+
27
+ class kraken(ccxt.async_support.kraken):
28
+
29
+ def describe(self):
30
+ return self.deep_extend(super(kraken, self).describe(), {
31
+ 'has': {
32
+ 'ws': True,
33
+ 'watchBalance': False, # no such type of subscription 2021-01-05
34
+ 'watchMyTrades': True,
35
+ 'watchOHLCV': True,
36
+ 'watchOrderBook': True,
37
+ 'watchOrderBookForSymbols': True,
38
+ 'watchOrders': True,
39
+ 'watchTicker': True,
40
+ 'watchTickers': True,
41
+ 'watchTrades': True,
42
+ 'watchTradesForSymbols': True,
43
+ 'createOrderWs': True,
44
+ 'editOrderWs': True,
45
+ 'cancelOrderWs': True,
46
+ 'cancelOrdersWs': True,
47
+ 'cancelAllOrdersWs': True,
48
+ # 'watchHeartbeat': True,
49
+ # 'watchStatus': True,
50
+ },
51
+ 'urls': {
52
+ 'api': {
53
+ 'ws': {
54
+ 'public': 'wss://ws.kraken.com',
55
+ 'private': 'wss://ws-auth.kraken.com',
56
+ 'beta': 'wss://beta-ws.kraken.com',
57
+ 'beta-private': 'wss://beta-ws-auth.kraken.com',
58
+ },
59
+ },
60
+ },
61
+ # 'versions': {
62
+ # 'ws': '0.2.0',
63
+ # },
64
+ 'options': {
65
+ 'tradesLimit': 1000,
66
+ 'OHLCVLimit': 1000,
67
+ 'ordersLimit': 1000,
68
+ 'symbolsByOrderId': {},
69
+ 'checksum': True,
70
+ },
71
+ 'exceptions': {
72
+ 'ws': {
73
+ 'exact': {
74
+ 'Event(s) not found': BadRequest,
75
+ },
76
+ 'broad': {
77
+ 'Already subscribed': BadRequest,
78
+ 'Currency pair not in ISO 4217-A3 format': BadSymbol,
79
+ 'Malformed request': BadRequest,
80
+ 'Pair field must be an array': BadRequest,
81
+ 'Pair field unsupported for self subscription type': BadRequest,
82
+ 'Pair(s) not found': BadSymbol,
83
+ 'Subscription book depth must be an integer': BadRequest,
84
+ 'Subscription depth not supported': BadRequest,
85
+ 'Subscription field must be an object': BadRequest,
86
+ 'Subscription name invalid': BadRequest,
87
+ 'Subscription object unsupported field': BadRequest,
88
+ 'Subscription ohlc interval must be an integer': BadRequest,
89
+ 'Subscription ohlc interval not supported': BadRequest,
90
+ 'Subscription ohlc requires interval': BadRequest,
91
+ 'EAccount:Invalid permissions': PermissionDenied,
92
+ 'EAuth:Account temporary disabled': AccountSuspended,
93
+ 'EAuth:Account unconfirmed': AuthenticationError,
94
+ 'EAuth:Rate limit exceeded': RateLimitExceeded,
95
+ 'EAuth:Too many requests': RateLimitExceeded,
96
+ 'EDatabase: Internal error(to be deprecated)': ExchangeError,
97
+ 'EGeneral:Internal error[:<code>]': ExchangeError,
98
+ 'EGeneral:Invalid arguments': BadRequest,
99
+ 'EOrder:Cannot open opposing position': InvalidOrder,
100
+ 'EOrder:Cannot open position': InvalidOrder,
101
+ 'EOrder:Insufficient funds(insufficient user funds)': InsufficientFunds,
102
+ 'EOrder:Insufficient margin(exchange does not have sufficient funds to allow margin trading)': InsufficientFunds,
103
+ 'EOrder:Invalid price': InvalidOrder,
104
+ 'EOrder:Margin allowance exceeded': InvalidOrder,
105
+ 'EOrder:Margin level too low': InvalidOrder,
106
+ 'EOrder:Margin position size exceeded(client would exceed the maximum position size for self pair)': InvalidOrder,
107
+ 'EOrder:Order minimum not met(volume too low)': InvalidOrder,
108
+ 'EOrder:Orders limit exceeded': InvalidOrder,
109
+ 'EOrder:Positions limit exceeded': InvalidOrder,
110
+ 'EOrder:Rate limit exceeded': RateLimitExceeded,
111
+ 'EOrder:Scheduled orders limit exceeded': InvalidOrder,
112
+ 'EOrder:Unknown position': OrderNotFound,
113
+ 'EOrder:Unknown order': OrderNotFound,
114
+ 'EOrder:Invalid order': InvalidOrder,
115
+ 'EService:Deadline elapsed': ExchangeNotAvailable,
116
+ 'EService:Market in cancel_only mode': NotSupported,
117
+ 'EService:Market in limit_only mode': NotSupported,
118
+ 'EService:Market in post_only mode': NotSupported,
119
+ 'EService:Unavailable': ExchangeNotAvailable,
120
+ 'ETrade:Invalid request': BadRequest,
121
+ },
122
+ },
123
+ },
124
+ })
125
+
126
+ async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
127
+ """
128
+ :see: https://docs.kraken.com/websockets/#message-addOrder
129
+ create a trade order
130
+ :param str symbol: unified symbol of the market to create an order in
131
+ :param str type: 'market' or 'limit'
132
+ :param str side: 'buy' or 'sell'
133
+ :param float amount: how much of currency you want to trade in units of base currency
134
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
135
+ :param dict [params]: extra parameters specific to the exchange API endpoint
136
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
137
+ """
138
+ await self.load_markets()
139
+ token = await self.authenticate()
140
+ market = self.market(symbol)
141
+ url = self.urls['api']['ws']['private']
142
+ requestId = self.request_id()
143
+ messageHash = requestId
144
+ request: dict = {
145
+ 'event': 'addOrder',
146
+ 'token': token,
147
+ 'reqid': requestId,
148
+ 'ordertype': type,
149
+ 'type': side,
150
+ 'pair': market['wsId'],
151
+ 'volume': self.amount_to_precision(symbol, amount),
152
+ }
153
+ request, params = self.orderRequest('createOrderWs', symbol, type, request, amount, price, params)
154
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
155
+
156
+ def handle_create_edit_order(self, client, message):
157
+ #
158
+ # createOrder
159
+ # {
160
+ # "descr": "sell 0.00010000 XBTUSDT @ market",
161
+ # "event": "addOrderStatus",
162
+ # "reqid": 1,
163
+ # "status": "ok",
164
+ # "txid": "OAVXZH-XIE54-JCYYDG"
165
+ # }
166
+ # editOrder
167
+ # {
168
+ # "descr": "order edited price = 9000.00000000",
169
+ # "event": "editOrderStatus",
170
+ # "originaltxid": "O65KZW-J4AW3-VFS74A",
171
+ # "reqid": 3,
172
+ # "status": "ok",
173
+ # "txid": "OTI672-HJFAO-XOIPPK"
174
+ # }
175
+ #
176
+ order = self.parse_order(message)
177
+ messageHash = self.safe_value(message, 'reqid')
178
+ client.resolve(order, messageHash)
179
+
180
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
181
+ """
182
+ edit a trade order
183
+ :see: https://docs.kraken.com/websockets/#message-editOrder
184
+ :param str id: order id
185
+ :param str symbol: unified symbol of the market to create an order in
186
+ :param str type: 'market' or 'limit'
187
+ :param str side: 'buy' or 'sell'
188
+ :param float amount: how much of the currency you want to trade in units of the base currency
189
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
190
+ :param dict [params]: extra parameters specific to the exchange API endpoint
191
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
192
+ """
193
+ await self.load_markets()
194
+ token = await self.authenticate()
195
+ market = self.market(symbol)
196
+ url = self.urls['api']['ws']['private']
197
+ requestId = self.request_id()
198
+ messageHash = requestId
199
+ request: dict = {
200
+ 'event': 'editOrder',
201
+ 'token': token,
202
+ 'reqid': requestId,
203
+ 'orderid': id,
204
+ 'pair': market['wsId'],
205
+ }
206
+ if amount is not None:
207
+ request['volume'] = self.amount_to_precision(symbol, amount)
208
+ request, params = self.orderRequest('editOrderWs', symbol, type, request, amount, price, params)
209
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
210
+
211
+ async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
212
+ """
213
+ :see: https://docs.kraken.com/websockets/#message-cancelOrder
214
+ cancel multiple orders
215
+ :param str[] ids: order ids
216
+ :param str symbol: unified market symbol, default is None
217
+ :param dict [params]: extra parameters specific to the exchange API endpoint
218
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
219
+ """
220
+ await self.load_markets()
221
+ token = await self.authenticate()
222
+ url = self.urls['api']['ws']['private']
223
+ requestId = self.request_id()
224
+ messageHash = requestId
225
+ request: dict = {
226
+ 'event': 'cancelOrder',
227
+ 'token': token,
228
+ 'reqid': requestId,
229
+ 'txid': ids,
230
+ }
231
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
232
+
233
+ async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
234
+ """
235
+ :see: https://docs.kraken.com/websockets/#message-cancelOrder
236
+ cancels an open order
237
+ :param str id: order id
238
+ :param str symbol: unified symbol of the market the order was made in
239
+ :param dict [params]: extra parameters specific to the exchange API endpoint
240
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
241
+ """
242
+ await self.load_markets()
243
+ token = await self.authenticate()
244
+ url = self.urls['api']['ws']['private']
245
+ requestId = self.request_id()
246
+ messageHash = requestId
247
+ clientOrderId = self.safe_value_2(params, 'userref', 'clientOrderId', id)
248
+ params = self.omit(params, ['userref', 'clientOrderId'])
249
+ request: dict = {
250
+ 'event': 'cancelOrder',
251
+ 'token': token,
252
+ 'reqid': requestId,
253
+ 'txid': [clientOrderId],
254
+ }
255
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
256
+
257
+ def handle_cancel_order(self, client, message):
258
+ #
259
+ # success
260
+ # {
261
+ # "event": "cancelOrderStatus",
262
+ # "status": "ok"
263
+ # "reqid": 1,
264
+ # }
265
+ #
266
+ reqId = self.safe_value(message, 'reqid')
267
+ client.resolve(message, reqId)
268
+
269
+ async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
270
+ """
271
+ :see: https://docs.kraken.com/websockets/#message-cancelAll
272
+ cancel all open orders
273
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
274
+ :param dict [params]: extra parameters specific to the exchange API endpoint
275
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
276
+ """
277
+ if symbol is not None:
278
+ raise NotSupported(self.id + ' cancelAllOrdersWs() does not support cancelling orders in a specific market.')
279
+ await self.load_markets()
280
+ token = await self.authenticate()
281
+ url = self.urls['api']['ws']['private']
282
+ requestId = self.request_id()
283
+ messageHash = requestId
284
+ request: dict = {
285
+ 'event': 'cancelAll',
286
+ 'token': token,
287
+ 'reqid': requestId,
288
+ }
289
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
290
+
291
+ def handle_cancel_all_orders(self, client, message):
292
+ #
293
+ # {
294
+ # "count": 2,
295
+ # "event": "cancelAllStatus",
296
+ # "status": "ok",
297
+ # "reqId": 1
298
+ # }
299
+ #
300
+ reqId = self.safe_value(message, 'reqid')
301
+ client.resolve(message, reqId)
302
+
303
+ def handle_ticker(self, client, message, subscription):
304
+ #
305
+ # [
306
+ # 0, # channelID
307
+ # {
308
+ # "a": ["5525.40000", 1, "1.000"], # ask, wholeAskVolume, askVolume
309
+ # "b": ["5525.10000", 1, "1.000"], # bid, wholeBidVolume, bidVolume
310
+ # "c": ["5525.10000", "0.00398963"], # closing price, volume
311
+ # "h": ["5783.00000", "5783.00000"], # high price today, high price 24h ago
312
+ # "l": ["5505.00000", "5505.00000"], # low price today, low price 24h ago
313
+ # "o": ["5760.70000", "5763.40000"], # open price today, open price 24h ago
314
+ # "p": ["5631.44067", "5653.78939"], # vwap today, vwap 24h ago
315
+ # "t": [11493, 16267], # number of trades today, 24 hours ago
316
+ # "v": ["2634.11501494", "3591.17907851"], # volume today, volume 24 hours ago
317
+ # },
318
+ # "ticker",
319
+ # "XBT/USD"
320
+ # ]
321
+ #
322
+ wsName = message[3]
323
+ market = self.safe_value(self.options['marketsByWsName'], wsName)
324
+ symbol = market['symbol']
325
+ messageHash = self.get_message_hash('ticker', None, symbol)
326
+ ticker = message[1]
327
+ vwap = self.safe_string(ticker['p'], 0)
328
+ quoteVolume = None
329
+ baseVolume = self.safe_string(ticker['v'], 0)
330
+ if baseVolume is not None and vwap is not None:
331
+ quoteVolume = Precise.string_mul(baseVolume, vwap)
332
+ last = self.safe_string(ticker['c'], 0)
333
+ result = self.safe_ticker({
334
+ 'symbol': symbol,
335
+ 'timestamp': None,
336
+ 'datetime': None,
337
+ 'high': self.safe_string(ticker['h'], 0),
338
+ 'low': self.safe_string(ticker['l'], 0),
339
+ 'bid': self.safe_string(ticker['b'], 0),
340
+ 'bidVolume': self.safe_string(ticker['b'], 2),
341
+ 'ask': self.safe_string(ticker['a'], 0),
342
+ 'askVolume': self.safe_string(ticker['a'], 2),
343
+ 'vwap': vwap,
344
+ 'open': self.safe_string(ticker['o'], 0),
345
+ 'close': last,
346
+ 'last': last,
347
+ 'previousClose': None,
348
+ 'change': None,
349
+ 'percentage': None,
350
+ 'average': None,
351
+ 'baseVolume': baseVolume,
352
+ 'quoteVolume': quoteVolume,
353
+ 'info': ticker,
354
+ })
355
+ self.tickers[symbol] = result
356
+ client.resolve(result, messageHash)
357
+
358
+ def handle_trades(self, client: Client, message, subscription):
359
+ #
360
+ # [
361
+ # 0, # channelID
362
+ # [ # price volume time side type misc
363
+ # ["5541.20000", "0.15850568", "1534614057.321596", "s", "l", ""],
364
+ # ["6060.00000", "0.02455000", "1534614057.324998", "b", "l", ""],
365
+ # ],
366
+ # "trade",
367
+ # "XBT/USD"
368
+ # ]
369
+ #
370
+ wsName = self.safe_string(message, 3)
371
+ name = self.safe_string(message, 2)
372
+ market = self.safe_value(self.options['marketsByWsName'], wsName)
373
+ symbol = market['symbol']
374
+ messageHash = self.get_message_hash(name, None, symbol)
375
+ stored = self.safe_value(self.trades, symbol)
376
+ if stored is None:
377
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
378
+ stored = ArrayCache(limit)
379
+ self.trades[symbol] = stored
380
+ trades = self.safe_value(message, 1, [])
381
+ parsed = self.parse_trades(trades, market)
382
+ for i in range(0, len(parsed)):
383
+ stored.append(parsed[i])
384
+ client.resolve(stored, messageHash)
385
+
386
+ def handle_ohlcv(self, client: Client, message, subscription):
387
+ #
388
+ # [
389
+ # 216, # channelID
390
+ # [
391
+ # "1574454214.962096", # Time, seconds since epoch
392
+ # "1574454240.000000", # End timestamp of the interval
393
+ # "0.020970", # Open price at midnight UTC
394
+ # "0.020970", # Intraday high price
395
+ # "0.020970", # Intraday low price
396
+ # "0.020970", # Closing price at midnight UTC
397
+ # "0.020970", # Volume weighted average price
398
+ # "0.08636138", # Accumulated volume today
399
+ # 1, # Number of trades today
400
+ # ],
401
+ # "ohlc-1", # Channel Name of subscription
402
+ # "ETH/XBT", # Asset pair
403
+ # ]
404
+ #
405
+ info = self.safe_value(subscription, 'subscription', {})
406
+ interval = self.safe_integer(info, 'interval')
407
+ name = self.safe_string(info, 'name')
408
+ wsName = self.safe_string(message, 3)
409
+ market = self.safe_value(self.options['marketsByWsName'], wsName)
410
+ symbol = market['symbol']
411
+ timeframe = self.find_timeframe(interval)
412
+ duration = self.parse_timeframe(timeframe)
413
+ if timeframe is not None:
414
+ candle = self.safe_value(message, 1)
415
+ messageHash = name + ':' + timeframe + ':' + wsName
416
+ timestamp = self.safe_float(candle, 1)
417
+ timestamp -= duration
418
+ ts = self.parse_to_int(timestamp * 1000)
419
+ result = [
420
+ ts,
421
+ self.safe_float(candle, 2),
422
+ self.safe_float(candle, 3),
423
+ self.safe_float(candle, 4),
424
+ self.safe_float(candle, 5),
425
+ self.safe_float(candle, 7),
426
+ ]
427
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
428
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
429
+ if stored is None:
430
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
431
+ stored = ArrayCacheByTimestamp(limit)
432
+ self.ohlcvs[symbol][timeframe] = stored
433
+ stored.append(result)
434
+ client.resolve(stored, messageHash)
435
+
436
+ def request_id(self):
437
+ # their support said that reqid must be an int32, not documented
438
+ reqid = self.sum(self.safe_integer(self.options, 'reqid', 0), 1)
439
+ self.options['reqid'] = reqid
440
+ return reqid
441
+
442
+ async def watch_public(self, name, symbol, params={}):
443
+ await self.load_markets()
444
+ market = self.market(symbol)
445
+ wsName = self.safe_value(market['info'], 'wsname')
446
+ messageHash = name + ':' + wsName
447
+ url = self.urls['api']['ws']['public']
448
+ requestId = self.request_id()
449
+ subscribe: dict = {
450
+ 'event': 'subscribe',
451
+ 'reqid': requestId,
452
+ 'pair': [
453
+ wsName,
454
+ ],
455
+ 'subscription': {
456
+ 'name': name,
457
+ },
458
+ }
459
+ request = self.deep_extend(subscribe, params)
460
+ return await self.watch(url, messageHash, request, messageHash)
461
+
462
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
463
+ """
464
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
465
+ :param str symbol: unified symbol of the market to fetch the ticker for
466
+ :param dict [params]: extra parameters specific to the exchange API endpoint
467
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
468
+ """
469
+ await self.load_markets()
470
+ symbol = self.symbol(symbol)
471
+ tickers = await self.watch_tickers([symbol], params)
472
+ return tickers[symbol]
473
+
474
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
475
+ """
476
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
477
+ :param str symbol: unified symbol of the market to fetch the ticker for
478
+ :param dict [params]: extra parameters specific to the exchange API endpoint
479
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
480
+ """
481
+ await self.load_markets()
482
+ symbols = self.market_symbols(symbols, None, False)
483
+ ticker = await self.watch_multi_helper('ticker', 'ticker', symbols, None, params)
484
+ if self.newUpdates:
485
+ result: dict = {}
486
+ result[ticker['symbol']] = ticker
487
+ return result
488
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
489
+
490
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
491
+ """
492
+ get the list of most recent trades for a particular symbol
493
+ :see: https://docs.kraken.com/websockets/#message-trade
494
+ :param str symbol: unified symbol of the market to fetch trades for
495
+ :param int [since]: timestamp in ms of the earliest trade to fetch
496
+ :param int [limit]: the maximum amount of trades to fetch
497
+ :param dict [params]: extra parameters specific to the exchange API endpoint
498
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
499
+ """
500
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
501
+
502
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
503
+ """
504
+ :see: https://docs.kraken.com/websockets/#message-trade
505
+ get the list of most recent trades for a list of symbols
506
+ :param str[] symbols: unified symbol of the market to fetch trades for
507
+ :param int [since]: timestamp in ms of the earliest trade to fetch
508
+ :param int [limit]: the maximum amount of trades to fetch
509
+ :param dict [params]: extra parameters specific to the exchange API endpoint
510
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
511
+ """
512
+ trades = await self.watch_multi_helper('trade', 'trade', symbols, None, params)
513
+ if self.newUpdates:
514
+ first = self.safe_list(trades, 0)
515
+ tradeSymbol = self.safe_string(first, 'symbol')
516
+ limit = trades.getLimit(tradeSymbol, limit)
517
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
518
+
519
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
520
+ """
521
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
522
+ :see: https://docs.kraken.com/websockets/#message-book
523
+ :param str symbol: unified symbol of the market to fetch the order book for
524
+ :param int [limit]: the maximum amount of order book entries to return
525
+ :param dict [params]: extra parameters specific to the exchange API endpoint
526
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
527
+ """
528
+ return await self.watch_order_book_for_symbols([symbol], limit, params)
529
+
530
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
531
+ """
532
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
533
+ :see: https://docs.kraken.com/websockets/#message-book
534
+ :param str[] symbols: unified array of symbols
535
+ :param int [limit]: the maximum amount of order book entries to return
536
+ :param dict [params]: extra parameters specific to the exchange API endpoint
537
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
538
+ """
539
+ request: dict = {}
540
+ if limit is not None:
541
+ if self.in_array(limit, [10, 25, 100, 500, 1000]):
542
+ request['subscription'] = {
543
+ 'depth': limit, # default 10, valid options 10, 25, 100, 500, 1000
544
+ }
545
+ else:
546
+ raise NotSupported(self.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only')
547
+ orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(request, params))
548
+ return orderbook.limit()
549
+
550
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
551
+ """
552
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
553
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
554
+ :param str timeframe: the length of time each candle represents
555
+ :param int [since]: timestamp in ms of the earliest candle to fetch
556
+ :param int [limit]: the maximum amount of candles to fetch
557
+ :param dict [params]: extra parameters specific to the exchange API endpoint
558
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
559
+ """
560
+ await self.load_markets()
561
+ name = 'ohlc'
562
+ market = self.market(symbol)
563
+ symbol = market['symbol']
564
+ wsName = self.safe_value(market['info'], 'wsname')
565
+ messageHash = name + ':' + timeframe + ':' + wsName
566
+ url = self.urls['api']['ws']['public']
567
+ requestId = self.request_id()
568
+ subscribe: dict = {
569
+ 'event': 'subscribe',
570
+ 'reqid': requestId,
571
+ 'pair': [
572
+ wsName,
573
+ ],
574
+ 'subscription': {
575
+ 'name': name,
576
+ 'interval': self.safe_value(self.timeframes, timeframe, timeframe),
577
+ },
578
+ }
579
+ request = self.deep_extend(subscribe, params)
580
+ ohlcv = await self.watch(url, messageHash, request, messageHash)
581
+ if self.newUpdates:
582
+ limit = ohlcv.getLimit(symbol, limit)
583
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
584
+
585
+ async def load_markets(self, reload=False, params={}):
586
+ markets = await super(kraken, self).load_markets(reload, params)
587
+ marketsByWsName = self.safe_value(self.options, 'marketsByWsName')
588
+ if (marketsByWsName is None) or reload:
589
+ marketsByWsName = {}
590
+ for i in range(0, len(self.symbols)):
591
+ symbol = self.symbols[i]
592
+ market = self.markets[symbol]
593
+ if market['darkpool']:
594
+ info = self.safe_value(market, 'info', {})
595
+ altname = self.safe_string(info, 'altname')
596
+ wsName = altname[0:3] + '/' + altname[3:]
597
+ marketsByWsName[wsName] = market
598
+ else:
599
+ info = self.safe_value(market, 'info', {})
600
+ wsName = self.safe_string(info, 'wsname')
601
+ marketsByWsName[wsName] = market
602
+ self.options['marketsByWsName'] = marketsByWsName
603
+ return markets
604
+
605
+ async def watch_heartbeat(self, params={}):
606
+ await self.load_markets()
607
+ event = 'heartbeat'
608
+ url = self.urls['api']['ws']['public']
609
+ return await self.watch(url, event)
610
+
611
+ def handle_heartbeat(self, client: Client, message):
612
+ #
613
+ # every second(approx) if no other updates are sent
614
+ #
615
+ # {"event": "heartbeat"}
616
+ #
617
+ event = self.safe_string(message, 'event')
618
+ client.resolve(message, event)
619
+
620
+ def handle_order_book(self, client: Client, message, subscription):
621
+ #
622
+ # first message(snapshot)
623
+ #
624
+ # [
625
+ # 1234, # channelID
626
+ # {
627
+ # "as": [
628
+ # ["5541.30000", "2.50700000", "1534614248.123678"],
629
+ # ["5541.80000", "0.33000000", "1534614098.345543"],
630
+ # ["5542.70000", "0.64700000", "1534614244.654432"]
631
+ # ],
632
+ # "bs": [
633
+ # ["5541.20000", "1.52900000", "1534614248.765567"],
634
+ # ["5539.90000", "0.30000000", "1534614241.769870"],
635
+ # ["5539.50000", "5.00000000", "1534613831.243486"]
636
+ # ]
637
+ # },
638
+ # "book-10",
639
+ # "XBT/USD"
640
+ # ]
641
+ #
642
+ # subsequent updates
643
+ #
644
+ # [
645
+ # 1234,
646
+ # { # optional
647
+ # "a": [
648
+ # ["5541.30000", "2.50700000", "1534614248.456738"],
649
+ # ["5542.50000", "0.40100000", "1534614248.456738"]
650
+ # ]
651
+ # },
652
+ # { # optional
653
+ # "b": [
654
+ # ["5541.30000", "0.00000000", "1534614335.345903"]
655
+ # ]
656
+ # },
657
+ # "book-10",
658
+ # "XBT/USD"
659
+ # ]
660
+ #
661
+ messageLength = len(message)
662
+ wsName = message[messageLength - 1]
663
+ bookDepthString = message[messageLength - 2]
664
+ parts = bookDepthString.split('-')
665
+ depth = self.safe_integer(parts, 1, 10)
666
+ market = self.safe_value(self.options['marketsByWsName'], wsName)
667
+ symbol = market['symbol']
668
+ timestamp = None
669
+ messageHash = self.get_message_hash('orderbook', None, symbol)
670
+ # if self is a snapshot
671
+ if 'as' in message[1]:
672
+ # todo get depth from marketsByWsName
673
+ self.orderbooks[symbol] = self.order_book({}, depth)
674
+ orderbook = self.orderbooks[symbol]
675
+ sides: dict = {
676
+ 'as': 'asks',
677
+ 'bs': 'bids',
678
+ }
679
+ keys = list(sides.keys())
680
+ for i in range(0, len(keys)):
681
+ key = keys[i]
682
+ side = sides[key]
683
+ bookside = orderbook[side]
684
+ deltas = self.safe_value(message[1], key, [])
685
+ timestamp = self.custom_handle_deltas(bookside, deltas, timestamp)
686
+ orderbook['symbol'] = symbol
687
+ orderbook['timestamp'] = timestamp
688
+ orderbook['datetime'] = self.iso8601(timestamp)
689
+ client.resolve(orderbook, messageHash)
690
+ else:
691
+ orderbook = self.orderbooks[symbol]
692
+ # else, if self is an orderbook update
693
+ a = None
694
+ b = None
695
+ c = None
696
+ if messageLength == 5:
697
+ a = self.safe_value(message[1], 'a', [])
698
+ b = self.safe_value(message[2], 'b', [])
699
+ c = self.safe_integer(message[1], 'c')
700
+ c = self.safe_integer(message[2], 'c', c)
701
+ else:
702
+ c = self.safe_integer(message[1], 'c')
703
+ if 'a' in message[1]:
704
+ a = self.safe_value(message[1], 'a', [])
705
+ else:
706
+ b = self.safe_value(message[1], 'b', [])
707
+ storedAsks = orderbook['asks']
708
+ storedBids = orderbook['bids']
709
+ example = None
710
+ if a is not None:
711
+ timestamp = self.custom_handle_deltas(storedAsks, a, timestamp)
712
+ example = self.safe_value(a, 0)
713
+ if b is not None:
714
+ timestamp = self.custom_handle_deltas(storedBids, b, timestamp)
715
+ example = self.safe_value(b, 0)
716
+ # don't remove self line or I will poop on your face
717
+ orderbook.limit()
718
+ checksum = self.safe_bool(self.options, 'checksum', True)
719
+ if checksum:
720
+ priceString = self.safe_string(example, 0)
721
+ amountString = self.safe_string(example, 1)
722
+ priceParts = priceString.split('.')
723
+ amountParts = amountString.split('.')
724
+ priceLength = len(priceParts[1]) - 0
725
+ amountLength = len(amountParts[1]) - 0
726
+ payloadArray = []
727
+ if c is not None:
728
+ for i in range(0, 10):
729
+ formatted = self.format_number(storedAsks[i][0], priceLength) + self.format_number(storedAsks[i][1], amountLength)
730
+ payloadArray.append(formatted)
731
+ for i in range(0, 10):
732
+ formatted = self.format_number(storedBids[i][0], priceLength) + self.format_number(storedBids[i][1], amountLength)
733
+ payloadArray.append(formatted)
734
+ payload = ''.join(payloadArray)
735
+ localChecksum = self.crc32(payload, False)
736
+ if localChecksum != c:
737
+ error = InvalidNonce(self.id + ' invalid checksum')
738
+ del client.subscriptions[messageHash]
739
+ del self.orderbooks[symbol]
740
+ client.reject(error, messageHash)
741
+ return
742
+ orderbook['symbol'] = symbol
743
+ orderbook['timestamp'] = timestamp
744
+ orderbook['datetime'] = self.iso8601(timestamp)
745
+ client.resolve(orderbook, messageHash)
746
+
747
+ def format_number(self, n, length):
748
+ stringNumber = self.number_to_string(n)
749
+ parts = stringNumber.split('.')
750
+ integer = self.safe_string(parts, 0)
751
+ decimals = self.safe_string(parts, 1, '')
752
+ paddedDecimals = decimals.ljust(length, '0')
753
+ joined = integer + paddedDecimals
754
+ i = 0
755
+ while(joined[i] == '0'):
756
+ i += 1
757
+ if i > 0:
758
+ return joined[i:]
759
+ else:
760
+ return joined
761
+
762
+ def custom_handle_deltas(self, bookside, deltas, timestamp=None):
763
+ for j in range(0, len(deltas)):
764
+ delta = deltas[j]
765
+ price = self.parse_number(delta[0])
766
+ amount = self.parse_number(delta[1])
767
+ oldTimestamp = timestamp if timestamp else 0
768
+ timestamp = max(oldTimestamp, self.parse_to_int(float(delta[2]) * 1000))
769
+ bookside.store(price, amount)
770
+ return timestamp
771
+
772
+ def handle_system_status(self, client: Client, message):
773
+ #
774
+ # todo: answer the question whether handleSystemStatus should be renamed
775
+ # and unified for any usage pattern that
776
+ # involves system status and maintenance updates
777
+ #
778
+ # {
779
+ # "connectionID": 15527282728335292000,
780
+ # "event": "systemStatus",
781
+ # "status": "online", # online|maintenance|(custom status tbd)
782
+ # "version": "0.2.0"
783
+ # }
784
+ #
785
+ return message
786
+
787
+ async def authenticate(self, params={}):
788
+ url = self.urls['api']['ws']['private']
789
+ client = self.client(url)
790
+ authenticated = 'authenticated'
791
+ subscription = self.safe_value(client.subscriptions, authenticated)
792
+ if subscription is None:
793
+ response = await self.privatePostGetWebSocketsToken(params)
794
+ #
795
+ # {
796
+ # "error":[],
797
+ # "result":{
798
+ # "token":"xeAQ\/RCChBYNVh53sTv1yZ5H4wIbwDF20PiHtTF+4UI",
799
+ # "expires":900
800
+ # }
801
+ # }
802
+ #
803
+ subscription = self.safe_value(response, 'result')
804
+ client.subscriptions[authenticated] = subscription
805
+ return self.safe_string(subscription, 'token')
806
+
807
+ async def watch_private(self, name, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
808
+ await self.load_markets()
809
+ token = await self.authenticate()
810
+ subscriptionHash = name
811
+ messageHash = name
812
+ if symbol is not None:
813
+ symbol = self.symbol(symbol)
814
+ messageHash += ':' + symbol
815
+ url = self.urls['api']['ws']['private']
816
+ requestId = self.request_id()
817
+ subscribe: dict = {
818
+ 'event': 'subscribe',
819
+ 'reqid': requestId,
820
+ 'subscription': {
821
+ 'name': name,
822
+ 'token': token,
823
+ },
824
+ }
825
+ request = self.deep_extend(subscribe, params)
826
+ result = await self.watch(url, messageHash, request, subscriptionHash)
827
+ if self.newUpdates:
828
+ limit = result.getLimit(symbol, limit)
829
+ return self.filter_by_symbol_since_limit(result, symbol, since, limit)
830
+
831
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
832
+ """
833
+ watches information on multiple trades made by the user
834
+ :param str symbol: unified market symbol of the market trades were made in
835
+ :param int [since]: the earliest time in ms to fetch trades for
836
+ :param int [limit]: the maximum number of trade structures to retrieve
837
+ :param dict [params]: extra parameters specific to the exchange API endpoint
838
+ :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
839
+ """
840
+ return await self.watch_private('ownTrades', symbol, since, limit, params)
841
+
842
+ def handle_my_trades(self, client: Client, message, subscription=None):
843
+ #
844
+ # [
845
+ # [
846
+ # {
847
+ # "TT5UC3-GOIRW-6AZZ6R": {
848
+ # "cost": "1493.90107",
849
+ # "fee": "3.88415",
850
+ # "margin": "0.00000",
851
+ # "ordertxid": "OTLAS3-RRHUF-NDWH5A",
852
+ # "ordertype": "market",
853
+ # "pair": "XBT/USDT",
854
+ # "postxid": "TKH2SE-M7IF5-CFI7LT",
855
+ # "price": "6851.50005",
856
+ # "time": "1586822919.335498",
857
+ # "type": "sell",
858
+ # "vol": "0.21804000"
859
+ # }
860
+ # },
861
+ # {
862
+ # "TIY6G4-LKLAI-Y3GD4A": {
863
+ # "cost": "22.17134",
864
+ # "fee": "0.05765",
865
+ # "margin": "0.00000",
866
+ # "ordertxid": "ODQXS7-MOLK6-ICXKAA",
867
+ # "ordertype": "market",
868
+ # "pair": "ETH/USD",
869
+ # "postxid": "TKH2SE-M7IF5-CFI7LT",
870
+ # "price": "169.97999",
871
+ # "time": "1586340530.895739",
872
+ # "type": "buy",
873
+ # "vol": "0.13043500"
874
+ # }
875
+ # },
876
+ # ],
877
+ # "ownTrades",
878
+ # {sequence: 1}
879
+ # ]
880
+ #
881
+ allTrades = self.safe_value(message, 0, [])
882
+ allTradesLength = len(allTrades)
883
+ if allTradesLength > 0:
884
+ if self.myTrades is None:
885
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
886
+ self.myTrades = ArrayCache(limit)
887
+ stored = self.myTrades
888
+ symbols: dict = {}
889
+ for i in range(0, len(allTrades)):
890
+ trades = self.safe_value(allTrades, i, {})
891
+ ids = list(trades.keys())
892
+ for j in range(0, len(ids)):
893
+ id = ids[j]
894
+ trade = trades[id]
895
+ parsed = self.parse_ws_trade(self.extend({'id': id}, trade))
896
+ stored.append(parsed)
897
+ symbol = parsed['symbol']
898
+ symbols[symbol] = True
899
+ name = 'ownTrades'
900
+ client.resolve(self.myTrades, name)
901
+ keys = list(symbols.keys())
902
+ for i in range(0, len(keys)):
903
+ messageHash = name + ':' + keys[i]
904
+ client.resolve(self.myTrades, messageHash)
905
+
906
+ def parse_ws_trade(self, trade, market=None):
907
+ #
908
+ # {
909
+ # "id": "TIMIRG-WUNNE-RRJ6GT", # injected from outside
910
+ # "ordertxid": "OQRPN2-LRHFY-HIFA7D",
911
+ # "postxid": "TKH2SE-M7IF5-CFI7LT",
912
+ # "pair": "USDCUSDT",
913
+ # "time": 1586340086.457,
914
+ # "type": "sell",
915
+ # "ordertype": "market",
916
+ # "price": "0.99860000",
917
+ # "cost": "22.16892001",
918
+ # "fee": "0.04433784",
919
+ # "vol": "22.20000000",
920
+ # "margin": "0.00000000",
921
+ # "misc": ''
922
+ # }
923
+ #
924
+ # {
925
+ # "id": "TIY6G4-LKLAI-Y3GD4A",
926
+ # "cost": "22.17134",
927
+ # "fee": "0.05765",
928
+ # "margin": "0.00000",
929
+ # "ordertxid": "ODQXS7-MOLK6-ICXKAA",
930
+ # "ordertype": "market",
931
+ # "pair": "ETH/USD",
932
+ # "postxid": "TKH2SE-M7IF5-CFI7LT",
933
+ # "price": "169.97999",
934
+ # "time": "1586340530.895739",
935
+ # "type": "buy",
936
+ # "vol": "0.13043500"
937
+ # }
938
+ #
939
+ wsName = self.safe_string(trade, 'pair')
940
+ market = self.safe_value(self.options['marketsByWsName'], wsName, market)
941
+ symbol = None
942
+ orderId = self.safe_string(trade, 'ordertxid')
943
+ id = self.safe_string_2(trade, 'id', 'postxid')
944
+ timestamp = self.safe_timestamp(trade, 'time')
945
+ side = self.safe_string(trade, 'type')
946
+ type = self.safe_string(trade, 'ordertype')
947
+ price = self.safe_float(trade, 'price')
948
+ amount = self.safe_float(trade, 'vol')
949
+ cost = None
950
+ fee = None
951
+ if 'fee' in trade:
952
+ currency = None
953
+ if market is not None:
954
+ currency = market['quote']
955
+ fee = {
956
+ 'cost': self.safe_float(trade, 'fee'),
957
+ 'currency': currency,
958
+ }
959
+ if market is not None:
960
+ symbol = market['symbol']
961
+ if price is not None:
962
+ if amount is not None:
963
+ cost = price * amount
964
+ return {
965
+ 'id': id,
966
+ 'order': orderId,
967
+ 'info': trade,
968
+ 'timestamp': timestamp,
969
+ 'datetime': self.iso8601(timestamp),
970
+ 'symbol': symbol,
971
+ 'type': type,
972
+ 'side': side,
973
+ 'takerOrMaker': None,
974
+ 'price': price,
975
+ 'amount': amount,
976
+ 'cost': cost,
977
+ 'fee': fee,
978
+ }
979
+
980
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
981
+ """
982
+ :see: https://docs.kraken.com/websockets/#message-openOrders
983
+ watches information on multiple orders made by the user
984
+ :param str symbol: unified market symbol of the market orders were made in
985
+ :param int [since]: the earliest time in ms to fetch orders for
986
+ :param int [limit]: the maximum number of orde structures to retrieve
987
+ :param dict [params]: maximum number of orderic to the exchange API endpoint
988
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
989
+ """
990
+ return await self.watch_private('openOrders', symbol, since, limit, params)
991
+
992
+ def handle_orders(self, client: Client, message, subscription=None):
993
+ #
994
+ # [
995
+ # [
996
+ # {
997
+ # "OGTT3Y-C6I3P-XRI6HX": {
998
+ # "cost": "0.00000",
999
+ # "descr": {
1000
+ # "close": "",
1001
+ # "leverage": "0:1",
1002
+ # "order": "sell 10.00345345 XBT/EUR @ limit 34.50000 with 0:1 leverage",
1003
+ # "ordertype": "limit",
1004
+ # "pair": "XBT/EUR",
1005
+ # "price": "34.50000",
1006
+ # "price2": "0.00000",
1007
+ # "type": "sell"
1008
+ # },
1009
+ # "expiretm": "0.000000",
1010
+ # "fee": "0.00000",
1011
+ # "limitprice": "34.50000",
1012
+ # "misc": "",
1013
+ # "oflags": "fcib",
1014
+ # "opentm": "0.000000",
1015
+ # "price": "34.50000",
1016
+ # "refid": "OKIVMP-5GVZN-Z2D2UA",
1017
+ # "starttm": "0.000000",
1018
+ # "status": "open",
1019
+ # "stopprice": "0.000000",
1020
+ # "userref": 0,
1021
+ # "vol": "10.00345345",
1022
+ # "vol_exec": "0.00000000"
1023
+ # }
1024
+ # },
1025
+ # {
1026
+ # "OGTT3Y-C6I3P-XRI6HX": {
1027
+ # "cost": "0.00000",
1028
+ # "descr": {
1029
+ # "close": "",
1030
+ # "leverage": "0:1",
1031
+ # "order": "sell 0.00000010 XBT/EUR @ limit 5334.60000 with 0:1 leverage",
1032
+ # "ordertype": "limit",
1033
+ # "pair": "XBT/EUR",
1034
+ # "price": "5334.60000",
1035
+ # "price2": "0.00000",
1036
+ # "type": "sell"
1037
+ # },
1038
+ # "expiretm": "0.000000",
1039
+ # "fee": "0.00000",
1040
+ # "limitprice": "5334.60000",
1041
+ # "misc": "",
1042
+ # "oflags": "fcib",
1043
+ # "opentm": "0.000000",
1044
+ # "price": "5334.60000",
1045
+ # "refid": "OKIVMP-5GVZN-Z2D2UA",
1046
+ # "starttm": "0.000000",
1047
+ # "status": "open",
1048
+ # "stopprice": "0.000000",
1049
+ # "userref": 0,
1050
+ # "vol": "0.00000010",
1051
+ # "vol_exec": "0.00000000"
1052
+ # }
1053
+ # },
1054
+ # ],
1055
+ # "openOrders",
1056
+ # {"sequence": 234}
1057
+ # ]
1058
+ #
1059
+ # status-change
1060
+ #
1061
+ # [
1062
+ # [
1063
+ # {"OGTT3Y-C6I3P-XRI6HX": {"status": "closed"}},
1064
+ # {"OGTT3Y-C6I3P-XRI6HX": {"status": "closed"}},
1065
+ # ],
1066
+ # "openOrders",
1067
+ # {"sequence": 59342}
1068
+ # ]
1069
+ #
1070
+ allOrders = self.safe_value(message, 0, [])
1071
+ allOrdersLength = len(allOrders)
1072
+ if allOrdersLength > 0:
1073
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
1074
+ if self.orders is None:
1075
+ self.orders = ArrayCacheBySymbolById(limit)
1076
+ stored = self.orders
1077
+ symbols: dict = {}
1078
+ for i in range(0, len(allOrders)):
1079
+ orders = self.safe_value(allOrders, i, {})
1080
+ ids = list(orders.keys())
1081
+ for j in range(0, len(ids)):
1082
+ id = ids[j]
1083
+ order = orders[id]
1084
+ parsed = self.parse_ws_order(order)
1085
+ parsed['id'] = id
1086
+ symbol = None
1087
+ symbolsByOrderId = self.safe_value(self.options, 'symbolsByOrderId', {})
1088
+ if parsed['symbol'] is not None:
1089
+ symbol = parsed['symbol']
1090
+ symbolsByOrderId[id] = symbol
1091
+ self.options['symbolsByOrderId'] = symbolsByOrderId
1092
+ else:
1093
+ symbol = self.safe_string(symbolsByOrderId, id)
1094
+ previousOrders = self.safe_value(stored.hashmap, symbol)
1095
+ previousOrder = self.safe_value(previousOrders, id)
1096
+ newOrder = parsed
1097
+ if previousOrder is not None:
1098
+ newRawOrder = self.extend(previousOrder['info'], newOrder['info'])
1099
+ newOrder = self.parse_ws_order(newRawOrder)
1100
+ newOrder['id'] = id
1101
+ length = len(stored)
1102
+ if length == limit and (previousOrder is None):
1103
+ first = stored[0]
1104
+ if first['id'] in symbolsByOrderId:
1105
+ del symbolsByOrderId[first['id']]
1106
+ stored.append(newOrder)
1107
+ symbols[symbol] = True
1108
+ name = 'openOrders'
1109
+ client.resolve(self.orders, name)
1110
+ keys = list(symbols.keys())
1111
+ for i in range(0, len(keys)):
1112
+ messageHash = name + ':' + keys[i]
1113
+ client.resolve(self.orders, messageHash)
1114
+
1115
+ def parse_ws_order(self, order, market=None):
1116
+ #
1117
+ # createOrder
1118
+ # {
1119
+ # "avg_price": "0.00000",
1120
+ # "cost": "0.00000",
1121
+ # "descr": {
1122
+ # "close": null,
1123
+ # "leverage": null,
1124
+ # "order": "sell 0.01000000 ETH/USDT @ limit 1900.00000",
1125
+ # "ordertype": "limit",
1126
+ # "pair": "ETH/USDT",
1127
+ # "price": "1900.00000",
1128
+ # "price2": "0.00000",
1129
+ # "type": "sell"
1130
+ # },
1131
+ # "expiretm": null,
1132
+ # "fee": "0.00000",
1133
+ # "limitprice": "0.00000",
1134
+ # "misc": '',
1135
+ # "oflags": "fciq",
1136
+ # "opentm": "1667522705.757622",
1137
+ # "refid": null,
1138
+ # "starttm": null,
1139
+ # "status": "open",
1140
+ # "stopprice": "0.00000",
1141
+ # "timeinforce": "GTC",
1142
+ # "userref": 0,
1143
+ # "vol": "0.01000000",
1144
+ # "vol_exec": "0.00000000"
1145
+ # }
1146
+ #
1147
+ description = self.safe_value(order, 'descr', {})
1148
+ orderDescription = self.safe_string(description, 'order')
1149
+ side = None
1150
+ type = None
1151
+ wsName = None
1152
+ price = None
1153
+ amount = None
1154
+ if orderDescription is not None:
1155
+ parts = orderDescription.split(' ')
1156
+ side = self.safe_string(parts, 0)
1157
+ amount = self.safe_string(parts, 1)
1158
+ wsName = self.safe_string(parts, 2)
1159
+ type = self.safe_string(parts, 4)
1160
+ price = self.safe_string(parts, 5)
1161
+ side = self.safe_string(description, 'type', side)
1162
+ type = self.safe_string(description, 'ordertype', type)
1163
+ wsName = self.safe_string(description, 'pair', wsName)
1164
+ market = self.safe_value(self.options['marketsByWsName'], wsName, market)
1165
+ symbol = None
1166
+ timestamp = self.safe_timestamp(order, 'opentm')
1167
+ amount = self.safe_string(order, 'vol', amount)
1168
+ filled = self.safe_string(order, 'vol_exec')
1169
+ fee = None
1170
+ cost = self.safe_string(order, 'cost')
1171
+ price = self.safe_string(description, 'price', price)
1172
+ if (price is None) or (Precise.string_eq(price, '0.0')):
1173
+ price = self.safe_string(description, 'price2')
1174
+ if (price is None) or (Precise.string_eq(price, '0.0')):
1175
+ price = self.safe_string(order, 'price', price)
1176
+ average = self.safe_string_2(order, 'avg_price', 'price')
1177
+ if market is not None:
1178
+ symbol = market['symbol']
1179
+ if 'fee' in order:
1180
+ flags = order['oflags']
1181
+ feeCost = self.safe_string(order, 'fee')
1182
+ fee = {
1183
+ 'cost': feeCost,
1184
+ 'rate': None,
1185
+ }
1186
+ if flags.find('fciq') >= 0:
1187
+ fee['currency'] = market['quote']
1188
+ elif flags.find('fcib') >= 0:
1189
+ fee['currency'] = market['base']
1190
+ status = self.parse_order_status(self.safe_string(order, 'status'))
1191
+ id = self.safe_string(order, 'id')
1192
+ if id is None:
1193
+ txid = self.safe_value(order, 'txid')
1194
+ id = self.safe_string(txid, 0)
1195
+ clientOrderId = self.safe_string(order, 'userref')
1196
+ rawTrades = self.safe_value(order, 'trades')
1197
+ trades = None
1198
+ if rawTrades is not None:
1199
+ trades = self.parse_trades(rawTrades, market, None, None, {'order': id})
1200
+ stopPrice = self.safe_number(order, 'stopprice')
1201
+ return self.safe_order({
1202
+ 'id': id,
1203
+ 'clientOrderId': clientOrderId,
1204
+ 'info': order,
1205
+ 'timestamp': timestamp,
1206
+ 'datetime': self.iso8601(timestamp),
1207
+ 'lastTradeTimestamp': None,
1208
+ 'status': status,
1209
+ 'symbol': symbol,
1210
+ 'type': type,
1211
+ 'timeInForce': None,
1212
+ 'postOnly': None,
1213
+ 'side': side,
1214
+ 'price': price,
1215
+ 'stopPrice': stopPrice,
1216
+ 'triggerPrice': stopPrice,
1217
+ 'cost': cost,
1218
+ 'amount': amount,
1219
+ 'filled': filled,
1220
+ 'average': average,
1221
+ 'remaining': None,
1222
+ 'fee': fee,
1223
+ 'trades': trades,
1224
+ })
1225
+
1226
+ async def watch_multi_helper(self, unifiedName: str, channelName: str, symbols: Strings = None, subscriptionArgs=None, params={}):
1227
+ await self.load_markets()
1228
+ # symbols are required
1229
+ symbols = self.market_symbols(symbols, None, False, True, False)
1230
+ messageHashes = []
1231
+ for i in range(0, len(symbols)):
1232
+ messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
1233
+ # for WS subscriptions, we can't use .marketIds(symbols), instead a custom is field needed
1234
+ markets = self.markets_for_symbols(symbols)
1235
+ wsMarketIds = []
1236
+ for i in range(0, len(markets)):
1237
+ wsMarketId = self.safe_string(markets[i]['info'], 'wsname')
1238
+ wsMarketIds.append(wsMarketId)
1239
+ request: dict = {
1240
+ 'event': 'subscribe',
1241
+ 'reqid': self.request_id(),
1242
+ 'pair': wsMarketIds,
1243
+ 'subscription': {
1244
+ 'name': channelName,
1245
+ },
1246
+ }
1247
+ url = self.urls['api']['ws']['public']
1248
+ return await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes, subscriptionArgs)
1249
+
1250
+ def get_message_hash(self, unifiedElementName: str, subChannelName: Str = None, symbol: Str = None):
1251
+ # unifiedElementName can be : orderbook, trade, ticker, bidask ...
1252
+ # subChannelName only applies to channel that needs specific variation(i.e. depth_50, depth_100..) to be selected
1253
+ withSymbol = symbol is not None
1254
+ messageHash = unifiedElementName
1255
+ if not withSymbol:
1256
+ messageHash += 's'
1257
+ else:
1258
+ messageHash += '@' + symbol
1259
+ if subChannelName is not None:
1260
+ messageHash += '#' + subChannelName
1261
+ return messageHash
1262
+
1263
+ def handle_subscription_status(self, client: Client, message):
1264
+ #
1265
+ # public
1266
+ #
1267
+ # {
1268
+ # "channelID": 210,
1269
+ # "channelName": "book-10",
1270
+ # "event": "subscriptionStatus",
1271
+ # "reqid": 1574146735269,
1272
+ # "pair": "ETH/XBT",
1273
+ # "status": "subscribed",
1274
+ # "subscription": {depth: 10, name: "book"}
1275
+ # }
1276
+ #
1277
+ # private
1278
+ #
1279
+ # {
1280
+ # "channelName": "openOrders",
1281
+ # "event": "subscriptionStatus",
1282
+ # "reqid": 1,
1283
+ # "status": "subscribed",
1284
+ # "subscription": {maxratecount: 125, name: "openOrders"}
1285
+ # }
1286
+ #
1287
+ channelId = self.safe_string(message, 'channelID')
1288
+ if channelId is not None:
1289
+ client.subscriptions[channelId] = message
1290
+ # requestId = self.safe_string(message, "reqid")
1291
+ # if requestId in client.futures:
1292
+ # del client.futures[requestId]
1293
+ # }
1294
+
1295
+ def handle_error_message(self, client: Client, message):
1296
+ #
1297
+ # {
1298
+ # "errorMessage": "Currency pair not in ISO 4217-A3 format foobar",
1299
+ # "event": "subscriptionStatus",
1300
+ # "pair": "foobar",
1301
+ # "reqid": 1574146735269,
1302
+ # "status": "error",
1303
+ # "subscription": {name: "ticker"}
1304
+ # }
1305
+ #
1306
+ errorMessage = self.safe_string(message, 'errorMessage')
1307
+ if errorMessage is not None:
1308
+ requestId = self.safe_value(message, 'reqid')
1309
+ if requestId is not None:
1310
+ broad = self.exceptions['ws']['broad']
1311
+ broadKey = self.find_broadly_matched_key(broad, errorMessage)
1312
+ exception = None
1313
+ if broadKey is None:
1314
+ exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
1315
+ else:
1316
+ exception = broad[broadKey](errorMessage)
1317
+ client.reject(exception, requestId)
1318
+ return False
1319
+ return True
1320
+
1321
+ def handle_message(self, client: Client, message):
1322
+ if isinstance(message, list):
1323
+ channelId = self.safe_string(message, 0)
1324
+ subscription = self.safe_value(client.subscriptions, channelId, {})
1325
+ info = self.safe_value(subscription, 'subscription', {})
1326
+ messageLength = len(message)
1327
+ channelName = self.safe_string(message, messageLength - 2)
1328
+ name = self.safe_string(info, 'name')
1329
+ methods: dict = {
1330
+ # public
1331
+ 'book': self.handle_order_book,
1332
+ 'ohlc': self.handle_ohlcv,
1333
+ 'ticker': self.handle_ticker,
1334
+ 'trade': self.handle_trades,
1335
+ # private
1336
+ 'openOrders': self.handle_orders,
1337
+ 'ownTrades': self.handle_my_trades,
1338
+ }
1339
+ method = self.safe_value_2(methods, name, channelName)
1340
+ if method is not None:
1341
+ method(client, message, subscription)
1342
+ else:
1343
+ if self.handle_error_message(client, message):
1344
+ event = self.safe_string(message, 'event')
1345
+ methods: dict = {
1346
+ 'heartbeat': self.handle_heartbeat,
1347
+ 'systemStatus': self.handle_system_status,
1348
+ 'subscriptionStatus': self.handle_subscription_status,
1349
+ 'addOrderStatus': self.handle_create_edit_order,
1350
+ 'editOrderStatus': self.handle_create_edit_order,
1351
+ 'cancelOrderStatus': self.handle_cancel_order,
1352
+ 'cancelAllStatus': self.handle_cancel_all_orders,
1353
+ }
1354
+ method = self.safe_value(methods, event)
1355
+ if method is not None:
1356
+ method(client, message)