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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2405 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.tokocrypto import ImplicitAPI
8
+ import hashlib
9
+ import json
10
+ from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
11
+ from typing import List
12
+ from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import PermissionDenied
15
+ from ccxt.base.errors import AccountSuspended
16
+ from ccxt.base.errors import ArgumentsRequired
17
+ from ccxt.base.errors import BadRequest
18
+ from ccxt.base.errors import BadSymbol
19
+ from ccxt.base.errors import MarginModeAlreadySet
20
+ from ccxt.base.errors import BadResponse
21
+ from ccxt.base.errors import InsufficientFunds
22
+ from ccxt.base.errors import InvalidOrder
23
+ from ccxt.base.errors import OrderNotFound
24
+ from ccxt.base.errors import OrderImmediatelyFillable
25
+ from ccxt.base.errors import OrderNotFillable
26
+ from ccxt.base.errors import NotSupported
27
+ from ccxt.base.errors import DDoSProtection
28
+ from ccxt.base.errors import RateLimitExceeded
29
+ from ccxt.base.errors import ExchangeNotAvailable
30
+ from ccxt.base.errors import OnMaintenance
31
+ from ccxt.base.errors import InvalidNonce
32
+ from ccxt.base.errors import RequestTimeout
33
+ from ccxt.base.decimal_to_precision import TRUNCATE
34
+ from ccxt.base.decimal_to_precision import TICK_SIZE
35
+ from ccxt.base.precise import Precise
36
+
37
+
38
+ class tokocrypto(Exchange, ImplicitAPI):
39
+
40
+ def describe(self):
41
+ return self.deep_extend(super(tokocrypto, self).describe(), {
42
+ 'id': 'tokocrypto',
43
+ 'name': 'Tokocrypto',
44
+ 'countries': ['ID'], # Indonesia
45
+ 'certified': False,
46
+ 'pro': False,
47
+ 'version': 'v1',
48
+ # new metainfo interface
49
+ 'has': {
50
+ 'CORS': None,
51
+ 'spot': True,
52
+ 'margin': True,
53
+ 'swap': False,
54
+ 'future': False,
55
+ 'option': False,
56
+ 'addMargin': None,
57
+ 'borrowMargin': None,
58
+ 'cancelAllOrders': False,
59
+ 'cancelOrder': True,
60
+ 'cancelOrders': None,
61
+ 'createDepositAddress': False,
62
+ 'createMarketBuyOrderWithCost': True,
63
+ 'createMarketOrderWithCost': False,
64
+ 'createMarketSellOrderWithCost': False,
65
+ 'createOrder': True,
66
+ 'createReduceOnlyOrder': None,
67
+ 'createStopLimitOrder': True,
68
+ 'createStopMarketOrder': True,
69
+ 'createStopOrder': True,
70
+ 'fetchAccounts': False,
71
+ 'fetchBalance': True,
72
+ 'fetchBidsAsks': True,
73
+ 'fetchBorrowInterest': None,
74
+ 'fetchBorrowRateHistories': None,
75
+ 'fetchBorrowRateHistory': None,
76
+ 'fetchCanceledOrders': False,
77
+ 'fetchClosedOrder': False,
78
+ 'fetchClosedOrders': 'emulated',
79
+ 'fetchCrossBorrowRate': False,
80
+ 'fetchCrossBorrowRates': False,
81
+ 'fetchCurrencies': False,
82
+ 'fetchDeposit': False,
83
+ 'fetchDepositAddress': True,
84
+ 'fetchDepositAddresses': False,
85
+ 'fetchDepositAddressesByNetwork': False,
86
+ 'fetchDeposits': True,
87
+ 'fetchDepositsWithdrawals': False,
88
+ 'fetchFundingHistory': False,
89
+ 'fetchFundingRate': False,
90
+ 'fetchFundingRateHistory': False,
91
+ 'fetchFundingRates': False,
92
+ 'fetchIndexOHLCV': False,
93
+ 'fetchIsolatedBorrowRate': False,
94
+ 'fetchIsolatedBorrowRates': False,
95
+ 'fetchL3OrderBook': False,
96
+ 'fetchLedger': None,
97
+ 'fetchLeverage': False,
98
+ 'fetchLeverageTiers': False,
99
+ 'fetchMarketLeverageTiers': 'emulated',
100
+ 'fetchMarkets': True,
101
+ 'fetchMarkOHLCV': False,
102
+ 'fetchMyTrades': True,
103
+ 'fetchOHLCV': True,
104
+ 'fetchOpenInterestHistory': False,
105
+ 'fetchOpenOrder': False,
106
+ 'fetchOpenOrders': True,
107
+ 'fetchOrder': True,
108
+ 'fetchOrderBook': True,
109
+ 'fetchOrderBooks': False,
110
+ 'fetchOrders': True,
111
+ 'fetchOrderTrades': False,
112
+ 'fetchPosition': False,
113
+ 'fetchPositions': False,
114
+ 'fetchPositionsRisk': False,
115
+ 'fetchPremiumIndexOHLCV': False,
116
+ 'fetchStatus': False,
117
+ 'fetchTicker': False,
118
+ 'fetchTickers': False,
119
+ 'fetchTime': True,
120
+ 'fetchTrades': True,
121
+ 'fetchTradingFee': False,
122
+ 'fetchTradingFees': False,
123
+ 'fetchTradingLimits': False,
124
+ 'fetchTransactionFee': False,
125
+ 'fetchTransactionFees': False,
126
+ 'fetchTransactions': False,
127
+ 'fetchTransfers': False,
128
+ 'fetchWithdrawal': False,
129
+ 'fetchWithdrawals': True,
130
+ 'fetchWithdrawalWhitelist': False,
131
+ 'reduceMargin': False,
132
+ 'repayCrossMargin': False,
133
+ 'repayIsolatedMargin': False,
134
+ 'setLeverage': False,
135
+ 'setMargin': False,
136
+ 'setMarginMode': False,
137
+ 'setPositionMode': False,
138
+ 'signIn': False,
139
+ 'transfer': False,
140
+ 'withdraw': True,
141
+ },
142
+ 'timeframes': {
143
+ '1m': '1m',
144
+ '3m': '3m',
145
+ '5m': '5m',
146
+ '15m': '15m',
147
+ '30m': '30m',
148
+ '1h': '1h',
149
+ '2h': '2h',
150
+ '4h': '4h',
151
+ '6h': '6h',
152
+ '8h': '8h',
153
+ '12h': '12h',
154
+ '1d': '1d',
155
+ '3d': '3d',
156
+ '1w': '1w',
157
+ '1M': '1M',
158
+ },
159
+ 'urls': {
160
+ 'logo': 'https://user-images.githubusercontent.com/1294454/183870484-d3398d0c-f6a1-4cce-91b8-d58792308716.jpg',
161
+ 'api': {
162
+ 'rest': {
163
+ 'public': 'https://www.tokocrypto.com',
164
+ 'binance': 'https://api.binance.com/api/v3',
165
+ 'private': 'https://www.tokocrypto.com',
166
+ },
167
+ },
168
+ 'www': 'https://tokocrypto.com',
169
+ # 'referral': 'https://www.binance.us/?ref=35005074',
170
+ 'doc': 'https://www.tokocrypto.com/apidocs/',
171
+ 'fees': 'https://www.tokocrypto.com/fees/newschedule',
172
+ },
173
+ 'api': {
174
+ 'binance': {
175
+ 'get': {
176
+ 'ping': 1,
177
+ 'time': 1,
178
+ 'depth': {'cost': 1, 'byLimit': [[100, 1], [500, 5], [1000, 10], [5000, 50]]},
179
+ 'trades': 1,
180
+ 'aggTrades': 1,
181
+ 'historicalTrades': 5,
182
+ 'klines': 1,
183
+ 'ticker/24hr': {'cost': 1, 'noSymbol': 40},
184
+ 'ticker/price': {'cost': 1, 'noSymbol': 2},
185
+ 'ticker/bookTicker': {'cost': 1, 'noSymbol': 2},
186
+ 'exchangeInfo': 10,
187
+ },
188
+ 'put': {
189
+ 'userDataStream': 1,
190
+ },
191
+ 'post': {
192
+ 'userDataStream': 1,
193
+ },
194
+ 'delete': {
195
+ 'userDataStream': 1,
196
+ },
197
+ },
198
+ 'public': {
199
+ 'get': {
200
+ 'open/v1/common/time': 1,
201
+ 'open/v1/common/symbols': 1,
202
+ # all the actual symbols are type 1
203
+ 'open/v1/market/depth': 1, # when symbol type is not 1
204
+ 'open/v1/market/trades': 1, # when symbol type is not 1
205
+ 'open/v1/market/agg-trades': 1, # when symbol type is not 1
206
+ 'open/v1/market/klines': 1, # when symbol type is not 1
207
+ },
208
+ },
209
+ 'private': {
210
+ 'get': {
211
+ 'open/v1/orders/detail': 1,
212
+ 'open/v1/orders': 1,
213
+ 'open/v1/account/spot': 1,
214
+ 'open/v1/account/spot/asset': 1,
215
+ 'open/v1/orders/trades': 1,
216
+ 'open/v1/withdraws': 1,
217
+ 'open/v1/deposits': 1,
218
+ 'open/v1/deposits/address': 1,
219
+ },
220
+ 'post': {
221
+ 'open/v1/orders': 1,
222
+ 'open/v1/orders/cancel': 1,
223
+ 'open/v1/orders/oco': 1,
224
+ 'open/v1/withdraws': 1,
225
+ 'open/v1/user-data-stream': 1,
226
+ },
227
+ },
228
+ },
229
+ 'fees': {
230
+ 'trading': {
231
+ 'tierBased': True,
232
+ 'percentage': True,
233
+ 'taker': self.parse_number('0.0075'), # 0.1% trading fee, zero fees for all trading pairs before November 1
234
+ 'maker': self.parse_number('0.0075'), # 0.1% trading fee, zero fees for all trading pairs before November 1
235
+ },
236
+ },
237
+ 'precisionMode': TICK_SIZE,
238
+ 'options': {
239
+ # 'fetchTradesMethod': 'binanceGetTrades', # binanceGetTrades, binanceGetAggTrades
240
+ 'createMarketBuyOrderRequiresPrice': True,
241
+ 'defaultTimeInForce': 'GTC', # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
242
+ # 'defaultType': 'spot', # 'spot', 'future', 'margin', 'delivery'
243
+ 'hasAlreadyAuthenticatedSuccessfully': False,
244
+ 'warnOnFetchOpenOrdersWithoutSymbol': True,
245
+ # 'fetchPositions': 'positionRisk', # or 'account'
246
+ 'recvWindow': 5 * 1000, # 5 sec, binance default
247
+ 'timeDifference': 0, # the difference between system clock and Binance clock
248
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
249
+ 'newOrderRespType': {
250
+ 'market': 'FULL', # 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
251
+ 'limit': 'FULL', # we change it from 'ACK' by default to 'FULL'(returns immediately if limit is not hit)
252
+ },
253
+ 'quoteOrderQty': False, # whether market orders support amounts in quote currency
254
+ 'networks': {
255
+ 'ERC20': 'ETH',
256
+ 'TRC20': 'TRX',
257
+ 'BEP2': 'BNB',
258
+ 'BEP20': 'BSC',
259
+ 'OMNI': 'OMNI',
260
+ 'EOS': 'EOS',
261
+ 'SPL': 'SOL',
262
+ },
263
+ 'reverseNetworks': {
264
+ 'tronscan.org': 'TRC20',
265
+ 'etherscan.io': 'ERC20',
266
+ 'bscscan.com': 'BSC',
267
+ 'explorer.binance.org': 'BEP2',
268
+ 'bithomp.com': 'XRP',
269
+ 'bloks.io': 'EOS',
270
+ 'stellar.expert': 'XLM',
271
+ 'blockchair.com/bitcoin': 'BTC',
272
+ 'blockchair.com/bitcoin-cash': 'BCH',
273
+ 'blockchair.com/ecash': 'XEC',
274
+ 'explorer.litecoin.net': 'LTC',
275
+ 'explorer.avax.network': 'AVAX',
276
+ 'solscan.io': 'SOL',
277
+ 'polkadot.subscan.io': 'DOT',
278
+ 'dashboard.internetcomputer.org': 'ICP',
279
+ 'explorer.chiliz.com': 'CHZ',
280
+ 'cardanoscan.io': 'ADA',
281
+ 'mainnet.theoan.com': 'AION',
282
+ 'algoexplorer.io': 'ALGO',
283
+ 'explorer.ambrosus.com': 'AMB',
284
+ 'viewblock.io/zilliqa': 'ZIL',
285
+ 'viewblock.io/arweave': 'AR',
286
+ 'explorer.ark.io': 'ARK',
287
+ 'atomscan.com': 'ATOM',
288
+ 'www.mintscan.io': 'CTK',
289
+ 'explorer.bitcoindiamond.org': 'BCD',
290
+ 'btgexplorer.com': 'BTG',
291
+ 'bts.ai': 'BTS',
292
+ 'explorer.celo.org': 'CELO',
293
+ 'explorer.nervos.org': 'CKB',
294
+ 'cerebro.cortexlabs.ai': 'CTXC',
295
+ 'chainz.cryptoid.info': 'VIA',
296
+ 'explorer.dcrdata.org': 'DCR',
297
+ 'digiexplorer.info': 'DGB',
298
+ 'dock.subscan.io': 'DOCK',
299
+ 'dogechain.info': 'DOGE',
300
+ 'explorer.elrond.com': 'EGLD',
301
+ 'blockscout.com': 'ETC',
302
+ 'explore-fetchhub.fetch.ai': 'FET',
303
+ 'filfox.info': 'FIL',
304
+ 'fio.bloks.io': 'FIO',
305
+ 'explorer.firo.org': 'FIRO',
306
+ 'neoscan.io': 'NEO',
307
+ 'ftmscan.com': 'FTM',
308
+ 'explorer.gochain.io': 'GO',
309
+ 'block.gxb.io': 'GXS',
310
+ 'hash-hash.info': 'HBAR',
311
+ 'www.hiveblockexplorer.com': 'HIVE',
312
+ 'explorer.helium.com': 'HNT',
313
+ 'tracker.icon.foundation': 'ICX',
314
+ 'www.iostabc.com': 'IOST',
315
+ 'explorer.iota.org': 'IOTA',
316
+ 'iotexscan.io': 'IOTX',
317
+ 'irishub.iobscan.io': 'IRIS',
318
+ 'kava.mintscan.io': 'KAVA',
319
+ 'scope.klaytn.com': 'KLAY',
320
+ 'kmdexplorer.io': 'KMD',
321
+ 'kusama.subscan.io': 'KSM',
322
+ 'explorer.lto.network': 'LTO',
323
+ 'polygonscan.com': 'POLYGON',
324
+ 'explorer.ont.io': 'ONT',
325
+ 'minaexplorer.com': 'MINA',
326
+ 'nanolooker.com': 'NANO',
327
+ 'explorer.nebulas.io': 'NAS',
328
+ 'explorer.nbs.plus': 'NBS',
329
+ 'explorer.nebl.io': 'NEBL',
330
+ 'nulscan.io': 'NULS',
331
+ 'nxscan.com': 'NXS',
332
+ 'explorer.harmony.one': 'ONE',
333
+ 'explorer.poa.network': 'POA',
334
+ 'qtum.info': 'QTUM',
335
+ 'explorer.rsk.co': 'RSK',
336
+ 'www.oasisscan.com': 'ROSE',
337
+ 'ravencoin.network': 'RVN',
338
+ 'sc.tokenview.com': 'SC',
339
+ 'secretnodes.com': 'SCRT',
340
+ 'explorer.skycoin.com': 'SKY',
341
+ 'steemscan.com': 'STEEM',
342
+ 'explorer.stacks.co': 'STX',
343
+ 'www.thetascan.io': 'THETA',
344
+ 'scan.tomochain.com': 'TOMO',
345
+ 'explore.vechain.org': 'VET',
346
+ 'explorer.vite.net': 'VITE',
347
+ 'www.wanscan.org': 'WAN',
348
+ 'wavesexplorer.com': 'WAVES',
349
+ 'wax.eosx.io': 'WAXP',
350
+ 'waltonchain.pro': 'WTC',
351
+ 'chain.nem.ninja': 'XEM',
352
+ 'verge-blockchain.info': 'XVG',
353
+ 'explorer.yoyow.org': 'YOYOW',
354
+ 'explorer.zcha.in': 'ZEC',
355
+ 'explorer.zensystem.io': 'ZEN',
356
+ },
357
+ 'impliedNetworks': {
358
+ 'ETH': {'ERC20': 'ETH'},
359
+ 'TRX': {'TRC20': 'TRX'},
360
+ },
361
+ 'legalMoney': {
362
+ 'MXN': True,
363
+ 'UGX': True,
364
+ 'SEK': True,
365
+ 'CHF': True,
366
+ 'VND': True,
367
+ 'AED': True,
368
+ 'DKK': True,
369
+ 'KZT': True,
370
+ 'HUF': True,
371
+ 'PEN': True,
372
+ 'PHP': True,
373
+ 'USD': True,
374
+ 'TRY': True,
375
+ 'EUR': True,
376
+ 'NGN': True,
377
+ 'PLN': True,
378
+ 'BRL': True,
379
+ 'ZAR': True,
380
+ 'KES': True,
381
+ 'ARS': True,
382
+ 'RUB': True,
383
+ 'AUD': True,
384
+ 'NOK': True,
385
+ 'CZK': True,
386
+ 'GBP': True,
387
+ 'UAH': True,
388
+ 'GHS': True,
389
+ 'HKD': True,
390
+ 'CAD': True,
391
+ 'INR': True,
392
+ 'JPY': True,
393
+ 'NZD': True,
394
+ },
395
+ },
396
+ # https://binance-docs.github.io/apidocs/spot/en/#error-codes-2
397
+ 'exceptions': {
398
+ 'exact': {
399
+ 'System is under maintenance.': OnMaintenance, # {"code":1,"msg":"System is under maintenance."}
400
+ 'System abnormality': ExchangeError, # {"code":-1000,"msg":"System abnormality"}
401
+ 'You are not authorized to execute self request.': PermissionDenied, # {"msg":"You are not authorized to execute self request."}
402
+ 'API key does not exist': AuthenticationError,
403
+ 'Order would trigger immediately.': OrderImmediatelyFillable,
404
+ 'Stop price would trigger immediately.': OrderImmediatelyFillable, # {"code":-2010,"msg":"Stop price would trigger immediately."}
405
+ 'Order would immediately match and take.': OrderImmediatelyFillable, # {"code":-2010,"msg":"Order would immediately match and take."}
406
+ 'Account has insufficient balance for requested action.': InsufficientFunds,
407
+ 'Rest API trading is not enabled.': ExchangeNotAvailable,
408
+ "You don't have permission.": PermissionDenied, # {"msg":"You don't have permission.","success":false}
409
+ 'Market is closed.': ExchangeNotAvailable, # {"code":-1013,"msg":"Market is closed."}
410
+ 'Too many requests. Please try again later.': DDoSProtection, # {"msg":"Too many requests. Please try again later.","success":false}
411
+ 'This action disabled is on self account.': AccountSuspended, # {"code":-2010,"msg":"This action disabled is on self account."}
412
+ '-1000': ExchangeNotAvailable, # {"code":-1000,"msg":"An unknown error occured while processing the request."}
413
+ '-1001': ExchangeNotAvailable, # {"code":-1001,"msg":"'Internal error; unable to process your request. Please try again.'"}
414
+ '-1002': AuthenticationError, # {"code":-1002,"msg":"'You are not authorized to execute self request.'"}
415
+ '-1003': RateLimitExceeded, # {"code":-1003,"msg":"Too much request weight used, current limit is 1200 request weight per 1 MINUTE. Please use the websocket for live updates to avoid polling the API."}
416
+ '-1004': DDoSProtection, # {"code":-1004,"msg":"Server is busy, please wait and try again"}
417
+ '-1005': PermissionDenied, # {"code":-1005,"msg":"No such IP has been white listed"}
418
+ '-1006': BadResponse, # {"code":-1006,"msg":"An unexpected response was received from the message bus. Execution status unknown."}
419
+ '-1007': RequestTimeout, # {"code":-1007,"msg":"Timeout waiting for response from backend server. Send status unknown; execution status unknown."}
420
+ '-1010': BadResponse, # {"code":-1010,"msg":"ERROR_MSG_RECEIVED."}
421
+ '-1011': PermissionDenied, # {"code":-1011,"msg":"This IP cannot access self route."}
422
+ '-1013': InvalidOrder, # {"code":-1013,"msg":"createOrder -> 'invalid quantity'/'invalid price'/MIN_NOTIONAL"}
423
+ '-1014': InvalidOrder, # {"code":-1014,"msg":"Unsupported order combination."}
424
+ '-1015': RateLimitExceeded, # {"code":-1015,"msg":"'Too many new orders; current limit is %s orders per %s.'"}
425
+ '-1016': ExchangeNotAvailable, # {"code":-1016,"msg":"'This service is no longer available.',"}
426
+ '-1020': BadRequest, # {"code":-1020,"msg":"'This operation is not supported.'"}
427
+ '-1021': InvalidNonce, # {"code":-1021,"msg":"'your time is ahead of server'"}
428
+ '-1022': AuthenticationError, # {"code":-1022,"msg":"Signature for self request is not valid."}
429
+ '-1023': BadRequest, # {"code":-1023,"msg":"Start time is greater than end time."}
430
+ '-1099': AuthenticationError, # {"code":-1099,"msg":"Not found, authenticated, or authorized"}
431
+ '-1100': BadRequest, # {"code":-1100,"msg":"createOrder(symbol, 1, asdf) -> 'Illegal characters found in parameter 'price'"}
432
+ '-1101': BadRequest, # {"code":-1101,"msg":"Too many parameters; expected %s and received %s."}
433
+ '-1102': BadRequest, # {"code":-1102,"msg":"Param %s or %s must be sent, but both were empty"}
434
+ '-1103': BadRequest, # {"code":-1103,"msg":"An unknown parameter was sent."}
435
+ '-1104': BadRequest, # {"code":-1104,"msg":"Not all sent parameters were read, read 8 parameters but was sent 9"}
436
+ '-1105': BadRequest, # {"code":-1105,"msg":"Parameter %s was empty."}
437
+ '-1106': BadRequest, # {"code":-1106,"msg":"Parameter %s sent when not required."}
438
+ '-1108': BadRequest, # {"code":-1108,"msg":"Invalid asset."}
439
+ '-1109': AuthenticationError, # {"code":-1109,"msg":"Invalid account."}
440
+ '-1110': BadRequest, # {"code":-1110,"msg":"Invalid symbolType."}
441
+ '-1111': BadRequest, # {"code":-1111,"msg":"Precision is over the maximum defined for self asset."}
442
+ '-1112': InvalidOrder, # {"code":-1112,"msg":"No orders on book for symbol."}
443
+ '-1113': BadRequest, # {"code":-1113,"msg":"Withdrawal amount must be negative."}
444
+ '-1114': BadRequest, # {"code":-1114,"msg":"TimeInForce parameter sent when not required."}
445
+ '-1115': BadRequest, # {"code":-1115,"msg":"Invalid timeInForce."}
446
+ '-1116': BadRequest, # {"code":-1116,"msg":"Invalid orderType."}
447
+ '-1117': BadRequest, # {"code":-1117,"msg":"Invalid side."}
448
+ '-1118': BadRequest, # {"code":-1118,"msg":"New client order ID was empty."}
449
+ '-1119': BadRequest, # {"code":-1119,"msg":"Original client order ID was empty."}
450
+ '-1120': BadRequest, # {"code":-1120,"msg":"Invalid interval."}
451
+ '-1121': BadSymbol, # {"code":-1121,"msg":"Invalid symbol."}
452
+ '-1125': AuthenticationError, # {"code":-1125,"msg":"This listenKey does not exist."}
453
+ '-1127': BadRequest, # {"code":-1127,"msg":"More than %s hours between startTime and endTime."}
454
+ '-1128': BadRequest, # {"code":-1128,"msg":"{"code":-1128,"msg":"Combination of optional parameters invalid."}"}
455
+ '-1130': BadRequest, # {"code":-1130,"msg":"Data sent for paramter %s is not valid."}
456
+ '-1131': BadRequest, # {"code":-1131,"msg":"recvWindow must be less than 60000"}
457
+ '-1136': BadRequest, # {"code":-1136,"msg":"Invalid newOrderRespType"}
458
+ '-2008': AuthenticationError, # {"code":-2008,"msg":"Invalid Api-Key ID."}
459
+ '-2010': ExchangeError, # {"code":-2010,"msg":"generic error code for createOrder -> 'Account has insufficient balance for requested action.', {"code":-2010,"msg":"Rest API trading is not enabled."}, etc..."}
460
+ '-2011': OrderNotFound, # {"code":-2011,"msg":"cancelOrder(1, 'BTC/USDT') -> 'UNKNOWN_ORDER'"}
461
+ '-2013': OrderNotFound, # {"code":-2013,"msg":"fetchOrder(1, 'BTC/USDT') -> 'Order does not exist'"}
462
+ '-2014': AuthenticationError, # {"code":-2014,"msg":"API-key format invalid."}
463
+ '-2015': AuthenticationError, # {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
464
+ '-2016': BadRequest, # {"code":-2016,"msg":"No trading window could be found for the symbol. Try ticker/24hrs instead."}
465
+ '-2018': InsufficientFunds, # {"code":-2018,"msg":"Balance is insufficient"}
466
+ '-2019': InsufficientFunds, # {"code":-2019,"msg":"Margin is insufficient."}
467
+ '-2020': OrderNotFillable, # {"code":-2020,"msg":"Unable to fill."}
468
+ '-2021': OrderImmediatelyFillable, # {"code":-2021,"msg":"Order would immediately trigger."}
469
+ '-2022': InvalidOrder, # {"code":-2022,"msg":"ReduceOnly Order is rejected."}
470
+ '-2023': InsufficientFunds, # {"code":-2023,"msg":"User in liquidation mode now."}
471
+ '-2024': InsufficientFunds, # {"code":-2024,"msg":"Position is not sufficient."}
472
+ '-2025': InvalidOrder, # {"code":-2025,"msg":"Reach max open order limit."}
473
+ '-2026': InvalidOrder, # {"code":-2026,"msg":"This OrderType is not supported when reduceOnly."}
474
+ '-2027': InvalidOrder, # {"code":-2027,"msg":"Exceeded the maximum allowable position at current leverage."}
475
+ '-2028': InsufficientFunds, # {"code":-2028,"msg":"Leverage is smaller than permitted: insufficient margin balance"}
476
+ '-3000': ExchangeError, # {"code":-3000,"msg":"Internal server error."}
477
+ '-3001': AuthenticationError, # {"code":-3001,"msg":"Please enable 2FA first."}
478
+ '-3002': BadSymbol, # {"code":-3002,"msg":"We don't have self asset."}
479
+ '-3003': BadRequest, # {"code":-3003,"msg":"Margin account does not exist."}
480
+ '-3004': ExchangeError, # {"code":-3004,"msg":"Trade not allowed."}
481
+ '-3005': InsufficientFunds, # {"code":-3005,"msg":"Transferring out not allowed. Transfer out amount exceeds max amount."}
482
+ '-3006': InsufficientFunds, # {"code":-3006,"msg":"Your borrow amount has exceed maximum borrow amount."}
483
+ '-3007': ExchangeError, # {"code":-3007,"msg":"You have pending transaction, please try again later.."}
484
+ '-3008': InsufficientFunds, # {"code":-3008,"msg":"Borrow not allowed. Your borrow amount has exceed maximum borrow amount."}
485
+ '-3009': BadRequest, # {"code":-3009,"msg":"This asset are not allowed to transfer into margin account currently."}
486
+ '-3010': ExchangeError, # {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."}
487
+ '-3011': BadRequest, # {"code":-3011,"msg":"Your input date is invalid."}
488
+ '-3012': ExchangeError, # {"code":-3012,"msg":"Borrow is banned for self asset."}
489
+ '-3013': BadRequest, # {"code":-3013,"msg":"Borrow amount less than minimum borrow amount."}
490
+ '-3014': AccountSuspended, # {"code":-3014,"msg":"Borrow is banned for self account."}
491
+ '-3015': ExchangeError, # {"code":-3015,"msg":"Repay amount exceeds borrow amount."}
492
+ '-3016': BadRequest, # {"code":-3016,"msg":"Repay amount less than minimum repay amount."}
493
+ '-3017': ExchangeError, # {"code":-3017,"msg":"This asset are not allowed to transfer into margin account currently."}
494
+ '-3018': AccountSuspended, # {"code":-3018,"msg":"Transferring in has been banned for self account."}
495
+ '-3019': AccountSuspended, # {"code":-3019,"msg":"Transferring out has been banned for self account."}
496
+ '-3020': InsufficientFunds, # {"code":-3020,"msg":"Transfer out amount exceeds max amount."}
497
+ '-3021': BadRequest, # {"code":-3021,"msg":"Margin account are not allowed to trade self trading pair."}
498
+ '-3022': AccountSuspended, # {"code":-3022,"msg":"You account's trading is banned."}
499
+ '-3023': BadRequest, # {"code":-3023,"msg":"You can't transfer out/place order under current margin level."}
500
+ '-3024': ExchangeError, # {"code":-3024,"msg":"The unpaid debt is too small after self repayment."}
501
+ '-3025': BadRequest, # {"code":-3025,"msg":"Your input date is invalid."}
502
+ '-3026': BadRequest, # {"code":-3026,"msg":"Your input param is invalid."}
503
+ '-3027': BadSymbol, # {"code":-3027,"msg":"Not a valid margin asset."}
504
+ '-3028': BadSymbol, # {"code":-3028,"msg":"Not a valid margin pair."}
505
+ '-3029': ExchangeError, # {"code":-3029,"msg":"Transfer failed."}
506
+ '-3036': AccountSuspended, # {"code":-3036,"msg":"This account is not allowed to repay."}
507
+ '-3037': ExchangeError, # {"code":-3037,"msg":"PNL is clearing. Wait a second."}
508
+ '-3038': BadRequest, # {"code":-3038,"msg":"Listen key not found."}
509
+ '-3041': InsufficientFunds, # {"code":-3041,"msg":"Balance is not enough"}
510
+ '-3042': BadRequest, # {"code":-3042,"msg":"PriceIndex not available for self margin pair."}
511
+ '-3043': BadRequest, # {"code":-3043,"msg":"Transferring in not allowed."}
512
+ '-3044': DDoSProtection, # {"code":-3044,"msg":"System busy."}
513
+ '-3045': ExchangeError, # {"code":-3045,"msg":"The system doesn't have enough asset now."}
514
+ '-3999': ExchangeError, # {"code":-3999,"msg":"This function is only available for invited users."}
515
+ '-4001': BadRequest, # {"code":-4001 ,"msg":"Invalid operation."}
516
+ '-4002': BadRequest, # {"code":-4002 ,"msg":"Invalid get."}
517
+ '-4003': BadRequest, # {"code":-4003 ,"msg":"Your input email is invalid."}
518
+ '-4004': AuthenticationError, # {"code":-4004,"msg":"You don't login or auth."}
519
+ '-4005': RateLimitExceeded, # {"code":-4005 ,"msg":"Too many new requests."}
520
+ '-4006': BadRequest, # {"code":-4006 ,"msg":"Support main account only."}
521
+ '-4007': BadRequest, # {"code":-4007 ,"msg":"Address validation is not passed."}
522
+ '-4008': BadRequest, # {"code":-4008 ,"msg":"Address tag validation is not passed."}
523
+ '-4010': BadRequest, # {"code":-4010 ,"msg":"White list mail has been confirmed."} # [TODO] possible bug: it should probably be "has not been confirmed"
524
+ '-4011': BadRequest, # {"code":-4011 ,"msg":"White list mail is invalid."}
525
+ '-4012': BadRequest, # {"code":-4012 ,"msg":"White list is not opened."}
526
+ '-4013': AuthenticationError, # {"code":-4013 ,"msg":"2FA is not opened."}
527
+ '-4014': PermissionDenied, # {"code":-4014 ,"msg":"Withdraw is not allowed within 2 min login."}
528
+ '-4015': ExchangeError, # {"code":-4015 ,"msg":"Withdraw is limited."}
529
+ '-4016': PermissionDenied, # {"code":-4016 ,"msg":"Within 24 hours after password modification, withdrawal is prohibited."}
530
+ '-4017': PermissionDenied, # {"code":-4017 ,"msg":"Within 24 hours after the release of 2FA, withdrawal is prohibited."}
531
+ '-4018': BadSymbol, # {"code":-4018,"msg":"We don't have self asset."}
532
+ '-4019': BadSymbol, # {"code":-4019,"msg":"Current asset is not open for withdrawal."}
533
+ '-4021': BadRequest, # {"code":-4021,"msg":"Asset withdrawal must be an %s multiple of %s."}
534
+ '-4022': BadRequest, # {"code":-4022,"msg":"Not less than the minimum pick-up quantity %s."}
535
+ '-4023': ExchangeError, # {"code":-4023,"msg":"Within 24 hours, the withdrawal exceeds the maximum amount."}
536
+ '-4024': InsufficientFunds, # {"code":-4024,"msg":"You don't have self asset."}
537
+ '-4025': InsufficientFunds, # {"code":-4025,"msg":"The number of hold asset is less than zero."}
538
+ '-4026': InsufficientFunds, # {"code":-4026,"msg":"You have insufficient balance."}
539
+ '-4027': ExchangeError, # {"code":-4027,"msg":"Failed to obtain tranId."}
540
+ '-4028': BadRequest, # {"code":-4028,"msg":"The amount of withdrawal must be greater than the Commission."}
541
+ '-4029': BadRequest, # {"code":-4029,"msg":"The withdrawal record does not exist."}
542
+ '-4030': ExchangeError, # {"code":-4030,"msg":"Confirmation of successful asset withdrawal. [TODO] possible bug in docs"}
543
+ '-4031': ExchangeError, # {"code":-4031,"msg":"Cancellation failed."}
544
+ '-4032': ExchangeError, # {"code":-4032,"msg":"Withdraw verification exception."}
545
+ '-4033': BadRequest, # {"code":-4033,"msg":"Illegal address."}
546
+ '-4034': ExchangeError, # {"code":-4034,"msg":"The address is suspected of fake."}
547
+ '-4035': PermissionDenied, # {"code":-4035,"msg":"This address is not on the whitelist. Please join and try again."}
548
+ '-4036': BadRequest, # {"code":-4036,"msg":"The new address needs to be withdrawn in {0} hours."}
549
+ '-4037': ExchangeError, # {"code":-4037,"msg":"Re-sending Mail failed."}
550
+ '-4038': ExchangeError, # {"code":-4038,"msg":"Please try again in 5 minutes."}
551
+ '-4039': BadRequest, # {"code":-4039,"msg":"The user does not exist."}
552
+ '-4040': BadRequest, # {"code":-4040,"msg":"This address not charged."}
553
+ '-4041': ExchangeError, # {"code":-4041,"msg":"Please try again in one minute."}
554
+ '-4042': ExchangeError, # {"code":-4042,"msg":"This asset cannot get deposit address again."}
555
+ '-4043': BadRequest, # {"code":-4043,"msg":"More than 100 recharge addresses were used in 24 hours."}
556
+ '-4044': BadRequest, # {"code":-4044,"msg":"This is a blacklist country."}
557
+ '-4045': ExchangeError, # {"code":-4045,"msg":"Failure to acquire assets."}
558
+ '-4046': AuthenticationError, # {"code":-4046,"msg":"Agreement not confirmed."}
559
+ '-4047': BadRequest, # {"code":-4047,"msg":"Time interval must be within 0-90 days"}
560
+ '-5001': BadRequest, # {"code":-5001,"msg":"Don't allow transfer to micro assets."}
561
+ '-5002': InsufficientFunds, # {"code":-5002,"msg":"You have insufficient balance."}
562
+ '-5003': InsufficientFunds, # {"code":-5003,"msg":"You don't have self asset."}
563
+ '-5004': BadRequest, # {"code":-5004,"msg":"The residual balances of %s have exceeded 0.001BTC, Please re-choose."}
564
+ '-5005': InsufficientFunds, # {"code":-5005,"msg":"The residual balances of %s is too low, Please re-choose."}
565
+ '-5006': BadRequest, # {"code":-5006,"msg":"Only transfer once in 24 hours."}
566
+ '-5007': BadRequest, # {"code":-5007,"msg":"Quantity must be greater than zero."}
567
+ '-5008': InsufficientFunds, # {"code":-5008,"msg":"Insufficient amount of returnable assets."}
568
+ '-5009': BadRequest, # {"code":-5009,"msg":"Product does not exist."}
569
+ '-5010': ExchangeError, # {"code":-5010,"msg":"Asset transfer fail."}
570
+ '-5011': BadRequest, # {"code":-5011,"msg":"future account not exists."}
571
+ '-5012': ExchangeError, # {"code":-5012,"msg":"Asset transfer is in pending."}
572
+ '-5013': InsufficientFunds, # {"code":-5013,"msg":"Asset transfer failed: insufficient balance""} # undocumented
573
+ '-5021': BadRequest, # {"code":-5021,"msg":"This parent sub have no relation"}
574
+ '-6001': BadRequest, # {"code":-6001,"msg":"Daily product not exists."}
575
+ '-6003': BadRequest, # {"code":-6003,"msg":"Product not exist or you don't have permission"}
576
+ '-6004': ExchangeError, # {"code":-6004,"msg":"Product not in purchase status"}
577
+ '-6005': InvalidOrder, # {"code":-6005,"msg":"Smaller than min purchase limit"}
578
+ '-6006': BadRequest, # {"code":-6006,"msg":"Redeem amount error"}
579
+ '-6007': BadRequest, # {"code":-6007,"msg":"Not in redeem time"}
580
+ '-6008': BadRequest, # {"code":-6008,"msg":"Product not in redeem status"}
581
+ '-6009': RateLimitExceeded, # {"code":-6009,"msg":"Request frequency too high"}
582
+ '-6011': BadRequest, # {"code":-6011,"msg":"Exceeding the maximum num allowed to purchase per user"}
583
+ '-6012': InsufficientFunds, # {"code":-6012,"msg":"Balance not enough"}
584
+ '-6013': ExchangeError, # {"code":-6013,"msg":"Purchasing failed"}
585
+ '-6014': BadRequest, # {"code":-6014,"msg":"Exceed up-limit allowed to purchased"}
586
+ '-6015': BadRequest, # {"code":-6015,"msg":"Empty request body"}
587
+ '-6016': BadRequest, # {"code":-6016,"msg":"Parameter err"}
588
+ '-6017': BadRequest, # {"code":-6017,"msg":"Not in whitelist"}
589
+ '-6018': BadRequest, # {"code":-6018,"msg":"Asset not enough"}
590
+ '-6019': AuthenticationError, # {"code":-6019,"msg":"Need confirm"}
591
+ '-6020': BadRequest, # {"code":-6020,"msg":"Project not exists"}
592
+ '-7001': BadRequest, # {"code":-7001,"msg":"Date range is not supported."}
593
+ '-7002': BadRequest, # {"code":-7002,"msg":"Data request type is not supported."}
594
+ '-9000': InsufficientFunds, # {"code":-9000,"msg":"user have no avaliable amount"}"
595
+ '-10017': BadRequest, # {"code":-10017,"msg":"Repay amount should not be larger than liability."}
596
+ '-11008': InsufficientFunds, # {"code":-11008,"msg":"Exceeding the account's maximum borrowable limit."} # undocumented
597
+ '-12014': RateLimitExceeded, # {"code":-12014,"msg":"More than 1 request in 3 seconds"}
598
+ '-13000': BadRequest, # {"code":-13000,"msg":"Redeption of the token is forbiden now"}
599
+ '-13001': BadRequest, # {"code":-13001,"msg":"Exceeds individual 24h redemption limit of the token"}
600
+ '-13002': BadRequest, # {"code":-13002,"msg":"Exceeds total 24h redemption limit of the token"}
601
+ '-13003': BadRequest, # {"code":-13003,"msg":"Subscription of the token is forbiden now"}
602
+ '-13004': BadRequest, # {"code":-13004,"msg":"Exceeds individual 24h subscription limit of the token"}
603
+ '-13005': BadRequest, # {"code":-13005,"msg":"Exceeds total 24h subscription limit of the token"}
604
+ '-13006': InvalidOrder, # {"code":-13006,"msg":"Subscription amount is too small"}
605
+ '-13007': AuthenticationError, # {"code":-13007,"msg":"The Agreement is not signed"}
606
+ '-21001': BadRequest, # {"code":-21001,"msg":"USER_IS_NOT_UNIACCOUNT"}
607
+ '-21002': BadRequest, # {"code":-21002,"msg":"UNI_ACCOUNT_CANT_TRANSFER_FUTURE"}
608
+ '-21003': BadRequest, # {"code":-21003,"msg":"NET_ASSET_MUST_LTE_RATIO"}
609
+ '100001003': BadRequest, # {"code":100001003,"msg":"Verification failed"} # undocumented
610
+ '2202': InsufficientFunds, # {"code":2202,"msg":"Insufficient balance","data":{"code":-2010,"msg":"Account has insufficient balance for requested action."},"timestamp":1662733681161}
611
+ '3210': InvalidOrder, # {"code":3210,"msg":"The total volume is too low","data":{"code":-1013,"msg":"Filter failure: MIN_NOTIONAL"},"timestamp":1662734704462}
612
+ '3203': InvalidOrder, # {"code":3203,"msg":"Incorrect Order Quantity","timestamp":1662734809758}
613
+ '3211': InvalidOrder, # {"code":3211,"msg":"The total volume must be greater than 10","timestamp":1662739358179}
614
+ '3207': InvalidOrder, # {"code":3207,"msg":"The price cannot be lower than 12.18","timestamp":1662739502856}
615
+ '3218': OrderNotFound, # {"code":3218,"msg":"Order does not exist","timestamp":1662739749275}
616
+ },
617
+ 'broad': {
618
+ 'has no operation privilege': PermissionDenied,
619
+ 'MAX_POSITION': InvalidOrder, # {"code":-2010,"msg":"Filter failure: MAX_POSITION"}
620
+ },
621
+ },
622
+ })
623
+
624
+ def nonce(self):
625
+ return self.milliseconds() - self.options['timeDifference']
626
+
627
+ async def fetch_time(self, params={}):
628
+ """
629
+ :see: https://www.tokocrypto.com/apidocs/#check-server-time
630
+ fetches the current integer timestamp in milliseconds from the exchange server
631
+ :param dict [params]: extra parameters specific to the exchange API endpoint
632
+ :returns int: the current integer timestamp in milliseconds from the exchange server
633
+ """
634
+ response = await self.publicGetOpenV1CommonTime(params)
635
+ #
636
+ #
637
+ #
638
+ return self.safe_integer(response, 'serverTime')
639
+
640
+ async def fetch_markets(self, params={}) -> List[Market]:
641
+ """
642
+ :see: https://www.tokocrypto.com/apidocs/#get-all-supported-trading-symbol
643
+ retrieves data on all markets for tokocrypto
644
+ :param dict [params]: extra parameters specific to the exchange API endpoint
645
+ :returns dict[]: an array of objects representing market data
646
+ """
647
+ response = await self.publicGetOpenV1CommonSymbols(params)
648
+ #
649
+ # {
650
+ # "code":0,
651
+ # "msg":"Success",
652
+ # "data":{
653
+ # "list":[
654
+ # {
655
+ # "type":1,
656
+ # "symbol":"1INCH_BTC",
657
+ # "baseAsset":"1INCH",
658
+ # "basePrecision":8,
659
+ # "quoteAsset":"BTC",
660
+ # "quotePrecision":8,
661
+ # "filters":[
662
+ # {"filterType":"PRICE_FILTER","minPrice":"0.00000001","maxPrice":"1000.00000000","tickSize":"0.00000001","applyToMarket":false},
663
+ # {"filterType":"PERCENT_PRICE","multiplierUp":5,"multiplierDown":0.2,"avgPriceMins":"5","applyToMarket":false},
664
+ # {"filterType":"LOT_SIZE","minQty":"0.10000000","maxQty":"90000000.00000000","stepSize":"0.10000000","applyToMarket":false},
665
+ # {"filterType":"MIN_NOTIONAL","avgPriceMins":"5","minNotional":"0.00010000","applyToMarket":true},
666
+ # {"filterType":"ICEBERG_PARTS","applyToMarket":false,"limit":"10"},
667
+ # {"filterType":"MARKET_LOT_SIZE","minQty":"0.00000000","maxQty":"79460.14117231","stepSize":"0.00000000","applyToMarket":false},
668
+ # {"filterType":"TRAILING_DELTA","applyToMarket":false},
669
+ # {"filterType":"MAX_NUM_ORDERS","applyToMarket":false},
670
+ # {"filterType":"MAX_NUM_ALGO_ORDERS","applyToMarket":false,"maxNumAlgoOrders":"5"}
671
+ # ],
672
+ # "orderTypes":["LIMIT","LIMIT_MAKER","MARKET","STOP_LOSS_LIMIT","TAKE_PROFIT_LIMIT"],
673
+ # "icebergEnable":1,
674
+ # "ocoEnable":1,
675
+ # "spotTradingEnable":1,
676
+ # "marginTradingEnable":1,
677
+ # "permissions":["SPOT","MARGIN"]
678
+ # },
679
+ # ]
680
+ # },
681
+ # "timestamp":1659492212507
682
+ # }
683
+ #
684
+ if self.options['adjustForTimeDifference']:
685
+ await self.load_time_difference()
686
+ data = self.safe_value(response, 'data', {})
687
+ list = self.safe_value(data, 'list', [])
688
+ result = []
689
+ for i in range(0, len(list)):
690
+ market = list[i]
691
+ baseId = self.safe_string(market, 'baseAsset')
692
+ quoteId = self.safe_string(market, 'quoteAsset')
693
+ id = self.safe_string(market, 'symbol')
694
+ lowercaseId = self.safe_string_lower(market, 'symbol')
695
+ settleId = self.safe_string(market, 'marginAsset')
696
+ base = self.safe_currency_code(baseId)
697
+ quote = self.safe_currency_code(quoteId)
698
+ settle = self.safe_currency_code(settleId)
699
+ symbol = base + '/' + quote
700
+ filters = self.safe_value(market, 'filters', [])
701
+ filtersByType = self.index_by(filters, 'filterType')
702
+ status = self.safe_string(market, 'spotTradingEnable')
703
+ active = (status == '1')
704
+ permissions = self.safe_value(market, 'permissions', [])
705
+ for j in range(0, len(permissions)):
706
+ if permissions[j] == 'TRD_GRP_003':
707
+ active = False
708
+ break
709
+ isMarginTradingAllowed = self.safe_bool(market, 'isMarginTradingAllowed', False)
710
+ entry: dict = {
711
+ 'id': id,
712
+ 'lowercaseId': lowercaseId,
713
+ 'symbol': symbol,
714
+ 'base': base,
715
+ 'quote': quote,
716
+ 'settle': settle,
717
+ 'baseId': baseId,
718
+ 'quoteId': quoteId,
719
+ 'settleId': settleId,
720
+ 'type': 'spot',
721
+ 'spot': True,
722
+ 'margin': isMarginTradingAllowed,
723
+ 'swap': False,
724
+ 'future': False,
725
+ 'delivery': False,
726
+ 'option': False,
727
+ 'active': active,
728
+ 'contract': False,
729
+ 'linear': None,
730
+ 'inverse': None,
731
+ 'contractSize': None,
732
+ 'expiry': None,
733
+ 'expiryDatetime': None,
734
+ 'strike': None,
735
+ 'optionType': None,
736
+ 'precision': {
737
+ 'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'quantityPrecision'))),
738
+ 'price': self.parse_number(self.parse_precision(self.safe_string(market, 'pricePrecision'))),
739
+ 'base': self.parse_number(self.parse_precision(self.safe_string(market, 'baseAssetPrecision'))),
740
+ 'quote': self.parse_number(self.parse_precision(self.safe_string(market, 'quotePrecision'))),
741
+ },
742
+ 'limits': {
743
+ 'leverage': {
744
+ 'min': None,
745
+ 'max': None,
746
+ },
747
+ 'amount': {
748
+ 'min': None,
749
+ 'max': None,
750
+ },
751
+ 'price': {
752
+ 'min': None,
753
+ 'max': None,
754
+ },
755
+ 'cost': {
756
+ 'min': None,
757
+ 'max': None,
758
+ },
759
+ },
760
+ 'created': None,
761
+ 'info': market,
762
+ }
763
+ if 'PRICE_FILTER' in filtersByType:
764
+ filter = self.safe_value(filtersByType, 'PRICE_FILTER', {})
765
+ entry['precision']['price'] = self.safe_number(filter, 'tickSize')
766
+ # PRICE_FILTER reports zero values for maxPrice
767
+ # since they updated filter types in November 2018
768
+ # https://github.com/ccxt/ccxt/issues/4286
769
+ # therefore limits['price']['max'] doesn't have any meaningful value except None
770
+ entry['limits']['price'] = {
771
+ 'min': self.safe_number(filter, 'minPrice'),
772
+ 'max': self.safe_number(filter, 'maxPrice'),
773
+ }
774
+ entry['precision']['price'] = filter['tickSize']
775
+ if 'LOT_SIZE' in filtersByType:
776
+ filter = self.safe_value(filtersByType, 'LOT_SIZE', {})
777
+ entry['precision']['amount'] = self.safe_number(filter, 'stepSize')
778
+ entry['limits']['amount'] = {
779
+ 'min': self.safe_number(filter, 'minQty'),
780
+ 'max': self.safe_number(filter, 'maxQty'),
781
+ }
782
+ if 'MARKET_LOT_SIZE' in filtersByType:
783
+ filter = self.safe_value(filtersByType, 'MARKET_LOT_SIZE', {})
784
+ entry['limits']['market'] = {
785
+ 'min': self.safe_number(filter, 'minQty'),
786
+ 'max': self.safe_number(filter, 'maxQty'),
787
+ }
788
+ if 'MIN_NOTIONAL' in filtersByType:
789
+ filter = self.safe_value(filtersByType, 'MIN_NOTIONAL', {})
790
+ entry['limits']['cost']['min'] = self.safe_number_2(filter, 'minNotional', 'notional')
791
+ result.append(entry)
792
+ return result
793
+
794
+ async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
795
+ """
796
+ :see: https://www.tokocrypto.com/apidocs/#order-book
797
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
798
+ :param str symbol: unified symbol of the market to fetch the order book for
799
+ :param int [limit]: the maximum amount of order book entries to return
800
+ :param dict [params]: extra parameters specific to the exchange API endpoint
801
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
802
+ """
803
+ await self.load_markets()
804
+ market = self.market(symbol)
805
+ request: dict = {}
806
+ if limit is not None:
807
+ request['limit'] = limit # default 100, max 5000, see https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#order-book
808
+ response = None
809
+ if market['quote'] == 'USDT':
810
+ request['symbol'] = market['baseId'] + market['quoteId']
811
+ response = await self.binanceGetDepth(self.extend(request, params))
812
+ else:
813
+ request['symbol'] = market['id']
814
+ response = await self.publicGetOpenV1MarketDepth(self.extend(request, params))
815
+ #
816
+ # future
817
+ #
818
+ # {
819
+ # "lastUpdateId":333598053905,
820
+ # "E":1618631511986,
821
+ # "T":1618631511964,
822
+ # "bids":[
823
+ # ["2493.56","20.189"],
824
+ # ["2493.54","1.000"],
825
+ # ["2493.51","0.005"]
826
+ # ],
827
+ # "asks":[
828
+ # ["2493.57","0.877"],
829
+ # ["2493.62","0.063"],
830
+ # ["2493.71","12.054"],
831
+ # ]
832
+ # }
833
+ # type not 1
834
+ # {
835
+ # "code":0,
836
+ # "msg":"Success",
837
+ # "data":{
838
+ # "lastUpdateId":3204783,
839
+ # "bids":[],
840
+ # "asks": []
841
+ # },
842
+ # "timestamp":1692262634599
843
+ # }
844
+ data = self.safe_value(response, 'data', response)
845
+ timestamp = self.safe_integer_2(response, 'T', 'timestamp')
846
+ orderbook = self.parse_order_book(data, symbol, timestamp)
847
+ orderbook['nonce'] = self.safe_integer(data, 'lastUpdateId')
848
+ return orderbook
849
+
850
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
851
+ #
852
+ # aggregate trades
853
+ # https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
854
+ #
855
+ # {
856
+ # "a": 26129, # Aggregate tradeId
857
+ # "p": "0.01633102", # Price
858
+ # "q": "4.70443515", # Quantity
859
+ # "f": 27781, # First tradeId
860
+ # "l": 27781, # Last tradeId
861
+ # "T": 1498793709153, # Timestamp
862
+ # "m": True, # Was the buyer the maker?
863
+ # "M": True # Was the trade the best price match?
864
+ # }
865
+ #
866
+ # recent public trades and old public trades
867
+ # https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#recent-trades-list
868
+ # https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#old-trade-lookup-market_data
869
+ #
870
+ # {
871
+ # "id": 28457,
872
+ # "price": "4.00000100",
873
+ # "qty": "12.00000000",
874
+ # "time": 1499865549590,
875
+ # "isBuyerMaker": True,
876
+ # "isBestMatch": True
877
+ # }
878
+ #
879
+ # private trades
880
+ # https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#account-trade-list-user_data
881
+ #
882
+ # {
883
+ # "symbol": "BNBBTC",
884
+ # "id": 28457,
885
+ # "orderId": 100234,
886
+ # "price": "4.00000100",
887
+ # "qty": "12.00000000",
888
+ # "commission": "10.10000000",
889
+ # "commissionAsset": "BNB",
890
+ # "time": 1499865549590,
891
+ # "isBuyer": True,
892
+ # "isMaker": False,
893
+ # "isBestMatch": True
894
+ # }
895
+ #
896
+ # futures trades
897
+ # https://binance-docs.github.io/apidocs/futures/en/#account-trade-list-user_data
898
+ #
899
+ # {
900
+ # "accountId": 20,
901
+ # "buyer": False,
902
+ # "commission": "-0.07819010",
903
+ # "commissionAsset": "USDT",
904
+ # "counterPartyId": 653,
905
+ # "id": 698759,
906
+ # "maker": False,
907
+ # "orderId": 25851813,
908
+ # "price": "7819.01",
909
+ # "qty": "0.002",
910
+ # "quoteQty": "0.01563",
911
+ # "realizedPnl": "-0.91539999",
912
+ # "side": "SELL",
913
+ # "symbol": "BTCUSDT",
914
+ # "time": 1569514978020
915
+ # }
916
+ # {
917
+ # "symbol": "BTCUSDT",
918
+ # "id": 477128891,
919
+ # "orderId": 13809777875,
920
+ # "side": "SELL",
921
+ # "price": "38479.55",
922
+ # "qty": "0.001",
923
+ # "realizedPnl": "-0.00009534",
924
+ # "marginAsset": "USDT",
925
+ # "quoteQty": "38.47955",
926
+ # "commission": "-0.00076959",
927
+ # "commissionAsset": "USDT",
928
+ # "time": 1612733566708,
929
+ # "positionSide": "BOTH",
930
+ # "maker": True,
931
+ # "buyer": False
932
+ # }
933
+ #
934
+ # {respType: FULL}
935
+ #
936
+ # {
937
+ # "price": "4000.00000000",
938
+ # "qty": "1.00000000",
939
+ # "commission": "4.00000000",
940
+ # "commissionAsset": "USDT",
941
+ # "tradeId": "1234",
942
+ # }
943
+ #
944
+ timestamp = self.safe_integer_2(trade, 'T', 'time')
945
+ price = self.safe_string_2(trade, 'p', 'price')
946
+ amount = self.safe_string_2(trade, 'q', 'qty')
947
+ cost = self.safe_string_2(trade, 'quoteQty', 'baseQty') # inverse futures
948
+ marketId = self.safe_string(trade, 'symbol')
949
+ symbol = self.safe_symbol(marketId, market)
950
+ id = self.safe_string_2(trade, 't', 'a')
951
+ id = self.safe_string_2(trade, 'id', 'tradeId', id)
952
+ side: Str = None
953
+ orderId = self.safe_string(trade, 'orderId')
954
+ buyerMaker = self.safe_value_2(trade, 'm', 'isBuyerMaker')
955
+ takerOrMaker: Str = None
956
+ if buyerMaker is not None:
957
+ side = 'sell' if buyerMaker else 'buy' # self is reversed intentionally
958
+ takerOrMaker = 'taker'
959
+ elif 'side' in trade:
960
+ side = self.safe_string_lower(trade, 'side')
961
+ else:
962
+ if 'isBuyer' in trade:
963
+ side = 'buy' if trade['isBuyer'] else 'sell' # self is a True side
964
+ fee = None
965
+ if 'commission' in trade:
966
+ fee = {
967
+ 'cost': self.safe_string(trade, 'commission'),
968
+ 'currency': self.safe_currency_code(self.safe_string(trade, 'commissionAsset')),
969
+ }
970
+ if 'isMaker' in trade:
971
+ takerOrMaker = 'maker' if trade['isMaker'] else 'taker'
972
+ if 'maker' in trade:
973
+ takerOrMaker = 'maker' if trade['maker'] else 'taker'
974
+ return self.safe_trade({
975
+ 'info': trade,
976
+ 'timestamp': timestamp,
977
+ 'datetime': self.iso8601(timestamp),
978
+ 'symbol': symbol,
979
+ 'id': id,
980
+ 'order': orderId,
981
+ 'type': None,
982
+ 'side': side,
983
+ 'takerOrMaker': takerOrMaker,
984
+ 'price': price,
985
+ 'amount': amount,
986
+ 'cost': cost,
987
+ 'fee': fee,
988
+ }, market)
989
+
990
+ async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
991
+ """
992
+ :see: https://www.tokocrypto.com/apidocs/#recent-trades-list
993
+ :see: https://www.tokocrypto.com/apidocs/#compressedaggregate-trades-list
994
+ get the list of most recent trades for a particular symbol
995
+ :param str symbol: unified symbol of the market to fetch trades for
996
+ :param int [since]: timestamp in ms of the earliest trade to fetch
997
+ :param int [limit]: the maximum amount of trades to fetch
998
+ :param dict [params]: extra parameters specific to the exchange API endpoint
999
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1000
+ """
1001
+ await self.load_markets()
1002
+ market = self.market(symbol)
1003
+ request: dict = {
1004
+ 'symbol': self.get_market_id_by_type(market),
1005
+ # 'fromId': 123, # ID to get aggregate trades from INCLUSIVE.
1006
+ # 'startTime': 456, # Timestamp in ms to get aggregate trades from INCLUSIVE.
1007
+ # 'endTime': 789, # Timestamp in ms to get aggregate trades until INCLUSIVE.
1008
+ # 'limit': 500, # default = 500, maximum = 1000
1009
+ }
1010
+ if market['quote'] != 'USDT':
1011
+ if limit is not None:
1012
+ request['limit'] = limit
1013
+ responseInner = self.publicGetOpenV1MarketTrades(self.extend(request, params))
1014
+ #
1015
+ # {
1016
+ # "code": 0,
1017
+ # "msg": "success",
1018
+ # "data": {
1019
+ # "list": [
1020
+ # {
1021
+ # "id": 28457,
1022
+ # "price": "4.00000100",
1023
+ # "qty": "12.00000000",
1024
+ # "time": 1499865549590,
1025
+ # "isBuyerMaker": True,
1026
+ # "isBestMatch": True
1027
+ # }
1028
+ # ]
1029
+ # },
1030
+ # "timestamp": 1571921637091
1031
+ # }
1032
+ #
1033
+ data = self.safe_dict(responseInner, 'data', {})
1034
+ list = self.safe_list(data, 'list', [])
1035
+ return self.parse_trades(list, market, since, limit)
1036
+ if limit is not None:
1037
+ request['limit'] = limit # default = 500, maximum = 1000
1038
+ defaultMethod = 'binanceGetTrades'
1039
+ method = self.safe_string(self.options, 'fetchTradesMethod', defaultMethod)
1040
+ response = None
1041
+ if (method == 'binanceGetAggTrades') and (since is not None):
1042
+ request['startTime'] = since
1043
+ # https://github.com/ccxt/ccxt/issues/6400
1044
+ # https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
1045
+ request['endTime'] = self.sum(since, 3600000)
1046
+ response = await self.binanceGetAggTrades(self.extend(request, params))
1047
+ else:
1048
+ response = await self.binanceGetTrades(self.extend(request, params))
1049
+ #
1050
+ # Caveats:
1051
+ # - default limit(500) applies only if no other parameters set, trades up
1052
+ # to the maximum limit may be returned to satisfy other parameters
1053
+ # - if both limit and time window is set and time window contains more
1054
+ # trades than the limit then the last trades from the window are returned
1055
+ # - 'tradeId' accepted and returned by self method is "aggregate" trade id
1056
+ # which is different from actual trade id
1057
+ # - setting both fromId and time window results in error
1058
+ #
1059
+ # aggregate trades
1060
+ #
1061
+ # [
1062
+ # {
1063
+ # "a": 26129, # Aggregate tradeId
1064
+ # "p": "0.01633102", # Price
1065
+ # "q": "4.70443515", # Quantity
1066
+ # "f": 27781, # First tradeId
1067
+ # "l": 27781, # Last tradeId
1068
+ # "T": 1498793709153, # Timestamp
1069
+ # "m": True, # Was the buyer the maker?
1070
+ # "M": True # Was the trade the best price match?
1071
+ # }
1072
+ # ]
1073
+ #
1074
+ # recent public trades and historical public trades
1075
+ #
1076
+ # [
1077
+ # {
1078
+ # "id": 28457,
1079
+ # "price": "4.00000100",
1080
+ # "qty": "12.00000000",
1081
+ # "time": 1499865549590,
1082
+ # "isBuyerMaker": True,
1083
+ # "isBestMatch": True
1084
+ # }
1085
+ # ]
1086
+ #
1087
+ return self.parse_trades(response, market, since, limit)
1088
+
1089
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1090
+ #
1091
+ # {
1092
+ # "symbol": "ETHBTC",
1093
+ # "priceChange": "0.00068700",
1094
+ # "priceChangePercent": "2.075",
1095
+ # "weightedAvgPrice": "0.03342681",
1096
+ # "prevClosePrice": "0.03310300",
1097
+ # "lastPrice": "0.03378900",
1098
+ # "lastQty": "0.07700000",
1099
+ # "bidPrice": "0.03378900",
1100
+ # "bidQty": "7.16800000",
1101
+ # "askPrice": "0.03379000",
1102
+ # "askQty": "24.00000000",
1103
+ # "openPrice": "0.03310200",
1104
+ # "highPrice": "0.03388900",
1105
+ # "lowPrice": "0.03306900",
1106
+ # "volume": "205478.41000000",
1107
+ # "quoteVolume": "6868.48826294",
1108
+ # "openTime": 1601469986932,
1109
+ # "closeTime": 1601556386932,
1110
+ # "firstId": 196098772,
1111
+ # "lastId": 196186315,
1112
+ # "count": 87544
1113
+ # }
1114
+ #
1115
+ # coinm
1116
+ # {
1117
+ # "baseVolume": "214549.95171161",
1118
+ # "closeTime": "1621965286847",
1119
+ # "count": "1283779",
1120
+ # "firstId": "152560106",
1121
+ # "highPrice": "39938.3",
1122
+ # "lastId": "153843955",
1123
+ # "lastPrice": "37993.4",
1124
+ # "lastQty": "1",
1125
+ # "lowPrice": "36457.2",
1126
+ # "openPrice": "37783.4",
1127
+ # "openTime": "1621878840000",
1128
+ # "pair": "BTCUSD",
1129
+ # "priceChange": "210.0",
1130
+ # "priceChangePercent": "0.556",
1131
+ # "symbol": "BTCUSD_PERP",
1132
+ # "volume": "81990451",
1133
+ # "weightedAvgPrice": "38215.08713747"
1134
+ # }
1135
+ #
1136
+ timestamp = self.safe_integer(ticker, 'closeTime')
1137
+ marketId = self.safe_string(ticker, 'symbol')
1138
+ symbol = self.safe_symbol(marketId, market)
1139
+ last = self.safe_string(ticker, 'lastPrice')
1140
+ isCoinm = ('baseVolume' in ticker)
1141
+ baseVolume = None
1142
+ quoteVolume = None
1143
+ if isCoinm:
1144
+ baseVolume = self.safe_string(ticker, 'baseVolume')
1145
+ quoteVolume = self.safe_string(ticker, 'volume')
1146
+ else:
1147
+ baseVolume = self.safe_string(ticker, 'volume')
1148
+ quoteVolume = self.safe_string(ticker, 'quoteVolume')
1149
+ return self.safe_ticker({
1150
+ 'symbol': symbol,
1151
+ 'timestamp': timestamp,
1152
+ 'datetime': self.iso8601(timestamp),
1153
+ 'high': self.safe_string(ticker, 'highPrice'),
1154
+ 'low': self.safe_string(ticker, 'lowPrice'),
1155
+ 'bid': self.safe_string(ticker, 'bidPrice'),
1156
+ 'bidVolume': self.safe_string(ticker, 'bidQty'),
1157
+ 'ask': self.safe_string(ticker, 'askPrice'),
1158
+ 'askVolume': self.safe_string(ticker, 'askQty'),
1159
+ 'vwap': self.safe_string(ticker, 'weightedAvgPrice'),
1160
+ 'open': self.safe_string(ticker, 'openPrice'),
1161
+ 'close': last,
1162
+ 'last': last,
1163
+ 'previousClose': self.safe_string(ticker, 'prevClosePrice'), # previous day close
1164
+ 'change': self.safe_string(ticker, 'priceChange'),
1165
+ 'percentage': self.safe_string(ticker, 'priceChangePercent'),
1166
+ 'average': None,
1167
+ 'baseVolume': baseVolume,
1168
+ 'quoteVolume': quoteVolume,
1169
+ 'info': ticker,
1170
+ }, market)
1171
+
1172
+ async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1173
+ """
1174
+ :see: https://binance-docs.github.io/apidocs/spot/en/#24hr-ticker-price-change-statistics
1175
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1176
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1177
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1178
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1179
+ """
1180
+ await self.load_markets()
1181
+ response = await self.binanceGetTicker24hr(params)
1182
+ return self.parse_tickers(response, symbols)
1183
+
1184
+ def get_market_id_by_type(self, market):
1185
+ if market['quote'] == 'USDT':
1186
+ return market['baseId'] + market['quoteId']
1187
+ return market['id']
1188
+
1189
+ async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1190
+ """
1191
+ :see: https://binance-docs.github.io/apidocs/spot/en/#24hr-ticker-price-change-statistics
1192
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1193
+ :param str symbol: unified symbol of the market to fetch the ticker for
1194
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1195
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1196
+ """
1197
+ await self.load_markets()
1198
+ market = self.market(symbol)
1199
+ request: dict = {
1200
+ 'symbol': market['baseId'] + market['quoteId'],
1201
+ }
1202
+ response = await self.binanceGetTicker24hr(self.extend(request, params))
1203
+ if isinstance(response, list):
1204
+ firstTicker = self.safe_dict(response, 0, {})
1205
+ return self.parse_ticker(firstTicker, market)
1206
+ return self.parse_ticker(response, market)
1207
+
1208
+ async def fetch_bids_asks(self, symbols: Strings = None, params={}):
1209
+ """
1210
+ :see: https://binance-docs.github.io/apidocs/spot/en/#symbol-order-book-ticker
1211
+ fetches the bid and ask price and volume for multiple markets
1212
+ :param str[]|None symbols: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
1213
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1214
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1215
+ """
1216
+ await self.load_markets()
1217
+ response = await self.binanceGetTickerBookTicker(params)
1218
+ return self.parse_tickers(response, symbols)
1219
+
1220
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1221
+ # when api method = publicGetKlines or fapiPublicGetKlines or dapiPublicGetKlines
1222
+ # [
1223
+ # 1591478520000, # open time
1224
+ # "0.02501300", # open
1225
+ # "0.02501800", # high
1226
+ # "0.02500000", # low
1227
+ # "0.02500000", # close
1228
+ # "22.19000000", # volume
1229
+ # 1591478579999, # close time
1230
+ # "0.55490906", # quote asset volume
1231
+ # 40, # number of trades
1232
+ # "10.92900000", # taker buy base asset volume
1233
+ # "0.27336462", # taker buy quote asset volume
1234
+ # "0" # ignore
1235
+ # ]
1236
+ #
1237
+ # when api method = fapiPublicGetMarkPriceKlines or fapiPublicGetIndexPriceKlines
1238
+ # [
1239
+ # [
1240
+ # 1591256460000, # Open time
1241
+ # "9653.29201333", # Open
1242
+ # "9654.56401333", # High
1243
+ # "9653.07367333", # Low
1244
+ # "9653.07367333", # Close(or latest price)
1245
+ # "0", # Ignore
1246
+ # 1591256519999, # Close time
1247
+ # "0", # Ignore
1248
+ # 60, # Number of bisic data
1249
+ # "0", # Ignore
1250
+ # "0", # Ignore
1251
+ # "0" # Ignore
1252
+ # ]
1253
+ # ]
1254
+ #
1255
+ return [
1256
+ self.safe_integer(ohlcv, 0),
1257
+ self.safe_number(ohlcv, 1),
1258
+ self.safe_number(ohlcv, 2),
1259
+ self.safe_number(ohlcv, 3),
1260
+ self.safe_number(ohlcv, 4),
1261
+ self.safe_number(ohlcv, 5),
1262
+ ]
1263
+
1264
+ async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1265
+ """
1266
+ :see: https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1267
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1268
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1269
+ :param str timeframe: the length of time each candle represents
1270
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1271
+ :param int [limit]: the maximum amount of candles to fetch
1272
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1273
+ :param str [params.price]: "mark" or "index" for mark price and index price candles
1274
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
1275
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1276
+ """
1277
+ await self.load_markets()
1278
+ market = self.market(symbol)
1279
+ # binance docs say that the default limit 500, max 1500 for futures, max 1000 for spot markets
1280
+ # the reality is that the time range wider than 500 candles won't work right
1281
+ defaultLimit = 500
1282
+ maxLimit = 1500
1283
+ price = self.safe_string(params, 'price')
1284
+ until = self.safe_integer(params, 'until')
1285
+ params = self.omit(params, ['price', 'until'])
1286
+ limit = defaultLimit if (limit is None) else min(limit, maxLimit)
1287
+ request: dict = {
1288
+ 'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1289
+ 'limit': limit,
1290
+ }
1291
+ if price == 'index':
1292
+ request['pair'] = market['id'] # Index price takes self argument instead of symbol
1293
+ else:
1294
+ request['symbol'] = self.get_market_id_by_type(market)
1295
+ # duration = self.parse_timeframe(timeframe)
1296
+ if since is not None:
1297
+ request['startTime'] = since
1298
+ if until is not None:
1299
+ request['endTime'] = until
1300
+ response = None
1301
+ if market['quote'] == 'USDT':
1302
+ response = await self.binanceGetKlines(self.extend(request, params))
1303
+ else:
1304
+ response = await self.publicGetOpenV1MarketKlines(self.extend(request, params))
1305
+ #
1306
+ # [
1307
+ # [1591478520000,"0.02501300","0.02501800","0.02500000","0.02500000","22.19000000",1591478579999,"0.55490906",40,"10.92900000","0.27336462","0"],
1308
+ # [1591478580000,"0.02499600","0.02500900","0.02499400","0.02500300","21.34700000",1591478639999,"0.53370468",24,"7.53800000","0.18850725","0"],
1309
+ # [1591478640000,"0.02500800","0.02501100","0.02500300","0.02500800","154.14200000",1591478699999,"3.85405839",97,"5.32300000","0.13312641","0"],
1310
+ # ]
1311
+ #
1312
+ data = self.safe_list(response, 'data', response)
1313
+ return self.parse_ohlcvs(data, market, timeframe, since, limit)
1314
+
1315
+ async def fetch_balance(self, params={}) -> Balances:
1316
+ """
1317
+ :see: https://www.tokocrypto.com/apidocs/#account-information-signed
1318
+ query for balance and get the amount of funds available for trading or funds locked in orders
1319
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1320
+ :param str [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
1321
+ :param str [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
1322
+ :param str[]|None [params.symbols]: unified market symbols, only used in isolated margin mode
1323
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1324
+ """
1325
+ await self.load_markets()
1326
+ defaultType = self.safe_string_2(self.options, 'fetchBalance', 'defaultType', 'spot')
1327
+ type = self.safe_string(params, 'type', defaultType)
1328
+ defaultMarginMode = self.safe_string_2(self.options, 'marginMode', 'defaultMarginMode')
1329
+ marginMode = self.safe_string_lower(params, 'marginMode', defaultMarginMode)
1330
+ request: dict = {}
1331
+ response = await self.privateGetOpenV1AccountSpot(self.extend(request, params))
1332
+ #
1333
+ # spot
1334
+ #
1335
+ # {
1336
+ # "code":0,
1337
+ # "msg":"Success",
1338
+ # "data":{
1339
+ # "makerCommission":"0.00100000",
1340
+ # "takerCommission":"0.00100000",
1341
+ # "buyerCommission":"0.00000000",
1342
+ # "sellerCommission":"0.00000000",
1343
+ # "canTrade":1,
1344
+ # "canWithdraw":1,
1345
+ # "canDeposit":1,
1346
+ # "status":1,
1347
+ # "accountAssets":[
1348
+ # {"asset":"1INCH","free":"0","locked":"0"},
1349
+ # {"asset":"AAVE","free":"0","locked":"0"},
1350
+ # {"asset":"ACA","free":"0","locked":"0"}
1351
+ # ],
1352
+ # },
1353
+ # "timestamp":1659666786943
1354
+ # }
1355
+ #
1356
+ return self.parse_balance_custom(response, type, marginMode)
1357
+
1358
+ def parse_balance_custom(self, response, type=None, marginMode=None):
1359
+ timestamp = self.safe_integer(response, 'updateTime')
1360
+ result: dict = {
1361
+ 'info': response,
1362
+ 'timestamp': timestamp,
1363
+ 'datetime': self.iso8601(timestamp),
1364
+ }
1365
+ data = self.safe_value(response, 'data', {})
1366
+ balances = self.safe_value(data, 'accountAssets', [])
1367
+ for i in range(0, len(balances)):
1368
+ balance = balances[i]
1369
+ currencyId = self.safe_string(balance, 'asset')
1370
+ code = self.safe_currency_code(currencyId)
1371
+ account = self.account()
1372
+ account['free'] = self.safe_string(balance, 'free')
1373
+ account['used'] = self.safe_string(balance, 'locked')
1374
+ result[code] = account
1375
+ return self.safe_balance(result)
1376
+
1377
+ def parse_order_status(self, status: Str):
1378
+ statuses: dict = {
1379
+ '-2': 'open',
1380
+ '0': 'open', # NEW
1381
+ '1': 'open', # PARTIALLY_FILLED
1382
+ '2': 'closed', # FILLED
1383
+ '3': 'canceled', # CANCELED
1384
+ '4': 'canceling', # PENDING_CANCEL(currently unused)
1385
+ '5': 'rejected', # REJECTED
1386
+ '6': 'expired', # EXPIRED
1387
+ 'NEW': 'open',
1388
+ 'PARTIALLY_FILLED': 'open',
1389
+ 'FILLED': 'closed',
1390
+ 'CANCELED': 'canceled',
1391
+ 'PENDING_CANCEL': 'canceling', # currently unused
1392
+ 'REJECTED': 'rejected',
1393
+ 'EXPIRED': 'expired',
1394
+ }
1395
+ return self.safe_string(statuses, status, status)
1396
+
1397
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1398
+ #
1399
+ # spot
1400
+ #
1401
+ # {
1402
+ # "symbol": "LTCBTC",
1403
+ # "orderId": 1,
1404
+ # "clientOrderId": "myOrder1",
1405
+ # "price": "0.1",
1406
+ # "origQty": "1.0",
1407
+ # "executedQty": "0.0",
1408
+ # "cummulativeQuoteQty": "0.0",
1409
+ # "status": "NEW",
1410
+ # "timeInForce": "GTC",
1411
+ # "type": "LIMIT",
1412
+ # "side": "BUY",
1413
+ # "stopPrice": "0.0",
1414
+ # "icebergQty": "0.0",
1415
+ # "time": 1499827319559,
1416
+ # "updateTime": 1499827319559,
1417
+ # "isWorking": True
1418
+ # }
1419
+ # createOrder
1420
+ # {
1421
+ # "orderId": "145265071",
1422
+ # "bOrderListId": "0",
1423
+ # "clientId": "49c09c3c2cd54419a59c05441f517b3c",
1424
+ # "bOrderId": "35247529",
1425
+ # "symbol": "USDT_BIDR",
1426
+ # "symbolType": "1",
1427
+ # "side": "0",
1428
+ # "type": "1",
1429
+ # "price": "11915",
1430
+ # "origQty": "2",
1431
+ # "origQuoteQty": "23830.00",
1432
+ # "executedQty": "0.00000000",
1433
+ # "executedPrice": "0",
1434
+ # "executedQuoteQty": "0.00",
1435
+ # "timeInForce": "1",
1436
+ # "stopPrice": "0",
1437
+ # "icebergQty": "0",
1438
+ # "status": "0",
1439
+ # "createTime": "1662711074372"
1440
+ # }
1441
+ #
1442
+ # createOrder with {"newOrderRespType": "FULL"}
1443
+ #
1444
+ # {
1445
+ # "symbol": "BTCUSDT",
1446
+ # "orderId": 5403233939,
1447
+ # "orderListId": -1,
1448
+ # "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e",
1449
+ # "transactTime": 1617151923742,
1450
+ # "price": "0.00000000",
1451
+ # "origQty": "0.00050000",
1452
+ # "executedQty": "0.00050000",
1453
+ # "cummulativeQuoteQty": "29.47081500",
1454
+ # "status": "FILLED",
1455
+ # "timeInForce": "GTC",
1456
+ # "type": "MARKET",
1457
+ # "side": "BUY",
1458
+ # "fills": [
1459
+ # {
1460
+ # "price": "58941.63000000",
1461
+ # "qty": "0.00050000",
1462
+ # "commission": "0.00007050",
1463
+ # "commissionAsset": "BNB",
1464
+ # "tradeId": 737466631
1465
+ # }
1466
+ # ]
1467
+ # }
1468
+ #
1469
+ # delivery
1470
+ #
1471
+ # {
1472
+ # "orderId": "18742727411",
1473
+ # "symbol": "ETHUSD_PERP",
1474
+ # "pair": "ETHUSD",
1475
+ # "status": "FILLED",
1476
+ # "clientOrderId": "x-xcKtGhcu3e2d1503fdd543b3b02419",
1477
+ # "price": "0",
1478
+ # "avgPrice": "4522.14",
1479
+ # "origQty": "1",
1480
+ # "executedQty": "1",
1481
+ # "cumBase": "0.00221134",
1482
+ # "timeInForce": "GTC",
1483
+ # "type": "MARKET",
1484
+ # "reduceOnly": False,
1485
+ # "closePosition": False,
1486
+ # "side": "SELL",
1487
+ # "positionSide": "BOTH",
1488
+ # "stopPrice": "0",
1489
+ # "workingType": "CONTRACT_PRICE",
1490
+ # "priceProtect": False,
1491
+ # "origType": "MARKET",
1492
+ # "time": "1636061952660",
1493
+ # "updateTime": "1636061952660"
1494
+ # }
1495
+ #
1496
+ status = self.parse_order_status(self.safe_string(order, 'status'))
1497
+ marketId = self.safe_string(order, 'symbol')
1498
+ symbol = self.safe_symbol(marketId, market)
1499
+ filled = self.safe_string(order, 'executedQty', '0')
1500
+ timestamp = self.safe_integer(order, 'createTime')
1501
+ average = self.safe_string(order, 'avgPrice')
1502
+ price = self.safe_string_2(order, 'price', 'executedPrice')
1503
+ amount = self.safe_string(order, 'origQty')
1504
+ # - Spot/Margin market: cummulativeQuoteQty
1505
+ # Note self is not the actual cost, since Binance futures uses leverage to calculate margins.
1506
+ cost = self.safe_string_n(order, ['cummulativeQuoteQty', 'cumQuote', 'executedQuoteQty', 'cumBase'])
1507
+ id = self.safe_string(order, 'orderId')
1508
+ type = self.parse_order_type(self.safe_string_lower(order, 'type'))
1509
+ side = self.safe_string_lower(order, 'side')
1510
+ if side == '0':
1511
+ side = 'buy'
1512
+ elif side == '1':
1513
+ side = 'sell'
1514
+ fills = self.safe_value(order, 'fills', [])
1515
+ clientOrderId = self.safe_string_2(order, 'clientOrderId', 'clientId')
1516
+ timeInForce = self.safe_string(order, 'timeInForce')
1517
+ if timeInForce == 'GTX':
1518
+ # GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
1519
+ timeInForce = 'PO'
1520
+ postOnly = (type == 'limit_maker') or (timeInForce == 'PO')
1521
+ stopPriceString = self.safe_string(order, 'stopPrice')
1522
+ stopPrice = self.parse_number(self.omit_zero(stopPriceString))
1523
+ return self.safe_order({
1524
+ 'info': order,
1525
+ 'id': id,
1526
+ 'clientOrderId': clientOrderId,
1527
+ 'timestamp': timestamp,
1528
+ 'datetime': self.iso8601(timestamp),
1529
+ 'lastTradeTimestamp': None,
1530
+ 'symbol': symbol,
1531
+ 'type': type,
1532
+ 'timeInForce': timeInForce,
1533
+ 'postOnly': postOnly,
1534
+ 'reduceOnly': self.safe_value(order, 'reduceOnly'),
1535
+ 'side': side,
1536
+ 'price': price,
1537
+ 'stopPrice': stopPrice,
1538
+ 'triggerPrice': stopPrice,
1539
+ 'amount': amount,
1540
+ 'cost': cost,
1541
+ 'average': average,
1542
+ 'filled': filled,
1543
+ 'remaining': None,
1544
+ 'status': status,
1545
+ 'fee': None,
1546
+ 'trades': fills,
1547
+ }, market)
1548
+
1549
+ def parse_order_type(self, status):
1550
+ statuses: dict = {
1551
+ '2': 'market',
1552
+ '1': 'limit',
1553
+ '4': 'limit',
1554
+ '7': 'limit',
1555
+ }
1556
+ return self.safe_string(statuses, status, status)
1557
+
1558
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1559
+ """
1560
+ create a trade order
1561
+ :see: https://www.tokocrypto.com/apidocs/#new-order--signed
1562
+ :see: https://www.tokocrypto.com/apidocs/#account-trade-list-signed
1563
+ :param str symbol: unified symbol of the market to create an order in
1564
+ :param str type: 'market' or 'limit'
1565
+ :param str side: 'buy' or 'sell'
1566
+ :param float amount: how much of currency you want to trade in units of base currency
1567
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1568
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1569
+ :param float [params.triggerPrice]: the price at which a trigger order would be triggered
1570
+ :param float [params.cost]: for spot market buy orders, the quote quantity that can be used alternative for the amount
1571
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1572
+ """
1573
+ await self.load_markets()
1574
+ market = self.market(symbol)
1575
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clientId')
1576
+ postOnly = self.safe_bool(params, 'postOnly', False)
1577
+ # only supported for spot/margin api
1578
+ if postOnly:
1579
+ type = 'LIMIT_MAKER'
1580
+ params = self.omit(params, ['clientId', 'clientOrderId'])
1581
+ initialUppercaseType = type.upper()
1582
+ uppercaseType = initialUppercaseType
1583
+ stopPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
1584
+ if stopPrice is not None:
1585
+ params = self.omit(params, ['triggerPrice', 'stopPrice'])
1586
+ if uppercaseType == 'MARKET':
1587
+ uppercaseType = 'STOP_LOSS'
1588
+ elif uppercaseType == 'LIMIT':
1589
+ uppercaseType = 'STOP_LOSS_LIMIT'
1590
+ validOrderTypes = self.safe_value(market['info'], 'orderTypes')
1591
+ if not self.in_array(uppercaseType, validOrderTypes):
1592
+ if initialUppercaseType != uppercaseType:
1593
+ raise InvalidOrder(self.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
1594
+ else:
1595
+ raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
1596
+ reverseOrderTypeMapping: dict = {
1597
+ 'LIMIT': 1,
1598
+ 'MARKET': 2,
1599
+ 'STOP_LOSS': 3,
1600
+ 'STOP_LOSS_LIMIT': 4,
1601
+ 'TAKE_PROFIT': 5,
1602
+ 'TAKE_PROFIT_LIMIT': 6,
1603
+ 'LIMIT_MAKER': 7,
1604
+ }
1605
+ request: dict = {
1606
+ 'symbol': market['baseId'] + '_' + market['quoteId'],
1607
+ 'type': self.safe_string(reverseOrderTypeMapping, uppercaseType),
1608
+ }
1609
+ if side == 'buy':
1610
+ request['side'] = 0
1611
+ elif side == 'sell':
1612
+ request['side'] = 1
1613
+ if clientOrderId is None:
1614
+ broker = self.safe_value(self.options, 'broker')
1615
+ if broker is not None:
1616
+ brokerId = self.safe_string(broker, 'marketType')
1617
+ if brokerId is not None:
1618
+ request['clientId'] = brokerId + self.uuid22()
1619
+ else:
1620
+ request['clientId'] = clientOrderId
1621
+ # additional required fields depending on the order type
1622
+ priceIsRequired = False
1623
+ stopPriceIsRequired = False
1624
+ quantityIsRequired = False
1625
+ #
1626
+ # spot/margin
1627
+ #
1628
+ # LIMIT timeInForce, quantity, price
1629
+ # MARKET quantity or quoteOrderQty
1630
+ # STOP_LOSS quantity, stopPrice
1631
+ # STOP_LOSS_LIMIT timeInForce, quantity, price, stopPrice
1632
+ # TAKE_PROFIT quantity, stopPrice
1633
+ # TAKE_PROFIT_LIMIT timeInForce, quantity, price, stopPrice
1634
+ # LIMIT_MAKER quantity, price
1635
+ #
1636
+ if uppercaseType == 'MARKET':
1637
+ if side == 'buy':
1638
+ precision = market['precision']['price']
1639
+ quoteAmount = None
1640
+ createMarketBuyOrderRequiresPrice = True
1641
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1642
+ cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
1643
+ params = self.omit(params, ['cost', 'quoteOrderQty'])
1644
+ if cost is not None:
1645
+ quoteAmount = cost
1646
+ elif createMarketBuyOrderRequiresPrice:
1647
+ if price is None:
1648
+ raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1649
+ else:
1650
+ amountString = self.number_to_string(amount)
1651
+ priceString = self.number_to_string(price)
1652
+ quoteAmount = Precise.string_mul(amountString, priceString)
1653
+ else:
1654
+ quoteAmount = amount
1655
+ request['quoteOrderQty'] = self.decimal_to_precision(quoteAmount, TRUNCATE, precision, self.precisionMode)
1656
+ else:
1657
+ quantityIsRequired = True
1658
+ elif uppercaseType == 'LIMIT':
1659
+ priceIsRequired = True
1660
+ quantityIsRequired = True
1661
+ elif (uppercaseType == 'STOP_LOSS') or (uppercaseType == 'TAKE_PROFIT'):
1662
+ stopPriceIsRequired = True
1663
+ quantityIsRequired = True
1664
+ if market['linear'] or market['inverse']:
1665
+ priceIsRequired = True
1666
+ elif (uppercaseType == 'STOP_LOSS_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
1667
+ quantityIsRequired = True
1668
+ stopPriceIsRequired = True
1669
+ priceIsRequired = True
1670
+ elif uppercaseType == 'LIMIT_MAKER':
1671
+ priceIsRequired = True
1672
+ quantityIsRequired = True
1673
+ if quantityIsRequired:
1674
+ request['quantity'] = self.amount_to_precision(symbol, amount)
1675
+ if priceIsRequired:
1676
+ if price is None:
1677
+ raise InvalidOrder(self.id + ' createOrder() requires a price argument for a ' + type + ' order')
1678
+ request['price'] = self.price_to_precision(symbol, price)
1679
+ if stopPriceIsRequired:
1680
+ if stopPrice is None:
1681
+ raise InvalidOrder(self.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order')
1682
+ else:
1683
+ request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
1684
+ response = await self.privatePostOpenV1Orders(self.extend(request, params))
1685
+ #
1686
+ # {
1687
+ # "code": 0,
1688
+ # "msg": "Success",
1689
+ # "data": {
1690
+ # "orderId": 145264846,
1691
+ # "bOrderListId": 0,
1692
+ # "clientId": "4ee2ab5e55e74b358eaf98079c670d17",
1693
+ # "bOrderId": 35247499,
1694
+ # "symbol": "USDT_BIDR",
1695
+ # "symbolType": 1,
1696
+ # "side": 0,
1697
+ # "type": 1,
1698
+ # "price": "11915",
1699
+ # "origQty": "2",
1700
+ # "origQuoteQty": "23830.00",
1701
+ # "executedQty": "0.00000000",
1702
+ # "executedPrice": "0",
1703
+ # "executedQuoteQty": "0.00",
1704
+ # "timeInForce": 1,
1705
+ # "stopPrice": 0,
1706
+ # "icebergQty": "0",
1707
+ # "status": 0,
1708
+ # "createTime": 1662710994848
1709
+ # },
1710
+ # "timestamp": 1662710994975
1711
+ # }
1712
+ #
1713
+ rawOrder = self.safe_dict(response, 'data', {})
1714
+ return self.parse_order(rawOrder, market)
1715
+
1716
+ async def fetch_order(self, id: str, symbol: Str = None, params={}):
1717
+ """
1718
+ :see: https://www.tokocrypto.com/apidocs/#all-orders-signed
1719
+ fetches information on an order made by the user
1720
+ :param str symbol: unified symbol of the market the order was made in
1721
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1722
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1723
+ """
1724
+ request: dict = {
1725
+ 'orderId': id,
1726
+ }
1727
+ response = await self.privateGetOpenV1Orders(self.extend(request, params))
1728
+ #
1729
+ # {
1730
+ # "code": 0,
1731
+ # "msg": "Success",
1732
+ # "data": {
1733
+ # "list": [{
1734
+ # "orderId": "145221985",
1735
+ # "clientId": "201515331fd64d03aedbe687a38152e3",
1736
+ # "bOrderId": "35239632",
1737
+ # "bOrderListId": "0",
1738
+ # "symbol": "USDT_BIDR",
1739
+ # "symbolType": 1,
1740
+ # "side": 0,
1741
+ # "type": 1,
1742
+ # "price": "11907",
1743
+ # "origQty": "2",
1744
+ # "origQuoteQty": "23814",
1745
+ # "executedQty": "0",
1746
+ # "executedPrice": "0",
1747
+ # "executedQuoteQty": "0",
1748
+ # "timeInForce": 1,
1749
+ # "stopPrice": "0",
1750
+ # "icebergQty": "0",
1751
+ # "status": 0,
1752
+ # "createTime": 1662699360000
1753
+ # }]
1754
+ # },
1755
+ # "timestamp": 1662710056523
1756
+ # }
1757
+ #
1758
+ data = self.safe_value(response, 'data', {})
1759
+ list = self.safe_value(data, 'list', [])
1760
+ rawOrder = self.safe_dict(list, 0, {})
1761
+ return self.parse_order(rawOrder)
1762
+
1763
+ async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1764
+ """
1765
+ :see: https://www.tokocrypto.com/apidocs/#all-orders-signed
1766
+ fetches information on multiple orders made by the user
1767
+ :param str symbol: unified market symbol of the market orders were made in
1768
+ :param int [since]: the earliest time in ms to fetch orders for
1769
+ :param int [limit]: the maximum number of order structures to retrieve
1770
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1771
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1772
+ """
1773
+ if symbol is None:
1774
+ raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
1775
+ await self.load_markets()
1776
+ market = self.market(symbol)
1777
+ request: dict = {
1778
+ 'symbol': market['id'],
1779
+ # 'type': -1, # -1 = all, 1 = open, 2 = closed
1780
+ # 'side': 1, # or 2
1781
+ # 'startTime': since,
1782
+ # 'endTime': self.milliseconds(),
1783
+ # 'fromId': 'starting order ID', # if defined, the "direct" field becomes mandatory
1784
+ # 'direct': 'prev', # prev, next
1785
+ # 'limit': 500, # default 500, max 1000
1786
+ }
1787
+ if since is not None:
1788
+ request['startTime'] = since
1789
+ if limit is not None:
1790
+ request['limit'] = limit
1791
+ response = await self.privateGetOpenV1Orders(self.extend(request, params))
1792
+ #
1793
+ # {
1794
+ # "code": 0,
1795
+ # "msg": "success",
1796
+ # "data": {
1797
+ # "list": [
1798
+ # {
1799
+ # "orderId": "4", # order id
1800
+ # "bOrderId": "100001", # binance order id
1801
+ # "bOrderListId": -1, # Unless part of an OCO, the value will always be -1.
1802
+ # "clientId": "1aa4f99ad7bc4fab903395afd25d0597", # client custom order id
1803
+ # "symbol": "ADA_USDT",
1804
+ # "symbolType": 1,
1805
+ # "side": 1,
1806
+ # "type": 1,
1807
+ # "price": "0.1",
1808
+ # "origQty": "10",
1809
+ # "origQuoteQty": "1",
1810
+ # "executedQty": "0",
1811
+ # "executedPrice": "0",
1812
+ # "executedQuoteQty": "0",
1813
+ # "timeInForce": 1,
1814
+ # "stopPrice": "0.0000000000000000",
1815
+ # "icebergQty": "0.0000000000000000",
1816
+ # "status": 0,
1817
+ # "isWorking": 0,
1818
+ # "createTime": 1572692016811
1819
+ # }
1820
+ # ]
1821
+ # },
1822
+ # "timestamp": 1572860756458
1823
+ # }
1824
+ #
1825
+ data = self.safe_value(response, 'data', {})
1826
+ orders = self.safe_list(data, 'list', [])
1827
+ return self.parse_orders(orders, market, since, limit)
1828
+
1829
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1830
+ """
1831
+ :see: https://www.tokocrypto.com/apidocs/#all-orders-signed
1832
+ fetch all unfilled currently open orders
1833
+ :param str symbol: unified market symbol
1834
+ :param int [since]: the earliest time in ms to fetch open orders for
1835
+ :param int [limit]: the maximum number of open orders structures to retrieve
1836
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1837
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1838
+ """
1839
+ request: dict = {'type': 1} # -1 = all, 1 = open, 2 = closed
1840
+ return await self.fetch_orders(symbol, since, limit, self.extend(request, params))
1841
+
1842
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1843
+ """
1844
+ :see: https://www.tokocrypto.com/apidocs/#all-orders-signed
1845
+ fetches information on multiple closed orders made by the user
1846
+ :param str symbol: unified market symbol of the market orders were made in
1847
+ :param int [since]: the earliest time in ms to fetch orders for
1848
+ :param int [limit]: the maximum number of order structures to retrieve
1849
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1850
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1851
+ """
1852
+ request: dict = {'type': 2} # -1 = all, 1 = open, 2 = closed
1853
+ return await self.fetch_orders(symbol, since, limit, self.extend(request, params))
1854
+
1855
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
1856
+ """
1857
+ :see: https://www.tokocrypto.com/apidocs/#cancel-order-signed
1858
+ cancels an open order
1859
+ :param str id: order id
1860
+ :param str symbol: unified symbol of the market the order was made in
1861
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1862
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1863
+ """
1864
+ request: dict = {
1865
+ 'orderId': id,
1866
+ }
1867
+ response = await self.privatePostOpenV1OrdersCancel(self.extend(request, params))
1868
+ #
1869
+ # {
1870
+ # "code": 0,
1871
+ # "msg": "Success",
1872
+ # "data": {
1873
+ # "orderId": "145221985",
1874
+ # "bOrderListId": "0",
1875
+ # "clientId": "201515331fd64d03aedbe687a38152e3",
1876
+ # "bOrderId": "35239632",
1877
+ # "symbol": "USDT_BIDR",
1878
+ # "symbolType": 1,
1879
+ # "type": 1,
1880
+ # "side": 0,
1881
+ # "price": "11907.0000000000000000",
1882
+ # "origQty": "2.0000000000000000",
1883
+ # "origQuoteQty": "23814.0000000000000000",
1884
+ # "executedPrice": "0.0000000000000000",
1885
+ # "executedQty": "0.00000000",
1886
+ # "executedQuoteQty": "0.00",
1887
+ # "timeInForce": 1,
1888
+ # "stopPrice": "0.0000000000000000",
1889
+ # "icebergQty": "0.0000000000000000",
1890
+ # "status": 3
1891
+ # },
1892
+ # "timestamp": 1662710683634
1893
+ # }
1894
+ #
1895
+ rawOrder = self.safe_dict(response, 'data', {})
1896
+ return self.parse_order(rawOrder)
1897
+
1898
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1899
+ """
1900
+ :see: https://www.tokocrypto.com/apidocs/#account-trade-list-signed
1901
+ fetch all trades made by the user
1902
+ :param str symbol: unified market symbol
1903
+ :param int [since]: the earliest time in ms to fetch trades for
1904
+ :param int [limit]: the maximum number of trades structures to retrieve
1905
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1906
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1907
+ """
1908
+ if symbol is None:
1909
+ raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
1910
+ await self.load_markets()
1911
+ market = self.market(symbol)
1912
+ request: dict = {
1913
+ 'symbol': market['id'],
1914
+ }
1915
+ endTime = self.safe_integer_2(params, 'until', 'endTime')
1916
+ if since is not None:
1917
+ request['startTime'] = since
1918
+ if endTime is not None:
1919
+ request['endTime'] = endTime
1920
+ params = self.omit(params, ['endTime', 'until'])
1921
+ if limit is not None:
1922
+ request['limit'] = limit
1923
+ response = await self.privateGetOpenV1OrdersTrades(self.extend(request, params))
1924
+ #
1925
+ # {
1926
+ # "code": 0,
1927
+ # "msg": "success",
1928
+ # "data": {
1929
+ # "list": [
1930
+ # {
1931
+ # "tradeId": "3",
1932
+ # "orderId": "2",
1933
+ # "symbol": "ADA_USDT",
1934
+ # "price": "0.04398",
1935
+ # "qty": "250",
1936
+ # "quoteQty": "10.995",
1937
+ # "commission": "0.25",
1938
+ # "commissionAsset": "ADA",
1939
+ # "isBuyer": 1,
1940
+ # "isMaker": 0,
1941
+ # "isBestMatch": 1,
1942
+ # "time": "1572920872276"
1943
+ # }
1944
+ # ]
1945
+ # },
1946
+ # "timestamp": 1573723498893
1947
+ # }
1948
+ #
1949
+ data = self.safe_value(response, 'data', {})
1950
+ trades = self.safe_list(data, 'list', [])
1951
+ return self.parse_trades(trades, market, since, limit)
1952
+
1953
+ async def fetch_deposit_address(self, code: str, params={}):
1954
+ """
1955
+ :see: https://www.tokocrypto.com/apidocs/#deposit-address-signed
1956
+ fetch the deposit address for a currency associated with self account
1957
+ :param str code: unified currency code
1958
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1959
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1960
+ """
1961
+ await self.load_markets()
1962
+ currency = self.currency(code)
1963
+ request: dict = {
1964
+ 'asset': currency['id'],
1965
+ # 'network': 'ETH', # 'BSC', 'XMR', you can get network and isDefault in networkList in the response of sapiGetCapitalConfigDetail
1966
+ }
1967
+ networks = self.safe_value(self.options, 'networks', {})
1968
+ network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
1969
+ network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
1970
+ if network is not None:
1971
+ request['network'] = network
1972
+ params = self.omit(params, 'network')
1973
+ # has support for the 'network' parameter
1974
+ # https://binance-docs.github.io/apidocs/spot/en/#deposit-address-supporting-network-user_data
1975
+ response = await self.privateGetOpenV1DepositsAddress(self.extend(request, params))
1976
+ #
1977
+ # {
1978
+ # "code":0,
1979
+ # "msg":"Success",
1980
+ # "data":{
1981
+ # "uid":"182395",
1982
+ # "asset":"USDT",
1983
+ # "network":"ETH",
1984
+ # "address":"0x101a925704f6ff13295ab8dd7a60988d116aaedf",
1985
+ # "addressTag":"",
1986
+ # "status":1
1987
+ # },
1988
+ # "timestamp":1660685915746
1989
+ # }
1990
+ #
1991
+ data = self.safe_value(response, 'data', {})
1992
+ address = self.safe_string(data, 'address')
1993
+ tag = self.safe_string(data, 'addressTag', '')
1994
+ if len(tag) == 0:
1995
+ tag = None
1996
+ self.check_address(address)
1997
+ return {
1998
+ 'currency': code,
1999
+ 'address': address,
2000
+ 'tag': tag,
2001
+ 'network': self.safe_string(data, 'network'),
2002
+ 'info': response,
2003
+ }
2004
+
2005
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2006
+ """
2007
+ :see: https://www.tokocrypto.com/apidocs/#deposit-history-signed
2008
+ fetch all deposits made to an account
2009
+ :param str code: unified currency code
2010
+ :param int [since]: the earliest time in ms to fetch deposits for
2011
+ :param int [limit]: the maximum number of deposits structures to retrieve
2012
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2013
+ :param int [params.until]: the latest time in ms to fetch deposits for
2014
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2015
+ """
2016
+ await self.load_markets()
2017
+ currency = None
2018
+ request: dict = {}
2019
+ until = self.safe_integer(params, 'until')
2020
+ if code is not None:
2021
+ currency = self.currency(code)
2022
+ request['coin'] = currency['id']
2023
+ if since is not None:
2024
+ request['startTime'] = since
2025
+ # max 3 months range https://github.com/ccxt/ccxt/issues/6495
2026
+ endTime = self.sum(since, 7776000000)
2027
+ if until is not None:
2028
+ endTime = min(endTime, until)
2029
+ request['endTime'] = endTime
2030
+ if limit is not None:
2031
+ request['limit'] = limit
2032
+ response = await self.privateGetOpenV1Deposits(self.extend(request, params))
2033
+ #
2034
+ # {
2035
+ # "code":0,
2036
+ # "msg":"Success",
2037
+ # "data":{
2038
+ # "list":[
2039
+ # {
2040
+ # "id":5167969,
2041
+ # "asset":"BIDR",
2042
+ # "network":"BSC",
2043
+ # "address":"0x101a925704f6ff13295ab8dd7a60988d116aaedf",
2044
+ # "addressTag":"",
2045
+ # "txId":"113409337867",
2046
+ # "amount":"15000",
2047
+ # "transferType":1,
2048
+ # "status":1,
2049
+ # "insertTime":"1659429390000"
2050
+ # },
2051
+ # ]
2052
+ # },
2053
+ # "timestamp":1659758865998
2054
+ # }
2055
+ #
2056
+ data = self.safe_value(response, 'data', {})
2057
+ deposits = self.safe_list(data, 'list', [])
2058
+ return self.parse_transactions(deposits, currency, since, limit)
2059
+
2060
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2061
+ """
2062
+ :see: https://www.tokocrypto.com/apidocs/#withdraw-signed
2063
+ fetch all withdrawals made from an account
2064
+ :param str code: unified currency code
2065
+ :param int [since]: the earliest time in ms to fetch withdrawals for
2066
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
2067
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2068
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2069
+ """
2070
+ await self.load_markets()
2071
+ request: dict = {}
2072
+ currency = None
2073
+ if code is not None:
2074
+ currency = self.currency(code)
2075
+ request['coin'] = currency['id']
2076
+ if since is not None:
2077
+ request['startTime'] = since
2078
+ # max 3 months range https://github.com/ccxt/ccxt/issues/6495
2079
+ request['endTime'] = self.sum(since, 7776000000)
2080
+ if limit is not None:
2081
+ request['limit'] = limit
2082
+ response = await self.privateGetOpenV1Withdraws(self.extend(request, params))
2083
+ #
2084
+ # {
2085
+ # "code":0,
2086
+ # "msg":"Success",
2087
+ # "data":{
2088
+ # "list":[
2089
+ # {
2090
+ # "id":4245859,
2091
+ # "clientId":"198",
2092
+ # "asset":"BIDR",
2093
+ # "network":"BSC",
2094
+ # "address":"0xff1c75149cc492e7d5566145b859fcafc900b6e9",
2095
+ # "addressTag":"",
2096
+ # "amount":"10000",
2097
+ # "fee":"0",
2098
+ # "txId":"113501794501",
2099
+ # "transferType":1,
2100
+ # "status":10,
2101
+ # "createTime":1659521314413
2102
+ # }
2103
+ # ]
2104
+ # },
2105
+ # "timestamp":1659759062187
2106
+ # }
2107
+ #
2108
+ data = self.safe_value(response, 'data', {})
2109
+ withdrawals = self.safe_list(data, 'list', [])
2110
+ return self.parse_transactions(withdrawals, currency, since, limit)
2111
+
2112
+ def parse_transaction_status_by_type(self, status, type=None):
2113
+ statusesByType: dict = {
2114
+ 'deposit': {
2115
+ '0': 'pending',
2116
+ '1': 'ok',
2117
+ },
2118
+ 'withdrawal': {
2119
+ '0': 'pending', # Email Sent
2120
+ '1': 'canceled', # Cancelled(different from 1 = ok in deposits)
2121
+ '2': 'pending', # Awaiting Approval
2122
+ '3': 'failed', # Rejected
2123
+ '4': 'pending', # Processing
2124
+ '5': 'failed', # Failure
2125
+ '10': 'ok', # Completed
2126
+ },
2127
+ }
2128
+ statuses = self.safe_value(statusesByType, type, {})
2129
+ return self.safe_string(statuses, status, status)
2130
+
2131
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2132
+ #
2133
+ # fetchDeposits
2134
+ #
2135
+ # {
2136
+ # "id": 5167969,
2137
+ # "asset": "BIDR",
2138
+ # "network": "BSC",
2139
+ # "address": "0x101a925704f6ff13295ab8dd7a60988d116aaedf",
2140
+ # "addressTag": "",
2141
+ # "txId": "113409337867",
2142
+ # "amount": "15000",
2143
+ # "transferType": 1,
2144
+ # "status": 1,
2145
+ # "insertTime": "1659429390000"
2146
+ # }
2147
+ #
2148
+ # fetchWithdrawals
2149
+ #
2150
+ # {
2151
+ # "id": 4245859,
2152
+ # "clientId": "198",
2153
+ # "asset": "BIDR",
2154
+ # "network": "BSC",
2155
+ # "address": "0xff1c75149cc492e7d5566145b859fcafc900b6e9",
2156
+ # "addressTag": "",
2157
+ # "amount": "10000",
2158
+ # "fee": "0",
2159
+ # "txId": "113501794501",
2160
+ # "transferType": 1,
2161
+ # "status": 10,
2162
+ # "createTime": 1659521314413
2163
+ # }
2164
+ #
2165
+ # withdraw
2166
+ #
2167
+ # {
2168
+ # "code": 0,
2169
+ # "msg": "成功",
2170
+ # "data": {
2171
+ # "withdrawId":"12"
2172
+ # },
2173
+ # "timestamp": 1571745049095
2174
+ # }
2175
+ #
2176
+ address = self.safe_string(transaction, 'address')
2177
+ tag = self.safe_string(transaction, 'addressTag') # set but unused
2178
+ if tag is not None:
2179
+ if len(tag) < 1:
2180
+ tag = None
2181
+ txid = self.safe_string(transaction, 'txId')
2182
+ if (txid is not None) and (txid.find('Internal transfer ') >= 0):
2183
+ txid = txid[18:]
2184
+ currencyId = self.safe_string_2(transaction, 'coin', 'fiatCurrency')
2185
+ code = self.safe_currency_code(currencyId, currency)
2186
+ timestamp = None
2187
+ insertTime = self.safe_integer(transaction, 'insertTime')
2188
+ createTime = self.safe_integer_2(transaction, 'createTime', 'timestamp')
2189
+ type = self.safe_string(transaction, 'type')
2190
+ if type is None:
2191
+ if (insertTime is not None) and (createTime is None):
2192
+ type = 'deposit'
2193
+ timestamp = insertTime
2194
+ elif (insertTime is None) and (createTime is not None):
2195
+ type = 'withdrawal'
2196
+ timestamp = createTime
2197
+ feeCost = self.safe_number_2(transaction, 'transactionFee', 'totalFee')
2198
+ fee = {
2199
+ 'currency': None,
2200
+ 'cost': None,
2201
+ 'rate': None,
2202
+ }
2203
+ if feeCost is not None:
2204
+ fee['currency'] = code
2205
+ fee['cost'] = feeCost
2206
+ internalRaw = self.safe_integer(transaction, 'transferType')
2207
+ internal = False
2208
+ if internalRaw is not None:
2209
+ internal = True
2210
+ id = self.safe_string(transaction, 'id')
2211
+ if id is None:
2212
+ data = self.safe_value(transaction, 'data', {})
2213
+ id = self.safe_string(data, 'withdrawId')
2214
+ type = 'withdrawal'
2215
+ return {
2216
+ 'info': transaction,
2217
+ 'id': id,
2218
+ 'txid': txid,
2219
+ 'type': type,
2220
+ 'currency': code,
2221
+ 'network': self.safe_string(transaction, 'network'),
2222
+ 'amount': self.safe_number(transaction, 'amount'),
2223
+ 'status': self.parse_transaction_status_by_type(self.safe_string(transaction, 'status'), type),
2224
+ 'timestamp': timestamp,
2225
+ 'datetime': self.iso8601(timestamp),
2226
+ 'address': address,
2227
+ 'addressFrom': None,
2228
+ 'addressTo': address,
2229
+ 'tag': tag,
2230
+ 'tagFrom': None,
2231
+ 'tagTo': tag,
2232
+ 'updated': self.safe_integer_2(transaction, 'successTime', 'updateTime'),
2233
+ 'comment': None,
2234
+ 'internal': internal,
2235
+ 'fee': fee,
2236
+ }
2237
+
2238
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2239
+ """
2240
+ :see: https://www.tokocrypto.com/apidocs/#withdraw-signed
2241
+ make a withdrawal
2242
+ :param str code: unified currency code
2243
+ :param float amount: the amount to withdraw
2244
+ :param str address: the address to withdraw to
2245
+ :param str tag:
2246
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2247
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2248
+ """
2249
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
2250
+ await self.load_markets()
2251
+ self.check_address(address)
2252
+ currency = self.currency(code)
2253
+ request: dict = {
2254
+ 'asset': currency['id'],
2255
+ # 'clientId': 'string', # # client's custom id for withdraw order, server does not check it's uniqueness, automatically generated if not sent
2256
+ # 'network': 'string',
2257
+ 'address': address,
2258
+ # 'addressTag': 'string', # for coins like XRP, XMR, etc
2259
+ 'amount': self.number_to_string(amount),
2260
+ }
2261
+ if tag is not None:
2262
+ request['addressTag'] = tag
2263
+ networkCode, query = self.handle_network_code_and_params(params)
2264
+ networkId = self.network_code_to_id(networkCode)
2265
+ if networkId is not None:
2266
+ request['network'] = networkId.upper()
2267
+ response = await self.privatePostOpenV1Withdraws(self.extend(request, query))
2268
+ #
2269
+ # {
2270
+ # "code": 0,
2271
+ # "msg": "成功",
2272
+ # "data": {
2273
+ # "withdrawId":"12"
2274
+ # },
2275
+ # "timestamp": 1571745049095
2276
+ # }
2277
+ #
2278
+ return self.parse_transaction(response, currency)
2279
+
2280
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2281
+ if not (api in self.urls['api']['rest']):
2282
+ raise NotSupported(self.id + ' does not have a testnet/sandbox URL for ' + api + ' endpoints')
2283
+ url = self.urls['api']['rest'][api]
2284
+ url += '/' + path
2285
+ if api == 'wapi':
2286
+ url += '.html'
2287
+ userDataStream = (path == 'userDataStream') or (path == 'listenKey')
2288
+ if userDataStream:
2289
+ if self.apiKey:
2290
+ # v1 special case for userDataStream
2291
+ headers = {
2292
+ 'X-MBX-APIKEY': self.apiKey,
2293
+ 'Content-Type': 'application/x-www-form-urlencoded',
2294
+ }
2295
+ if method != 'GET':
2296
+ body = self.urlencode(params)
2297
+ else:
2298
+ raise AuthenticationError(self.id + ' userDataStream endpoint requires `apiKey` credential')
2299
+ elif (api == 'private') or (api == 'sapi' and path != 'system/status') or (api == 'sapiV3') or (api == 'wapi' and path != 'systemStatus') or (api == 'dapiPrivate') or (api == 'dapiPrivateV2') or (api == 'fapiPrivate') or (api == 'fapiPrivateV2'):
2300
+ self.check_required_credentials()
2301
+ query = None
2302
+ defaultRecvWindow = self.safe_integer(self.options, 'recvWindow')
2303
+ extendedParams = self.extend({
2304
+ 'timestamp': self.nonce(),
2305
+ }, params)
2306
+ if defaultRecvWindow is not None:
2307
+ extendedParams['recvWindow'] = defaultRecvWindow
2308
+ recvWindow = self.safe_integer(params, 'recvWindow')
2309
+ if recvWindow is not None:
2310
+ extendedParams['recvWindow'] = recvWindow
2311
+ if (api == 'sapi') and (path == 'asset/dust'):
2312
+ query = self.urlencode_with_array_repeat(extendedParams)
2313
+ elif (path == 'batchOrders') or (path.find('sub-account') >= 0) or (path == 'capital/withdraw/apply') or (path.find('staking') >= 0):
2314
+ query = self.rawencode(extendedParams)
2315
+ else:
2316
+ query = self.urlencode(extendedParams)
2317
+ signature = self.hmac(self.encode(query), self.encode(self.secret), hashlib.sha256)
2318
+ query += '&' + 'signature=' + signature
2319
+ headers = {
2320
+ 'X-MBX-APIKEY': self.apiKey,
2321
+ }
2322
+ if (method == 'GET') or (method == 'DELETE') or (api == 'wapi'):
2323
+ url += '?' + query
2324
+ else:
2325
+ body = query
2326
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
2327
+ else:
2328
+ if params:
2329
+ url += '?' + self.urlencode(params)
2330
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
2331
+
2332
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2333
+ if (code == 418) or (code == 429):
2334
+ raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason + ' ' + body)
2335
+ # error response in a form: {"code": -1013, "msg": "Invalid quantity."}
2336
+ # following block cointains legacy checks against message patterns in "msg" property
2337
+ # will switch "code" checks eventually, when we know all of them
2338
+ if code >= 400:
2339
+ if body.find('Price * QTY is zero or less') >= 0:
2340
+ raise InvalidOrder(self.id + ' order cost = amount * price is zero or less ' + body)
2341
+ if body.find('LOT_SIZE') >= 0:
2342
+ raise InvalidOrder(self.id + ' order amount should be evenly divisible by lot size ' + body)
2343
+ if body.find('PRICE_FILTER') >= 0:
2344
+ raise InvalidOrder(self.id + ' order price is invalid, i.e. exceeds allowed price precision, exceeds min price or max price limits or is invalid value in general, use self.price_to_precision(symbol, amount) ' + body)
2345
+ if response is None:
2346
+ return None # fallback to default error handler
2347
+ # check success value for wapi endpoints
2348
+ # response in format {'msg': 'The coin does not exist.', 'success': True/false}
2349
+ success = self.safe_bool(response, 'success', True)
2350
+ if not success:
2351
+ messageInner = self.safe_string(response, 'msg')
2352
+ parsedMessage = None
2353
+ if messageInner is not None:
2354
+ try:
2355
+ parsedMessage = json.loads(messageInner)
2356
+ except Exception as e:
2357
+ # do nothing
2358
+ parsedMessage = None
2359
+ if parsedMessage is not None:
2360
+ response = parsedMessage
2361
+ message = self.safe_string(response, 'msg')
2362
+ if message is not None:
2363
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, self.id + ' ' + message)
2364
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, self.id + ' ' + message)
2365
+ # checks against error codes
2366
+ error = self.safe_string(response, 'code')
2367
+ if error is not None:
2368
+ # https://github.com/ccxt/ccxt/issues/6501
2369
+ # https://github.com/ccxt/ccxt/issues/7742
2370
+ if (error == '200') or Precise.string_equals(error, '0'):
2371
+ return None
2372
+ # a workaround for {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
2373
+ # despite that their message is very confusing, it is raised by Binance
2374
+ # on a temporary ban, the API key is valid, but disabled for a while
2375
+ if (error == '-2015') and self.options['hasAlreadyAuthenticatedSuccessfully']:
2376
+ raise DDoSProtection(self.id + ' ' + body)
2377
+ feedback = self.id + ' ' + body
2378
+ if message == 'No need to change margin type.':
2379
+ # not an error
2380
+ # https://github.com/ccxt/ccxt/issues/11268
2381
+ # https://github.com/ccxt/ccxt/pull/11624
2382
+ # POST https://fapi.binance.com/fapi/v1/marginType 400 Bad Request
2383
+ # binanceusdm {"code":-4046,"msg":"No need to change margin type."}
2384
+ raise MarginModeAlreadySet(feedback)
2385
+ self.throw_exactly_matched_exception(self.exceptions['exact'], error, feedback)
2386
+ raise ExchangeError(feedback)
2387
+ if not success:
2388
+ raise ExchangeError(self.id + ' ' + body)
2389
+ return None
2390
+
2391
+ def calculate_rate_limiter_cost(self, api, method, path, params, config={}):
2392
+ if ('noCoin' in config) and not ('coin' in params):
2393
+ return config['noCoin']
2394
+ elif ('noSymbol' in config) and not ('symbol' in params):
2395
+ return config['noSymbol']
2396
+ elif ('noPoolId' in config) and not ('poolId' in params):
2397
+ return config['noPoolId']
2398
+ elif ('byLimit' in config) and ('limit' in params):
2399
+ limit = params['limit']
2400
+ byLimit = config['byLimit']
2401
+ for i in range(0, len(byLimit)):
2402
+ entry = byLimit[i]
2403
+ if limit <= entry[0]:
2404
+ return entry[1]
2405
+ return self.safe_integer(config, 'cost', 1)