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/kucoin.py ADDED
@@ -0,0 +1,1133 @@
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 Balances, Int, Order, OrderBook, 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 ArgumentsRequired
13
+
14
+
15
+ class kucoin(ccxt.async_support.kucoin):
16
+
17
+ def describe(self):
18
+ return self.deep_extend(super(kucoin, self).describe(), {
19
+ 'has': {
20
+ 'ws': True,
21
+ 'createOrderWs': False,
22
+ 'editOrderWs': False,
23
+ 'fetchOpenOrdersWs': False,
24
+ 'fetchOrderWs': False,
25
+ 'cancelOrderWs': False,
26
+ 'cancelOrdersWs': False,
27
+ 'cancelAllOrdersWs': False,
28
+ 'watchBidsAsks': True,
29
+ 'watchOrderBook': True,
30
+ 'watchOrders': True,
31
+ 'watchMyTrades': True,
32
+ 'watchTickers': True,
33
+ 'watchTicker': True,
34
+ 'watchTrades': True,
35
+ 'watchTradesForSymbols': True,
36
+ 'watchOrderBookForSymbols': True,
37
+ 'watchBalance': True,
38
+ 'watchOHLCV': True,
39
+ },
40
+ 'options': {
41
+ 'tradesLimit': 1000,
42
+ 'watchTicker': {
43
+ 'name': 'market/snapshot', # market/ticker
44
+ },
45
+ 'watchOrderBook': {
46
+ 'snapshotDelay': 5,
47
+ 'snapshotMaxRetries': 3,
48
+ 'method': '/market/level2', # '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50'
49
+ },
50
+ },
51
+ 'streaming': {
52
+ # kucoin does not support built-in ws protocol-level ping-pong
53
+ # instead it requires a custom json-based text ping-pong
54
+ # https://docs.kucoin.com/#ping
55
+ 'ping': self.ping,
56
+ },
57
+ })
58
+
59
+ async def negotiate(self, privateChannel, params={}):
60
+ connectId = 'private' if privateChannel else 'public'
61
+ urls = self.safe_value(self.options, 'urls', {})
62
+ spawaned = self.safe_value(urls, connectId)
63
+ if spawaned is not None:
64
+ return await spawaned
65
+ # we store an awaitable to the url
66
+ # so that multiple calls don't asynchronously
67
+ # fetch different urls and overwrite each other
68
+ urls[connectId] = self.spawn(self.negotiate_helper, privateChannel, params)
69
+ self.options['urls'] = urls
70
+ future = urls[connectId]
71
+ return await future
72
+
73
+ async def negotiate_helper(self, privateChannel, params={}):
74
+ response = None
75
+ connectId = 'private' if privateChannel else 'public'
76
+ try:
77
+ if privateChannel:
78
+ response = await self.privatePostBulletPrivate(params)
79
+ #
80
+ # {
81
+ # "code": "200000",
82
+ # "data": {
83
+ # "instanceServers": [
84
+ # {
85
+ # "pingInterval": 50000,
86
+ # "endpoint": "wss://push-private.kucoin.com/endpoint",
87
+ # "protocol": "websocket",
88
+ # "encrypt": True,
89
+ # "pingTimeout": 10000
90
+ # }
91
+ # ],
92
+ # "token": "2neAiuYvAU61ZDXANAGAsiL4-iAExhsBXZxftpOeh_55i3Ysy2q2LEsEWU64mdzUOPusi34M_wGoSf7iNyEWJ1UQy47YbpY4zVdzilNP-Bj3iXzrjjGlWtiYB9J6i9GjsxUuhPw3BlrzazF6ghq4Lzf7scStOz3KkxjwpsOBCH4=.WNQmhZQeUKIkh97KYgU0Lg=="
93
+ # }
94
+ # }
95
+ #
96
+ else:
97
+ response = await self.publicPostBulletPublic(params)
98
+ data = self.safe_value(response, 'data', {})
99
+ instanceServers = self.safe_value(data, 'instanceServers', [])
100
+ firstInstanceServer = self.safe_value(instanceServers, 0)
101
+ pingInterval = self.safe_integer(firstInstanceServer, 'pingInterval')
102
+ endpoint = self.safe_string(firstInstanceServer, 'endpoint')
103
+ token = self.safe_string(data, 'token')
104
+ result = endpoint + '?' + self.urlencode({
105
+ 'token': token,
106
+ 'privateChannel': privateChannel,
107
+ 'connectId': connectId,
108
+ })
109
+ client = self.client(result)
110
+ client.keepAlive = pingInterval
111
+ return result
112
+ except Exception as e:
113
+ future = self.safe_value(self.options['urls'], connectId)
114
+ future.reject(e)
115
+ del self.options['urls'][connectId]
116
+ return None
117
+
118
+ def request_id(self):
119
+ requestId = self.sum(self.safe_integer(self.options, 'requestId', 0), 1)
120
+ self.options['requestId'] = requestId
121
+ return requestId
122
+
123
+ async def subscribe(self, url, messageHash, subscriptionHash, params={}, subscription=None):
124
+ requestId = str(self.request_id())
125
+ request: dict = {
126
+ 'id': requestId,
127
+ 'type': 'subscribe',
128
+ 'topic': subscriptionHash,
129
+ 'response': True,
130
+ }
131
+ message = self.extend(request, params)
132
+ client = self.client(url)
133
+ if not (subscriptionHash in client.subscriptions):
134
+ client.subscriptions[requestId] = subscriptionHash
135
+ return await self.watch(url, messageHash, message, subscriptionHash, subscription)
136
+
137
+ async def subscribe_multiple(self, url, messageHashes, topic, subscriptionHashes, params={}, subscription=None):
138
+ requestId = str(self.request_id())
139
+ request: dict = {
140
+ 'id': requestId,
141
+ 'type': 'subscribe',
142
+ 'topic': topic,
143
+ 'response': True,
144
+ }
145
+ message = self.extend(request, params)
146
+ client = self.client(url)
147
+ for i in range(0, len(subscriptionHashes)):
148
+ subscriptionHash = subscriptionHashes[i]
149
+ if not (subscriptionHash in client.subscriptions):
150
+ client.subscriptions[requestId] = subscriptionHash
151
+ return await self.watch_multiple(url, messageHashes, message, subscriptionHashes, subscription)
152
+
153
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
154
+ """
155
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
156
+ :param str symbol: unified symbol of the market to fetch the ticker for
157
+ :param dict [params]: extra parameters specific to the exchange API endpoint
158
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
159
+ """
160
+ await self.load_markets()
161
+ market = self.market(symbol)
162
+ symbol = market['symbol']
163
+ url = await self.negotiate(False)
164
+ method, query = self.handle_option_and_params(params, 'watchTicker', 'method', '/market/snapshot')
165
+ topic = method + ':' + market['id']
166
+ messageHash = 'ticker:' + symbol
167
+ return await self.subscribe(url, messageHash, topic, query)
168
+
169
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
170
+ """
171
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/ticker
172
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
173
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
174
+ :param dict [params]: extra parameters specific to the exchange API endpoint
175
+ :param str [params.method]: either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
176
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
177
+ """
178
+ await self.load_markets()
179
+ symbols = self.market_symbols(symbols)
180
+ messageHash = 'tickers'
181
+ method = None
182
+ method, params = self.handle_option_and_params(params, 'watchTickers', 'method', '/market/ticker')
183
+ messageHashes = []
184
+ topics = []
185
+ if symbols is not None:
186
+ for i in range(0, len(symbols)):
187
+ symbol = symbols[i]
188
+ messageHashes.append('ticker:' + symbol)
189
+ market = self.market(symbol)
190
+ topics.append(method + ':' + market['id'])
191
+ url = await self.negotiate(False)
192
+ tickers = None
193
+ if symbols is None:
194
+ allTopic = method + ':all'
195
+ tickers = await self.subscribe(url, messageHash, allTopic, params)
196
+ if self.newUpdates:
197
+ return tickers
198
+ else:
199
+ marketIds = self.market_ids(symbols)
200
+ symbolsTopic = method + ':' + ','.join(marketIds)
201
+ tickers = await self.subscribe_multiple(url, messageHashes, symbolsTopic, topics, params)
202
+ if self.newUpdates:
203
+ newDict: dict = {}
204
+ newDict[tickers['symbol']] = tickers
205
+ return newDict
206
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
207
+
208
+ def handle_ticker(self, client: Client, message):
209
+ #
210
+ # market/snapshot
211
+ #
212
+ # updates come in every 2 sec unless there
213
+ # were no changes since the previous update
214
+ #
215
+ # {
216
+ # "data": {
217
+ # "sequence": "1545896669291",
218
+ # "data": {
219
+ # "trading": True,
220
+ # "symbol": "KCS-BTC",
221
+ # "buy": 0.00011,
222
+ # "sell": 0.00012,
223
+ # "sort": 100,
224
+ # "volValue": 3.13851792584, # total
225
+ # "baseCurrency": "KCS",
226
+ # "market": "BTC",
227
+ # "quoteCurrency": "BTC",
228
+ # "symbolCode": "KCS-BTC",
229
+ # "datetime": 1548388122031,
230
+ # "high": 0.00013,
231
+ # "vol": 27514.34842,
232
+ # "low": 0.0001,
233
+ # "changePrice": -1.0e-5,
234
+ # "changeRate": -0.0769,
235
+ # "lastTradedPrice": 0.00012,
236
+ # "board": 0,
237
+ # "mark": 0
238
+ # }
239
+ # },
240
+ # "subject": "trade.snapshot",
241
+ # "topic": "/market/snapshot:KCS-BTC",
242
+ # "type": "message"
243
+ # }
244
+ #
245
+ # market/ticker
246
+ #
247
+ # {
248
+ # "type": "message",
249
+ # "topic": "/market/ticker:BTC-USDT",
250
+ # "subject": "trade.ticker",
251
+ # "data": {
252
+ # "bestAsk": "62163",
253
+ # "bestAskSize": "0.99011388",
254
+ # "bestBid": "62162.9",
255
+ # "bestBidSize": "0.04794181",
256
+ # "price": "62162.9",
257
+ # "sequence": "1621383371852",
258
+ # "size": "0.00832274",
259
+ # "time": 1634641987564
260
+ # }
261
+ # }
262
+ #
263
+ topic = self.safe_string(message, 'topic')
264
+ market = None
265
+ if topic is not None:
266
+ parts = topic.split(':')
267
+ first = self.safe_string(parts, 1)
268
+ marketId = None
269
+ if first == 'all':
270
+ marketId = self.safe_string(message, 'subject')
271
+ else:
272
+ marketId = first
273
+ market = self.safe_market(marketId, market, '-')
274
+ data = self.safe_value(message, 'data', {})
275
+ rawTicker = self.safe_value(data, 'data', data)
276
+ ticker = self.parse_ticker(rawTicker, market)
277
+ symbol = ticker['symbol']
278
+ self.tickers[symbol] = ticker
279
+ messageHash = 'ticker:' + symbol
280
+ client.resolve(ticker, messageHash)
281
+ # watchTickers
282
+ allTickers: dict = {}
283
+ allTickers[symbol] = ticker
284
+ client.resolve(allTickers, 'tickers')
285
+
286
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
287
+ """
288
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
289
+ watches best bid & ask for symbols
290
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
291
+ :param dict [params]: extra parameters specific to the exchange API endpoint
292
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
293
+ """
294
+ ticker = await self.watch_multi_helper('watchBidsAsks', '/spotMarket/level1:', symbols, params)
295
+ if self.newUpdates:
296
+ tickers: dict = {}
297
+ tickers[ticker['symbol']] = ticker
298
+ return tickers
299
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
300
+
301
+ async def watch_multi_helper(self, methodName, channelName: str, symbols: Strings = None, params={}):
302
+ await self.load_markets()
303
+ symbols = self.market_symbols(symbols, None, False, True, False)
304
+ length = len(symbols)
305
+ if length > 100:
306
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() accepts a maximum of 100 symbols')
307
+ messageHashes = []
308
+ for i in range(0, len(symbols)):
309
+ symbol = symbols[i]
310
+ market = self.market(symbol)
311
+ messageHashes.append('bidask@' + market['symbol'])
312
+ url = await self.negotiate(False)
313
+ marketIds = self.market_ids(symbols)
314
+ joined = ','.join(marketIds)
315
+ requestId = str(self.request_id())
316
+ request: dict = {
317
+ 'id': requestId,
318
+ 'type': 'subscribe',
319
+ 'topic': channelName + joined,
320
+ 'response': True,
321
+ }
322
+ message = self.extend(request, params)
323
+ return await self.watch_multiple(url, messageHashes, message, messageHashes)
324
+
325
+ def handle_bid_ask(self, client: Client, message):
326
+ #
327
+ # arrives one symbol dict
328
+ #
329
+ # {
330
+ # topic: '/spotMarket/level1:ETH-USDT',
331
+ # type: 'message',
332
+ # data: {
333
+ # asks: ['3347.42', '2.0778387'],
334
+ # bids: ['3347.41', '6.0411697'],
335
+ # timestamp: 1712231142085
336
+ # },
337
+ # subject: 'level1'
338
+ # }
339
+ #
340
+ parsedTicker = self.parse_ws_bid_ask(message)
341
+ symbol = parsedTicker['symbol']
342
+ self.bidsasks[symbol] = parsedTicker
343
+ messageHash = 'bidask@' + symbol
344
+ client.resolve(parsedTicker, messageHash)
345
+
346
+ def parse_ws_bid_ask(self, ticker, market=None):
347
+ topic = self.safe_string(ticker, 'topic')
348
+ parts = topic.split(':')
349
+ marketId = parts[1]
350
+ market = self.safe_market(marketId, market)
351
+ symbol = self.safe_string(market, 'symbol')
352
+ data = self.safe_dict(ticker, 'data', {})
353
+ ask = self.safe_list(data, 'asks', [])
354
+ bid = self.safe_list(data, 'bids', [])
355
+ timestamp = self.safe_integer(data, 'timestamp')
356
+ return self.safe_ticker({
357
+ 'symbol': symbol,
358
+ 'timestamp': timestamp,
359
+ 'datetime': self.iso8601(timestamp),
360
+ 'ask': self.safe_number(ask, 0),
361
+ 'askVolume': self.safe_number(ask, 1),
362
+ 'bid': self.safe_number(bid, 0),
363
+ 'bidVolume': self.safe_number(bid, 1),
364
+ 'info': ticker,
365
+ }, market)
366
+
367
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
368
+ """
369
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
370
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
371
+ :param str timeframe: the length of time each candle represents
372
+ :param int [since]: timestamp in ms of the earliest candle to fetch
373
+ :param int [limit]: the maximum amount of candles to fetch
374
+ :param dict [params]: extra parameters specific to the exchange API endpoint
375
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
376
+ """
377
+ await self.load_markets()
378
+ url = await self.negotiate(False)
379
+ market = self.market(symbol)
380
+ symbol = market['symbol']
381
+ period = self.safe_string(self.timeframes, timeframe, timeframe)
382
+ topic = '/market/candles:' + market['id'] + '_' + period
383
+ messageHash = 'candles:' + symbol + ':' + timeframe
384
+ ohlcv = await self.subscribe(url, messageHash, topic, params)
385
+ if self.newUpdates:
386
+ limit = ohlcv.getLimit(symbol, limit)
387
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
388
+
389
+ def handle_ohlcv(self, client: Client, message):
390
+ #
391
+ # {
392
+ # "data": {
393
+ # "symbol": "BTC-USDT",
394
+ # "candles": [
395
+ # "1624881240",
396
+ # "34138.8",
397
+ # "34121.6",
398
+ # "34138.8",
399
+ # "34097.9",
400
+ # "3.06097133",
401
+ # "104430.955068564"
402
+ # ],
403
+ # "time": 1624881284466023700
404
+ # },
405
+ # "subject": "trade.candles.update",
406
+ # "topic": "/market/candles:BTC-USDT_1min",
407
+ # "type": "message"
408
+ # }
409
+ #
410
+ data = self.safe_value(message, 'data', {})
411
+ marketId = self.safe_string(data, 'symbol')
412
+ candles = self.safe_value(data, 'candles', [])
413
+ topic = self.safe_string(message, 'topic')
414
+ parts = topic.split('_')
415
+ interval = self.safe_string(parts, 1)
416
+ # use a reverse lookup in a static map instead
417
+ timeframe = self.find_timeframe(interval)
418
+ market = self.safe_market(marketId)
419
+ symbol = market['symbol']
420
+ messageHash = 'candles:' + symbol + ':' + timeframe
421
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
422
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
423
+ if stored is None:
424
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
425
+ stored = ArrayCacheByTimestamp(limit)
426
+ self.ohlcvs[symbol][timeframe] = stored
427
+ ohlcv = self.parse_ohlcv(candles, market)
428
+ stored.append(ohlcv)
429
+ client.resolve(stored, messageHash)
430
+
431
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
432
+ """
433
+ get the list of most recent trades for a particular symbol
434
+ :param str symbol: unified symbol of the market to fetch trades for
435
+ :param int [since]: timestamp in ms of the earliest trade to fetch
436
+ :param int [limit]: the maximum amount of trades to fetch
437
+ :param dict [params]: extra parameters specific to the exchange API endpoint
438
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
439
+ """
440
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
441
+
442
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
443
+ """
444
+ get the list of most recent trades for a particular symbol
445
+ :param str symbol: unified symbol of the market to fetch trades for
446
+ :param int [since]: timestamp in ms of the earliest trade to fetch
447
+ :param int [limit]: the maximum amount of trades to fetch
448
+ :param dict [params]: extra parameters specific to the exchange API endpoint
449
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
450
+ """
451
+ symbolsLength = len(symbols)
452
+ if symbolsLength == 0:
453
+ raise ArgumentsRequired(self.id + ' watchTradesForSymbols() requires a non-empty array of symbols')
454
+ await self.load_markets()
455
+ symbols = self.market_symbols(symbols)
456
+ marketIds = self.market_ids(symbols)
457
+ url = await self.negotiate(False)
458
+ messageHashes = []
459
+ subscriptionHashes = []
460
+ topic = '/market/match:' + ','.join(marketIds)
461
+ for i in range(0, len(symbols)):
462
+ symbol = symbols[i]
463
+ messageHashes.append('trades:' + symbol)
464
+ marketId = marketIds[i]
465
+ subscriptionHashes.append('/market/match:' + marketId)
466
+ trades = await self.subscribe_multiple(url, messageHashes, topic, subscriptionHashes, params)
467
+ if self.newUpdates:
468
+ first = self.safe_value(trades, 0)
469
+ tradeSymbol = self.safe_string(first, 'symbol')
470
+ limit = trades.getLimit(tradeSymbol, limit)
471
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
472
+
473
+ def handle_trade(self, client: Client, message):
474
+ #
475
+ # {
476
+ # "data": {
477
+ # "sequence": "1568787654360",
478
+ # "symbol": "BTC-USDT",
479
+ # "side": "buy",
480
+ # "size": "0.00536577",
481
+ # "price": "9345",
482
+ # "takerOrderId": "5e356c4a9f1a790008f8d921",
483
+ # "time": "1580559434436443257",
484
+ # "type": "match",
485
+ # "makerOrderId": "5e356bffedf0010008fa5d7f",
486
+ # "tradeId": "5e356c4aeefabd62c62a1ece"
487
+ # },
488
+ # "subject": "trade.l3match",
489
+ # "topic": "/market/match:BTC-USDT",
490
+ # "type": "message"
491
+ # }
492
+ #
493
+ data = self.safe_value(message, 'data', {})
494
+ trade = self.parse_trade(data)
495
+ symbol = trade['symbol']
496
+ messageHash = 'trades:' + symbol
497
+ trades = self.safe_value(self.trades, symbol)
498
+ if trades is None:
499
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
500
+ trades = ArrayCache(limit)
501
+ self.trades[symbol] = trades
502
+ trades.append(trade)
503
+ client.resolve(trades, messageHash)
504
+
505
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
506
+ """
507
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
508
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
509
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
510
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
511
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
512
+ :param str symbol: unified symbol of the market to fetch the order book for
513
+ :param int [limit]: the maximum amount of order book entries to return
514
+ :param dict [params]: extra parameters specific to the exchange API endpoint
515
+ :param str [params.method]: either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
516
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
517
+ """
518
+ #
519
+ # https://docs.kucoin.com/#level-2-market-data
520
+ #
521
+ # 1. After receiving the websocket Level 2 data flow, cache the data.
522
+ # 2. Initiate a REST request to get the snapshot data of Level 2 order book.
523
+ # 3. Playback the cached Level 2 data flow.
524
+ # 4. Apply the new Level 2 data flow to the local snapshot to ensure that
525
+ # the sequence of the new Level 2 update lines up with the sequence of
526
+ # the previous Level 2 data. Discard all the message prior to that
527
+ # sequence, and then playback the change to snapshot.
528
+ # 5. Update the level2 full data based on sequence according to the
529
+ # size. If the price is 0, ignore the messages and update the sequence.
530
+ # If the size=0, update the sequence and remove the price of which the
531
+ # size is 0 out of level 2. Fr other cases, please update the price.
532
+ #
533
+ return await self.watch_order_book_for_symbols([symbol], limit, params)
534
+
535
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
536
+ """
537
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
538
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
539
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
540
+ :see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
541
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
542
+ :param str[] symbols: unified array of symbols
543
+ :param int [limit]: the maximum amount of order book entries to return
544
+ :param dict [params]: extra parameters specific to the exchange API endpoint
545
+ :param str [params.method]: either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
546
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
547
+ """
548
+ symbolsLength = len(symbols)
549
+ if symbolsLength == 0:
550
+ raise ArgumentsRequired(self.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols')
551
+ if limit is not None:
552
+ if (limit != 20) and (limit != 100) and (limit != 50) and (limit != 5):
553
+ raise ExchangeError(self.id + " watchOrderBook 'limit' argument must be None, 5, 20, 50 or 100")
554
+ await self.load_markets()
555
+ symbols = self.market_symbols(symbols)
556
+ marketIds = self.market_ids(symbols)
557
+ url = await self.negotiate(False)
558
+ method: Str = None
559
+ method, params = self.handle_option_and_params(params, 'watchOrderBook', 'method', '/market/level2')
560
+ if (limit == 5) or (limit == 50):
561
+ method = '/spotMarket/level2Depth' + str(limit)
562
+ topic = method + ':' + ','.join(marketIds)
563
+ messageHashes = []
564
+ subscriptionHashes = []
565
+ for i in range(0, len(symbols)):
566
+ symbol = symbols[i]
567
+ messageHashes.append('orderbook:' + symbol)
568
+ marketId = marketIds[i]
569
+ subscriptionHashes.append(method + ':' + marketId)
570
+ subscription = {}
571
+ if method == '/market/level2': # other streams return the entire orderbook, so we don't need to fetch the snapshot through REST
572
+ subscription = {
573
+ 'method': self.handle_order_book_subscription,
574
+ 'symbols': symbols,
575
+ 'limit': limit,
576
+ }
577
+ orderbook = await self.subscribe_multiple(url, messageHashes, topic, subscriptionHashes, params, subscription)
578
+ return orderbook.limit()
579
+
580
+ def handle_order_book(self, client: Client, message):
581
+ #
582
+ # initial snapshot is fetched with ccxt's fetchOrderBook
583
+ # the feed does not include a snapshot, just the deltas
584
+ #
585
+ # {
586
+ # "type":"message",
587
+ # "topic":"/market/level2:BTC-USDT",
588
+ # "subject":"trade.l2update",
589
+ # "data":{
590
+ # "sequenceStart":1545896669105,
591
+ # "sequenceEnd":1545896669106,
592
+ # "symbol":"BTC-USDT",
593
+ # "changes": {
594
+ # "asks": [["6","1","1545896669105"]], # price, size, sequence
595
+ # "bids": [["4","1","1545896669106"]]
596
+ # }
597
+ # }
598
+ # }
599
+ #
600
+ # {
601
+ # "topic": "/spotMarket/level2Depth5:BTC-USDT",
602
+ # "type": "message",
603
+ # "data": {
604
+ # "asks": [
605
+ # [
606
+ # "42815.6",
607
+ # "1.24016245"
608
+ # ]
609
+ # ],
610
+ # "bids": [
611
+ # [
612
+ # "42815.5",
613
+ # "0.08652716"
614
+ # ]
615
+ # ],
616
+ # "timestamp": 1707204474018
617
+ # },
618
+ # "subject": "level2"
619
+ # }
620
+ #
621
+ data = self.safe_value(message, 'data')
622
+ subject = self.safe_string(message, 'subject')
623
+ topic = self.safe_string(message, 'topic')
624
+ topicParts = topic.split(':')
625
+ topicSymbol = self.safe_string(topicParts, 1)
626
+ topicChannel = self.safe_string(topicParts, 0)
627
+ marketId = self.safe_string(data, 'symbol', topicSymbol)
628
+ symbol = self.safe_symbol(marketId, None, '-')
629
+ messageHash = 'orderbook:' + symbol
630
+ # orderbook = self.safe_dict(self.orderbooks, symbol)
631
+ if subject == 'level2':
632
+ if not (symbol in self.orderbooks):
633
+ self.orderbooks[symbol] = self.order_book()
634
+ else:
635
+ orderbook = self.orderbooks[symbol]
636
+ orderbook.reset()
637
+ self.orderbooks[symbol]['symbol'] = symbol
638
+ else:
639
+ if not (symbol in self.orderbooks):
640
+ self.orderbooks[symbol] = self.order_book()
641
+ orderbook = self.orderbooks[symbol]
642
+ nonce = self.safe_integer(orderbook, 'nonce')
643
+ deltaEnd = self.safe_integer_2(data, 'sequenceEnd', 'timestamp')
644
+ if nonce is None:
645
+ cacheLength = len(orderbook.cache)
646
+ subscriptions = list(client.subscriptions.keys())
647
+ subscription = None
648
+ for i in range(0, len(subscriptions)):
649
+ key = subscriptions[i]
650
+ if (key.find(topicSymbol) >= 0) and (key.find(topicChannel) >= 0):
651
+ subscription = client.subscriptions[key]
652
+ break
653
+ limit = self.safe_integer(subscription, 'limit')
654
+ snapshotDelay = self.handle_option('watchOrderBook', 'snapshotDelay', 5)
655
+ if cacheLength == snapshotDelay:
656
+ self.spawn(self.load_order_book, client, messageHash, symbol, limit, {})
657
+ orderbook.cache.append(data)
658
+ return
659
+ elif nonce >= deltaEnd:
660
+ return
661
+ self.handle_delta(self.orderbooks[symbol], data)
662
+ client.resolve(self.orderbooks[symbol], messageHash)
663
+
664
+ def get_cache_index(self, orderbook, cache):
665
+ firstDelta = self.safe_value(cache, 0)
666
+ nonce = self.safe_integer(orderbook, 'nonce')
667
+ firstDeltaStart = self.safe_integer(firstDelta, 'sequenceStart')
668
+ if nonce < firstDeltaStart - 1:
669
+ return -1
670
+ for i in range(0, len(cache)):
671
+ delta = cache[i]
672
+ deltaStart = self.safe_integer(delta, 'sequenceStart')
673
+ deltaEnd = self.safe_integer(delta, 'sequenceEnd')
674
+ if (nonce >= deltaStart - 1) and (nonce < deltaEnd):
675
+ return i
676
+ return len(cache)
677
+
678
+ def handle_delta(self, orderbook, delta):
679
+ timestamp = self.safe_integer_2(delta, 'time', 'timestamp')
680
+ orderbook['nonce'] = self.safe_integer(delta, 'sequenceEnd', timestamp)
681
+ orderbook['timestamp'] = timestamp
682
+ orderbook['datetime'] = self.iso8601(timestamp)
683
+ changes = self.safe_value(delta, 'changes', delta)
684
+ bids = self.safe_value(changes, 'bids', [])
685
+ asks = self.safe_value(changes, 'asks', [])
686
+ storedBids = orderbook['bids']
687
+ storedAsks = orderbook['asks']
688
+ self.handle_bid_asks(storedBids, bids)
689
+ self.handle_bid_asks(storedAsks, asks)
690
+
691
+ def handle_bid_asks(self, bookSide, bidAsks):
692
+ for i in range(0, len(bidAsks)):
693
+ bidAsk = self.parse_bid_ask(bidAsks[i])
694
+ bookSide.storeArray(bidAsk)
695
+
696
+ def handle_order_book_subscription(self, client: Client, message, subscription):
697
+ limit = self.safe_integer(subscription, 'limit')
698
+ symbols = self.safe_value(subscription, 'symbols')
699
+ if symbols is None:
700
+ symbol = self.safe_string(subscription, 'symbol')
701
+ self.orderbooks[symbol] = self.order_book({}, limit)
702
+ else:
703
+ for i in range(0, len(symbols)):
704
+ symbol = symbols[i]
705
+ self.orderbooks[symbol] = self.order_book({}, limit)
706
+ # moved snapshot initialization to handleOrderBook to fix
707
+ # https://github.com/ccxt/ccxt/issues/6820
708
+ # the general idea is to fetch the snapshot after the first delta
709
+ # but not before, because otherwise we cannot synchronize the feed
710
+
711
+ def handle_subscription_status(self, client: Client, message):
712
+ #
713
+ # {
714
+ # "id": "1578090438322",
715
+ # "type": "ack"
716
+ # }
717
+ #
718
+ id = self.safe_string(message, 'id')
719
+ if not (id in client.subscriptions):
720
+ return
721
+ subscriptionHash = self.safe_string(client.subscriptions, id)
722
+ subscription = self.safe_value(client.subscriptions, subscriptionHash)
723
+ del client.subscriptions[id]
724
+ method = self.safe_value(subscription, 'method')
725
+ if method is not None:
726
+ method(client, message, subscription)
727
+
728
+ def handle_system_status(self, client: Client, message):
729
+ #
730
+ # todo: answer the question whether handleSystemStatus should be renamed
731
+ # and unified for any usage pattern that
732
+ # involves system status and maintenance updates
733
+ #
734
+ # {
735
+ # "id": "1578090234088", # connectId
736
+ # "type": "welcome",
737
+ # }
738
+ #
739
+ return message
740
+
741
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
742
+ """
743
+ watches information on multiple orders made by the user
744
+ :param str symbol: unified market symbol of the market orders were made in
745
+ :param int [since]: the earliest time in ms to fetch orders for
746
+ :param int [limit]: the maximum number of order structures to retrieve
747
+ :param dict [params]: extra parameters specific to the exchange API endpoint
748
+ :param boolean [params.stop]: trigger orders are watched if True
749
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
750
+ """
751
+ await self.load_markets()
752
+ stop = self.safe_value_2(params, 'stop', 'trigger')
753
+ params = self.omit(params, ['stop', 'trigger'])
754
+ url = await self.negotiate(True)
755
+ topic = '/spotMarket/advancedOrders' if stop else '/spotMarket/tradeOrders'
756
+ request: dict = {
757
+ 'privateChannel': True,
758
+ }
759
+ messageHash = 'orders'
760
+ if symbol is not None:
761
+ market = self.market(symbol)
762
+ symbol = market['symbol']
763
+ messageHash = messageHash + ':' + symbol
764
+ orders = await self.subscribe(url, messageHash, topic, self.extend(request, params))
765
+ if self.newUpdates:
766
+ limit = orders.getLimit(symbol, limit)
767
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
768
+
769
+ def parse_ws_order_status(self, status):
770
+ statuses: dict = {
771
+ 'open': 'open',
772
+ 'filled': 'closed',
773
+ 'match': 'open',
774
+ 'update': 'open',
775
+ 'canceled': 'canceled',
776
+ 'cancel': 'canceled',
777
+ 'TRIGGERED': 'triggered',
778
+ }
779
+ return self.safe_string(statuses, status, status)
780
+
781
+ def parse_ws_order(self, order, market=None):
782
+ #
783
+ # /spotMarket/tradeOrders
784
+ #
785
+ # {
786
+ # "symbol": "XCAD-USDT",
787
+ # "orderType": "limit",
788
+ # "side": "buy",
789
+ # "orderId": "6249167327218b000135e749",
790
+ # "type": "canceled",
791
+ # "orderTime": 1648957043065280224,
792
+ # "size": "100.452",
793
+ # "filledSize": "0",
794
+ # "price": "2.9635",
795
+ # "clientOid": "buy-XCAD-USDT-1648957043010159",
796
+ # "remainSize": "0",
797
+ # "status": "done",
798
+ # "ts": 1648957054031001037
799
+ # }
800
+ #
801
+ # /spotMarket/advancedOrders
802
+ #
803
+ # {
804
+ # "createdAt": 1589789942337,
805
+ # "orderId": "5ec244f6a8a75e0009958237",
806
+ # "orderPrice": "0.00062",
807
+ # "orderType": "stop",
808
+ # "side": "sell",
809
+ # "size": "1",
810
+ # "stop": "entry",
811
+ # "stopPrice": "0.00062",
812
+ # "symbol": "KCS-BTC",
813
+ # "tradeType": "TRADE",
814
+ # "triggerSuccess": True,
815
+ # "ts": 1589790121382281286,
816
+ # "type": "triggered"
817
+ # }
818
+ #
819
+ rawType = self.safe_string(order, 'type')
820
+ status = self.parse_ws_order_status(rawType)
821
+ timestamp = self.safe_integer_2(order, 'orderTime', 'createdAt')
822
+ marketId = self.safe_string(order, 'symbol')
823
+ market = self.safe_market(marketId, market)
824
+ triggerPrice = self.safe_string(order, 'stopPrice')
825
+ triggerSuccess = self.safe_value(order, 'triggerSuccess')
826
+ triggerFail = (triggerSuccess is not True) and (triggerSuccess is not None) # TODO: updated to triggerSuccess == False once transpiler transpiles it correctly
827
+ if (status == 'triggered') and triggerFail:
828
+ status = 'canceled'
829
+ return self.safe_order({
830
+ 'info': order,
831
+ 'symbol': market['symbol'],
832
+ 'id': self.safe_string(order, 'orderId'),
833
+ 'clientOrderId': self.safe_string(order, 'clientOid'),
834
+ 'timestamp': timestamp,
835
+ 'datetime': self.iso8601(timestamp),
836
+ 'lastTradeTimestamp': None,
837
+ 'type': self.safe_string_lower(order, 'orderType'),
838
+ 'timeInForce': None,
839
+ 'postOnly': None,
840
+ 'side': self.safe_string_lower(order, 'side'),
841
+ 'price': self.safe_string_2(order, 'price', 'orderPrice'),
842
+ 'stopPrice': triggerPrice,
843
+ 'triggerPrice': triggerPrice,
844
+ 'amount': self.safe_string(order, 'size'),
845
+ 'cost': None,
846
+ 'average': None,
847
+ 'filled': self.safe_string(order, 'filledSize'),
848
+ 'remaining': None,
849
+ 'status': status,
850
+ 'fee': None,
851
+ 'trades': None,
852
+ }, market)
853
+
854
+ def handle_order(self, client: Client, message):
855
+ #
856
+ # Trigger Orders
857
+ #
858
+ # {
859
+ # "createdAt": 1692745706437,
860
+ # "error": "Balance insufficient!", # not always there
861
+ # "orderId": "vs86kp757vlda6ni003qs70v",
862
+ # "orderPrice": "0.26",
863
+ # "orderType": "stop",
864
+ # "side": "sell",
865
+ # "size": "5",
866
+ # "stop": "loss",
867
+ # "stopPrice": "0.26",
868
+ # "symbol": "ADA-USDT",
869
+ # "tradeType": "TRADE",
870
+ # "triggerSuccess": False, # not always there
871
+ # "ts": "1692745706442929298",
872
+ # "type": "open"
873
+ # }
874
+ #
875
+ messageHash = 'orders'
876
+ data = self.safe_value(message, 'data')
877
+ parsed = self.parse_ws_order(data)
878
+ symbol = self.safe_string(parsed, 'symbol')
879
+ orderId = self.safe_string(parsed, 'id')
880
+ triggerPrice = self.safe_value(parsed, 'triggerPrice')
881
+ isTriggerOrder = (triggerPrice is not None)
882
+ if self.orders is None:
883
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
884
+ self.orders = ArrayCacheBySymbolById(limit)
885
+ self.triggerOrders = ArrayCacheBySymbolById(limit)
886
+ cachedOrders = self.triggerOrders if isTriggerOrder else self.orders
887
+ orders = self.safe_value(cachedOrders.hashmap, symbol, {})
888
+ order = self.safe_value(orders, orderId)
889
+ if order is not None:
890
+ # todo add others to calculate average etc
891
+ if order['status'] == 'closed':
892
+ parsed['status'] = 'closed'
893
+ cachedOrders.append(parsed)
894
+ client.resolve(cachedOrders, messageHash)
895
+ symbolSpecificMessageHash = messageHash + ':' + symbol
896
+ client.resolve(cachedOrders, symbolSpecificMessageHash)
897
+
898
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
899
+ """
900
+ watches information on multiple trades made by the user
901
+ :param str symbol: unified market symbol of the market trades were made in
902
+ :param int [since]: the earliest time in ms to fetch trades for
903
+ :param int [limit]: the maximum number of trade structures to retrieve
904
+ :param dict [params]: extra parameters specific to the exchange API endpoint
905
+ :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
906
+ """
907
+ await self.load_markets()
908
+ url = await self.negotiate(True)
909
+ topic = '/spot/tradeFills'
910
+ request: dict = {
911
+ 'privateChannel': True,
912
+ }
913
+ messageHash = 'myTrades'
914
+ if symbol is not None:
915
+ market = self.market(symbol)
916
+ symbol = market['symbol']
917
+ messageHash = messageHash + ':' + market['symbol']
918
+ trades = await self.subscribe(url, messageHash, topic, self.extend(request, params))
919
+ if self.newUpdates:
920
+ limit = trades.getLimit(symbol, limit)
921
+ return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
922
+
923
+ def handle_my_trade(self, client: Client, message):
924
+ if self.myTrades is None:
925
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
926
+ self.myTrades = ArrayCacheBySymbolById(limit)
927
+ data = self.safe_dict(message, 'data')
928
+ parsed = self.parse_ws_trade(data)
929
+ self.myTrades.append(parsed)
930
+ messageHash = 'myTrades'
931
+ client.resolve(self.myTrades, messageHash)
932
+ symbolSpecificMessageHash = messageHash + ':' + parsed['symbol']
933
+ client.resolve(self.myTrades, symbolSpecificMessageHash)
934
+
935
+ def parse_ws_trade(self, trade, market=None):
936
+ #
937
+ # {
938
+ # "fee": 0.00262148,
939
+ # "feeCurrency": "USDT",
940
+ # "feeRate": 0.001,
941
+ # "orderId": "62417436b29df8000183df2f",
942
+ # "orderType": "market",
943
+ # "price": 131.074,
944
+ # "side": "sell",
945
+ # "size": 0.02,
946
+ # "symbol": "LTC-USDT",
947
+ # "time": "1648456758734571745",
948
+ # "tradeId": "624174362e113d2f467b3043"
949
+ # }
950
+ #
951
+ marketId = self.safe_string(trade, 'symbol')
952
+ market = self.safe_market(marketId, market, '-')
953
+ symbol = market['symbol']
954
+ type = self.safe_string(trade, 'orderType')
955
+ side = self.safe_string(trade, 'side')
956
+ tradeId = self.safe_string(trade, 'tradeId')
957
+ price = self.safe_string(trade, 'price')
958
+ amount = self.safe_string(trade, 'size')
959
+ order = self.safe_string(trade, 'orderId')
960
+ timestamp = self.safe_integer_product(trade, 'time', 0.000001)
961
+ feeCurrency = market['quote']
962
+ feeRate = self.safe_string(trade, 'feeRate')
963
+ feeCost = self.safe_string(trade, 'fee')
964
+ fee = {
965
+ 'cost': feeCost,
966
+ 'rate': feeRate,
967
+ 'currency': feeCurrency,
968
+ }
969
+ return self.safe_trade({
970
+ 'info': trade,
971
+ 'timestamp': timestamp,
972
+ 'datetime': self.iso8601(timestamp),
973
+ 'symbol': symbol,
974
+ 'id': tradeId,
975
+ 'order': order,
976
+ 'type': type,
977
+ 'takerOrMaker': None,
978
+ 'side': side,
979
+ 'price': price,
980
+ 'amount': amount,
981
+ 'cost': None,
982
+ 'fee': fee,
983
+ }, market)
984
+
985
+ async def watch_balance(self, params={}) -> Balances:
986
+ """
987
+ watch balance and get the amount of funds available for trading or funds locked in orders
988
+ :param dict [params]: extra parameters specific to the exchange API endpoint
989
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
990
+ """
991
+ await self.load_markets()
992
+ url = await self.negotiate(True)
993
+ topic = '/account/balance'
994
+ request: dict = {
995
+ 'privateChannel': True,
996
+ }
997
+ messageHash = 'balance'
998
+ return await self.subscribe(url, messageHash, topic, self.extend(request, params))
999
+
1000
+ def handle_balance(self, client: Client, message):
1001
+ #
1002
+ # {
1003
+ # "id":"6217a451294b030001e3a26a",
1004
+ # "type":"message",
1005
+ # "topic":"/account/balance",
1006
+ # "userId":"6217707c52f97f00012a67db",
1007
+ # "channelType":"private",
1008
+ # "subject":"account.balance",
1009
+ # "data":{
1010
+ # "accountId":"62177fe67810720001db2f18",
1011
+ # "available":"89",
1012
+ # "availableChange":"-30",
1013
+ # "currency":"USDT",
1014
+ # "hold":"0",
1015
+ # "holdChange":"0",
1016
+ # "relationContext":{
1017
+ # },
1018
+ # "relationEvent":"main.transfer",
1019
+ # "relationEventId":"6217a451294b030001e3a26a",
1020
+ # "time":"1645716561816",
1021
+ # "total":"89"
1022
+ # }
1023
+ #
1024
+ data = self.safe_value(message, 'data', {})
1025
+ messageHash = 'balance'
1026
+ currencyId = self.safe_string(data, 'currency')
1027
+ relationEvent = self.safe_string(data, 'relationEvent')
1028
+ requestAccountType = None
1029
+ if relationEvent is not None:
1030
+ relationEventParts = relationEvent.split('.')
1031
+ requestAccountType = self.safe_string(relationEventParts, 0)
1032
+ selectedType = self.safe_string_2(self.options, 'watchBalance', 'defaultType', 'trade') # trade, main, margin or other
1033
+ accountsByType = self.safe_value(self.options, 'accountsByType')
1034
+ uniformType = self.safe_string(accountsByType, requestAccountType, 'trade')
1035
+ if not (uniformType in self.balance):
1036
+ self.balance[uniformType] = {}
1037
+ self.balance[uniformType]['info'] = data
1038
+ timestamp = self.safe_integer(data, 'time')
1039
+ self.balance[uniformType]['timestamp'] = timestamp
1040
+ self.balance[uniformType]['datetime'] = self.iso8601(timestamp)
1041
+ code = self.safe_currency_code(currencyId)
1042
+ account = self.account()
1043
+ account['free'] = self.safe_string(data, 'available')
1044
+ account['used'] = self.safe_string(data, 'hold')
1045
+ account['total'] = self.safe_string(data, 'total')
1046
+ self.balance[uniformType][code] = account
1047
+ self.balance[uniformType] = self.safe_balance(self.balance[uniformType])
1048
+ if uniformType == selectedType:
1049
+ client.resolve(self.balance[uniformType], messageHash)
1050
+
1051
+ def handle_subject(self, client: Client, message):
1052
+ #
1053
+ # {
1054
+ # "type":"message",
1055
+ # "topic":"/market/level2:BTC-USDT",
1056
+ # "subject":"trade.l2update",
1057
+ # "data":{
1058
+ # "sequenceStart":1545896669105,
1059
+ # "sequenceEnd":1545896669106,
1060
+ # "symbol":"BTC-USDT",
1061
+ # "changes": {
1062
+ # "asks": [["6","1","1545896669105"]], # price, size, sequence
1063
+ # "bids": [["4","1","1545896669106"]]
1064
+ # }
1065
+ # }
1066
+ # }
1067
+ #
1068
+ topic = self.safe_string(message, 'topic')
1069
+ if topic == '/market/ticker:all':
1070
+ self.handle_ticker(client, message)
1071
+ return
1072
+ subject = self.safe_string(message, 'subject')
1073
+ methods: dict = {
1074
+ 'level1': self.handle_bid_ask,
1075
+ 'level2': self.handle_order_book,
1076
+ 'trade.l2update': self.handle_order_book,
1077
+ 'trade.ticker': self.handle_ticker,
1078
+ 'trade.snapshot': self.handle_ticker,
1079
+ 'trade.l3match': self.handle_trade,
1080
+ 'trade.candles.update': self.handle_ohlcv,
1081
+ 'account.balance': self.handle_balance,
1082
+ '/spot/tradeFills': self.handle_my_trade,
1083
+ 'orderChange': self.handle_order,
1084
+ 'stopOrder': self.handle_order,
1085
+ }
1086
+ method = self.safe_value(methods, subject)
1087
+ if method is not None:
1088
+ method(client, message)
1089
+
1090
+ def ping(self, client):
1091
+ # kucoin does not support built-in ws protocol-level ping-pong
1092
+ # instead it requires a custom json-based text ping-pong
1093
+ # https://docs.kucoin.com/#ping
1094
+ id = str(self.request_id())
1095
+ return {
1096
+ 'id': id,
1097
+ 'type': 'ping',
1098
+ }
1099
+
1100
+ def handle_pong(self, client: Client, message):
1101
+ client.lastPong = self.milliseconds()
1102
+ # https://docs.kucoin.com/#ping
1103
+
1104
+ def handle_error_message(self, client: Client, message):
1105
+ #
1106
+ # {
1107
+ # "id": "1",
1108
+ # "type": "error",
1109
+ # "code": 415,
1110
+ # "data": "type is not supported"
1111
+ # }
1112
+ #
1113
+ data = self.safe_string(message, 'data', '')
1114
+ if data == 'token is expired':
1115
+ type = 'public'
1116
+ if client.url.find('connectId=private') >= 0:
1117
+ type = 'private'
1118
+ self.options['urls'][type] = None
1119
+ self.handle_errors(None, None, client.url, None, None, data, message, None, None)
1120
+
1121
+ def handle_message(self, client: Client, message):
1122
+ type = self.safe_string(message, 'type')
1123
+ methods: dict = {
1124
+ # 'heartbeat': self.handleHeartbeat,
1125
+ 'welcome': self.handle_system_status,
1126
+ 'ack': self.handle_subscription_status,
1127
+ 'message': self.handle_subject,
1128
+ 'pong': self.handle_pong,
1129
+ 'error': self.handle_error_message,
1130
+ }
1131
+ method = self.safe_value(methods, type)
1132
+ if method is not None:
1133
+ method(client, message)