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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/whitebit.py ADDED
@@ -0,0 +1,2469 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.base.exchange import Exchange
7
+ from ccxt.abstract.whitebit import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import ArgumentsRequired
15
+ from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import BadSymbol
17
+ from ccxt.base.errors import InsufficientFunds
18
+ from ccxt.base.errors import InvalidOrder
19
+ from ccxt.base.errors import OrderNotFound
20
+ from ccxt.base.errors import NotSupported
21
+ from ccxt.base.errors import DDoSProtection
22
+ from ccxt.base.errors import ExchangeNotAvailable
23
+ from ccxt.base.decimal_to_precision import TICK_SIZE
24
+ from ccxt.base.precise import Precise
25
+
26
+
27
+ class whitebit(Exchange, ImplicitAPI):
28
+
29
+ def describe(self):
30
+ return self.deep_extend(super(whitebit, self).describe(), {
31
+ 'id': 'whitebit',
32
+ 'name': 'WhiteBit',
33
+ 'version': 'v4',
34
+ 'countries': ['EE'],
35
+ 'rateLimit': 50,
36
+ 'pro': True,
37
+ 'has': {
38
+ 'CORS': None,
39
+ 'spot': True,
40
+ 'margin': True,
41
+ 'swap': False,
42
+ 'future': False,
43
+ 'option': False,
44
+ 'cancelAllOrders': True,
45
+ 'cancelAllOrdersAfter': True,
46
+ 'cancelOrder': True,
47
+ 'cancelOrders': False,
48
+ 'createMarketBuyOrderWithCost': True,
49
+ 'createMarketOrderWithCost': False,
50
+ 'createMarketSellOrderWithCost': False,
51
+ 'createOrder': True,
52
+ 'createStopLimitOrder': True,
53
+ 'createStopMarketOrder': True,
54
+ 'createStopOrder': True,
55
+ 'editOrder': False,
56
+ 'fetchBalance': True,
57
+ 'fetchBorrowRateHistories': False,
58
+ 'fetchBorrowRateHistory': False,
59
+ 'fetchClosedOrders': True,
60
+ 'fetchCrossBorrowRate': False,
61
+ 'fetchCrossBorrowRates': False,
62
+ 'fetchCurrencies': True,
63
+ 'fetchDeposit': True,
64
+ 'fetchDepositAddress': True,
65
+ 'fetchDeposits': True,
66
+ 'fetchDepositsWithdrawals': True,
67
+ 'fetchDepositWithdrawFee': 'emulated',
68
+ 'fetchDepositWithdrawFees': True,
69
+ 'fetchFundingHistory': False,
70
+ 'fetchFundingRate': True,
71
+ 'fetchFundingRateHistory': False,
72
+ 'fetchFundingRates': True,
73
+ 'fetchIndexOHLCV': False,
74
+ 'fetchIsolatedBorrowRate': False,
75
+ 'fetchIsolatedBorrowRates': False,
76
+ 'fetchMarginMode': False,
77
+ 'fetchMarkets': True,
78
+ 'fetchMarkOHLCV': False,
79
+ 'fetchMyTrades': True,
80
+ 'fetchOHLCV': True,
81
+ 'fetchOpenInterestHistory': False,
82
+ 'fetchOpenOrders': True,
83
+ 'fetchOrderBook': True,
84
+ 'fetchOrderTrades': True,
85
+ 'fetchPositionMode': False,
86
+ 'fetchPremiumIndexOHLCV': False,
87
+ 'fetchStatus': True,
88
+ 'fetchTicker': True,
89
+ 'fetchTickers': True,
90
+ 'fetchTime': True,
91
+ 'fetchTrades': True,
92
+ 'fetchTradingFee': False,
93
+ 'fetchTradingFees': True,
94
+ 'fetchTransactionFees': True,
95
+ 'repayCrossMargin': False,
96
+ 'repayIsolatedMargin': False,
97
+ 'setLeverage': True,
98
+ 'transfer': True,
99
+ 'withdraw': True,
100
+ },
101
+ 'timeframes': {
102
+ '1m': '1m',
103
+ '3m': '3m',
104
+ '5m': '5m',
105
+ '15m': '15m',
106
+ '30m': '30m',
107
+ '1h': '1h',
108
+ '2h': '2h',
109
+ '4h': '4h',
110
+ '6h': '6h',
111
+ '8h': '8h',
112
+ '12h': '12h',
113
+ '1d': '1d',
114
+ '3d': '3d',
115
+ '1w': '1w',
116
+ '1M': '1M',
117
+ },
118
+ 'urls': {
119
+ 'logo': 'https://user-images.githubusercontent.com/1294454/66732963-8eb7dd00-ee66-11e9-849b-10d9282bb9e0.jpg',
120
+ 'api': {
121
+ 'v1': {
122
+ 'public': 'https://whitebit.com/api/v1/public',
123
+ 'private': 'https://whitebit.com/api/v1',
124
+ },
125
+ 'v2': {
126
+ 'public': 'https://whitebit.com/api/v2/public',
127
+ },
128
+ 'v4': {
129
+ 'public': 'https://whitebit.com/api/v4/public',
130
+ 'private': 'https://whitebit.com/api/v4',
131
+ },
132
+ },
133
+ 'www': 'https://www.whitebit.com',
134
+ 'doc': 'https://github.com/whitebit-exchange/api-docs',
135
+ 'fees': 'https://whitebit.com/fee-schedule',
136
+ 'referral': 'https://whitebit.com/referral/d9bdf40e-28f2-4b52-b2f9-cd1415d82963',
137
+ },
138
+ 'api': {
139
+ 'web': {
140
+ 'get': [
141
+ 'v1/healthcheck',
142
+ ],
143
+ },
144
+ 'v1': {
145
+ 'public': {
146
+ 'get': [
147
+ 'markets',
148
+ 'tickers',
149
+ 'ticker',
150
+ 'symbols',
151
+ 'depth/result',
152
+ 'history',
153
+ 'kline',
154
+ ],
155
+ },
156
+ 'private': {
157
+ 'post': [
158
+ 'account/balance',
159
+ 'order/new',
160
+ 'order/cancel',
161
+ 'orders',
162
+ 'account/order_history',
163
+ 'account/executed_history',
164
+ 'account/executed_history/all',
165
+ 'account/order',
166
+ ],
167
+ },
168
+ },
169
+ 'v2': {
170
+ 'public': {
171
+ 'get': [
172
+ 'markets',
173
+ 'ticker',
174
+ 'assets',
175
+ 'fee',
176
+ 'depth/{market}',
177
+ 'trades/{market}',
178
+ ],
179
+ },
180
+ },
181
+ 'v4': {
182
+ 'public': {
183
+ 'get': [
184
+ 'assets',
185
+ 'collateral/markets',
186
+ 'fee',
187
+ 'orderbook/{market}',
188
+ 'ticker',
189
+ 'trades/{market}',
190
+ 'time',
191
+ 'ping',
192
+ 'markets',
193
+ 'futures',
194
+ 'platform/status',
195
+ ],
196
+ },
197
+ 'private': {
198
+ 'post': [
199
+ 'collateral-account/balance',
200
+ 'collateral-account/balance-summary',
201
+ 'collateral-account/positions/history',
202
+ 'collateral-account/leverage',
203
+ 'collateral-account/positions/open',
204
+ 'collateral-account/summary',
205
+ 'main-account/address',
206
+ 'main-account/balance',
207
+ 'main-account/create-new-address',
208
+ 'main-account/codes',
209
+ 'main-account/codes/apply',
210
+ 'main-account/codes/my',
211
+ 'main-account/codes/history',
212
+ 'main-account/fiat-deposit-url',
213
+ 'main-account/history',
214
+ 'main-account/withdraw',
215
+ 'main-account/withdraw-pay',
216
+ 'main-account/transfer',
217
+ 'main-account/smart/plans',
218
+ 'main-account/smart/investment',
219
+ 'main-account/smart/investment/close',
220
+ 'main-account/smart/investments',
221
+ 'main-account/fee',
222
+ 'main-account/smart/interest-payment-history',
223
+ 'trade-account/balance',
224
+ 'trade-account/executed-history',
225
+ 'trade-account/order',
226
+ 'trade-account/order/history',
227
+ 'order/collateral/limit',
228
+ 'order/collateral/market',
229
+ 'order/collateral/stop-limit',
230
+ 'order/collateral/trigger-market',
231
+ 'order/new',
232
+ 'order/market',
233
+ 'order/stock_market',
234
+ 'order/stop_limit',
235
+ 'order/stop_market',
236
+ 'order/cancel',
237
+ 'order/cancel/all',
238
+ 'order/kill-switch',
239
+ 'order/kill-switch/status',
240
+ 'order/bulk',
241
+ 'order/modify',
242
+ 'orders',
243
+ 'oco-orders',
244
+ 'order/collateral/oco',
245
+ 'order/oco-cancel',
246
+ 'order/oto-cancel',
247
+ 'profile/websocket_token',
248
+ 'convert/estimate',
249
+ 'convert/confirm',
250
+ 'convert/history',
251
+ 'sub-account/create',
252
+ 'sub-account/delete',
253
+ 'sub-account/edit',
254
+ 'sub-account/list',
255
+ 'sub-account/transfer',
256
+ 'sub-account/block',
257
+ 'sub-account/unblock',
258
+ 'sub-account/balances',
259
+ 'sub-account/transfer/history',
260
+ ],
261
+ },
262
+ },
263
+ },
264
+ 'fees': {
265
+ 'trading': {
266
+ 'tierBased': False,
267
+ 'percentage': True,
268
+ 'taker': self.parse_number('0.001'),
269
+ 'maker': self.parse_number('0.001'),
270
+ },
271
+ },
272
+ 'options': {
273
+ 'fiatCurrencies': ['EUR', 'USD', 'RUB', 'UAH'],
274
+ 'fetchBalance': {
275
+ 'account': 'spot',
276
+ },
277
+ 'accountsByType': {
278
+ 'funding': 'main',
279
+ 'main': 'main',
280
+ 'spot': 'spot',
281
+ 'margin': 'collateral',
282
+ 'trade': 'spot',
283
+ },
284
+ 'networksById': {
285
+ 'BEP20': 'BSC',
286
+ },
287
+ 'defaultType': 'spot',
288
+ 'brokerId': 'ccxt',
289
+ },
290
+ 'precisionMode': TICK_SIZE,
291
+ 'exceptions': {
292
+ 'exact': {
293
+ 'Unauthorized request.': AuthenticationError, # {"code":10,"message":"Unauthorized request."}
294
+ 'The market format is invalid.': BadSymbol, # {"code":0,"message":"Validation failed","errors":{"market":["The market format is invalid."]}}
295
+ 'Market is not available': BadSymbol, # {"success":false,"message":{"market":["Market is not available"]},"result":[]}
296
+ 'Invalid payload.': BadRequest, # {"code":9,"message":"Invalid payload."}
297
+ 'Amount must be greater than 0': InvalidOrder, # {"code":0,"message":"Validation failed","errors":{"amount":["Amount must be greater than 0"]}}
298
+ 'Not enough balance.': InsufficientFunds, # {"code":10,"message":"Inner validation failed","errors":{"amount":["Not enough balance."]}}
299
+ 'The order id field is required.': InvalidOrder, # {"code":0,"message":"Validation failed","errors":{"orderId":["The order id field is required."]}}
300
+ 'Not enough balance': InsufficientFunds, # {"code":0,"message":"Validation failed","errors":{"amount":["Not enough balance"]}}
301
+ 'This action is unauthorized.': PermissionDenied, # {"code":0,"message":"This action is unauthorized."}
302
+ 'This API Key is not authorized to perform self action.': PermissionDenied, # {"code":4,"message":"This API Key is not authorized to perform self action."}
303
+ 'Unexecuted order was not found.': OrderNotFound, # {"code":2,"message":"Inner validation failed","errors":{"order_id":["Unexecuted order was not found."]}}
304
+ 'The selected from is invalid.': BadRequest, # {"code":0,"message":"Validation failed","errors":{"from":["The selected from is invalid."]}}
305
+ '503': ExchangeNotAvailable, # {"response":null,"status":503,"errors":{"message":[""]},"notification":null,"warning":null,"_token":null},
306
+ '422': OrderNotFound, # {"response":null,"status":422,"errors":{"orderId":["Finished order id 1295772653 not found on your account"]},"notification":null,"warning":"Finished order id 1295772653 not found on your account","_token":null}
307
+ },
308
+ 'broad': {
309
+ 'This action is unauthorized': PermissionDenied, # {"code":2,"message":"This action is unauthorized. Enable your key in API settings"}
310
+ 'Given amount is less than min amount': InvalidOrder, # {"code":0,"message":"Validation failed","errors":{"amount":["Given amount is less than min amount 200000"],"total":["Total is less than 5.05"]}}
311
+ 'Total is less than': InvalidOrder, # {"code":0,"message":"Validation failed","errors":{"amount":["Given amount is less than min amount 200000"],"total":["Total is less than 5.05"]}}
312
+ 'fee must be no less than': InvalidOrder, # {"code":0,"message":"Validation failed","errors":{"amount":["Total amount + fee must be no less than 5.05505"]}}
313
+ 'Enable your key in API settings': PermissionDenied, # {"code":2,"message":"This action is unauthorized. Enable your key in API settings"}
314
+ 'You don\'t have such amount for transfer': InsufficientFunds, # {"code":3,"message":"Inner validation failed","errors":{"amount":["You don't have such amount for transfer(available 0.44523433, in amount: 2)"]}}
315
+ },
316
+ },
317
+ })
318
+
319
+ def fetch_markets(self, params={}) -> List[Market]:
320
+ """
321
+ retrieves data on all markets for whitebit
322
+ :see: https://docs.whitebit.com/public/http-v4/#market-info
323
+ :param dict [params]: extra parameters specific to the exchange API endpoint
324
+ :returns dict[]: an array of objects representing market data
325
+ """
326
+ markets = self.v4PublicGetMarkets()
327
+ #
328
+ # [
329
+ # {
330
+ # "name": "SON_USD", # Market pair name
331
+ # "stock": "SON", # Ticker of stock currency
332
+ # "money": "USD", # Ticker of money currency
333
+ # "stockPrec": "3", # Stock currency precision
334
+ # "moneyPrec": "2", # Precision of money currency
335
+ # "feePrec": "4", # Fee precision
336
+ # "makerFee": "0.1", # Default maker fee ratio
337
+ # "takerFee": "0.1", # Default taker fee ratio
338
+ # "minAmount": "0.001", # Minimal amount of stock to trade
339
+ # "minTotal": "0.001", # Minimal amount of money to trade
340
+ # "tradesEnabled": True, # Is trading enabled
341
+ # "isCollateral": True, # Is margin trading enabled
342
+ # "type": "spot", # Market type. Possible values: "spot", "futures"
343
+ # "maxTotal": "1000000000" # Maximum total(amount * price) of money to trade
344
+ # },
345
+ # {
346
+ # ...
347
+ # }
348
+ # ]
349
+ #
350
+ return self.parse_markets(markets)
351
+
352
+ def parse_market(self, market: dict) -> Market:
353
+ id = self.safe_string(market, 'name')
354
+ baseId = self.safe_string(market, 'stock')
355
+ quoteId = self.safe_string(market, 'money')
356
+ quoteId = 'USDT' if (quoteId == 'PERP') else quoteId
357
+ base = self.safe_currency_code(baseId)
358
+ quote = self.safe_currency_code(quoteId)
359
+ active = self.safe_value(market, 'tradesEnabled')
360
+ isCollateral = self.safe_value(market, 'isCollateral')
361
+ typeId = self.safe_string(market, 'type')
362
+ type: MarketType
363
+ settle: Str = None
364
+ settleId: Str = None
365
+ symbol = base + '/' + quote
366
+ swap = typeId == 'futures'
367
+ margin = isCollateral and not swap
368
+ contract = False
369
+ amountPrecision = self.parse_number(self.parse_precision(self.safe_string(market, 'stockPrec')))
370
+ contractSize = amountPrecision
371
+ linear: Bool = None
372
+ inverse: Bool = None
373
+ if swap:
374
+ settleId = quoteId
375
+ settle = self.safe_currency_code(settleId)
376
+ symbol = symbol + ':' + settle
377
+ type = 'swap'
378
+ contract = True
379
+ linear = True
380
+ inverse = False
381
+ else:
382
+ type = 'spot'
383
+ takerFeeRate = self.safe_string(market, 'takerFee')
384
+ taker = Precise.string_div(takerFeeRate, '100')
385
+ makerFeeRate = self.safe_string(market, 'makerFee')
386
+ maker = Precise.string_div(makerFeeRate, '100')
387
+ return {
388
+ 'id': id,
389
+ 'symbol': symbol,
390
+ 'base': base,
391
+ 'quote': quote,
392
+ 'settle': settle,
393
+ 'baseId': baseId,
394
+ 'quoteId': quoteId,
395
+ 'settleId': settleId,
396
+ 'type': type,
397
+ 'spot': not swap,
398
+ 'margin': margin,
399
+ 'swap': swap,
400
+ 'future': False,
401
+ 'option': False,
402
+ 'active': active,
403
+ 'contract': contract,
404
+ 'linear': linear,
405
+ 'inverse': inverse,
406
+ 'taker': self.parse_number(taker),
407
+ 'maker': self.parse_number(maker),
408
+ 'contractSize': contractSize,
409
+ 'expiry': None,
410
+ 'expiryDatetime': None,
411
+ 'strike': None,
412
+ 'optionType': None,
413
+ 'precision': {
414
+ 'amount': amountPrecision,
415
+ 'price': self.parse_number(self.parse_precision(self.safe_string(market, 'moneyPrec'))),
416
+ },
417
+ 'limits': {
418
+ 'leverage': {
419
+ 'min': None,
420
+ 'max': None,
421
+ },
422
+ 'amount': {
423
+ 'min': self.safe_number(market, 'minAmount'),
424
+ 'max': None,
425
+ },
426
+ 'price': {
427
+ 'min': None,
428
+ 'max': None,
429
+ },
430
+ 'cost': {
431
+ 'min': self.safe_number(market, 'minTotal'),
432
+ 'max': self.safe_number(market, 'maxTotal'),
433
+ },
434
+ },
435
+ 'created': None,
436
+ 'info': market,
437
+ }
438
+
439
+ def fetch_currencies(self, params={}) -> Currencies:
440
+ """
441
+ fetches all available currencies on an exchange
442
+ :see: https://docs.whitebit.com/public/http-v4/#asset-status-list
443
+ :param dict [params]: extra parameters specific to the exchange API endpoint
444
+ :returns dict: an associative dictionary of currencies
445
+ """
446
+ response = self.v4PublicGetAssets(params)
447
+ #
448
+ # "BTC": {
449
+ # "name": "Bitcoin",
450
+ # "unified_cryptoasset_id": 1,
451
+ # "can_withdraw": True,
452
+ # "can_deposit": True,
453
+ # "min_withdraw": "0.001",
454
+ # "max_withdraw": "2",
455
+ # "maker_fee": "0.1",
456
+ # "taker_fee": "0.1",
457
+ # "min_deposit": "0.0001",
458
+ # "max_deposit": "0",
459
+ # },
460
+ #
461
+ ids = list(response.keys())
462
+ result: dict = {}
463
+ for i in range(0, len(ids)):
464
+ id = ids[i]
465
+ currency = response[id]
466
+ # breaks down in Python due to utf8 encoding issues on the exchange side
467
+ # name = self.safe_string(currency, 'name')
468
+ canDeposit = self.safe_bool(currency, 'can_deposit', True)
469
+ canWithdraw = self.safe_bool(currency, 'can_withdraw', True)
470
+ active = canDeposit and canWithdraw
471
+ code = self.safe_currency_code(id)
472
+ result[code] = {
473
+ 'id': id,
474
+ 'code': code,
475
+ 'info': currency, # the original payload
476
+ 'name': None, # see the comment above
477
+ 'active': active,
478
+ 'deposit': canDeposit,
479
+ 'withdraw': canWithdraw,
480
+ 'fee': None,
481
+ 'precision': None,
482
+ 'limits': {
483
+ 'amount': {
484
+ 'min': None,
485
+ 'max': None,
486
+ },
487
+ 'withdraw': {
488
+ 'min': self.safe_number(currency, 'min_withdraw'),
489
+ 'max': self.safe_number(currency, 'max_withdraw'),
490
+ },
491
+ },
492
+ }
493
+ return result
494
+
495
+ def fetch_transaction_fees(self, codes: Strings = None, params={}):
496
+ """
497
+ * @deprecated
498
+ please use fetchDepositWithdrawFees instead
499
+ :see: https://docs.whitebit.com/public/http-v4/#fee
500
+ :param str[]|None codes: not used by fetchTransactionFees()
501
+ :param dict [params]: extra parameters specific to the exchange API endpoint
502
+ :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
503
+ """
504
+ self.load_markets()
505
+ response = self.v4PublicGetFee(params)
506
+ #
507
+ # {
508
+ # "1INCH":{
509
+ # "is_depositable":true,
510
+ # "is_withdrawal":true,
511
+ # "ticker":"1INCH",
512
+ # "name":"1inch",
513
+ # "providers":[
514
+ # ],
515
+ # "withdraw":{
516
+ # "max_amount":"0",
517
+ # "min_amount":"21.5",
518
+ # "fixed":"17.5",
519
+ # "flex":null
520
+ # },
521
+ # "deposit":{
522
+ # "max_amount":"0",
523
+ # "min_amount":"19.5",
524
+ # "fixed":null,
525
+ # "flex":null
526
+ # }
527
+ # },
528
+ # {...}
529
+ # }
530
+ #
531
+ currenciesIds = list(response.keys())
532
+ withdrawFees: dict = {}
533
+ depositFees: dict = {}
534
+ for i in range(0, len(currenciesIds)):
535
+ currency = currenciesIds[i]
536
+ data = response[currency]
537
+ code = self.safe_currency_code(currency)
538
+ withdraw = self.safe_value(data, 'withdraw', {})
539
+ withdrawFees[code] = self.safe_string(withdraw, 'fixed')
540
+ deposit = self.safe_value(data, 'deposit', {})
541
+ depositFees[code] = self.safe_string(deposit, 'fixed')
542
+ return {
543
+ 'withdraw': withdrawFees,
544
+ 'deposit': depositFees,
545
+ 'info': response,
546
+ }
547
+
548
+ def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
549
+ """
550
+ fetch deposit and withdraw fees
551
+ :see: https://docs.whitebit.com/public/http-v4/#fee
552
+ :param str[]|None codes: not used by fetchDepositWithdrawFees()
553
+ :param dict [params]: extra parameters specific to the exchange API endpoint
554
+ :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
555
+ """
556
+ self.load_markets()
557
+ response = self.v4PublicGetFee(params)
558
+ #
559
+ # {
560
+ # "1INCH": {
561
+ # "is_depositable": True,
562
+ # "is_withdrawal": True,
563
+ # "ticker": "1INCH",
564
+ # "name": "1inch",
565
+ # "providers": [],
566
+ # "withdraw": {
567
+ # "max_amount": "0",
568
+ # "min_amount": "21.5",
569
+ # "fixed": "17.5",
570
+ # "flex": null
571
+ # },
572
+ # "deposit": {
573
+ # "max_amount": "0",
574
+ # "min_amount": "19.5",
575
+ # "fixed": null,
576
+ # "flex": null
577
+ # }
578
+ # },
579
+ # "WBT(ERC20)": {
580
+ # "is_depositable": True,
581
+ # "is_withdrawal": True,
582
+ # "ticker": "WBT",
583
+ # "name": "WhiteBIT Token",
584
+ # "providers": [],
585
+ # "withdraw": {max_amount: "0", min_amount: '0.7', fixed: "0.253", flex: null},
586
+ # "deposit": {max_amount: "0", min_amount: "0.35", fixed: null, flex: null}
587
+ # },
588
+ # "WBT(TRC20)": {
589
+ # "is_depositable": True,
590
+ # "is_withdrawal": True,
591
+ # "ticker": "WBT",
592
+ # "name": "WhiteBIT Token",
593
+ # "providers": [],
594
+ # "withdraw": {max_amount: "0", min_amount: "1.5", fixed: "0.075", flex: null},
595
+ # "deposit": {max_amount: "0", min_amount: "0.75", fixed: null, flex: null}
596
+ # },
597
+ # ...
598
+ # }
599
+ #
600
+ return self.parse_deposit_withdraw_fees(response, codes)
601
+
602
+ def parse_deposit_withdraw_fees(self, response, codes=None, currencyIdKey=None):
603
+ #
604
+ # {
605
+ # "1INCH": {
606
+ # "is_depositable": True,
607
+ # "is_withdrawal": True,
608
+ # "ticker": "1INCH",
609
+ # "name": "1inch",
610
+ # "providers": [],
611
+ # "withdraw": {
612
+ # "max_amount": "0",
613
+ # "min_amount": "21.5",
614
+ # "fixed": "17.5",
615
+ # "flex": null
616
+ # },
617
+ # "deposit": {
618
+ # "max_amount": "0",
619
+ # "min_amount": "19.5",
620
+ # "fixed": null,
621
+ # "flex": null
622
+ # }
623
+ # },
624
+ # "WBT(ERC20)": {
625
+ # "is_depositable": True,
626
+ # "is_withdrawal": True,
627
+ # "ticker": "WBT",
628
+ # "name": "WhiteBIT Token",
629
+ # "providers": [],
630
+ # "withdraw": {max_amount: "0", min_amount: "0.7", fixed: "0.253", flex: null},
631
+ # "deposit": {max_amount: "0", min_amount: "0.35", fixed: null, flex: null}
632
+ # },
633
+ # "WBT(TRC20)": {
634
+ # "is_depositable": True,
635
+ # "is_withdrawal": True,
636
+ # "ticker": "WBT",
637
+ # "name": "WhiteBIT Token",
638
+ # "providers": [],
639
+ # "withdraw": {max_amount: "0", min_amount: "1.5", fixed: "0.075", flex: null},
640
+ # "deposit": {max_amount: "0", min_amount: "0.75", fixed: null, flex: null}
641
+ # },
642
+ # ...
643
+ # }
644
+ #
645
+ depositWithdrawFees: dict = {}
646
+ codes = self.market_codes(codes)
647
+ currencyIds = list(response.keys())
648
+ for i in range(0, len(currencyIds)):
649
+ entry = currencyIds[i]
650
+ splitEntry = entry.split(' ')
651
+ currencyId = splitEntry[0]
652
+ feeInfo = response[entry]
653
+ code = self.safe_currency_code(currencyId)
654
+ if (codes is None) or (self.in_array(code, codes)):
655
+ depositWithdrawFee = self.safe_value(depositWithdrawFees, code)
656
+ if depositWithdrawFee is None:
657
+ depositWithdrawFees[code] = self.deposit_withdraw_fee({})
658
+ depositWithdrawFees[code]['info'][entry] = feeInfo
659
+ networkId = self.safe_string(splitEntry, 1)
660
+ withdraw = self.safe_value(feeInfo, 'withdraw')
661
+ deposit = self.safe_value(feeInfo, 'deposit')
662
+ withdrawFee = self.safe_number(withdraw, 'fixed')
663
+ depositFee = self.safe_number(deposit, 'fixed')
664
+ withdrawResult: dict = {
665
+ 'fee': withdrawFee,
666
+ 'percentage': False if (withdrawFee is not None) else None,
667
+ }
668
+ depositResult: dict = {
669
+ 'fee': depositFee,
670
+ 'percentage': False if (depositFee is not None) else None,
671
+ }
672
+ if networkId is not None:
673
+ networkLength = len(networkId)
674
+ networkId = networkId[1:networkLength - 1]
675
+ networkCode = self.network_id_to_code(networkId)
676
+ depositWithdrawFees[code]['networks'][networkCode] = {
677
+ 'withdraw': withdrawResult,
678
+ 'deposit': depositResult,
679
+ }
680
+ else:
681
+ depositWithdrawFees[code]['withdraw'] = withdrawResult
682
+ depositWithdrawFees[code]['deposit'] = depositResult
683
+ depositWithdrawCodes = list(depositWithdrawFees.keys())
684
+ for i in range(0, len(depositWithdrawCodes)):
685
+ code = depositWithdrawCodes[i]
686
+ currency = self.currency(code)
687
+ depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
688
+ return depositWithdrawFees
689
+
690
+ def fetch_trading_fees(self, params={}) -> TradingFees:
691
+ """
692
+ fetch the trading fees for multiple markets
693
+ :see: https://docs.whitebit.com/public/http-v4/#asset-status-list
694
+ :param dict [params]: extra parameters specific to the exchange API endpoint
695
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
696
+ """
697
+ self.load_markets()
698
+ response = self.v4PublicGetAssets(params)
699
+ #
700
+ # {
701
+ # "1INCH": {
702
+ # "name": "1inch",
703
+ # "unified_cryptoasset_id": "8104",
704
+ # "can_withdraw": True,
705
+ # "can_deposit": True,
706
+ # "min_withdraw": "33",
707
+ # "max_withdraw": "0",
708
+ # "maker_fee": "0.1",
709
+ # "taker_fee": "0.1",
710
+ # "min_deposit": "30",
711
+ # "max_deposit": "0"
712
+ # },
713
+ # ...
714
+ # }
715
+ #
716
+ result: dict = {}
717
+ for i in range(0, len(self.symbols)):
718
+ symbol = self.symbols[i]
719
+ market = self.market(symbol)
720
+ fee = self.safe_value(response, market['baseId'], {})
721
+ makerFee = self.safe_string(fee, 'maker_fee')
722
+ takerFee = self.safe_string(fee, 'taker_fee')
723
+ makerFee = Precise.string_div(makerFee, '100')
724
+ takerFee = Precise.string_div(takerFee, '100')
725
+ result[symbol] = {
726
+ 'info': fee,
727
+ 'symbol': market['symbol'],
728
+ 'percentage': True,
729
+ 'tierBased': False,
730
+ 'maker': self.parse_number(makerFee),
731
+ 'taker': self.parse_number(takerFee),
732
+ }
733
+ return result
734
+
735
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
736
+ """
737
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
738
+ :see: https://docs.whitebit.com/public/http-v4/#market-activity
739
+ :param str symbol: unified symbol of the market to fetch the ticker for
740
+ :param dict [params]: extra parameters specific to the exchange API endpoint
741
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
742
+ """
743
+ self.load_markets()
744
+ market = self.market(symbol)
745
+ request: dict = {
746
+ 'market': market['id'],
747
+ }
748
+ response = self.v1PublicGetTicker(self.extend(request, params))
749
+ #
750
+ # {
751
+ # "success":true,
752
+ # "message":"",
753
+ # "result": {
754
+ # "bid":"0.021979",
755
+ # "ask":"0.021996",
756
+ # "open":"0.02182",
757
+ # "high":"0.022039",
758
+ # "low":"0.02161",
759
+ # "last":"0.021987",
760
+ # "volume":"2810.267",
761
+ # "deal":"61.383565474",
762
+ # "change":"0.76",
763
+ # },
764
+ # }
765
+ #
766
+ ticker = self.safe_dict(response, 'result', {})
767
+ return self.parse_ticker(ticker, market)
768
+
769
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
770
+ #
771
+ # FetchTicker(v1)
772
+ #
773
+ # {
774
+ # "bid": "0.021979",
775
+ # "ask": "0.021996",
776
+ # "open": "0.02182",
777
+ # "high": "0.022039",
778
+ # "low": "0.02161",
779
+ # "last": "0.021987",
780
+ # "volume": "2810.267",
781
+ # "deal": "61.383565474",
782
+ # "change": "0.76",
783
+ # }
784
+ #
785
+ # FetchTickers(v4)
786
+ #
787
+ # "BCH_RUB": {
788
+ # "base_id": 1831,
789
+ # "quote_id": 0,
790
+ # "last_price": "32830.21",
791
+ # "quote_volume": "1494659.8024096",
792
+ # "base_volume": "46.1083",
793
+ # "isFrozen": False,
794
+ # "change": "2.12" # in percent
795
+ # }
796
+ #
797
+ market = self.safe_market(None, market)
798
+ last = self.safe_string(ticker, 'last_price')
799
+ return self.safe_ticker({
800
+ 'symbol': market['symbol'],
801
+ 'timestamp': None,
802
+ 'datetime': None,
803
+ 'high': self.safe_string(ticker, 'high'),
804
+ 'low': self.safe_string(ticker, 'low'),
805
+ 'bid': self.safe_string(ticker, 'bid'),
806
+ 'bidVolume': None,
807
+ 'ask': self.safe_string(ticker, 'ask'),
808
+ 'askVolume': None,
809
+ 'vwap': None,
810
+ 'open': self.safe_string(ticker, 'open'),
811
+ 'close': last,
812
+ 'last': last,
813
+ 'previousClose': None,
814
+ 'change': None,
815
+ 'percentage': self.safe_string(ticker, 'change'),
816
+ 'average': None,
817
+ 'baseVolume': self.safe_string_2(ticker, 'base_volume', 'volume'),
818
+ 'quoteVolume': self.safe_string_2(ticker, 'quote_volume', 'deal'),
819
+ 'info': ticker,
820
+ }, market)
821
+
822
+ def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
823
+ """
824
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
825
+ :see: https://docs.whitebit.com/public/http-v4/#market-activity
826
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
827
+ :param dict [params]: extra parameters specific to the exchange API endpoint
828
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
829
+ """
830
+ self.load_markets()
831
+ symbols = self.market_symbols(symbols)
832
+ response = self.v4PublicGetTicker(params)
833
+ #
834
+ # "BCH_RUB": {
835
+ # "base_id":1831,
836
+ # "quote_id":0,
837
+ # "last_price":"32830.21",
838
+ # "quote_volume":"1494659.8024096",
839
+ # "base_volume":"46.1083",
840
+ # "isFrozen":false,
841
+ # "change":"2.12"
842
+ # },
843
+ #
844
+ marketIds = list(response.keys())
845
+ result: dict = {}
846
+ for i in range(0, len(marketIds)):
847
+ marketId = marketIds[i]
848
+ market = self.safe_market(marketId)
849
+ ticker = self.parse_ticker(response[marketId], market)
850
+ symbol = ticker['symbol']
851
+ result[symbol] = ticker
852
+ return self.filter_by_array_tickers(result, 'symbol', symbols)
853
+
854
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
855
+ """
856
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
857
+ :see: https://docs.whitebit.com/public/http-v4/#orderbook
858
+ :param str symbol: unified symbol of the market to fetch the order book for
859
+ :param int [limit]: the maximum amount of order book entries to return
860
+ :param dict [params]: extra parameters specific to the exchange API endpoint
861
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
862
+ """
863
+ self.load_markets()
864
+ market = self.market(symbol)
865
+ request: dict = {
866
+ 'market': market['id'],
867
+ }
868
+ if limit is not None:
869
+ request['limit'] = limit # default = 100, maximum = 100
870
+ response = self.v4PublicGetOrderbookMarket(self.extend(request, params))
871
+ #
872
+ # {
873
+ # "timestamp": 1594391413,
874
+ # "asks": [
875
+ # [
876
+ # "9184.41",
877
+ # "0.773162"
878
+ # ],
879
+ # [...]
880
+ # ],
881
+ # "bids": [
882
+ # [
883
+ # "9181.19",
884
+ # "0.010873"
885
+ # ],
886
+ # [...]
887
+ # ]
888
+ # }
889
+ #
890
+ timestamp = self.safe_timestamp(response, 'timestamp')
891
+ return self.parse_order_book(response, symbol, timestamp)
892
+
893
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
894
+ """
895
+ get the list of most recent trades for a particular symbol
896
+ :see: https://docs.whitebit.com/public/http-v4/#recent-trades
897
+ :param str symbol: unified symbol of the market to fetch trades for
898
+ :param int [since]: timestamp in ms of the earliest trade to fetch
899
+ :param int [limit]: the maximum amount of trades to fetch
900
+ :param dict [params]: extra parameters specific to the exchange API endpoint
901
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
902
+ """
903
+ self.load_markets()
904
+ market = self.market(symbol)
905
+ request: dict = {
906
+ 'market': market['id'],
907
+ }
908
+ response = self.v4PublicGetTradesMarket(self.extend(request, params))
909
+ #
910
+ # [
911
+ # {
912
+ # "tradeID": 158056419,
913
+ # "price": "9186.13",
914
+ # "quote_volume": "0.0021",
915
+ # "base_volume": "9186.13",
916
+ # "trade_timestamp": 1594391747,
917
+ # "type": "sell"
918
+ # },
919
+ # ],
920
+ #
921
+ return self.parse_trades(response, market, since, limit)
922
+
923
+ def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
924
+ """
925
+ fetch all trades made by the user
926
+ :see: https://docs.whitebit.com/private/http-trade-v4/#query-executed-order-history
927
+ :param str symbol: unified symbol of the market to fetch trades for
928
+ :param int [since]: timestamp in ms of the earliest trade to fetch
929
+ :param int [limit]: the maximum amount of trades to fetch
930
+ :param dict [params]: extra parameters specific to the exchange API endpoint
931
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
932
+ """
933
+ self.load_markets()
934
+ market: Market = None
935
+ request: dict = {}
936
+ if symbol is not None:
937
+ market = self.market(symbol)
938
+ request['market'] = market['id']
939
+ response = self.v4PrivatePostTradeAccountExecutedHistory(self.extend(request, params))
940
+ #
941
+ # when no symbol is provided
942
+ #
943
+ # {
944
+ # "USDC_USDT":[
945
+ # {
946
+ # "id":"1343815269",
947
+ # "clientOrderId":"",
948
+ # "time":"1641051917.532965",
949
+ # "side":"sell",
950
+ # "role":"2",
951
+ # "amount":"9.986",
952
+ # "price":"0.9995",
953
+ # "deal":"9.981007",
954
+ # "fee":"0.009981007",
955
+ # "orderId":"58166729555"
956
+ # },
957
+ # ]
958
+ # }
959
+ #
960
+ # when a symbol is provided
961
+ #
962
+ # [
963
+ # {
964
+ # "id": 1343815269,
965
+ # "clientOrderId": '',
966
+ # "time": 1641051917.532965,
967
+ # "side": "sell",
968
+ # "role": 2,
969
+ # "amount": "9.986",
970
+ # "price": "0.9995",
971
+ # "deal": "9.981007",
972
+ # "fee": "0.009981007",
973
+ # "orderId": 58166729555,
974
+ # },
975
+ # ]
976
+ #
977
+ if isinstance(response, list):
978
+ return self.parse_trades(response, market, since, limit)
979
+ else:
980
+ results = []
981
+ keys = list(response.keys())
982
+ for i in range(0, len(keys)):
983
+ marketId = keys[i]
984
+ marketNew = self.safe_market(marketId, None, '_')
985
+ rawTrades = self.safe_value(response, marketId, [])
986
+ parsed = self.parse_trades(rawTrades, marketNew, since, limit)
987
+ results = self.array_concat(results, parsed)
988
+ results = self.sort_by_2(results, 'timestamp', 'id')
989
+ return self.filter_by_since_limit(results, since, limit, 'timestamp')
990
+
991
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
992
+ #
993
+ # fetchTradesV4
994
+ #
995
+ # {
996
+ # "tradeID": 158056419,
997
+ # "price": "9186.13",
998
+ # "quote_volume": "0.0021",
999
+ # "base_volume": "9186.13",
1000
+ # "trade_timestamp": 1594391747,
1001
+ # "type": "sell"
1002
+ # }
1003
+ #
1004
+ # orderTrades(v4Private)
1005
+ #
1006
+ # {
1007
+ # "time": 1593342324.613711,
1008
+ # "fee": "0.00000419198",
1009
+ # "price": "0.00000701",
1010
+ # "amount": "598",
1011
+ # "id": 149156519, # trade id
1012
+ # "dealOrderId": 3134995325, # orderId
1013
+ # "clientOrderId": "customId11",
1014
+ # "role": 2, # 1 = maker, 2 = taker
1015
+ # "deal": "0.00419198" # amount in money
1016
+ # }
1017
+ #
1018
+ # fetchMyTrades
1019
+ #
1020
+ # {
1021
+ # "id": 1343815269,
1022
+ # "clientOrderId": '',
1023
+ # "time": 1641051917.532965,
1024
+ # "side": "sell",
1025
+ # "role": 2,
1026
+ # "amount": "9.986",
1027
+ # "price": "0.9995",
1028
+ # "deal": "9.981007",
1029
+ # "fee": "0.009981007",
1030
+ # "orderId": 58166729555,
1031
+ # }
1032
+ #
1033
+ market = self.safe_market(None, market)
1034
+ timestamp = self.safe_timestamp_2(trade, 'time', 'trade_timestamp')
1035
+ orderId = self.safe_string_2(trade, 'dealOrderId', 'orderId')
1036
+ cost = self.safe_string(trade, 'deal')
1037
+ price = self.safe_string(trade, 'price')
1038
+ amount = self.safe_string_2(trade, 'amount', 'quote_volume')
1039
+ id = self.safe_string_2(trade, 'id', 'tradeID')
1040
+ side = self.safe_string_2(trade, 'type', 'side')
1041
+ symbol = market['symbol']
1042
+ role = self.safe_integer(trade, 'role')
1043
+ takerOrMaker: Str = None
1044
+ if role is not None:
1045
+ takerOrMaker = 'maker' if (role == 1) else 'taker'
1046
+ fee = None
1047
+ feeCost = self.safe_string(trade, 'fee')
1048
+ if feeCost is not None:
1049
+ fee = {
1050
+ 'cost': feeCost,
1051
+ 'currency': market['quote'],
1052
+ }
1053
+ return self.safe_trade({
1054
+ 'info': trade,
1055
+ 'timestamp': timestamp,
1056
+ 'datetime': self.iso8601(timestamp),
1057
+ 'symbol': symbol,
1058
+ 'id': id,
1059
+ 'order': orderId,
1060
+ 'type': None,
1061
+ 'takerOrMaker': takerOrMaker,
1062
+ 'side': side,
1063
+ 'price': price,
1064
+ 'amount': amount,
1065
+ 'cost': cost,
1066
+ 'fee': fee,
1067
+ }, market)
1068
+
1069
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1070
+ """
1071
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1072
+ :see: https://docs.whitebit.com/public/http-v1/#kline
1073
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1074
+ :param str timeframe: the length of time each candle represents
1075
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1076
+ :param int [limit]: the maximum amount of candles to fetch
1077
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1078
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1079
+ """
1080
+ self.load_markets()
1081
+ market = self.market(symbol)
1082
+ request: dict = {
1083
+ 'market': market['id'],
1084
+ 'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1085
+ }
1086
+ if since is not None:
1087
+ maxLimit = 1440
1088
+ if limit is None:
1089
+ limit = maxLimit
1090
+ limit = min(limit, maxLimit)
1091
+ start = self.parse_to_int(since / 1000)
1092
+ request['start'] = start
1093
+ if limit is not None:
1094
+ request['limit'] = min(limit, 1440)
1095
+ response = self.v1PublicGetKline(self.extend(request, params))
1096
+ #
1097
+ # {
1098
+ # "success":true,
1099
+ # "message":"",
1100
+ # "result":[
1101
+ # [1591488000,"0.025025","0.025025","0.025029","0.025023","6.181","0.154686629"],
1102
+ # [1591488060,"0.025028","0.025033","0.025035","0.025026","8.067","0.201921167"],
1103
+ # [1591488120,"0.025034","0.02505","0.02505","0.025034","20.089","0.503114696"],
1104
+ # ]
1105
+ # }
1106
+ #
1107
+ result = self.safe_list(response, 'result', [])
1108
+ return self.parse_ohlcvs(result, market, timeframe, since, limit)
1109
+
1110
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1111
+ #
1112
+ # [
1113
+ # 1591488000,
1114
+ # "0.025025",
1115
+ # "0.025025",
1116
+ # "0.025029",
1117
+ # "0.025023",
1118
+ # "6.181",
1119
+ # "0.154686629"
1120
+ # ]
1121
+ #
1122
+ return [
1123
+ self.safe_timestamp(ohlcv, 0), # timestamp
1124
+ self.safe_number(ohlcv, 1), # open
1125
+ self.safe_number(ohlcv, 3), # high
1126
+ self.safe_number(ohlcv, 4), # low
1127
+ self.safe_number(ohlcv, 2), # close
1128
+ self.safe_number(ohlcv, 5), # volume
1129
+ ]
1130
+
1131
+ def fetch_status(self, params={}):
1132
+ """
1133
+ the latest known information on the availability of the exchange API
1134
+ :see: https://docs.whitebit.com/public/http-v4/#server-status
1135
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1136
+ :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
1137
+ """
1138
+ response = self.v4PublicGetPing(params)
1139
+ #
1140
+ # [
1141
+ # "pong"
1142
+ # ]
1143
+ #
1144
+ status = self.safe_string(response, 0)
1145
+ return {
1146
+ 'status': 'ok' if (status == 'pong') else status,
1147
+ 'updated': None,
1148
+ 'eta': None,
1149
+ 'url': None,
1150
+ 'info': response,
1151
+ }
1152
+
1153
+ def fetch_time(self, params={}):
1154
+ """
1155
+ fetches the current integer timestamp in milliseconds from the exchange server
1156
+ :see: https://docs.whitebit.com/public/http-v4/#server-time
1157
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1158
+ :returns int: the current integer timestamp in milliseconds from the exchange server
1159
+ """
1160
+ response = self.v4PublicGetTime(params)
1161
+ #
1162
+ # {
1163
+ # "time":1635467280514
1164
+ # }
1165
+ #
1166
+ return self.safe_integer(response, 'time')
1167
+
1168
+ def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
1169
+ """
1170
+ create a market order by providing the symbol, side and cost
1171
+ :param str symbol: unified symbol of the market to create an order in
1172
+ :param str side: 'buy' or 'sell'
1173
+ :param float cost: how much you want to trade in units of the quote currency
1174
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1175
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1176
+ """
1177
+ params['cost'] = cost
1178
+ # only buy side is supported
1179
+ return self.create_order(symbol, 'market', side, 0, None, params)
1180
+
1181
+ def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
1182
+ """
1183
+ create a market buy order by providing the symbol and cost
1184
+ :param str symbol: unified symbol of the market to create an order in
1185
+ :param float cost: how much you want to trade in units of the quote currency
1186
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1187
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1188
+ """
1189
+ return self.create_market_order_with_cost(symbol, 'buy', cost, params)
1190
+
1191
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1192
+ """
1193
+ create a trade order
1194
+ :see: https://docs.whitebit.com/private/http-trade-v4/#create-limit-order
1195
+ :see: https://docs.whitebit.com/private/http-trade-v4/#create-market-order
1196
+ :see: https://docs.whitebit.com/private/http-trade-v4/#create-buy-stock-market-order
1197
+ :see: https://docs.whitebit.com/private/http-trade-v4/#create-stop-limit-order
1198
+ :see: https://docs.whitebit.com/private/http-trade-v4/#create-stop-market-order
1199
+ :param str symbol: unified symbol of the market to create an order in
1200
+ :param str type: 'market' or 'limit'
1201
+ :param str side: 'buy' or 'sell'
1202
+ :param float amount: how much of currency you want to trade in units of base currency
1203
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1204
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1205
+ :param float [params.cost]: *market orders only* the cost of the order in units of the base currency
1206
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1207
+ """
1208
+ self.load_markets()
1209
+ market = self.market(symbol)
1210
+ request: dict = {
1211
+ 'market': market['id'],
1212
+ 'side': side,
1213
+ }
1214
+ cost = None
1215
+ cost, params = self.handle_param_string(params, 'cost')
1216
+ if cost is not None:
1217
+ if (side != 'buy') or (type != 'market'):
1218
+ raise InvalidOrder(self.id + ' createOrder() cost is only supported for market buy orders')
1219
+ request['amount'] = self.cost_to_precision(symbol, cost)
1220
+ else:
1221
+ request['amount'] = self.amount_to_precision(symbol, amount)
1222
+ clientOrderId = self.safe_string_2(params, 'clOrdId', 'clientOrderId')
1223
+ if clientOrderId is None:
1224
+ brokerId = self.safe_string(self.options, 'brokerId')
1225
+ if brokerId is not None:
1226
+ request['clientOrderId'] = brokerId + self.uuid16()
1227
+ else:
1228
+ request['clientOrderId'] = clientOrderId
1229
+ params = self.omit(params, ['clientOrderId'])
1230
+ marketType = self.safe_string(market, 'type')
1231
+ isLimitOrder = type == 'limit'
1232
+ isMarketOrder = type == 'market'
1233
+ stopPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'activation_price'])
1234
+ isStopOrder = (stopPrice is not None)
1235
+ postOnly = self.is_post_only(isMarketOrder, False, params)
1236
+ marginMode, query = self.handle_margin_mode_and_params('createOrder', params)
1237
+ if postOnly:
1238
+ request['postOnly'] = True
1239
+ if marginMode is not None and marginMode != 'cross':
1240
+ raise NotSupported(self.id + ' createOrder() is only available for cross margin')
1241
+ params = self.omit(query, ['postOnly', 'triggerPrice', 'stopPrice'])
1242
+ useCollateralEndpoint = marginMode is not None or marketType == 'swap'
1243
+ response = None
1244
+ if isStopOrder:
1245
+ request['activation_price'] = self.price_to_precision(symbol, stopPrice)
1246
+ if isLimitOrder:
1247
+ # stop limit order
1248
+ request['price'] = self.price_to_precision(symbol, price)
1249
+ response = self.v4PrivatePostOrderStopLimit(self.extend(request, params))
1250
+ else:
1251
+ # stop market order
1252
+ if useCollateralEndpoint:
1253
+ response = self.v4PrivatePostOrderCollateralTriggerMarket(self.extend(request, params))
1254
+ else:
1255
+ response = self.v4PrivatePostOrderStopMarket(self.extend(request, params))
1256
+ else:
1257
+ if isLimitOrder:
1258
+ # limit order
1259
+ request['price'] = self.price_to_precision(symbol, price)
1260
+ if useCollateralEndpoint:
1261
+ response = self.v4PrivatePostOrderCollateralLimit(self.extend(request, params))
1262
+ else:
1263
+ response = self.v4PrivatePostOrderNew(self.extend(request, params))
1264
+ else:
1265
+ # market order
1266
+ if useCollateralEndpoint:
1267
+ response = self.v4PrivatePostOrderCollateralMarket(self.extend(request, params))
1268
+ else:
1269
+ if cost is not None:
1270
+ response = self.v4PrivatePostOrderMarket(self.extend(request, params))
1271
+ else:
1272
+ response = self.v4PrivatePostOrderStockMarket(self.extend(request, params))
1273
+ return self.parse_order(response)
1274
+
1275
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1276
+ """
1277
+ edit a trade order
1278
+ :see: https://docs.whitebit.com/private/http-trade-v4/#modify-order
1279
+ :param str id: cancel order id
1280
+ :param str symbol: unified symbol of the market to create an order in
1281
+ :param str type: 'market' or 'limit'
1282
+ :param str side: 'buy' or 'sell'
1283
+ :param float amount: how much of currency you want to trade in units of base currency
1284
+ :param float price: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
1285
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1286
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1287
+ """
1288
+ if id is None:
1289
+ raise ArgumentsRequired(self.id + ' editOrder() requires a id argument')
1290
+ if symbol is None:
1291
+ raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
1292
+ self.load_markets()
1293
+ market = self.market(symbol)
1294
+ request: dict = {
1295
+ 'orderId': id,
1296
+ 'market': market['id'],
1297
+ }
1298
+ clientOrderId = self.safe_string_2(params, 'clOrdId', 'clientOrderId')
1299
+ if clientOrderId is not None:
1300
+ # Update clientOrderId of the order
1301
+ request['clientOrderId'] = clientOrderId
1302
+ isLimitOrder = type == 'limit'
1303
+ stopPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'activation_price'])
1304
+ isStopOrder = (stopPrice is not None)
1305
+ params = self.omit(params, ['clOrdId', 'clientOrderId', 'triggerPrice', 'stopPrice'])
1306
+ if isStopOrder:
1307
+ request['activation_price'] = self.price_to_precision(symbol, stopPrice)
1308
+ if isLimitOrder:
1309
+ # stop limit order
1310
+ request['amount'] = self.amount_to_precision(symbol, amount)
1311
+ request['price'] = self.price_to_precision(symbol, price)
1312
+ else:
1313
+ # stop market order
1314
+ if side == 'buy':
1315
+ # Use total parameter instead of amount for modify buy stop market order
1316
+ request['total'] = self.amount_to_precision(symbol, amount)
1317
+ else:
1318
+ request['amount'] = self.amount_to_precision(symbol, amount)
1319
+ else:
1320
+ request['amount'] = self.amount_to_precision(symbol, amount)
1321
+ if isLimitOrder:
1322
+ # limit order
1323
+ request['price'] = self.price_to_precision(symbol, price)
1324
+ response = self.v4PrivatePostOrderModify(self.extend(request, params))
1325
+ return self.parse_order(response)
1326
+
1327
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
1328
+ """
1329
+ cancels an open order
1330
+ :see: https://docs.whitebit.com/private/http-trade-v4/#cancel-order
1331
+ :param str id: order id
1332
+ :param str symbol: unified symbol of the market the order was made in
1333
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1334
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1335
+ """
1336
+ if symbol is None:
1337
+ raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
1338
+ self.load_markets()
1339
+ market = self.market(symbol)
1340
+ request: dict = {
1341
+ 'market': market['id'],
1342
+ 'orderId': int(id),
1343
+ }
1344
+ response = self.v4PrivatePostOrderCancel(self.extend(request, params))
1345
+ #
1346
+ # {
1347
+ # "orderId": 4180284841, # order id
1348
+ # "clientOrderId": "customId11", # custom order identifier; "clientOrderId": "" - if not specified.
1349
+ # "market": "BTC_USDT", # deal market
1350
+ # "side": "buy", # order side
1351
+ # "type": "stop market", # order type
1352
+ # "timestamp": 1595792396.165973, # current timestamp
1353
+ # "dealMoney": "0", # if order finished - amount in money currency that is finished
1354
+ # "dealStock": "0", # if order finished - amount in stock currency that is finished
1355
+ # "amount": "0.001", # amount
1356
+ # "takerFee": "0.001", # maker fee ratio. If the number less than 0.0001 - it will be rounded to zero
1357
+ # "makerFee": "0.001", # maker fee ratio. If the number less than 0.0001 - it will be rounded to zero
1358
+ # "left": "0.001", # if order not finished - rest of the amount that must be finished
1359
+ # "dealFee": "0", # fee in money that you pay if order is finished
1360
+ # "price": "40000", # price if price isset
1361
+ # "activation_price": "40000" # activation price if activation price is set
1362
+ # }
1363
+ #
1364
+ return self.parse_order(response)
1365
+
1366
+ def cancel_all_orders(self, symbol: Str = None, params={}):
1367
+ """
1368
+ cancel all open orders
1369
+ :see: https://docs.whitebit.com/private/http-trade-v4/#cancel-all-orders
1370
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1371
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1372
+ :param str [params.type]: market type, ['swap', 'spot']
1373
+ :param boolean [params.isMargin]: cancel all margin orders
1374
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1375
+ """
1376
+ self.load_markets()
1377
+ market = None
1378
+ request: dict = {}
1379
+ if symbol is not None:
1380
+ market = self.market(symbol)
1381
+ request['market'] = market['id']
1382
+ type = None
1383
+ type, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
1384
+ requestType = []
1385
+ if type == 'spot':
1386
+ isMargin = None
1387
+ isMargin, params = self.handle_option_and_params(params, 'cancelAllOrders', 'isMargin', False)
1388
+ if isMargin:
1389
+ requestType.append('margin')
1390
+ else:
1391
+ requestType.append('spot')
1392
+ elif type == 'swap':
1393
+ requestType.append('futures')
1394
+ else:
1395
+ raise NotSupported(self.id + ' cancelAllOrders() does not support ' + type + ' type')
1396
+ request['type'] = requestType
1397
+ response = self.v4PrivatePostOrderCancelAll(self.extend(request, params))
1398
+ #
1399
+ # []
1400
+ #
1401
+ return self.parse_orders(response, market)
1402
+
1403
+ def cancel_all_orders_after(self, timeout: Int, params={}):
1404
+ """
1405
+ dead man's switch, cancel all orders after the given timeout
1406
+ :see: https://docs.whitebit.com/private/http-trade-v4/#sync-kill-switch-timer
1407
+ :param number timeout: time in milliseconds, 0 represents cancel the timer
1408
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1409
+ :param str [params.types]: Order types value. Example: "spot", "margin", "futures" or None
1410
+ :param str [params.symbol]: symbol unified symbol of the market the order was made in
1411
+ :returns dict: the api result
1412
+ """
1413
+ self.load_markets()
1414
+ symbol = self.safe_string(params, 'symbol')
1415
+ if symbol is None:
1416
+ raise ArgumentsRequired(self.id + ' cancelAllOrdersAfter() requires a symbol argument in params')
1417
+ market = self.market(symbol)
1418
+ params = self.omit(params, 'symbol')
1419
+ isBiggerThanZero = (timeout > 0)
1420
+ request: dict = {
1421
+ 'market': market['id'],
1422
+ # 'timeout': self.number_to_string(timeout / 1000) if (timeout > 0) else null,
1423
+ }
1424
+ if isBiggerThanZero:
1425
+ request['timeout'] = self.number_to_string(timeout / 1000)
1426
+ else:
1427
+ request['timeout'] = 'null'
1428
+ response = self.v4PrivatePostOrderKillSwitch(self.extend(request, params))
1429
+ #
1430
+ # {
1431
+ # "market": "BTC_USDT", # currency market,
1432
+ # "startTime": 1662478154, # now timestamp,
1433
+ # "cancellationTime": 1662478154, # now + timer_value,
1434
+ # "types": ["spot", "margin"]
1435
+ # }
1436
+ #
1437
+ return response
1438
+
1439
+ def parse_balance(self, response) -> Balances:
1440
+ balanceKeys = list(response.keys())
1441
+ result: dict = {}
1442
+ for i in range(0, len(balanceKeys)):
1443
+ id = balanceKeys[i]
1444
+ code = self.safe_currency_code(id)
1445
+ balance = response[id]
1446
+ if isinstance(balance, dict) and balance is not None:
1447
+ account = self.account()
1448
+ account['free'] = self.safe_string_2(balance, 'available', 'main_balance')
1449
+ account['used'] = self.safe_string(balance, 'freeze')
1450
+ account['total'] = self.safe_string(balance, 'main_balance')
1451
+ result[code] = account
1452
+ else:
1453
+ account = self.account()
1454
+ account['total'] = balance
1455
+ result[code] = account
1456
+ return self.safe_balance(result)
1457
+
1458
+ def fetch_balance(self, params={}) -> Balances:
1459
+ """
1460
+ query for balance and get the amount of funds available for trading or funds locked in orders
1461
+ :see: https://docs.whitebit.com/private/http-main-v4/#main-balance
1462
+ :see: https://docs.whitebit.com/private/http-trade-v4/#trading-balance
1463
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1464
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1465
+ """
1466
+ self.load_markets()
1467
+ marketType = None
1468
+ marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
1469
+ response = None
1470
+ if marketType == 'swap':
1471
+ response = self.v4PrivatePostCollateralAccountBalance(params)
1472
+ else:
1473
+ options = self.safe_value(self.options, 'fetchBalance', {})
1474
+ defaultAccount = self.safe_string(options, 'account')
1475
+ account = self.safe_string_2(params, 'account', 'type', defaultAccount)
1476
+ params = self.omit(params, ['account', 'type'])
1477
+ if account == 'main' or account == 'funding':
1478
+ response = self.v4PrivatePostMainAccountBalance(params)
1479
+ else:
1480
+ response = self.v4PrivatePostTradeAccountBalance(params)
1481
+ #
1482
+ # main account
1483
+ #
1484
+ # {
1485
+ # "BTC":{"main_balance":"0.0013929494020316"},
1486
+ # "ETH":{"main_balance":"0.001398289308"},
1487
+ # }
1488
+ #
1489
+ # spot trade account
1490
+ #
1491
+ # {
1492
+ # "BTC": {"available": "0.123", "freeze": "1"},
1493
+ # "XMR": {"available": "3013", "freeze": "100"},
1494
+ # }
1495
+ #
1496
+ # swap
1497
+ #
1498
+ # {
1499
+ # "BTC": 1,
1500
+ # "USDT": 1000
1501
+ # }
1502
+ #
1503
+ return self.parse_balance(response)
1504
+
1505
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1506
+ """
1507
+ fetch all unfilled currently open orders
1508
+ :see: https://docs.whitebit.com/private/http-trade-v4/#query-unexecutedactive-orders
1509
+ :param str symbol: unified market symbol
1510
+ :param int [since]: the earliest time in ms to fetch open orders for
1511
+ :param int [limit]: the maximum number of open order structures to retrieve
1512
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1513
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1514
+ """
1515
+ if symbol is None:
1516
+ raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument')
1517
+ self.load_markets()
1518
+ market = self.market(symbol)
1519
+ request: dict = {
1520
+ 'market': market['id'],
1521
+ }
1522
+ if limit is not None:
1523
+ request['limit'] = min(limit, 100)
1524
+ response = self.v4PrivatePostOrders(self.extend(request, params))
1525
+ #
1526
+ # [
1527
+ # {
1528
+ # "orderId": 3686033640,
1529
+ # "clientOrderId": "customId11",
1530
+ # "market": "BTC_USDT",
1531
+ # "side": "buy",
1532
+ # "type": "limit",
1533
+ # "timestamp": 1594605801.49815, # current timestamp of unexecuted order
1534
+ # "dealMoney": "0", # executed amount in money
1535
+ # "dealStock": "0", # executed amount in stock
1536
+ # "amount": "2.241379", # active order amount
1537
+ # "takerFee": "0.001",
1538
+ # "makerFee": "0.001",
1539
+ # "left": "2.241379", # unexecuted amount in stock
1540
+ # "dealFee": "0", # executed fee by deal
1541
+ # "price": "40000"
1542
+ # },
1543
+ # ]
1544
+ #
1545
+ return self.parse_orders(response, market, since, limit, {'status': 'open'})
1546
+
1547
+ def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1548
+ """
1549
+ fetches information on multiple closed orders made by the user
1550
+ :see: https://docs.whitebit.com/private/http-trade-v4/#query-executed-orders
1551
+ :param str symbol: unified market symbol of the market orders were made in
1552
+ :param int [since]: the earliest time in ms to fetch orders for
1553
+ :param int [limit]: the maximum number of order structures to retrieve
1554
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1555
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1556
+ """
1557
+ self.load_markets()
1558
+ request: dict = {}
1559
+ market = None
1560
+ if symbol is not None:
1561
+ market = self.market(symbol)
1562
+ symbol = market['symbol']
1563
+ request['market'] = market['id']
1564
+ if limit is not None:
1565
+ request['limit'] = min(limit, 100) # default 50 max 100
1566
+ response = self.v4PrivatePostTradeAccountOrderHistory(self.extend(request, params))
1567
+ #
1568
+ # {
1569
+ # "BTC_USDT": [
1570
+ # {
1571
+ # "id": 160305483,
1572
+ # "clientOrderId": "customId11",
1573
+ # "time": 1594667731.724403,
1574
+ # "side": "sell",
1575
+ # "role": 2, # 1 = maker, 2 = taker
1576
+ # "amount": "0.000076",
1577
+ # "price": "9264.21",
1578
+ # "deal": "0.70407996",
1579
+ # "fee": "0.00070407996"
1580
+ # },
1581
+ # ],
1582
+ # }
1583
+ #
1584
+ marketIds = list(response.keys())
1585
+ results = []
1586
+ for i in range(0, len(marketIds)):
1587
+ marketId = marketIds[i]
1588
+ marketNew = self.safe_market(marketId, None, '_')
1589
+ orders = response[marketId]
1590
+ for j in range(0, len(orders)):
1591
+ order = self.parse_order(orders[j], marketNew)
1592
+ results.append(self.extend(order, {'status': 'closed'}))
1593
+ results = self.sort_by(results, 'timestamp')
1594
+ results = self.filter_by_symbol_since_limit(results, symbol, since, limit)
1595
+ return results
1596
+
1597
+ def parse_order_type(self, type: Str):
1598
+ types: dict = {
1599
+ 'limit': 'limit',
1600
+ 'market': 'market',
1601
+ 'stop market': 'market',
1602
+ 'stop limit': 'limit',
1603
+ 'stock market': 'market',
1604
+ 'margin limit': 'limit',
1605
+ 'margin market': 'market',
1606
+ }
1607
+ return self.safe_string(types, type, type)
1608
+
1609
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1610
+ #
1611
+ # createOrder, fetchOpenOrders, cancelOrder
1612
+ #
1613
+ # {
1614
+ # "orderId":105687928629,
1615
+ # "clientOrderId":"",
1616
+ # "market":"DOGE_USDT",
1617
+ # "side":"sell",
1618
+ # "type":"stop market",
1619
+ # "timestamp":1659091079.729576,
1620
+ # "dealMoney":"0", # executed amount in quote
1621
+ # "dealStock":"0", # base filled amount
1622
+ # "amount":"100",
1623
+ # "takerFee":"0.001",
1624
+ # "makerFee":"0",
1625
+ # "left":"100",
1626
+ # "price": "40000", # price if price isset
1627
+ # "dealFee":"0",
1628
+ # "activation_price":"0.065" # stop price(if stop limit or stop market)
1629
+ # }
1630
+ #
1631
+ # fetchClosedOrders
1632
+ #
1633
+ # {
1634
+ # "id":105531094719,
1635
+ # "clientOrderId":"",
1636
+ # "ctime":1659045334.550127,
1637
+ # "ftime":1659045334.550127,
1638
+ # "side":"buy",
1639
+ # "amount":"5.9940059", # cost in terms of quote for regular market orders, amount in terms or base for all other order types
1640
+ # "price":"0",
1641
+ # "type":"market",
1642
+ # "takerFee":"0.001",
1643
+ # "makerFee":"0",
1644
+ # "dealFee":"0.0059375815",
1645
+ # "dealStock":"85", # base filled amount
1646
+ # "dealMoney":"5.9375815", # executed amount in quote
1647
+ # }
1648
+ #
1649
+ marketId = self.safe_string(order, 'market')
1650
+ market = self.safe_market(marketId, market, '_')
1651
+ symbol = market['symbol']
1652
+ side = self.safe_string(order, 'side')
1653
+ filled = self.safe_string(order, 'dealStock')
1654
+ remaining = self.safe_string(order, 'left')
1655
+ clientOrderId = self.safe_string(order, 'clientOrderId')
1656
+ if clientOrderId == '':
1657
+ clientOrderId = None
1658
+ price = self.safe_string(order, 'price')
1659
+ stopPrice = self.safe_number(order, 'activation_price')
1660
+ orderId = self.safe_string_2(order, 'orderId', 'id')
1661
+ type = self.safe_string(order, 'type')
1662
+ orderType = self.parse_order_type(type)
1663
+ if orderType == 'market':
1664
+ remaining = None
1665
+ amount = self.safe_string(order, 'amount')
1666
+ cost = self.safe_string(order, 'dealMoney')
1667
+ if (side == 'buy') and ((type == 'market') or (type == 'stop market')):
1668
+ amount = filled
1669
+ dealFee = self.safe_string(order, 'dealFee')
1670
+ fee = None
1671
+ if dealFee is not None:
1672
+ fee = {
1673
+ 'cost': self.parse_number(dealFee),
1674
+ 'currency': market['quote'],
1675
+ }
1676
+ timestamp = self.safe_timestamp_2(order, 'ctime', 'timestamp')
1677
+ lastTradeTimestamp = self.safe_timestamp(order, 'ftime')
1678
+ return self.safe_order({
1679
+ 'info': order,
1680
+ 'id': orderId,
1681
+ 'symbol': symbol,
1682
+ 'clientOrderId': clientOrderId,
1683
+ 'timestamp': timestamp,
1684
+ 'datetime': self.iso8601(timestamp),
1685
+ 'lastTradeTimestamp': lastTradeTimestamp,
1686
+ 'timeInForce': None,
1687
+ 'postOnly': None,
1688
+ 'status': None,
1689
+ 'side': side,
1690
+ 'price': price,
1691
+ 'type': orderType,
1692
+ 'stopPrice': stopPrice,
1693
+ 'triggerPrice': stopPrice,
1694
+ 'amount': amount,
1695
+ 'filled': filled,
1696
+ 'remaining': remaining,
1697
+ 'average': None,
1698
+ 'cost': cost,
1699
+ 'fee': fee,
1700
+ 'trades': None,
1701
+ }, market)
1702
+
1703
+ def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1704
+ """
1705
+ fetch all the trades made from a single order
1706
+ :see: https://docs.whitebit.com/private/http-trade-v4/#query-executed-order-deals
1707
+ :param str id: order id
1708
+ :param str symbol: unified market symbol
1709
+ :param int [since]: the earliest time in ms to fetch trades for
1710
+ :param int [limit]: the maximum number of trades to retrieve
1711
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1712
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1713
+ """
1714
+ self.load_markets()
1715
+ request: dict = {
1716
+ 'orderId': int(id),
1717
+ }
1718
+ market = None
1719
+ if symbol is not None:
1720
+ market = self.market(symbol)
1721
+ request['market'] = market['id']
1722
+ if limit is not None:
1723
+ request['limit'] = min(limit, 100)
1724
+ response = self.v4PrivatePostTradeAccountOrder(self.extend(request, params))
1725
+ #
1726
+ # {
1727
+ # "records": [
1728
+ # {
1729
+ # "time": 1593342324.613711,
1730
+ # "fee": "0.00000419198",
1731
+ # "price": "0.00000701",
1732
+ # "amount": "598",
1733
+ # "id": 149156519, # trade id
1734
+ # "dealOrderId": 3134995325, # orderId
1735
+ # "clientOrderId": "customId11", # empty string if not specified
1736
+ # "role": 2, # 1 = maker, 2 = taker
1737
+ # "deal": "0.00419198"
1738
+ # }
1739
+ # ],
1740
+ # "offset": 0,
1741
+ # "limit": 100
1742
+ # }
1743
+ #
1744
+ data = self.safe_list(response, 'records', [])
1745
+ return self.parse_trades(data, market)
1746
+
1747
+ def fetch_deposit_address(self, code: str, params={}):
1748
+ """
1749
+ fetch the deposit address for a currency associated with self account
1750
+ :see: https://docs.whitebit.com/private/http-main-v4/#get-fiat-deposit-address
1751
+ :see: https://docs.whitebit.com/private/http-main-v4/#get-cryptocurrency-deposit-address
1752
+ :param str code: unified currency code
1753
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1754
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1755
+ """
1756
+ self.load_markets()
1757
+ currency = self.currency(code)
1758
+ request: dict = {
1759
+ 'ticker': currency['id'],
1760
+ }
1761
+ response = None
1762
+ if self.is_fiat(code):
1763
+ provider = self.safe_string(params, 'provider')
1764
+ if provider is None:
1765
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires a provider when the ticker is fiat')
1766
+ request['provider'] = provider
1767
+ amount = self.safe_number(params, 'amount')
1768
+ if amount is None:
1769
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires an amount when the ticker is fiat')
1770
+ request['amount'] = amount
1771
+ uniqueId = self.safe_value(params, 'uniqueId')
1772
+ if uniqueId is None:
1773
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() requires an uniqueId when the ticker is fiat')
1774
+ response = self.v4PrivatePostMainAccountFiatDepositUrl(self.extend(request, params))
1775
+ else:
1776
+ response = self.v4PrivatePostMainAccountAddress(self.extend(request, params))
1777
+ #
1778
+ # fiat
1779
+ #
1780
+ # {
1781
+ # "url": "https://someaddress.com"
1782
+ # }
1783
+ #
1784
+ # crypto
1785
+ #
1786
+ # {
1787
+ # "account": {
1788
+ # "address": "GDTSOI56XNVAKJNJBLJGRNZIVOCIZJRBIDKTWSCYEYNFAZEMBLN75RMN",
1789
+ # "memo": "48565488244493"
1790
+ # },
1791
+ # "required": {
1792
+ # "fixedFee": "0",
1793
+ # "flexFee": {
1794
+ # "maxFee": "0",
1795
+ # "minFee": "0",
1796
+ # "percent": "0"
1797
+ # },
1798
+ # "maxAmount": "0",
1799
+ # "minAmount": "1"
1800
+ # }
1801
+ # }
1802
+ #
1803
+ url = self.safe_string(response, 'url')
1804
+ account = self.safe_value(response, 'account', {})
1805
+ address = self.safe_string(account, 'address', url)
1806
+ tag = self.safe_string(account, 'memo')
1807
+ self.check_address(address)
1808
+ return {
1809
+ 'currency': code,
1810
+ 'address': address,
1811
+ 'tag': tag,
1812
+ 'network': None,
1813
+ 'info': response,
1814
+ }
1815
+
1816
+ def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
1817
+ """
1818
+ set the level of leverage for a market
1819
+ :see: https://docs.whitebit.com/private/http-trade-v4/#change-collateral-account-leverage
1820
+ :param float leverage: the rate of leverage
1821
+ :param str symbol: unified market symbol
1822
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1823
+ :returns dict: response from the exchange
1824
+ """
1825
+ self.load_markets()
1826
+ if symbol is not None:
1827
+ raise NotSupported(self.id + ' setLeverage() does not allow to set per symbol')
1828
+ if (leverage < 1) or (leverage > 20):
1829
+ raise BadRequest(self.id + ' setLeverage() leverage should be between 1 and 20')
1830
+ request: dict = {
1831
+ 'leverage': leverage,
1832
+ }
1833
+ return self.v4PrivatePostCollateralAccountLeverage(self.extend(request, params))
1834
+ # {
1835
+ # "leverage": 5
1836
+ # }
1837
+
1838
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1839
+ """
1840
+ transfer currency internally between wallets on the same account
1841
+ :see: https://docs.whitebit.com/private/http-main-v4/#transfer-between-main-and-trade-balances
1842
+ :param str code: unified currency code
1843
+ :param float amount: amount to transfer
1844
+ :param str fromAccount: account to transfer from - main, spot, collateral
1845
+ :param str toAccount: account to transfer to - main, spot, collateral
1846
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1847
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
1848
+ """
1849
+ self.load_markets()
1850
+ currency = self.currency(code)
1851
+ accountsByType = self.safe_value(self.options, 'accountsByType')
1852
+ fromAccountId = self.safe_string(accountsByType, fromAccount, fromAccount)
1853
+ toAccountId = self.safe_string(accountsByType, toAccount, toAccount)
1854
+ amountString = self.currency_to_precision(code, amount)
1855
+ request: dict = {
1856
+ 'ticker': currency['id'],
1857
+ 'amount': amountString,
1858
+ 'from': fromAccountId,
1859
+ 'to': toAccountId,
1860
+ }
1861
+ response = self.v4PrivatePostMainAccountTransfer(self.extend(request, params))
1862
+ #
1863
+ # []
1864
+ #
1865
+ return self.parse_transfer(response, currency)
1866
+
1867
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
1868
+ #
1869
+ # []
1870
+ #
1871
+ return {
1872
+ 'info': transfer,
1873
+ 'id': None,
1874
+ 'timestamp': None,
1875
+ 'datetime': None,
1876
+ 'currency': self.safe_currency_code(None, currency),
1877
+ 'amount': None,
1878
+ 'fromAccount': None,
1879
+ 'toAccount': None,
1880
+ 'status': None,
1881
+ }
1882
+
1883
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
1884
+ """
1885
+ make a withdrawal
1886
+ :see: https://docs.whitebit.com/private/http-main-v4/#create-withdraw-request
1887
+ :param str code: unified currency code
1888
+ :param float amount: the amount to withdraw
1889
+ :param str address: the address to withdraw to
1890
+ :param str tag:
1891
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1892
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1893
+ """
1894
+ self.load_markets()
1895
+ currency = self.currency(code) # check if it has canDeposit
1896
+ request: dict = {
1897
+ 'ticker': currency['id'],
1898
+ 'amount': self.currency_to_precision(code, amount),
1899
+ 'address': address,
1900
+ }
1901
+ uniqueId = self.safe_value(params, 'uniqueId')
1902
+ if uniqueId is None:
1903
+ uniqueId = self.uuid22()
1904
+ request['uniqueId'] = uniqueId
1905
+ if tag is not None:
1906
+ request['memo'] = tag
1907
+ if self.is_fiat(code):
1908
+ provider = self.safe_value(params, 'provider')
1909
+ if provider is None:
1910
+ raise ArgumentsRequired(self.id + ' withdraw() requires a provider when the ticker is fiat')
1911
+ request['provider'] = provider
1912
+ response = self.v4PrivatePostMainAccountWithdraw(self.extend(request, params))
1913
+ #
1914
+ # empty array with a success status
1915
+ # go to deposit/withdraw history and check you request status by uniqueId
1916
+ #
1917
+ # []
1918
+ #
1919
+ return self.extend({'id': uniqueId}, self.parse_transaction(response, currency))
1920
+
1921
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
1922
+ #
1923
+ # {
1924
+ # "address": "3ApEASLcrQtZpg1TsssFgYF5V5YQJAKvuE", # deposit address
1925
+ # "uniqueId": null, # unique Id of deposit
1926
+ # "transactionId": "a6d71d69-2b17-4ad8-8b15-2d686c54a1a5",
1927
+ # "createdAt": 1593437922, # timestamp of deposit
1928
+ # "currency": "Bitcoin", # deposit currency
1929
+ # "ticker": "BTC", # deposit currency ticker
1930
+ # "method": 1, # called method 1 - deposit, 2 - withdraw
1931
+ # "amount": "0.0006", # amount of deposit
1932
+ # "description": "", # deposit description
1933
+ # "memo": "", # deposit memo
1934
+ # "fee": "0", # deposit fee
1935
+ # "status": 15, # transactions status
1936
+ # "network": null, # if currency is multinetwork
1937
+ # "transactionHash": "a275a514013e4e0f927fd0d1bed215e7f6f2c4c6ce762836fe135ec22529d886", # deposit transaction hash
1938
+ # "details": {
1939
+ # "partial": { # details about partially successful withdrawals
1940
+ # "requestAmount": "50000", # requested withdrawal amount
1941
+ # "processedAmount": "39000", # processed withdrawal amount
1942
+ # "processedFee": "273", # fee for processed withdrawal amount
1943
+ # "normalizeTransaction": "" # deposit id
1944
+ # }
1945
+ # },
1946
+ # "confirmations": { # if transaction status == 15 you can see self object
1947
+ # "actual": 1, # current block confirmations
1948
+ # "required": 2 # required block confirmation for successful deposit
1949
+ # }
1950
+ # "centralized": False,
1951
+ # }
1952
+ #
1953
+ currency = self.safe_currency(None, currency)
1954
+ address = self.safe_string(transaction, 'address')
1955
+ timestamp = self.safe_timestamp(transaction, 'createdAt')
1956
+ currencyId = self.safe_string(transaction, 'ticker')
1957
+ status = self.safe_string(transaction, 'status')
1958
+ method = self.safe_string(transaction, 'method')
1959
+ return {
1960
+ 'id': self.safe_string(transaction, 'uniqueId'),
1961
+ 'txid': self.safe_string(transaction, 'transactionId'),
1962
+ 'timestamp': timestamp,
1963
+ 'datetime': self.iso8601(timestamp),
1964
+ 'network': self.safe_string(transaction, 'network'),
1965
+ 'addressFrom': address if (method == '1') else None,
1966
+ 'address': address,
1967
+ 'addressTo': address if (method == '2') else None,
1968
+ 'amount': self.safe_number(transaction, 'amount'),
1969
+ 'type': 'deposit' if (method == '1') else 'withdrawal',
1970
+ 'currency': self.safe_currency_code(currencyId, currency),
1971
+ 'status': self.parse_transaction_status(status),
1972
+ 'updated': None,
1973
+ 'tagFrom': None,
1974
+ 'tag': None,
1975
+ 'tagTo': None,
1976
+ 'comment': self.safe_string(transaction, 'description'),
1977
+ 'internal': None,
1978
+ 'fee': {
1979
+ 'cost': self.safe_number(transaction, 'fee'),
1980
+ 'currency': self.safe_currency_code(currencyId, currency),
1981
+ },
1982
+ 'info': transaction,
1983
+ }
1984
+
1985
+ def parse_transaction_status(self, status: Str):
1986
+ statuses: dict = {
1987
+ '1': 'pending',
1988
+ '2': 'pending',
1989
+ '3': 'ok',
1990
+ '4': 'canceled',
1991
+ '5': 'pending',
1992
+ '6': 'pending',
1993
+ '7': 'ok',
1994
+ '9': 'canceled',
1995
+ '10': 'pending',
1996
+ '11': 'pending',
1997
+ '12': 'pending',
1998
+ '13': 'pending',
1999
+ '14': 'pending',
2000
+ '15': 'pending',
2001
+ '16': 'pending',
2002
+ '17': 'pending',
2003
+ }
2004
+ return self.safe_string(statuses, status, status)
2005
+
2006
+ def fetch_deposit(self, id: str, code: Str = None, params={}):
2007
+ """
2008
+ fetch information on a deposit
2009
+ :see: https://docs.whitebit.com/private/http-main-v4/#get-depositwithdraw-history
2010
+ :param str id: deposit id
2011
+ :param str code: not used by whitebit fetchDeposit()
2012
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2013
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2014
+ """
2015
+ self.load_markets()
2016
+ currency = None
2017
+ request: dict = {
2018
+ 'transactionMethod': 1,
2019
+ 'uniqueId': id,
2020
+ 'limit': 1,
2021
+ 'offset': 0,
2022
+ }
2023
+ if code is not None:
2024
+ currency = self.currency(code)
2025
+ request['ticker'] = currency['id']
2026
+ response = self.v4PrivatePostMainAccountHistory(self.extend(request, params))
2027
+ #
2028
+ # {
2029
+ # "limit": 100,
2030
+ # "offset": 0,
2031
+ # "records": [
2032
+ # {
2033
+ # "address": "3ApEASLcrQtZpg1TsssFgYF5V5YQJAKvuE", # deposit address
2034
+ # "uniqueId": null, # unique Id of deposit
2035
+ # "createdAt": 1593437922, # timestamp of deposit
2036
+ # "currency": "Bitcoin", # deposit currency
2037
+ # "ticker": "BTC", # deposit currency ticker
2038
+ # "method": 1, # called method 1 - deposit, 2 - withdraw
2039
+ # "amount": "0.0006", # amount of deposit
2040
+ # "description": "", # deposit description
2041
+ # "memo": "", # deposit memo
2042
+ # "fee": "0", # deposit fee
2043
+ # "status": 15, # transactions status
2044
+ # "network": null, # if currency is multinetwork
2045
+ # "transactionHash": "a275a514013e4e0f927fd0d1bed215e7f6f2c4c6ce762836fe135ec22529d886", # deposit transaction hash
2046
+ # "details": {
2047
+ # "partial": { # details about partially successful withdrawals
2048
+ # "requestAmount": "50000", # requested withdrawal amount
2049
+ # "processedAmount": "39000", # processed withdrawal amount
2050
+ # "processedFee": "273", # fee for processed withdrawal amount
2051
+ # "normalizeTransaction": "" # deposit id
2052
+ # }
2053
+ # },
2054
+ # "confirmations": { # if transaction status == 15 you can see self object
2055
+ # "actual": 1, # current block confirmations
2056
+ # "required": 2 # required block confirmation for successful deposit
2057
+ # }
2058
+ # },
2059
+ # {...},
2060
+ # ],
2061
+ # "total": 300 # total number of transactions, use self for calculating ‘limit’ and ‘offset'
2062
+ # }
2063
+ #
2064
+ records = self.safe_value(response, 'records', [])
2065
+ first = self.safe_dict(records, 0, {})
2066
+ return self.parse_transaction(first, currency)
2067
+
2068
+ def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2069
+ """
2070
+ fetch all deposits made to an account
2071
+ :see: https://docs.whitebit.com/private/http-main-v4/#get-depositwithdraw-history
2072
+ :param str code: unified currency code
2073
+ :param int [since]: the earliest time in ms to fetch deposits for
2074
+ :param int [limit]: the maximum number of deposits structures to retrieve
2075
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2076
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2077
+ """
2078
+ self.load_markets()
2079
+ currency = None
2080
+ request: dict = {
2081
+ 'transactionMethod': 1,
2082
+ 'limit': 100,
2083
+ 'offset': 0,
2084
+ }
2085
+ if code is not None:
2086
+ currency = self.currency(code)
2087
+ request['ticker'] = currency['id']
2088
+ if limit is not None:
2089
+ request['limit'] = min(limit, 100)
2090
+ response = self.v4PrivatePostMainAccountHistory(self.extend(request, params))
2091
+ #
2092
+ # {
2093
+ # "limit": 100,
2094
+ # "offset": 0,
2095
+ # "records": [
2096
+ # {
2097
+ # "address": "3ApEASLcrQtZpg1TsssFgYF5V5YQJAKvuE", # deposit address
2098
+ # "uniqueId": null, # unique Id of deposit
2099
+ # "createdAt": 1593437922, # timestamp of deposit
2100
+ # "currency": "Bitcoin", # deposit currency
2101
+ # "ticker": "BTC", # deposit currency ticker
2102
+ # "method": 1, # called method 1 - deposit, 2 - withdraw
2103
+ # "amount": "0.0006", # amount of deposit
2104
+ # "description": "", # deposit description
2105
+ # "memo": "", # deposit memo
2106
+ # "fee": "0", # deposit fee
2107
+ # "status": 15, # transactions status
2108
+ # "network": null, # if currency is multinetwork
2109
+ # "transactionHash": "a275a514013e4e0f927fd0d1bed215e7f6f2c4c6ce762836fe135ec22529d886", # deposit transaction hash
2110
+ # "details": {
2111
+ # "partial": { # details about partially successful withdrawals
2112
+ # "requestAmount": "50000", # requested withdrawal amount
2113
+ # "processedAmount": "39000", # processed withdrawal amount
2114
+ # "processedFee": "273", # fee for processed withdrawal amount
2115
+ # "normalizeTransaction": "" # deposit id
2116
+ # }
2117
+ # },
2118
+ # "confirmations": { # if transaction status == 15 you can see self object
2119
+ # "actual": 1, # current block confirmations
2120
+ # "required": 2 # required block confirmation for successful deposit
2121
+ # }
2122
+ # },
2123
+ # {...},
2124
+ # ],
2125
+ # "total": 300 # total number of transactions, use self for calculating ‘limit’ and ‘offset'
2126
+ # }
2127
+ #
2128
+ records = self.safe_list(response, 'records', [])
2129
+ return self.parse_transactions(records, currency, since, limit)
2130
+
2131
+ def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2132
+ """
2133
+ fetch the interest owed by the user for borrowing currency for margin trading
2134
+ :see: https://docs.whitebit.com/private/http-trade-v4/#open-positions
2135
+ :param str code: unified currency code
2136
+ :param str symbol: unified market symbol
2137
+ :param int [since]: the earliest time in ms to fetch borrrow interest for
2138
+ :param int [limit]: the maximum number of structures to retrieve
2139
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2140
+ :returns dict[]: a list of `borrow interest structures <https://docs.ccxt.com/#/?id=borrow-interest-structure>`
2141
+ """
2142
+ self.load_markets()
2143
+ request: dict = {}
2144
+ market = None
2145
+ if symbol is not None:
2146
+ market = self.market(symbol)
2147
+ request['market'] = market['id']
2148
+ response = self.v4PrivatePostCollateralAccountPositionsOpen(self.extend(request, params))
2149
+ #
2150
+ # [
2151
+ # {
2152
+ # "positionId": 191823,
2153
+ # "market": "BTC_USDT",
2154
+ # "openDate": 1660340344.027163,
2155
+ # "modifyDate": 1660340344.027163,
2156
+ # "amount": "0.003075",
2157
+ # "basePrice": "24149.24512",
2158
+ # "liquidationPrice": "7059.02",
2159
+ # "leverage": "5",
2160
+ # "pnl": "-0.15",
2161
+ # "pnlPercent": "-0.20",
2162
+ # "margin": "14.86",
2163
+ # "freeMargin": "44.99",
2164
+ # "funding": "0",
2165
+ # "unrealizedFunding": "0.0000307828284903",
2166
+ # "liquidationState": null
2167
+ # }
2168
+ # ]
2169
+ #
2170
+ interest = self.parse_borrow_interests(response, market)
2171
+ return self.filter_by_currency_since_limit(interest, code, since, limit)
2172
+
2173
+ def parse_borrow_interest(self, info: dict, market: Market = None):
2174
+ #
2175
+ # {
2176
+ # "positionId": 191823,
2177
+ # "market": "BTC_USDT",
2178
+ # "openDate": 1660340344.027163,
2179
+ # "modifyDate": 1660340344.027163,
2180
+ # "amount": "0.003075",
2181
+ # "basePrice": "24149.24512",
2182
+ # "liquidationPrice": "7059.02",
2183
+ # "leverage": "5",
2184
+ # "pnl": "-0.15",
2185
+ # "pnlPercent": "-0.20",
2186
+ # "margin": "14.86",
2187
+ # "freeMargin": "44.99",
2188
+ # "funding": "0",
2189
+ # "unrealizedFunding": "0.0000307828284903",
2190
+ # "liquidationState": null
2191
+ # }
2192
+ #
2193
+ marketId = self.safe_string(info, 'market')
2194
+ symbol = self.safe_symbol(marketId, market, '_')
2195
+ timestamp = self.safe_timestamp(info, 'modifyDate')
2196
+ return {
2197
+ 'symbol': symbol,
2198
+ 'marginMode': 'cross',
2199
+ 'currency': 'USDT',
2200
+ 'interest': self.safe_number(info, 'unrealizedFunding'),
2201
+ 'interestRate': 0.00098, # https://whitebit.com/fees
2202
+ 'amountBorrowed': self.safe_number(info, 'amount'),
2203
+ 'timestamp': timestamp,
2204
+ 'datetime': self.iso8601(timestamp),
2205
+ 'info': info,
2206
+ }
2207
+
2208
+ def fetch_funding_rate(self, symbol: str, params={}):
2209
+ """
2210
+ :see: https://docs.whitebit.com/public/http-v4/#available-futures-markets-list
2211
+ fetch the current funding rate
2212
+ :param str symbol: unified market symbol
2213
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2214
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2215
+ """
2216
+ self.load_markets()
2217
+ symbol = self.symbol(symbol)
2218
+ response = self.fetch_funding_rates([symbol], params)
2219
+ return self.safe_value(response, symbol)
2220
+
2221
+ def fetch_funding_rates(self, symbols: Strings = None, params={}):
2222
+ """
2223
+ :see: https://docs.whitebit.com/public/http-v4/#available-futures-markets-list
2224
+ fetch the funding rate for multiple markets
2225
+ :param str[]|None symbols: list of unified market symbols
2226
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2227
+ :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
2228
+ """
2229
+ self.load_markets()
2230
+ symbols = self.market_symbols(symbols)
2231
+ response = self.v4PublicGetFutures(params)
2232
+ #
2233
+ # [
2234
+ # {
2235
+ # "name": "BTC_USDT",
2236
+ # "type": "direct",
2237
+ # "quanto_multiplier": "0.0001",
2238
+ # "ref_discount_rate": "0",
2239
+ # "order_price_deviate": "0.5",
2240
+ # "maintenance_rate": "0.005",
2241
+ # "mark_type": "index",
2242
+ # "last_price": "38026",
2243
+ # "mark_price": "37985.6",
2244
+ # "index_price": "37954.92",
2245
+ # "funding_rate_indicative": "0.000219",
2246
+ # "mark_price_round": "0.01",
2247
+ # "funding_offset": 0,
2248
+ # "in_delisting": False,
2249
+ # "risk_limit_base": "1000000",
2250
+ # "interest_rate": "0.0003",
2251
+ # "order_price_round": "0.1",
2252
+ # "order_size_min": 1,
2253
+ # "ref_rebate_rate": "0.2",
2254
+ # "funding_interval": 28800,
2255
+ # "risk_limit_step": "1000000",
2256
+ # "leverage_min": "1",
2257
+ # "leverage_max": "100",
2258
+ # "risk_limit_max": "8000000",
2259
+ # "maker_fee_rate": "-0.00025",
2260
+ # "taker_fee_rate": "0.00075",
2261
+ # "funding_rate": "0.002053",
2262
+ # "order_size_max": 1000000,
2263
+ # "funding_next_apply": 1610035200,
2264
+ # "short_users": 977,
2265
+ # "config_change_time": 1609899548,
2266
+ # "trade_size": 28530850594,
2267
+ # "position_size": 5223816,
2268
+ # "long_users": 455,
2269
+ # "funding_impact_value": "60000",
2270
+ # "orders_limit": 50,
2271
+ # "trade_id": 10851092,
2272
+ # "orderbook_id": 2129638396
2273
+ # }
2274
+ # ]
2275
+ #
2276
+ data = self.safe_value(response, 'result', [])
2277
+ result = self.parse_funding_rates(data)
2278
+ return self.filter_by_array(result, 'symbol', symbols)
2279
+
2280
+ def parse_funding_rate(self, contract, market: Market = None):
2281
+ #
2282
+ # {
2283
+ # "ticker_id":"ADA_PERP",
2284
+ # "stock_currency":"ADA",
2285
+ # "money_currency":"USDT",
2286
+ # "last_price":"0.296708",
2287
+ # "stock_volume":"7982130",
2288
+ # "money_volume":"2345758.29189",
2289
+ # "bid":"0.296608",
2290
+ # "ask":"0.296758",
2291
+ # "high":"0.298338",
2292
+ # "low":"0.290171",
2293
+ # "product_type":"Perpetual",
2294
+ # "open_interest":"46533000",
2295
+ # "index_price":"0.29659",
2296
+ # "index_name":"Cardano",
2297
+ # "index_currency":"ADA",
2298
+ # "funding_rate":"0.0001",
2299
+ # "next_funding_rate_timestamp":"1691193600000",
2300
+ # "brackets":{
2301
+ # "1":"0",
2302
+ # "2":"0",
2303
+ # "3":"0",
2304
+ # "5":"0",
2305
+ # "10":"0",
2306
+ # "20":"0",
2307
+ # "50":"-10000",
2308
+ # "100":"-5000"
2309
+ # },
2310
+ # "max_leverage":"100"
2311
+ # }
2312
+ #
2313
+ marketId = self.safe_string(contract, 'ticker_id')
2314
+ symbol = self.safe_symbol(marketId, market)
2315
+ markPrice = self.safe_number(contract, 'markPrice')
2316
+ indexPrice = self.safe_number(contract, 'indexPrice')
2317
+ interestRate = self.safe_number(contract, 'interestRate')
2318
+ fundingRate = self.safe_number(contract, 'funding_rate')
2319
+ nextFundingTime = self.safe_integer(contract, 'next_funding_rate_timestamp')
2320
+ return {
2321
+ 'info': contract,
2322
+ 'symbol': symbol,
2323
+ 'markPrice': markPrice,
2324
+ 'indexPrice': indexPrice,
2325
+ 'interestRate': interestRate,
2326
+ 'timestamp': None,
2327
+ 'datetime': None,
2328
+ 'fundingRate': fundingRate,
2329
+ 'fundingTimestamp': None,
2330
+ 'fundingDatetime': self.iso8601(None),
2331
+ 'nextFundingRate': None,
2332
+ 'nextFundingTimestamp': nextFundingTime,
2333
+ 'nextFundingDatetime': self.iso8601(nextFundingTime),
2334
+ 'previousFundingRate': None,
2335
+ 'previousFundingTimestamp': None,
2336
+ 'previousFundingDatetime': None,
2337
+ }
2338
+
2339
+ def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2340
+ """
2341
+ fetch history of deposits and withdrawals
2342
+ :see: https://github.com/whitebit-exchange/api-docs/blob/main/pages/private/http-main-v4.md#get-depositwithdraw-history
2343
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2344
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2345
+ :param int [limit]: max number of deposit/withdrawals to return, default = 50, Min: 1, Max: 100
2346
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2347
+ *
2348
+ * EXCHANGE SPECIFIC PARAMETERS
2349
+ :param number [params.transactionMethod]: Method. Example: 1 to display deposits / 2 to display withdraws. Do not send self parameter in order to receive both deposits and withdraws.
2350
+ :param str [params.address]: Can be used for filtering transactions by specific address or memo.
2351
+ :param str[] [params.addresses]: Can be used for filtering transactions by specific addresses or memos(max: 20).
2352
+ :param str [params.uniqueId]: Can be used for filtering transactions by specific unique id
2353
+ :param int [params.offset]: If you want the request to return entries starting from a particular line, you can use OFFSET clause to tell it where it should start. Default: 0, Min: 0, Max: 10000
2354
+ :param str[] [params.status]: Can be used for filtering transactions by status codes. Caution: You must use self parameter with appropriate transactionMethod and use valid status codes for self method. You can find them below. Example: "status": [3,7]
2355
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2356
+ """
2357
+ self.load_markets()
2358
+ request: dict = {}
2359
+ currency = None
2360
+ if code is not None:
2361
+ currency = self.currency(code)
2362
+ request['ticker'] = currency['id']
2363
+ if limit is not None:
2364
+ request['limit'] = limit # default 1000
2365
+ response = self.v4PrivatePostMainAccountHistory(self.extend(request, params))
2366
+ #
2367
+ # {
2368
+ # "limit": 100,
2369
+ # "offset": 0,
2370
+ # "records": [
2371
+ # {
2372
+ # "address": "3ApEASLcrQtZpg1TsssFgYF5V5YQJAKvuE", # deposit address
2373
+ # "uniqueId": null, # unique Id of deposit
2374
+ # "createdAt": 1593437922, # timestamp of deposit
2375
+ # "currency": "Bitcoin", # deposit currency
2376
+ # "ticker": "BTC", # deposit currency ticker
2377
+ # "method": 1, # called method 1 - deposit, 2 - withdraw
2378
+ # "amount": "0.0006", # amount of deposit
2379
+ # "description": "", # deposit description
2380
+ # "memo": "", # deposit memo
2381
+ # "fee": "0", # deposit fee
2382
+ # "status": 15, # transactions status
2383
+ # "network": null, # if currency is multinetwork
2384
+ # "transactionHash": "a275a514013e4e0f927fd0d1bed215e7f6f2c4c6ce762836fe135ec22529d886", # deposit transaction hash
2385
+ # "transactionId": "5e112b38-9652-11ed-a1eb-0242ac120002", # transaction id
2386
+ # "details": {
2387
+ # "partial": { # details about partially successful withdrawals
2388
+ # "requestAmount": "50000", # requested withdrawal amount
2389
+ # "processedAmount": "39000", # processed withdrawal amount
2390
+ # "processedFee": "273", # fee for processed withdrawal amount
2391
+ # "normalizeTransaction": "" # deposit id
2392
+ # }
2393
+ # },
2394
+ # "confirmations": { # if transaction status == 15(Pending) you can see self object
2395
+ # "actual": 1, # current block confirmations
2396
+ # "required": 2 # required block confirmation for successful deposit
2397
+ # }
2398
+ # },
2399
+ # {...},
2400
+ # ],
2401
+ # "total": 300 # total number of transactions, use self for calculating ‘limit’ and ‘offset'
2402
+ # }
2403
+ #
2404
+ records = self.safe_list(response, 'records')
2405
+ return self.parse_transactions(records, currency, since, limit)
2406
+
2407
+ def is_fiat(self, currency):
2408
+ fiatCurrencies = self.safe_value(self.options, 'fiatCurrencies', [])
2409
+ return self.in_array(currency, fiatCurrencies)
2410
+
2411
+ def nonce(self):
2412
+ return self.milliseconds()
2413
+
2414
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2415
+ query = self.omit(params, self.extract_params(path))
2416
+ version = self.safe_value(api, 0)
2417
+ accessibility = self.safe_value(api, 1)
2418
+ pathWithParams = '/' + self.implode_params(path, params)
2419
+ url = self.urls['api'][version][accessibility] + pathWithParams
2420
+ if accessibility == 'public':
2421
+ if query:
2422
+ url += '?' + self.urlencode(query)
2423
+ if accessibility == 'private':
2424
+ self.check_required_credentials()
2425
+ nonce = str(self.nonce())
2426
+ secret = self.encode(self.secret)
2427
+ request = '/' + 'api' + '/' + version + pathWithParams
2428
+ body = self.json(self.extend({'request': request, 'nonce': nonce}, params))
2429
+ payload = self.string_to_base64(body)
2430
+ signature = self.hmac(self.encode(payload), secret, hashlib.sha512)
2431
+ headers = {
2432
+ 'Content-Type': 'application/json',
2433
+ 'X-TXC-APIKEY': self.apiKey,
2434
+ 'X-TXC-PAYLOAD': payload,
2435
+ 'X-TXC-SIGNATURE': signature,
2436
+ }
2437
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
2438
+
2439
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2440
+ if (code == 418) or (code == 429):
2441
+ raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason + ' ' + body)
2442
+ if code == 404:
2443
+ raise ExchangeError(self.id + ' ' + str(code) + ' endpoint not found')
2444
+ if response is not None:
2445
+ # For cases where we have a meaningful status
2446
+ # {"response":null,"status":422,"errors":{"orderId":["Finished order id 435453454535 not found on your account"]},"notification":null,"warning":"Finished order id 435453454535 not found on your account","_token":null}
2447
+ status = self.safe_string(response, 'status')
2448
+ # {"code":10,"message":"Unauthorized request."}
2449
+ message = self.safe_string(response, 'message')
2450
+ # For these cases where we have a generic code variable error key
2451
+ # {"code":0,"message":"Validation failed","errors":{"amount":["Amount must be greater than 0"]}}
2452
+ codeNew = self.safe_integer(response, 'code')
2453
+ hasErrorStatus = status is not None and status != '200'
2454
+ if hasErrorStatus or codeNew is not None:
2455
+ feedback = self.id + ' ' + body
2456
+ errorInfo = message
2457
+ if hasErrorStatus:
2458
+ errorInfo = status
2459
+ else:
2460
+ errorObject = self.safe_value(response, 'errors')
2461
+ if errorObject is not None:
2462
+ errorKey = list(errorObject.keys())[0]
2463
+ errorMessageArray = self.safe_value(errorObject, errorKey, [])
2464
+ errorMessageLength = len(errorMessageArray)
2465
+ errorInfo = errorMessageArray[0] if (errorMessageLength > 0) else body
2466
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorInfo, feedback)
2467
+ self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
2468
+ raise ExchangeError(feedback)
2469
+ return None