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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3114 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.woo import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Account, Balances, Bool, Conversion, Currencies, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, TradingFees, Transaction, TransferEntry, TransferEntries
10
+ from typing import List
11
+ from typing import Any
12
+ from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import ArgumentsRequired
15
+ from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import InvalidOrder
17
+ from ccxt.base.errors import NotSupported
18
+ from ccxt.base.errors import RateLimitExceeded
19
+ from ccxt.base.errors import OnMaintenance
20
+ from ccxt.base.decimal_to_precision import TICK_SIZE
21
+ from ccxt.base.precise import Precise
22
+
23
+
24
+ class woo(Exchange, ImplicitAPI):
25
+
26
+ def describe(self):
27
+ return self.deep_extend(super(woo, self).describe(), {
28
+ 'id': 'woo',
29
+ 'name': 'WOO X',
30
+ 'countries': ['KY'], # Cayman Islands
31
+ 'rateLimit': 100,
32
+ 'version': 'v1',
33
+ 'certified': True,
34
+ 'pro': True,
35
+ 'hostname': 'woo.org',
36
+ 'has': {
37
+ 'CORS': None,
38
+ 'spot': True,
39
+ 'margin': True,
40
+ 'swap': True,
41
+ 'future': False,
42
+ 'option': False,
43
+ 'addMargin': False,
44
+ 'cancelAllOrders': True,
45
+ 'cancelAllOrdersAfter': True,
46
+ 'cancelOrder': True,
47
+ 'cancelWithdraw': False, # exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
48
+ 'closeAllPositions': False,
49
+ 'closePosition': False,
50
+ 'createConvertTrade': True,
51
+ 'createDepositAddress': False,
52
+ 'createMarketBuyOrderWithCost': True,
53
+ 'createMarketOrder': False,
54
+ 'createMarketOrderWithCost': False,
55
+ 'createMarketSellOrderWithCost': False,
56
+ 'createOrder': True,
57
+ 'createOrderWithTakeProfitAndStopLoss': True,
58
+ 'createReduceOnlyOrder': True,
59
+ 'createStopLimitOrder': False,
60
+ 'createStopLossOrder': True,
61
+ 'createStopMarketOrder': False,
62
+ 'createStopOrder': False,
63
+ 'createTakeProfitOrder': True,
64
+ 'createTrailingAmountOrder': True,
65
+ 'createTrailingPercentOrder': True,
66
+ 'createTriggerOrder': True,
67
+ 'fetchAccounts': True,
68
+ 'fetchBalance': True,
69
+ 'fetchCanceledOrders': False,
70
+ 'fetchClosedOrder': False,
71
+ 'fetchClosedOrders': True,
72
+ 'fetchConvertCurrencies': True,
73
+ 'fetchConvertQuote': True,
74
+ 'fetchConvertTrade': True,
75
+ 'fetchConvertTradeHistory': True,
76
+ 'fetchCurrencies': True,
77
+ 'fetchDepositAddress': True,
78
+ 'fetchDeposits': True,
79
+ 'fetchDepositsWithdrawals': True,
80
+ 'fetchFundingHistory': True,
81
+ 'fetchFundingRate': True,
82
+ 'fetchFundingRateHistory': True,
83
+ 'fetchFundingRates': True,
84
+ 'fetchIndexOHLCV': False,
85
+ 'fetchLedger': True,
86
+ 'fetchLeverage': True,
87
+ 'fetchMarginAdjustmentHistory': False,
88
+ 'fetchMarginMode': False,
89
+ 'fetchMarkets': True,
90
+ 'fetchMarkOHLCV': False,
91
+ 'fetchMyTrades': True,
92
+ 'fetchOHLCV': True,
93
+ 'fetchOpenInterestHistory': False,
94
+ 'fetchOpenOrder': False,
95
+ 'fetchOpenOrders': True,
96
+ 'fetchOrder': True,
97
+ 'fetchOrderBook': True,
98
+ 'fetchOrders': True,
99
+ 'fetchOrderTrades': True,
100
+ 'fetchPosition': True,
101
+ 'fetchPositionHistory': False,
102
+ 'fetchPositionMode': False,
103
+ 'fetchPositions': True,
104
+ 'fetchPositionsHistory': False,
105
+ 'fetchPremiumIndexOHLCV': False,
106
+ 'fetchStatus': True,
107
+ 'fetchTicker': False,
108
+ 'fetchTickers': False,
109
+ 'fetchTime': True,
110
+ 'fetchTrades': True,
111
+ 'fetchTradingFee': False,
112
+ 'fetchTradingFees': True,
113
+ 'fetchTransactions': 'emulated',
114
+ 'fetchTransfers': True,
115
+ 'fetchWithdrawals': True,
116
+ 'reduceMargin': False,
117
+ 'sandbox': True,
118
+ 'setLeverage': True,
119
+ 'setMargin': False,
120
+ 'setPositionMode': True,
121
+ 'transfer': True,
122
+ 'withdraw': True, # exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#token-withdraw
123
+ },
124
+ 'timeframes': {
125
+ '1m': '1m',
126
+ '5m': '5m',
127
+ '15m': '15m',
128
+ '30m': '30m',
129
+ '1h': '1h',
130
+ '4h': '4h',
131
+ '12h': '12h',
132
+ '1d': '1d',
133
+ '1w': '1w',
134
+ '1M': '1mon',
135
+ '1y': '1y',
136
+ },
137
+ 'urls': {
138
+ 'logo': 'https://user-images.githubusercontent.com/1294454/150730761-1a00e5e0-d28c-480f-9e65-089ce3e6ef3b.jpg',
139
+ 'api': {
140
+ 'pub': 'https://api-pub.woo.org',
141
+ 'public': 'https://api.{hostname}',
142
+ 'private': 'https://api.{hostname}',
143
+ },
144
+ 'test': {
145
+ 'pub': 'https://api-pub.staging.woo.org',
146
+ 'public': 'https://api.staging.woo.org',
147
+ 'private': 'https://api.staging.woo.org',
148
+ },
149
+ 'www': 'https://woo.org/',
150
+ 'doc': [
151
+ 'https://docs.woo.org/',
152
+ ],
153
+ 'fees': [
154
+ 'https://support.woo.org/hc/en-001/articles/4404611795353--Trading-Fees',
155
+ ],
156
+ 'referral': {
157
+ 'url': 'https://x.woo.org/register?ref=YWOWC96B',
158
+ 'discount': 0.35,
159
+ },
160
+ },
161
+ 'api': {
162
+ 'v1': {
163
+ 'pub': {
164
+ 'get': {
165
+ 'hist/kline': 10,
166
+ 'hist/trades': 1,
167
+ },
168
+ },
169
+ 'public': {
170
+ 'get': {
171
+ 'info': 1,
172
+ 'info/{symbol}': 1,
173
+ 'system_info': 1,
174
+ 'market_trades': 1,
175
+ 'token': 1,
176
+ 'token_network': 1,
177
+ 'funding_rates': 1,
178
+ 'funding_rate/{symbol}': 1,
179
+ 'funding_rate_history': 1,
180
+ 'futures': 1,
181
+ 'futures/{symbol}': 1,
182
+ 'orderbook/{symbol}': 1,
183
+ 'kline': 1,
184
+ },
185
+ },
186
+ 'private': {
187
+ 'get': {
188
+ 'client/token': 1,
189
+ 'order/{oid}': 1,
190
+ 'client/order/{client_order_id}': 1,
191
+ 'orders': 1,
192
+ 'client/trade/{tid}': 1,
193
+ 'order/{oid}/trades': 1,
194
+ 'client/trades': 1,
195
+ 'client/hist_trades': 1,
196
+ 'staking/yield_history': 1,
197
+ 'client/holding': 1,
198
+ 'asset/deposit': 10,
199
+ 'asset/history': 60,
200
+ 'sub_account/all': 60,
201
+ 'sub_account/assets': 60,
202
+ 'sub_account/asset_detail': 60,
203
+ 'sub_account/ip_restriction': 10,
204
+ 'asset/main_sub_transfer_history': 30,
205
+ 'token_interest': 60,
206
+ 'token_interest/{token}': 60,
207
+ 'interest/history': 60,
208
+ 'interest/repay': 60,
209
+ 'funding_fee/history': 30,
210
+ 'positions': 3.33, # 30 requests per 10 seconds
211
+ 'position/{symbol}': 3.33,
212
+ 'client/transaction_history': 60,
213
+ },
214
+ 'post': {
215
+ 'order': 5, # 2 requests per 1 second per symbol
216
+ 'order/cancel_all_after': 1,
217
+ 'asset/main_sub_transfer': 30, # 20 requests per 60 seconds
218
+ 'asset/ltv': 30,
219
+ 'asset/withdraw': 30, # implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#token-withdraw
220
+ 'asset/internal_withdraw': 30,
221
+ 'interest/repay': 60,
222
+ 'client/account_mode': 120,
223
+ 'client/position_mode': 5,
224
+ 'client/leverage': 120,
225
+ },
226
+ 'delete': {
227
+ 'order': 1,
228
+ 'client/order': 1,
229
+ 'orders': 1,
230
+ 'asset/withdraw': 120, # implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
231
+ },
232
+ },
233
+ },
234
+ 'v2': {
235
+ 'private': {
236
+ 'get': {
237
+ 'client/holding': 1,
238
+ },
239
+ },
240
+ },
241
+ 'v3': {
242
+ 'public': {
243
+ 'get': {
244
+ 'insuranceFund': 3,
245
+ },
246
+ },
247
+ 'private': {
248
+ 'get': {
249
+ 'algo/order/{oid}': 1,
250
+ 'algo/orders': 1,
251
+ 'balances': 1,
252
+ 'accountinfo': 60,
253
+ 'positions': 3.33,
254
+ 'buypower': 1,
255
+ 'referrals': 60,
256
+ 'referral_rewards': 60,
257
+ 'convert/exchangeInfo': 1,
258
+ 'convert/assetInfo': 1,
259
+ 'convert/rfq': 60,
260
+ 'convert/trade': 1,
261
+ 'convert/trades': 1,
262
+ },
263
+ 'post': {
264
+ 'algo/order': 5,
265
+ 'convert/rft': 60,
266
+ },
267
+ 'put': {
268
+ 'order/{oid}': 2,
269
+ 'order/client/{client_order_id}': 2,
270
+ 'algo/order/{oid}': 2,
271
+ 'algo/order/client/{client_order_id}': 2,
272
+ },
273
+ 'delete': {
274
+ 'algo/order/{order_id}': 1,
275
+ 'algo/orders/pending': 1,
276
+ 'algo/orders/pending/{symbol}': 1,
277
+ 'orders/pending': 1,
278
+ },
279
+ },
280
+ },
281
+ },
282
+ 'fees': {
283
+ 'trading': {
284
+ 'tierBased': True,
285
+ 'percentage': True,
286
+ 'maker': self.parse_number('0.0002'),
287
+ 'taker': self.parse_number('0.0005'),
288
+ },
289
+ },
290
+ 'options': {
291
+ 'sandboxMode': False,
292
+ 'createMarketBuyOrderRequiresPrice': True,
293
+ # these network aliases require manual mapping here
294
+ 'network-aliases-for-tokens': {
295
+ 'HT': 'ERC20',
296
+ 'OMG': 'ERC20',
297
+ 'UATOM': 'ATOM',
298
+ 'ZRX': 'ZRX',
299
+ },
300
+ 'networks': {
301
+ 'TRX': 'TRON',
302
+ 'TRC20': 'TRON',
303
+ 'ERC20': 'ETH',
304
+ 'BEP20': 'BSC',
305
+ },
306
+ # override defaultNetworkCodePriorities for a specific currency
307
+ 'defaultNetworkCodeForCurrencies': {
308
+ # 'USDT': 'TRC20',
309
+ # 'BTC': 'BTC',
310
+ },
311
+ 'transfer': {
312
+ 'fillResponseFromRequest': True,
313
+ },
314
+ 'brokerId': 'bc830de7-50f3-460b-9ee0-f430f83f9dad',
315
+ },
316
+ 'commonCurrencies': {},
317
+ 'exceptions': {
318
+ 'exact': {
319
+ '-1000': ExchangeError, # {"code": -1000, "message": "An unknown error occurred while processing the request"}
320
+ '-1001': AuthenticationError, # {"code": -1001, "message": "The api key or secret is in wrong format"}
321
+ '-1002': AuthenticationError, # {"code": -1002, "message": "API key or secret is invalid, it may because key have insufficient permission or the key is expired/revoked."}
322
+ '-1003': RateLimitExceeded, # {"code": -1003, "message": "Rate limit exceed."}
323
+ '-1004': BadRequest, # {"code": -1004, "message": "An unknown parameter was sent."}
324
+ '-1005': BadRequest, # {"code": -1005, "message": "Some parameters are in wrong format for api."}
325
+ '-1006': BadRequest, # {"code": -1006, "message": "The data is not found in server."}
326
+ '-1007': BadRequest, # {"code": -1007, "message": "The data is already exists or your request is duplicated."}
327
+ '-1008': InvalidOrder, # {"code": -1008, "message": "The quantity of settlement is too high than you can request."}
328
+ '-1009': BadRequest, # {"code": -1009, "message": "Can not request withdrawal settlement, you need to deposit other arrears first."}
329
+ '-1012': BadRequest, # {"code": -1012, "message": "Amount is required for buy market orders when margin disabled."} The place/cancel order request is rejected by internal module, it may because the account is in liquidation or other internal errors. Please try again in a few seconds."}
330
+ '-1101': InvalidOrder, # {"code": -1101, "message": "The risk exposure for client is too high, it may cause by sending too big order or the leverage is too low. please refer to client info to check the current exposure."}
331
+ '-1102': InvalidOrder, # {"code": -1102, "message": "The order value(price * size) is too small."}
332
+ '-1103': InvalidOrder, # {"code": -1103, "message": "The order price is not following the tick size rule for the symbol."}
333
+ '-1104': InvalidOrder, # {"code": -1104, "message": "The order quantity is not following the step size rule for the symbol."}
334
+ '-1105': InvalidOrder, # {"code": -1105, "message": "Price is X% too high or X% too low from the mid price."}
335
+ },
336
+ 'broad': {
337
+ 'Can not place': ExchangeError, # {"code": -1011, "message": "Can not place/cancel orders, it may because internal network error. Please try again in a few seconds."}
338
+ 'maintenance': OnMaintenance, # {"code":"-1011","message":"The system is under maintenance.","success":false}
339
+ 'symbol must not be blank': BadRequest, # when sending 'cancelOrder' without symbol [-1005]
340
+ 'The token is not supported': BadRequest, # when getting incorrect token's deposit address [-1005]
341
+ 'Your order and symbol are not valid or already canceled': BadRequest, # actual response whensending 'cancelOrder' for already canceled id [-1006]
342
+ 'Insufficient WOO. Please enable margin trading for leverage trading': BadRequest, # when selling insufficent token [-1012]
343
+ },
344
+ },
345
+ 'precisionMode': TICK_SIZE,
346
+ })
347
+
348
+ async def fetch_status(self, params={}):
349
+ """
350
+ the latest known information on the availability of the exchange API
351
+ :see: https://docs.woo.org/#get-system-maintenance-status-public
352
+ :param dict [params]: extra parameters specific to the exchange API endpoint
353
+ :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
354
+ """
355
+ response = await self.v1PublicGetSystemInfo(params)
356
+ #
357
+ # {
358
+ # "success": True,
359
+ # "data": {
360
+ # "status": "0",
361
+ # "msg": "System is functioning properly."
362
+ # },
363
+ # "timestamp": "1709274106602"
364
+ # }
365
+ #
366
+ data = self.safe_dict(response, 'data', {})
367
+ status = self.safe_string(data, 'status')
368
+ if status is None:
369
+ status = 'error'
370
+ elif status == '0':
371
+ status = 'ok'
372
+ else:
373
+ status = 'maintenance'
374
+ return {
375
+ 'status': status,
376
+ 'updated': None,
377
+ 'eta': None,
378
+ 'url': None,
379
+ 'info': response,
380
+ }
381
+
382
+ async def fetch_time(self, params={}):
383
+ """
384
+ fetches the current integer timestamp in milliseconds from the exchange server
385
+ :see: https://docs.woo.org/#get-system-maintenance-status-public
386
+ :param dict [params]: extra parameters specific to the exchange API endpoint
387
+ :returns int: the current integer timestamp in milliseconds from the exchange server
388
+ """
389
+ response = await self.v1PublicGetSystemInfo(params)
390
+ #
391
+ # {
392
+ # "success": True,
393
+ # "data": {
394
+ # "status": "0",
395
+ # "msg": "System is functioning properly."
396
+ # },
397
+ # "timestamp": "1709274106602"
398
+ # }
399
+ #
400
+ return self.safe_integer(response, 'timestamp')
401
+
402
+ async def fetch_markets(self, params={}) -> List[Market]:
403
+ """
404
+ retrieves data on all markets for woo
405
+ :see: https://docs.woo.org/#exchange-information
406
+ :param dict [params]: extra parameters specific to the exchange API endpoint
407
+ :returns dict[]: an array of objects representing market data
408
+ """
409
+ response = await self.v1PublicGetInfo(params)
410
+ #
411
+ # {
412
+ # "rows": [
413
+ # {
414
+ # "symbol": "SPOT_AAVE_USDT",
415
+ # "quote_min": 0,
416
+ # "quote_max": 100000,
417
+ # "quote_tick": 0.01,
418
+ # "base_min": 0.01,
419
+ # "base_max": 7284,
420
+ # "base_tick": 0.0001,
421
+ # "min_notional": 10,
422
+ # "price_range": 0.1,
423
+ # "created_time": "0",
424
+ # "updated_time": "1639107647.988",
425
+ # "is_stable": 0
426
+ # },
427
+ # ...
428
+ # "success": True
429
+ # }
430
+ #
431
+ data = self.safe_list(response, 'rows', [])
432
+ return self.parse_markets(data)
433
+
434
+ def parse_market(self, market: dict) -> Market:
435
+ marketId = self.safe_string(market, 'symbol')
436
+ parts = marketId.split('_')
437
+ first = self.safe_string(parts, 0)
438
+ marketType: MarketType
439
+ spot = False
440
+ swap = False
441
+ if first == 'SPOT':
442
+ spot = True
443
+ marketType = 'spot'
444
+ elif first == 'PERP':
445
+ swap = True
446
+ marketType = 'swap'
447
+ baseId = self.safe_string(parts, 1)
448
+ quoteId = self.safe_string(parts, 2)
449
+ base = self.safe_currency_code(baseId)
450
+ quote = self.safe_currency_code(quoteId)
451
+ settleId: Str = None
452
+ settle: Str = None
453
+ symbol = base + '/' + quote
454
+ contractSize: Num = None
455
+ linear: Bool = None
456
+ margin = True
457
+ contract = swap
458
+ if contract:
459
+ margin = False
460
+ settleId = self.safe_string(parts, 2)
461
+ settle = self.safe_currency_code(settleId)
462
+ symbol = base + '/' + quote + ':' + settle
463
+ contractSize = self.parse_number('1')
464
+ linear = True
465
+ return {
466
+ 'id': marketId,
467
+ 'symbol': symbol,
468
+ 'base': base,
469
+ 'quote': quote,
470
+ 'settle': settle,
471
+ 'baseId': baseId,
472
+ 'quoteId': quoteId,
473
+ 'settleId': settleId,
474
+ 'type': marketType,
475
+ 'spot': spot,
476
+ 'margin': margin,
477
+ 'swap': swap,
478
+ 'future': False,
479
+ 'option': False,
480
+ 'active': None,
481
+ 'contract': contract,
482
+ 'linear': linear,
483
+ 'inverse': None,
484
+ 'contractSize': contractSize,
485
+ 'expiry': None,
486
+ 'expiryDatetime': None,
487
+ 'strike': None,
488
+ 'optionType': None,
489
+ 'precision': {
490
+ 'amount': self.safe_number(market, 'base_tick'),
491
+ 'price': self.safe_number(market, 'quote_tick'),
492
+ },
493
+ 'limits': {
494
+ 'leverage': {
495
+ 'min': None,
496
+ 'max': None,
497
+ },
498
+ 'amount': {
499
+ 'min': self.safe_number(market, 'base_min'),
500
+ 'max': self.safe_number(market, 'base_max'),
501
+ },
502
+ 'price': {
503
+ 'min': self.safe_number(market, 'quote_min'),
504
+ 'max': self.safe_number(market, 'quote_max'),
505
+ },
506
+ 'cost': {
507
+ 'min': self.safe_number(market, 'min_notional'),
508
+ 'max': None,
509
+ },
510
+ },
511
+ 'created': self.safe_timestamp(market, 'created_time'),
512
+ 'info': market,
513
+ }
514
+
515
+ async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
516
+ """
517
+ get the list of most recent trades for a particular symbol
518
+ :see: https://docs.woo.org/#market-trades-public
519
+ :param str symbol: unified symbol of the market to fetch trades for
520
+ :param int [since]: timestamp in ms of the earliest trade to fetch
521
+ :param int [limit]: the maximum amount of trades to fetch
522
+ :param dict [params]: extra parameters specific to the exchange API endpoint
523
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
524
+ """
525
+ await self.load_markets()
526
+ market = self.market(symbol)
527
+ request: dict = {
528
+ 'symbol': market['id'],
529
+ }
530
+ if limit is not None:
531
+ request['limit'] = limit
532
+ response = await self.v1PublicGetMarketTrades(self.extend(request, params))
533
+ #
534
+ # {
535
+ # "success": True,
536
+ # "rows": [
537
+ # {
538
+ # "symbol": "SPOT_BTC_USDT",
539
+ # "side": "SELL",
540
+ # "executed_price": 46222.35,
541
+ # "executed_quantity": 0.0012,
542
+ # "executed_timestamp": "1641241162.329"
543
+ # },
544
+ # {
545
+ # "symbol": "SPOT_BTC_USDT",
546
+ # "side": "SELL",
547
+ # "executed_price": 46222.35,
548
+ # "executed_quantity": 0.0012,
549
+ # "executed_timestamp": "1641241162.329"
550
+ # },
551
+ # {
552
+ # "symbol": "SPOT_BTC_USDT",
553
+ # "side": "BUY",
554
+ # "executed_price": 46224.32,
555
+ # "executed_quantity": 0.00039,
556
+ # "executed_timestamp": "1641241162.287"
557
+ # },
558
+ # ...
559
+ # ]
560
+ # }
561
+ #
562
+ resultResponse = self.safe_list(response, 'rows', [])
563
+ return self.parse_trades(resultResponse, market, since, limit)
564
+
565
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
566
+ #
567
+ # public/market_trades
568
+ #
569
+ # {
570
+ # "symbol": "SPOT_BTC_USDT",
571
+ # "side": "SELL",
572
+ # "executed_price": 46222.35,
573
+ # "executed_quantity": 0.0012,
574
+ # "executed_timestamp": "1641241162.329"
575
+ # }
576
+ #
577
+ # fetchOrderTrades, fetchOrder
578
+ #
579
+ # {
580
+ # "id": "99119876",
581
+ # "symbol": "SPOT_WOO_USDT",
582
+ # "fee": "0.0024",
583
+ # "side": "BUY",
584
+ # "executed_timestamp": "1641481113.084",
585
+ # "order_id": "87001234",
586
+ # "order_tag": "default", <-- self param only in "fetchOrderTrades"
587
+ # "executed_price": "1",
588
+ # "executed_quantity": "12",
589
+ # "fee_asset": "WOO",
590
+ # "is_maker": "1"
591
+ # }
592
+ #
593
+ isFromFetchOrder = ('id' in trade)
594
+ timestamp = self.safe_timestamp(trade, 'executed_timestamp')
595
+ marketId = self.safe_string(trade, 'symbol')
596
+ market = self.safe_market(marketId, market)
597
+ symbol = market['symbol']
598
+ price = self.safe_string(trade, 'executed_price')
599
+ amount = self.safe_string(trade, 'executed_quantity')
600
+ order_id = self.safe_string(trade, 'order_id')
601
+ fee = self.parse_token_and_fee_temp(trade, 'fee_asset', 'fee')
602
+ cost = Precise.string_mul(price, amount)
603
+ side = self.safe_string_lower(trade, 'side')
604
+ id = self.safe_string(trade, 'id')
605
+ takerOrMaker: Str = None
606
+ if isFromFetchOrder:
607
+ isMaker = self.safe_string(trade, 'is_maker') == '1'
608
+ takerOrMaker = 'maker' if isMaker else 'taker'
609
+ return self.safe_trade({
610
+ 'id': id,
611
+ 'timestamp': timestamp,
612
+ 'datetime': self.iso8601(timestamp),
613
+ 'symbol': symbol,
614
+ 'side': side,
615
+ 'price': price,
616
+ 'amount': amount,
617
+ 'cost': cost,
618
+ 'order': order_id,
619
+ 'takerOrMaker': takerOrMaker,
620
+ 'type': None,
621
+ 'fee': fee,
622
+ 'info': trade,
623
+ }, market)
624
+
625
+ def parse_token_and_fee_temp(self, item, feeTokenKey, feeAmountKey):
626
+ feeCost = self.safe_string(item, feeAmountKey)
627
+ fee = None
628
+ if feeCost is not None:
629
+ feeCurrencyId = self.safe_string(item, feeTokenKey)
630
+ feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
631
+ fee = {
632
+ 'cost': feeCost,
633
+ 'currency': feeCurrencyCode,
634
+ }
635
+ return fee
636
+
637
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
638
+ """
639
+ fetch the trading fees for multiple markets
640
+ :see: https://docs.woo.org/#get-account-information-new
641
+ :param dict [params]: extra parameters specific to the exchange API endpoint
642
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
643
+ """
644
+ await self.load_markets()
645
+ response = await self.v3PrivateGetAccountinfo(params)
646
+ #
647
+ # {
648
+ # "success": True,
649
+ # "data": {
650
+ # "applicationId": "dsa",
651
+ # "account": "dsa",
652
+ # "alias": "haha",
653
+ # "accountMode": "MARGIN",
654
+ # "leverage": 1,
655
+ # "takerFeeRate": 1,
656
+ # "makerFeeRate": 1,
657
+ # "interestRate": 1,
658
+ # "futuresTakerFeeRate": 1,
659
+ # "futuresMakerFeeRate": 1,
660
+ # "otpauth": True,
661
+ # "marginRatio": 1,
662
+ # "openMarginRatio": 1,
663
+ # "initialMarginRatio": 1,
664
+ # "maintenanceMarginRatio": 1,
665
+ # "totalCollateral": 1,
666
+ # "freeCollateral": 1,
667
+ # "totalAccountValue": 1,
668
+ # "totalVaultValue": 1,
669
+ # "totalStakingValue": 1
670
+ # },
671
+ # "timestamp": 1673323685109
672
+ # }
673
+ #
674
+ data = self.safe_dict(response, 'data', {})
675
+ maker = self.safe_string(data, 'makerFeeRate')
676
+ taker = self.safe_string(data, 'takerFeeRate')
677
+ result: dict = {}
678
+ for i in range(0, len(self.symbols)):
679
+ symbol = self.symbols[i]
680
+ result[symbol] = {
681
+ 'info': response,
682
+ 'symbol': symbol,
683
+ 'maker': self.parse_number(Precise.string_div(maker, '10000')),
684
+ 'taker': self.parse_number(Precise.string_div(taker, '10000')),
685
+ 'percentage': True,
686
+ 'tierBased': True,
687
+ }
688
+ return result
689
+
690
+ async def fetch_currencies(self, params={}) -> Currencies:
691
+ """
692
+ fetches all available currencies on an exchange
693
+ :see: https://docs.woo.org/#available-token-public
694
+ :param dict [params]: extra parameters specific to the exchange API endpoint
695
+ :returns dict: an associative dictionary of currencies
696
+ """
697
+ result: dict = {}
698
+ tokenResponse = await self.v1PublicGetToken(params)
699
+ #
700
+ # {
701
+ # "rows": [
702
+ # {
703
+ # "token": "ETH_USDT",
704
+ # "fullname": "Tether",
705
+ # "decimals": 6,
706
+ # "balance_token": "USDT",
707
+ # "created_time": "0",
708
+ # "updated_time": "0"
709
+ # },
710
+ # {
711
+ # "token": "BSC_USDT",
712
+ # "fullname": "Tether",
713
+ # "decimals": 18,
714
+ # "balance_token": "USDT",
715
+ # "created_time": "0",
716
+ # "updated_time": "0"
717
+ # },
718
+ # {
719
+ # "token": "ZEC",
720
+ # "fullname": "ZCash",
721
+ # "decimals": 8,
722
+ # "balance_token": "ZEC",
723
+ # "created_time": "0",
724
+ # "updated_time": "0"
725
+ # },
726
+ # ...
727
+ # ],
728
+ # "success": True
729
+ # }
730
+ #
731
+ # only make one request for currrencies...
732
+ # tokenNetworkResponse = await self.v1PublicGetTokenNetwork(params)
733
+ #
734
+ # {
735
+ # "rows": [
736
+ # {
737
+ # "protocol": "ERC20",
738
+ # "token": "USDT",
739
+ # "name": "Ethereum",
740
+ # "minimum_withdrawal": 30,
741
+ # "withdrawal_fee": 25,
742
+ # "allow_deposit": 1,
743
+ # "allow_withdraw": 1
744
+ # },
745
+ # {
746
+ # "protocol": "TRC20",
747
+ # "token": "USDT",
748
+ # "name": "Tron",
749
+ # "minimum_withdrawal": 30,
750
+ # "withdrawal_fee": 1,
751
+ # "allow_deposit": 1,
752
+ # "allow_withdraw": 1
753
+ # },
754
+ # ...
755
+ # ],
756
+ # "success": True
757
+ # }
758
+ #
759
+ tokenRows = self.safe_list(tokenResponse, 'rows', [])
760
+ networksByCurrencyId = self.group_by(tokenRows, 'balance_token')
761
+ currencyIds = list(networksByCurrencyId.keys())
762
+ for i in range(0, len(currencyIds)):
763
+ currencyId = currencyIds[i]
764
+ networks = networksByCurrencyId[currencyId]
765
+ code = self.safe_currency_code(currencyId)
766
+ name: Str = None
767
+ minPrecision = None
768
+ resultingNetworks: dict = {}
769
+ for j in range(0, len(networks)):
770
+ network = networks[j]
771
+ name = self.safe_string(network, 'fullname')
772
+ networkId = self.safe_string(network, 'token')
773
+ splitted = networkId.split('_')
774
+ unifiedNetwork = splitted[0]
775
+ precision = self.parse_precision(self.safe_string(network, 'decimals'))
776
+ if precision is not None:
777
+ minPrecision = precision if (minPrecision is None) else Precise.string_min(precision, minPrecision)
778
+ resultingNetworks[unifiedNetwork] = {
779
+ 'id': networkId,
780
+ 'network': unifiedNetwork,
781
+ 'limits': {
782
+ 'withdraw': {
783
+ 'min': None,
784
+ 'max': None,
785
+ },
786
+ 'deposit': {
787
+ 'min': None,
788
+ 'max': None,
789
+ },
790
+ },
791
+ 'active': None,
792
+ 'deposit': None,
793
+ 'withdraw': None,
794
+ 'fee': None,
795
+ 'precision': self.parse_number(precision),
796
+ 'info': network,
797
+ }
798
+ result[code] = {
799
+ 'id': currencyId,
800
+ 'name': name,
801
+ 'code': code,
802
+ 'precision': self.parse_number(minPrecision),
803
+ 'active': None,
804
+ 'fee': None,
805
+ 'networks': resultingNetworks,
806
+ 'deposit': None,
807
+ 'withdraw': None,
808
+ 'limits': {
809
+ 'deposit': {
810
+ 'min': None,
811
+ 'max': None,
812
+ },
813
+ 'withdraw': {
814
+ 'min': None,
815
+ 'max': None,
816
+ },
817
+ },
818
+ 'info': networks,
819
+ }
820
+ return result
821
+
822
+ async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
823
+ """
824
+ create a market buy order by providing the symbol and cost
825
+ :see: https://docs.woo.org/#send-order
826
+ :param str symbol: unified symbol of the market to create an order in
827
+ :param float cost: how much you want to trade in units of the quote currency
828
+ :param dict [params]: extra parameters specific to the exchange API endpoint
829
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
830
+ """
831
+ await self.load_markets()
832
+ market = self.market(symbol)
833
+ if not market['spot']:
834
+ raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
835
+ params['createMarketBuyOrderRequiresPrice'] = False
836
+ return await self.create_order(symbol, 'market', 'buy', cost, None, params)
837
+
838
+ async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}) -> Order:
839
+ """
840
+ create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
841
+ :see: https://docs.woo.org/#send-algo-order
842
+ :param str symbol: unified symbol of the market to create an order in
843
+ :param str type: 'market' or 'limit'
844
+ :param str side: 'buy' or 'sell'
845
+ :param float amount: how much you want to trade in units of the base currency, or number of contracts
846
+ :param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
847
+ :param float trailingAmount: the quote amount to trail away from the current market price
848
+ :param float trailingTriggerPrice: the price to activate a trailing order, default uses the price argument
849
+ :param dict [params]: extra parameters specific to the exchange API endpoint
850
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
851
+ """
852
+ if trailingAmount is None:
853
+ raise ArgumentsRequired(self.id + ' createTrailingAmountOrder() requires a trailingAmount argument')
854
+ if trailingTriggerPrice is None:
855
+ raise ArgumentsRequired(self.id + ' createTrailingAmountOrder() requires a trailingTriggerPrice argument')
856
+ params['trailingAmount'] = trailingAmount
857
+ params['trailingTriggerPrice'] = trailingTriggerPrice
858
+ return await self.create_order(symbol, type, side, amount, price, params)
859
+
860
+ async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent=None, trailingTriggerPrice=None, params={}) -> Order:
861
+ """
862
+ create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
863
+ :see: https://docs.woo.org/#send-algo-order
864
+ :param str symbol: unified symbol of the market to create an order in
865
+ :param str type: 'market' or 'limit'
866
+ :param str side: 'buy' or 'sell'
867
+ :param float amount: how much you want to trade in units of the base currency, or number of contracts
868
+ :param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
869
+ :param float trailingPercent: the percent to trail away from the current market price
870
+ :param float trailingTriggerPrice: the price to activate a trailing order, default uses the price argument
871
+ :param dict [params]: extra parameters specific to the exchange API endpoint
872
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
873
+ """
874
+ if trailingPercent is None:
875
+ raise ArgumentsRequired(self.id + ' createTrailingPercentOrder() requires a trailingPercent argument')
876
+ if trailingTriggerPrice is None:
877
+ raise ArgumentsRequired(self.id + ' createTrailingPercentOrder() requires a trailingTriggerPrice argument')
878
+ params['trailingPercent'] = trailingPercent
879
+ params['trailingTriggerPrice'] = trailingTriggerPrice
880
+ return await self.create_order(symbol, type, side, amount, price, params)
881
+
882
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
883
+ """
884
+ create a trade order
885
+ :see: https://docs.woo.org/#send-order
886
+ :see: https://docs.woo.org/#send-algo-order
887
+ :param str symbol: unified symbol of the market to create an order in
888
+ :param str type: 'market' or 'limit'
889
+ :param str side: 'buy' or 'sell'
890
+ :param float amount: how much of currency you want to trade in units of base currency
891
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
892
+ :param dict [params]: extra parameters specific to the exchange API endpoint
893
+ :param float [params.triggerPrice]: The price a trigger order is triggered at
894
+ :param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered(perpetual swap markets only)
895
+ :param float [params.takeProfit.triggerPrice]: take profit trigger price
896
+ :param dict [params.stopLoss]: *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered(perpetual swap markets only)
897
+ :param float [params.stopLoss.triggerPrice]: stop loss trigger price
898
+ :param float [params.algoType]: 'STOP'or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
899
+ :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
900
+ :param str [params.trailingAmount]: the quote amount to trail away from the current market price
901
+ :param str [params.trailingPercent]: the percent to trail away from the current market price
902
+ :param str [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
903
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
904
+ """
905
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
906
+ params = self.omit(params, ['reduceOnly', 'reduce_only'])
907
+ orderType = type.upper()
908
+ await self.load_markets()
909
+ market = self.market(symbol)
910
+ orderSide = side.upper()
911
+ request: dict = {
912
+ 'symbol': market['id'],
913
+ 'side': orderSide,
914
+ }
915
+ stopPrice = self.safe_number_2(params, 'triggerPrice', 'stopPrice')
916
+ stopLoss = self.safe_value(params, 'stopLoss')
917
+ takeProfit = self.safe_value(params, 'takeProfit')
918
+ algoType = self.safe_string(params, 'algoType')
919
+ trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activatedPrice', self.number_to_string(price))
920
+ trailingAmount = self.safe_string_2(params, 'trailingAmount', 'callbackValue')
921
+ trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
922
+ isTrailingAmountOrder = trailingAmount is not None
923
+ isTrailingPercentOrder = trailingPercent is not None
924
+ isTrailing = isTrailingAmountOrder or isTrailingPercentOrder
925
+ isStop = isTrailing or stopPrice is not None or stopLoss is not None or takeProfit is not None or (self.safe_value(params, 'childOrders') is not None)
926
+ isMarket = orderType == 'MARKET'
927
+ timeInForce = self.safe_string_lower(params, 'timeInForce')
928
+ postOnly = self.is_post_only(isMarket, None, params)
929
+ reduceOnlyKey = 'reduceOnly' if isStop else 'reduce_only'
930
+ clientOrderIdKey = 'clientOrderId' if isStop else 'client_order_id'
931
+ orderQtyKey = 'quantity' if isStop else 'order_quantity'
932
+ priceKey = 'price' if isStop else 'order_price'
933
+ typeKey = 'type' if isStop else 'order_type'
934
+ request[typeKey] = orderType # LIMIT/MARKET/IOC/FOK/POST_ONLY/ASK/BID
935
+ if not isStop:
936
+ if postOnly:
937
+ request['order_type'] = 'POST_ONLY'
938
+ elif timeInForce == 'fok':
939
+ request['order_type'] = 'FOK'
940
+ elif timeInForce == 'ioc':
941
+ request['order_type'] = 'IOC'
942
+ if reduceOnly:
943
+ request[reduceOnlyKey] = reduceOnly
944
+ if price is not None:
945
+ request[priceKey] = self.price_to_precision(symbol, price)
946
+ if isMarket and not isStop:
947
+ # for market buy it requires the amount of quote currency to spend
948
+ if market['spot'] and orderSide == 'BUY':
949
+ quoteAmount = None
950
+ createMarketBuyOrderRequiresPrice = True
951
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
952
+ cost = self.safe_number_2(params, 'cost', 'order_amount')
953
+ params = self.omit(params, ['cost', 'order_amount'])
954
+ if cost is not None:
955
+ quoteAmount = self.cost_to_precision(symbol, cost)
956
+ elif createMarketBuyOrderRequiresPrice:
957
+ if price is None:
958
+ raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
959
+ else:
960
+ amountString = self.number_to_string(amount)
961
+ priceString = self.number_to_string(price)
962
+ costRequest = Precise.string_mul(amountString, priceString)
963
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
964
+ else:
965
+ quoteAmount = self.cost_to_precision(symbol, amount)
966
+ request['order_amount'] = quoteAmount
967
+ else:
968
+ request['order_quantity'] = self.amount_to_precision(symbol, amount)
969
+ elif algoType != 'POSITIONAL_TP_SL':
970
+ request[orderQtyKey] = self.amount_to_precision(symbol, amount)
971
+ clientOrderId = self.safe_string_n(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
972
+ if clientOrderId is not None:
973
+ request[clientOrderIdKey] = clientOrderId
974
+ if isTrailing:
975
+ if trailingTriggerPrice is None:
976
+ raise ArgumentsRequired(self.id + ' createOrder() requires a trailingTriggerPrice parameter for trailing orders')
977
+ request['activatedPrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
978
+ request['algoType'] = 'TRAILING_STOP'
979
+ if isTrailingAmountOrder:
980
+ request['callbackValue'] = trailingAmount
981
+ elif isTrailingPercentOrder:
982
+ convertedTrailingPercent = Precise.string_div(trailingPercent, '100')
983
+ request['callbackRate'] = convertedTrailingPercent
984
+ elif stopPrice is not None:
985
+ if algoType != 'TRAILING_STOP':
986
+ request['triggerPrice'] = self.price_to_precision(symbol, stopPrice)
987
+ request['algoType'] = 'STOP'
988
+ elif (stopLoss is not None) or (takeProfit is not None):
989
+ request['algoType'] = 'BRACKET'
990
+ outterOrder: dict = {
991
+ 'symbol': market['id'],
992
+ 'reduceOnly': False,
993
+ 'algoType': 'POSITIONAL_TP_SL',
994
+ 'childOrders': [],
995
+ }
996
+ closeSide = 'SELL' if (orderSide == 'BUY') else 'BUY'
997
+ if stopLoss is not None:
998
+ stopLossPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'price', stopLoss)
999
+ stopLossOrder: dict = {
1000
+ 'side': closeSide,
1001
+ 'algoType': 'STOP_LOSS',
1002
+ 'triggerPrice': self.price_to_precision(symbol, stopLossPrice),
1003
+ 'type': 'CLOSE_POSITION',
1004
+ 'reduceOnly': True,
1005
+ }
1006
+ outterOrder['childOrders'].append(stopLossOrder)
1007
+ if takeProfit is not None:
1008
+ takeProfitPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'price', takeProfit)
1009
+ takeProfitOrder: dict = {
1010
+ 'side': closeSide,
1011
+ 'algoType': 'TAKE_PROFIT',
1012
+ 'triggerPrice': self.price_to_precision(symbol, takeProfitPrice),
1013
+ 'type': 'CLOSE_POSITION',
1014
+ 'reduceOnly': True,
1015
+ }
1016
+ outterOrder['childOrders'].append(takeProfitOrder)
1017
+ request['childOrders'] = [outterOrder]
1018
+ params = self.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingPercent', 'trailingAmount', 'trailingTriggerPrice'])
1019
+ response = None
1020
+ if isStop:
1021
+ response = await self.v3PrivatePostAlgoOrder(self.extend(request, params))
1022
+ else:
1023
+ response = await self.v1PrivatePostOrder(self.extend(request, params))
1024
+ # {
1025
+ # "success": True,
1026
+ # "timestamp": "1641383206.489",
1027
+ # "order_id": "86980774",
1028
+ # "order_type": "LIMIT",
1029
+ # "order_price": "1", # null for "MARKET" order
1030
+ # "order_quantity": "12", # null for "MARKET" order
1031
+ # "order_amount": null, # NOT-null for "MARKET" order
1032
+ # "client_order_id": "0"
1033
+ # }
1034
+ # stop orders
1035
+ # {
1036
+ # "success": True,
1037
+ # "data": {
1038
+ # "rows": [
1039
+ # {
1040
+ # "orderId": "1578938",
1041
+ # "clientOrderId": "0",
1042
+ # "algoType": "STOP_LOSS",
1043
+ # "quantity": "0.1"
1044
+ # }
1045
+ # ]
1046
+ # },
1047
+ # "timestamp": "1686149372216"
1048
+ # }
1049
+ data = self.safe_dict(response, 'data')
1050
+ if data is not None:
1051
+ rows = self.safe_list(data, 'rows', [])
1052
+ return self.parse_order(rows[0], market)
1053
+ order = self.parse_order(response, market)
1054
+ order['type'] = type
1055
+ return order
1056
+
1057
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1058
+ """
1059
+ edit a trade order
1060
+ :see: https://docs.woo.org/#edit-order
1061
+ :see: https://docs.woo.org/#edit-order-by-client_order_id
1062
+ :see: https://docs.woo.org/#edit-algo-order
1063
+ :see: https://docs.woo.org/#edit-algo-order-by-client_order_id
1064
+ :param str id: order id
1065
+ :param str symbol: unified symbol of the market to create an order in
1066
+ :param str type: 'market' or 'limit'
1067
+ :param str side: 'buy' or 'sell'
1068
+ :param float amount: how much of currency you want to trade in units of base currency
1069
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1070
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1071
+ :param float [params.triggerPrice]: The price a trigger order is triggered at
1072
+ :param float [params.stopLossPrice]: price to trigger stop-loss orders
1073
+ :param float [params.takeProfitPrice]: price to trigger take-profit orders
1074
+ :param str [params.trailingAmount]: the quote amount to trail away from the current market price
1075
+ :param str [params.trailingPercent]: the percent to trail away from the current market price
1076
+ :param str [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
1077
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1078
+ """
1079
+ await self.load_markets()
1080
+ market = self.market(symbol)
1081
+ request: dict = {
1082
+ # 'quantity': self.amount_to_precision(symbol, amount),
1083
+ # 'price': self.price_to_precision(symbol, price),
1084
+ }
1085
+ if price is not None:
1086
+ request['price'] = self.price_to_precision(symbol, price)
1087
+ if amount is not None:
1088
+ request['quantity'] = self.amount_to_precision(symbol, amount)
1089
+ clientOrderIdUnified = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1090
+ clientOrderIdExchangeSpecific = self.safe_string(params, 'client_order_id', clientOrderIdUnified)
1091
+ isByClientOrder = clientOrderIdExchangeSpecific is not None
1092
+ stopPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'takeProfitPrice', 'stopLossPrice'])
1093
+ if stopPrice is not None:
1094
+ request['triggerPrice'] = self.price_to_precision(symbol, stopPrice)
1095
+ trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activatedPrice', self.number_to_string(price))
1096
+ trailingAmount = self.safe_string_2(params, 'trailingAmount', 'callbackValue')
1097
+ trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
1098
+ isTrailingAmountOrder = trailingAmount is not None
1099
+ isTrailingPercentOrder = trailingPercent is not None
1100
+ isTrailing = isTrailingAmountOrder or isTrailingPercentOrder
1101
+ if isTrailing:
1102
+ if trailingTriggerPrice is not None:
1103
+ request['activatedPrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
1104
+ if isTrailingAmountOrder:
1105
+ request['callbackValue'] = trailingAmount
1106
+ elif isTrailingPercentOrder:
1107
+ convertedTrailingPercent = Precise.string_div(trailingPercent, '100')
1108
+ request['callbackRate'] = convertedTrailingPercent
1109
+ params = self.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice', 'trailingTriggerPrice', 'trailingAmount', 'trailingPercent'])
1110
+ isStop = isTrailing or (stopPrice is not None) or (self.safe_value(params, 'childOrders') is not None)
1111
+ response = None
1112
+ if isByClientOrder:
1113
+ request['client_order_id'] = clientOrderIdExchangeSpecific
1114
+ if isStop:
1115
+ response = await self.v3PrivatePutAlgoOrderClientClientOrderId(self.extend(request, params))
1116
+ else:
1117
+ response = await self.v3PrivatePutOrderClientClientOrderId(self.extend(request, params))
1118
+ else:
1119
+ request['oid'] = id
1120
+ if isStop:
1121
+ response = await self.v3PrivatePutAlgoOrderOid(self.extend(request, params))
1122
+ else:
1123
+ response = await self.v3PrivatePutOrderOid(self.extend(request, params))
1124
+ #
1125
+ # {
1126
+ # "code": 0,
1127
+ # "data": {
1128
+ # "status": "string",
1129
+ # "success": True
1130
+ # },
1131
+ # "message": "string",
1132
+ # "success": True,
1133
+ # "timestamp": 0
1134
+ # }
1135
+ #
1136
+ data = self.safe_dict(response, 'data', {})
1137
+ return self.parse_order(data, market)
1138
+
1139
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
1140
+ """
1141
+ :see: https://docs.woo.org/#cancel-algo-order
1142
+ :see: https://docs.woo.org/#cancel-order
1143
+ :see: https://docs.woo.org/#cancel-order-by-client_order_id
1144
+ cancels an open order
1145
+ :param str id: order id
1146
+ :param str symbol: unified symbol of the market the order was made in
1147
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1148
+ :param boolean [params.stop]: whether the order is a stop/algo order
1149
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1150
+ """
1151
+ stop = self.safe_bool(params, 'stop', False)
1152
+ params = self.omit(params, 'stop')
1153
+ if not stop and (symbol is None):
1154
+ raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
1155
+ await self.load_markets()
1156
+ market: Market = None
1157
+ if symbol is not None:
1158
+ market = self.market(symbol)
1159
+ request: dict = {}
1160
+ clientOrderIdUnified = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1161
+ clientOrderIdExchangeSpecific = self.safe_string(params, 'client_order_id', clientOrderIdUnified)
1162
+ isByClientOrder = clientOrderIdExchangeSpecific is not None
1163
+ response = None
1164
+ if stop:
1165
+ request['order_id'] = id
1166
+ response = await self.v3PrivateDeleteAlgoOrderOrderId(self.extend(request, params))
1167
+ else:
1168
+ request['symbol'] = market['id']
1169
+ if isByClientOrder:
1170
+ request['client_order_id'] = clientOrderIdExchangeSpecific
1171
+ params = self.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
1172
+ response = await self.v1PrivateDeleteClientOrder(self.extend(request, params))
1173
+ else:
1174
+ request['order_id'] = id
1175
+ response = await self.v1PrivateDeleteOrder(self.extend(request, params))
1176
+ #
1177
+ # {success: True, status: "CANCEL_SENT"}
1178
+ #
1179
+ extendParams: dict = {'symbol': symbol}
1180
+ if isByClientOrder:
1181
+ extendParams['client_order_id'] = clientOrderIdExchangeSpecific
1182
+ else:
1183
+ extendParams['id'] = id
1184
+ return self.extend(self.parse_order(response), extendParams)
1185
+
1186
+ async def cancel_all_orders(self, symbol: Str = None, params={}):
1187
+ """
1188
+ :see: https://docs.woo.org/#cancel-all-pending-orders
1189
+ :see: https://docs.woo.org/#cancel-orders
1190
+ :see: https://docs.woo.org/#cancel-all-pending-algo-orders
1191
+ cancel all open orders in a market
1192
+ :param str symbol: unified market symbol
1193
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1194
+ :param boolean [params.stop]: whether the order is a stop/algo order
1195
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1196
+ """
1197
+ await self.load_markets()
1198
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1199
+ params = self.omit(params, ['stop', 'trigger'])
1200
+ if stop:
1201
+ return await self.v3PrivateDeleteAlgoOrdersPending(params)
1202
+ if symbol is None:
1203
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
1204
+ market = self.market(symbol)
1205
+ request: dict = {
1206
+ 'symbol': market['id'],
1207
+ }
1208
+ response = await self.v1PrivateDeleteOrders(self.extend(request, params))
1209
+ #
1210
+ # {
1211
+ # "success":true,
1212
+ # "status":"CANCEL_ALL_SENT"
1213
+ # }
1214
+ #
1215
+ return [
1216
+ self.safe_order(response),
1217
+ ]
1218
+
1219
+ async def cancel_all_orders_after(self, timeout: Int, params={}):
1220
+ """
1221
+ dead man's switch, cancel all orders after the given timeout
1222
+ :see: https://docs.woo.org/#cancel-all-after
1223
+ :param number timeout: time in milliseconds, 0 represents cancel the timer
1224
+ :param boolean activated: countdown
1225
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1226
+ :returns dict: the api result
1227
+ """
1228
+ await self.load_markets()
1229
+ request: dict = {
1230
+ 'trigger_after': timeout if (timeout > 0) else 0,
1231
+ }
1232
+ response = await self.v1PrivatePostOrderCancelAllAfter(self.extend(request, params))
1233
+ #
1234
+ # {
1235
+ # "success": True,
1236
+ # "data": {
1237
+ # "expected_trigger_time": 1711534302938
1238
+ # },
1239
+ # "timestamp": 1711534302943
1240
+ # }
1241
+ #
1242
+ return [
1243
+ self.safe_order(response),
1244
+ ]
1245
+
1246
+ async def fetch_order(self, id: str, symbol: Str = None, params={}):
1247
+ """
1248
+ :see: https://docs.woo.org/#get-algo-order
1249
+ :see: https://docs.woo.org/#get-order
1250
+ fetches information on an order made by the user
1251
+ :param str symbol: unified symbol of the market the order was made in
1252
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1253
+ :param boolean [params.stop]: whether the order is a stop/algo order
1254
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1255
+ """
1256
+ await self.load_markets()
1257
+ market = self.market(symbol) if (symbol is not None) else None
1258
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1259
+ params = self.omit(params, ['stop', 'trigger'])
1260
+ request: dict = {}
1261
+ clientOrderId = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1262
+ response = None
1263
+ if stop:
1264
+ request['oid'] = id
1265
+ response = await self.v3PrivateGetAlgoOrderOid(self.extend(request, params))
1266
+ elif clientOrderId:
1267
+ request['client_order_id'] = clientOrderId
1268
+ response = await self.v1PrivateGetClientOrderClientOrderId(self.extend(request, params))
1269
+ else:
1270
+ request['oid'] = id
1271
+ response = await self.v1PrivateGetOrderOid(self.extend(request, params))
1272
+ #
1273
+ # {
1274
+ # "success": True,
1275
+ # "symbol": "SPOT_WOO_USDT",
1276
+ # "status": "FILLED", # FILLED, NEW
1277
+ # "side": "BUY",
1278
+ # "created_time": "1641480933.000",
1279
+ # "order_id": "87541111",
1280
+ # "order_tag": "default",
1281
+ # "price": "1",
1282
+ # "type": "LIMIT",
1283
+ # "quantity": "12",
1284
+ # "amount": null,
1285
+ # "visible": "12",
1286
+ # "executed": "12", # or any partial amount
1287
+ # "total_fee": "0.0024",
1288
+ # "fee_asset": "WOO",
1289
+ # "client_order_id": null,
1290
+ # "average_executed_price": "1",
1291
+ # "Transactions": [
1292
+ # {
1293
+ # "id": "99111647",
1294
+ # "symbol": "SPOT_WOO_USDT",
1295
+ # "fee": "0.0024",
1296
+ # "side": "BUY",
1297
+ # "executed_timestamp": "1641482113.084",
1298
+ # "order_id": "87541111",
1299
+ # "executed_price": "1",
1300
+ # "executed_quantity": "12",
1301
+ # "fee_asset": "WOO",
1302
+ # "is_maker": "1"
1303
+ # }
1304
+ # ]
1305
+ # }
1306
+ #
1307
+ orders = self.safe_dict(response, 'data', response)
1308
+ return self.parse_order(orders, market)
1309
+
1310
+ async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1311
+ """
1312
+ fetches information on multiple orders made by the user
1313
+ :see: https://docs.woo.org/#get-orders
1314
+ :see: https://docs.woo.org/#get-algo-orders
1315
+ :param str symbol: unified market symbol of the market orders were made in
1316
+ :param int [since]: the earliest time in ms to fetch orders for
1317
+ :param int [limit]: the maximum number of order structures to retrieve
1318
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1319
+ :param boolean [params.stop]: whether the order is a stop/algo order
1320
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1321
+ :param str [params.side]: 'buy' or 'sell'
1322
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1323
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1324
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1325
+ """
1326
+ await self.load_markets()
1327
+ paginate = False
1328
+ paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
1329
+ if paginate:
1330
+ return await self.fetch_paginated_call_incremental('fetchOrders', symbol, since, limit, params, 'page', 500)
1331
+ request: dict = {}
1332
+ market: Market = None
1333
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1334
+ trailing = self.safe_bool(params, 'trailing', False)
1335
+ params = self.omit(params, ['stop', 'trailing', 'trigger'])
1336
+ if symbol is not None:
1337
+ market = self.market(symbol)
1338
+ request['symbol'] = market['id']
1339
+ if since is not None:
1340
+ if stop or trailing:
1341
+ request['createdTimeStart'] = since
1342
+ else:
1343
+ request['start_t'] = since
1344
+ if limit is not None:
1345
+ request['size'] = limit
1346
+ else:
1347
+ request['size'] = 500
1348
+ if stop:
1349
+ request['algoType'] = 'stop'
1350
+ elif trailing:
1351
+ request['algoType'] = 'TRAILING_STOP'
1352
+ response = None
1353
+ if stop or trailing:
1354
+ response = await self.v3PrivateGetAlgoOrders(self.extend(request, params))
1355
+ else:
1356
+ response = await self.v1PrivateGetOrders(self.extend(request, params))
1357
+ #
1358
+ # {
1359
+ # "success":true,
1360
+ # "meta":{
1361
+ # "total":1,
1362
+ # "records_per_page":100,
1363
+ # "current_page":1
1364
+ # },
1365
+ # "rows":[
1366
+ # {
1367
+ # "symbol":"PERP_BTC_USDT",
1368
+ # "status":"FILLED",
1369
+ # "side":"SELL",
1370
+ # "created_time":"1611617776.000",
1371
+ # "updated_time":"1611617776.000",
1372
+ # "order_id":52121167,
1373
+ # "order_tag":"default",
1374
+ # "price":null,
1375
+ # "type":"MARKET",
1376
+ # "quantity":0.002,
1377
+ # "amount":null,
1378
+ # "visible":0,
1379
+ # "executed":0.002,
1380
+ # "total_fee":0.01732885,
1381
+ # "fee_asset":"USDT",
1382
+ # "client_order_id":null,
1383
+ # "average_executed_price":28881.41
1384
+ # }
1385
+ # ]
1386
+ # }
1387
+ #
1388
+ data = self.safe_value(response, 'data', response)
1389
+ orders = self.safe_list(data, 'rows')
1390
+ return self.parse_orders(orders, market, since, limit)
1391
+
1392
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1393
+ """
1394
+ fetches information on multiple orders made by the user
1395
+ :see: https://docs.woo.org/#get-orders
1396
+ :see: https://docs.woo.org/#get-algo-orders
1397
+ :param str symbol: unified market symbol of the market orders were made in
1398
+ :param int [since]: the earliest time in ms to fetch orders for
1399
+ :param int [limit]: the maximum number of order structures to retrieve
1400
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1401
+ :param boolean [params.stop]: whether the order is a stop/algo order
1402
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1403
+ :param str [params.side]: 'buy' or 'sell'
1404
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1405
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1406
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1407
+ """
1408
+ await self.load_markets()
1409
+ extendedParams = self.extend(params, {'status': 'INCOMPLETE'})
1410
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1411
+
1412
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1413
+ """
1414
+ fetches information on multiple orders made by the user
1415
+ :see: https://docs.woo.org/#get-orders
1416
+ :see: https://docs.woo.org/#get-algo-orders
1417
+ :param str symbol: unified market symbol of the market orders were made in
1418
+ :param int [since]: the earliest time in ms to fetch orders for
1419
+ :param int [limit]: the maximum number of order structures to retrieve
1420
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1421
+ :param boolean [params.stop]: whether the order is a stop/algo order
1422
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1423
+ :param str [params.side]: 'buy' or 'sell'
1424
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1425
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1426
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1427
+ """
1428
+ await self.load_markets()
1429
+ extendedParams = self.extend(params, {'status': 'COMPLETED'})
1430
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1431
+
1432
+ def parse_time_in_force(self, timeInForce: Str):
1433
+ timeInForces: dict = {
1434
+ 'ioc': 'IOC',
1435
+ 'fok': 'FOK',
1436
+ 'post_only': 'PO',
1437
+ }
1438
+ return self.safe_string(timeInForces, timeInForce, None)
1439
+
1440
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1441
+ #
1442
+ # Possible input functions:
1443
+ # * createOrder
1444
+ # * cancelOrder
1445
+ # * fetchOrder
1446
+ # * fetchOrders
1447
+ # isFromFetchOrder = ('order_tag' in order); TO_DO
1448
+ #
1449
+ # stop order after creating it:
1450
+ # {
1451
+ # "orderId": "1578938",
1452
+ # "clientOrderId": "0",
1453
+ # "algoType": "STOP_LOSS",
1454
+ # "quantity": "0.1"
1455
+ # }
1456
+ # stop order after fetching it:
1457
+ # {
1458
+ # "algoOrderId": "1578958",
1459
+ # "clientOrderId": "0",
1460
+ # "rootAlgoOrderId": "1578958",
1461
+ # "parentAlgoOrderId": "0",
1462
+ # "symbol": "SPOT_LTC_USDT",
1463
+ # "orderTag": "default",
1464
+ # "algoType": "STOP_LOSS",
1465
+ # "side": "BUY",
1466
+ # "quantity": "0.1",
1467
+ # "isTriggered": False,
1468
+ # "triggerPrice": "100",
1469
+ # "triggerStatus": "USELESS",
1470
+ # "type": "LIMIT",
1471
+ # "rootAlgoStatus": "CANCELLED",
1472
+ # "algoStatus": "CANCELLED",
1473
+ # "triggerPriceType": "MARKET_PRICE",
1474
+ # "price": "75",
1475
+ # "triggerTime": "0",
1476
+ # "totalExecutedQuantity": "0",
1477
+ # "averageExecutedPrice": "0",
1478
+ # "totalFee": "0",
1479
+ # "feeAsset": '',
1480
+ # "reduceOnly": False,
1481
+ # "createdTime": "1686149609.744",
1482
+ # "updatedTime": "1686149903.362"
1483
+ # }
1484
+ #
1485
+ timestamp = self.safe_timestamp_n(order, ['timestamp', 'created_time', 'createdTime'])
1486
+ orderId = self.safe_string_n(order, ['order_id', 'orderId', 'algoOrderId'])
1487
+ clientOrderId = self.omit_zero(self.safe_string_2(order, 'client_order_id', 'clientOrderId')) # Somehow, self always returns 0 for limit order
1488
+ marketId = self.safe_string(order, 'symbol')
1489
+ market = self.safe_market(marketId, market)
1490
+ symbol = market['symbol']
1491
+ price = self.safe_string_2(order, 'order_price', 'price')
1492
+ amount = self.safe_string_2(order, 'order_quantity', 'quantity') # This is base amount
1493
+ cost = self.safe_string_2(order, 'order_amount', 'amount') # This is quote amount
1494
+ orderType = self.safe_string_lower_2(order, 'order_type', 'type')
1495
+ status = self.safe_value_2(order, 'status', 'algoStatus')
1496
+ side = self.safe_string_lower(order, 'side')
1497
+ filled = self.omit_zero(self.safe_value_2(order, 'executed', 'totalExecutedQuantity'))
1498
+ average = self.omit_zero(self.safe_string_2(order, 'average_executed_price', 'averageExecutedPrice'))
1499
+ remaining = Precise.string_sub(cost, filled)
1500
+ fee = self.safe_value_2(order, 'total_fee', 'totalFee')
1501
+ feeCurrency = self.safe_string_2(order, 'fee_asset', 'feeAsset')
1502
+ transactions = self.safe_value(order, 'Transactions')
1503
+ stopPrice = self.safe_number(order, 'triggerPrice')
1504
+ takeProfitPrice: Num = None
1505
+ stopLossPrice: Num = None
1506
+ childOrders = self.safe_value(order, 'childOrders')
1507
+ if childOrders is not None:
1508
+ first = self.safe_value(childOrders, 0)
1509
+ innerChildOrders = self.safe_value(first, 'childOrders', [])
1510
+ innerChildOrdersLength = len(innerChildOrders)
1511
+ if innerChildOrdersLength > 0:
1512
+ takeProfitOrder = self.safe_value(innerChildOrders, 0)
1513
+ stopLossOrder = self.safe_value(innerChildOrders, 1)
1514
+ takeProfitPrice = self.safe_number(takeProfitOrder, 'triggerPrice')
1515
+ stopLossPrice = self.safe_number(stopLossOrder, 'triggerPrice')
1516
+ lastUpdateTimestamp = self.safe_timestamp_2(order, 'updatedTime', 'updated_time')
1517
+ return self.safe_order({
1518
+ 'id': orderId,
1519
+ 'clientOrderId': clientOrderId,
1520
+ 'timestamp': timestamp,
1521
+ 'datetime': self.iso8601(timestamp),
1522
+ 'lastTradeTimestamp': None,
1523
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1524
+ 'status': self.parse_order_status(status),
1525
+ 'symbol': symbol,
1526
+ 'type': orderType,
1527
+ 'timeInForce': self.parse_time_in_force(orderType),
1528
+ 'postOnly': None, # TO_DO
1529
+ 'reduceOnly': self.safe_bool(order, 'reduce_only'),
1530
+ 'side': side,
1531
+ 'price': price,
1532
+ 'stopPrice': stopPrice,
1533
+ 'triggerPrice': stopPrice,
1534
+ 'takeProfitPrice': takeProfitPrice,
1535
+ 'stopLossPrice': stopLossPrice,
1536
+ 'average': average,
1537
+ 'amount': amount,
1538
+ 'filled': filled,
1539
+ 'remaining': remaining, # TO_DO
1540
+ 'cost': cost,
1541
+ 'trades': transactions,
1542
+ 'fee': {
1543
+ 'cost': fee,
1544
+ 'currency': feeCurrency,
1545
+ },
1546
+ 'info': order,
1547
+ }, market)
1548
+
1549
+ def parse_order_status(self, status: Str):
1550
+ if status is not None:
1551
+ statuses: dict = {
1552
+ 'NEW': 'open',
1553
+ 'FILLED': 'closed',
1554
+ 'CANCEL_SENT': 'canceled',
1555
+ 'CANCEL_ALL_SENT': 'canceled',
1556
+ 'CANCELLED': 'canceled',
1557
+ 'PARTIAL_FILLED': 'open',
1558
+ 'REJECTED': 'rejected',
1559
+ 'INCOMPLETE': 'open',
1560
+ 'COMPLETED': 'closed',
1561
+ }
1562
+ return self.safe_string(statuses, status, status)
1563
+ return status
1564
+
1565
+ async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1566
+ """
1567
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1568
+ :see: https://docs.woo.org/#orderbook-snapshot-public
1569
+ :param str symbol: unified symbol of the market to fetch the order book for
1570
+ :param int [limit]: the maximum amount of order book entries to return
1571
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1572
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1573
+ """
1574
+ await self.load_markets()
1575
+ market = self.market(symbol)
1576
+ request: dict = {
1577
+ 'symbol': market['id'],
1578
+ }
1579
+ if limit is not None:
1580
+ limit = min(limit, 1000)
1581
+ request['max_level'] = limit
1582
+ response = await self.v1PublicGetOrderbookSymbol(self.extend(request, params))
1583
+ #
1584
+ # {
1585
+ # "success": True,
1586
+ # "timestamp": "1641562961192",
1587
+ # "asks": [
1588
+ # {price: '0.921', quantity: "76.01"},
1589
+ # {price: '0.933', quantity: "477.10"},
1590
+ # ...
1591
+ # ],
1592
+ # "bids": [
1593
+ # {price: '0.940', quantity: "13502.47"},
1594
+ # {price: '0.932', quantity: "43.91"},
1595
+ # ...
1596
+ # ]
1597
+ # }
1598
+ #
1599
+ timestamp = self.safe_integer(response, 'timestamp')
1600
+ return self.parse_order_book(response, symbol, timestamp, 'bids', 'asks', 'price', 'quantity')
1601
+
1602
+ async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1603
+ """
1604
+ :see: https://docs.woo.org/#kline-public
1605
+ :see: https://docs.woo.org/#kline-historical-data-public
1606
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1607
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1608
+ :param str timeframe: the length of time each candle represents
1609
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1610
+ :param int [limit]: max=1000, max=100 when since is defined and is less than(now - (999 * (timeframe in ms)))
1611
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1612
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1613
+ """
1614
+ await self.load_markets()
1615
+ market = self.market(symbol)
1616
+ request: dict = {
1617
+ 'symbol': market['id'],
1618
+ 'type': self.safe_string(self.timeframes, timeframe, timeframe),
1619
+ }
1620
+ useHistEndpoint = since is not None
1621
+ if (limit is not None) and (since is not None):
1622
+ oneThousandCandles = self.parse_timeframe(timeframe) * 1000 * 999 # 999 because there will be delay between self and the request, causing the latest candle to be excluded sometimes
1623
+ startWithLimit = self.milliseconds() - oneThousandCandles
1624
+ useHistEndpoint = since < startWithLimit
1625
+ if useHistEndpoint:
1626
+ request['start_time'] = since
1627
+ elif limit is not None: # the hist endpoint does not accept limit
1628
+ request['limit'] = min(limit, 1000)
1629
+ response = None
1630
+ if not useHistEndpoint:
1631
+ response = await self.v1PublicGetKline(self.extend(request, params))
1632
+ #
1633
+ # {
1634
+ # "success": True,
1635
+ # "rows": [
1636
+ # {
1637
+ # "open": "0.94238",
1638
+ # "close": "0.94271",
1639
+ # "low": "0.94238",
1640
+ # "high": "0.94296",
1641
+ # "volume": "73.55",
1642
+ # "amount": "69.32040520",
1643
+ # "symbol": "SPOT_WOO_USDT",
1644
+ # "type": "1m",
1645
+ # "start_timestamp": "1641584700000",
1646
+ # "end_timestamp": "1641584760000"
1647
+ # },
1648
+ # ...
1649
+ # ]
1650
+ # }
1651
+ #
1652
+ else:
1653
+ response = await self.v1PubGetHistKline(self.extend(request, params))
1654
+ response = self.safe_dict(response, 'data')
1655
+ #
1656
+ # {
1657
+ # "success": True,
1658
+ # "data": {
1659
+ # "rows": [
1660
+ # {
1661
+ # "symbol": "SPOT_BTC_USDT",
1662
+ # "open": 44181.40000000,
1663
+ # "close": 44174.29000000,
1664
+ # "high": 44193.44000000,
1665
+ # "low": 44148.34000000,
1666
+ # "volume": 110.11930100,
1667
+ # "amount": 4863796.24318878,
1668
+ # "type": "1m",
1669
+ # "start_timestamp": 1704153600000,
1670
+ # "end_timestamp": 1704153660000
1671
+ # },
1672
+ # ...
1673
+ # ]
1674
+ # }
1675
+ # }
1676
+ #
1677
+ rows = self.safe_list(response, 'rows', [])
1678
+ return self.parse_ohlcvs(rows, market, timeframe, since, limit)
1679
+
1680
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1681
+ # example response in fetchOHLCV
1682
+ return [
1683
+ self.safe_integer(ohlcv, 'start_timestamp'),
1684
+ self.safe_number(ohlcv, 'open'),
1685
+ self.safe_number(ohlcv, 'high'),
1686
+ self.safe_number(ohlcv, 'low'),
1687
+ self.safe_number(ohlcv, 'close'),
1688
+ self.safe_number(ohlcv, 'volume'),
1689
+ ]
1690
+
1691
+ async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1692
+ """
1693
+ fetch all the trades made from a single order
1694
+ :see: https://docs.woo.org/#get-trades
1695
+ :param str id: order id
1696
+ :param str symbol: unified market symbol
1697
+ :param int [since]: the earliest time in ms to fetch trades for
1698
+ :param int [limit]: the maximum number of trades to retrieve
1699
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1700
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1701
+ """
1702
+ await self.load_markets()
1703
+ market: Market = None
1704
+ if symbol is not None:
1705
+ market = self.market(symbol)
1706
+ request: dict = {
1707
+ 'oid': id,
1708
+ }
1709
+ response = await self.v1PrivateGetOrderOidTrades(self.extend(request, params))
1710
+ # {
1711
+ # "success": True,
1712
+ # "rows": [
1713
+ # {
1714
+ # "id": "99111647",
1715
+ # "symbol": "SPOT_WOO_USDT",
1716
+ # "fee": "0.0024",
1717
+ # "side": "BUY",
1718
+ # "executed_timestamp": "1641482113.084",
1719
+ # "order_id": "87541111",
1720
+ # "order_tag": "default",
1721
+ # "executed_price": "1",
1722
+ # "executed_quantity": "12",
1723
+ # "fee_asset": "WOO",
1724
+ # "is_maker": "1"
1725
+ # }
1726
+ # ]
1727
+ # }
1728
+ trades = self.safe_list(response, 'rows', [])
1729
+ return self.parse_trades(trades, market, since, limit, params)
1730
+
1731
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1732
+ """
1733
+ fetch all trades made by the user
1734
+ :see: https://docs.woo.org/#get-trades
1735
+ :param str symbol: unified market symbol
1736
+ :param int [since]: the earliest time in ms to fetch trades for
1737
+ :param int [limit]: the maximum number of trades structures to retrieve
1738
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1739
+ :param boolean [params.paginate]: set to True if you want to fetch trades with pagination
1740
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1741
+ """
1742
+ await self.load_markets()
1743
+ paginate = False
1744
+ paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
1745
+ if paginate:
1746
+ return await self.fetch_paginated_call_incremental('fetchMyTrades', symbol, since, limit, params, 'page', 500)
1747
+ request: dict = {}
1748
+ market: Market = None
1749
+ if symbol is not None:
1750
+ market = self.market(symbol)
1751
+ request['symbol'] = market['id']
1752
+ if since is not None:
1753
+ request['start_t'] = since
1754
+ if limit is not None:
1755
+ request['size'] = limit
1756
+ else:
1757
+ request['size'] = 500
1758
+ response = await self.v1PrivateGetClientTrades(self.extend(request, params))
1759
+ # {
1760
+ # "success": True,
1761
+ # "meta": {
1762
+ # "records_per_page": 25,
1763
+ # "current_page": 1
1764
+ # },
1765
+ # "rows": [
1766
+ # {
1767
+ # "id": 5,
1768
+ # "symbol": "SPOT_BTC_USDT",
1769
+ # "order_id": 211,
1770
+ # "order_tag": "default",
1771
+ # "executed_price": 10892.84,
1772
+ # "executed_quantity": 0.002,
1773
+ # "is_maker": 0,
1774
+ # "side": "SELL",
1775
+ # "fee": 0,
1776
+ # "fee_asset": "USDT",
1777
+ # "executed_timestamp": "1566264290.250"
1778
+ # },
1779
+ # ...
1780
+ # ]
1781
+ # }
1782
+ trades = self.safe_list(response, 'rows', [])
1783
+ return self.parse_trades(trades, market, since, limit, params)
1784
+
1785
+ async def fetch_accounts(self, params={}) -> List[Account]:
1786
+ """
1787
+ fetch all the accounts associated with a profile
1788
+ :see: https://docs.woo.org/#get-assets-of-subaccounts
1789
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1790
+ :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
1791
+ """
1792
+ response = await self.v1PrivateGetSubAccountAssets(params)
1793
+ #
1794
+ # {
1795
+ # "rows": [{
1796
+ # "application_id": "13e4fc34-e2ff-4cb7-b1e4-4c22fee7d365",
1797
+ # "account": "Main",
1798
+ # "usdt_balance": "4.0"
1799
+ # },
1800
+ # {
1801
+ # "application_id": "432952aa-a401-4e26-aff6-972920aebba3",
1802
+ # "account": "subaccount",
1803
+ # "usdt_balance": "1.0"
1804
+ # }
1805
+ # ],
1806
+ # "success": True
1807
+ # }
1808
+ #
1809
+ rows = self.safe_list(response, 'rows', [])
1810
+ return self.parse_accounts(rows, params)
1811
+
1812
+ def parse_account(self, account):
1813
+ #
1814
+ # {
1815
+ # "application_id": "336952aa-a401-4e26-aff6-972920aebba3",
1816
+ # "account": "subaccount",
1817
+ # "usdt_balance": "1.0",
1818
+ # }
1819
+ #
1820
+ accountId = self.safe_string(account, 'account')
1821
+ return {
1822
+ 'info': account,
1823
+ 'id': self.safe_string(account, 'application_id'),
1824
+ 'name': accountId,
1825
+ 'code': None,
1826
+ 'type': accountId == 'main' if 'Main' else 'subaccount',
1827
+ }
1828
+
1829
+ async def fetch_balance(self, params={}) -> Balances:
1830
+ """
1831
+ query for balance and get the amount of funds available for trading or funds locked in orders
1832
+ :see: https://docs.woo.org/#get-current-holding-get-balance-new
1833
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1834
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1835
+ """
1836
+ await self.load_markets()
1837
+ response = await self.v3PrivateGetBalances(params)
1838
+ #
1839
+ # {
1840
+ # "success": True,
1841
+ # "data": {
1842
+ # "holding": [
1843
+ # {
1844
+ # "token": "0_token",
1845
+ # "holding": 1,
1846
+ # "frozen": 0,
1847
+ # "staked": 0,
1848
+ # "unbonding": 0,
1849
+ # "vault": 0,
1850
+ # "interest": 0,
1851
+ # "pendingShortQty": 0,
1852
+ # "pendingLongQty": 0,
1853
+ # "availableBalance": 0,
1854
+ # "updatedTime": 312321.121
1855
+ # }
1856
+ # ]
1857
+ # },
1858
+ # "timestamp": 1673323746259
1859
+ # }
1860
+ #
1861
+ data = self.safe_dict(response, 'data')
1862
+ return self.parse_balance(data)
1863
+
1864
+ def parse_balance(self, response) -> Balances:
1865
+ result: dict = {
1866
+ 'info': response,
1867
+ }
1868
+ balances = self.safe_list(response, 'holding', [])
1869
+ for i in range(0, len(balances)):
1870
+ balance = balances[i]
1871
+ code = self.safe_currency_code(self.safe_string(balance, 'token'))
1872
+ account = self.account()
1873
+ account['total'] = self.safe_string(balance, 'holding')
1874
+ account['free'] = self.safe_string(balance, 'availableBalance')
1875
+ result[code] = account
1876
+ return self.safe_balance(result)
1877
+
1878
+ async def fetch_deposit_address(self, code: str, params={}):
1879
+ """
1880
+ fetch the deposit address for a currency associated with self account
1881
+ :see: https://docs.woo.org/#get-token-deposit-address
1882
+ :param str code: unified currency code
1883
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1884
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1885
+ """
1886
+ # self method is TODO because of networks unification
1887
+ await self.load_markets()
1888
+ currency = self.currency(code)
1889
+ networkCodeDefault = self.default_network_code_for_currency(code)
1890
+ networkCode = self.safe_string(params, 'network', networkCodeDefault)
1891
+ params = self.omit(params, 'network')
1892
+ codeForExchange = networkCode + '_' + currency['code']
1893
+ request: dict = {
1894
+ 'token': codeForExchange,
1895
+ }
1896
+ response = await self.v1PrivateGetAssetDeposit(self.extend(request, params))
1897
+ # {
1898
+ # "success": True,
1899
+ # "address": "3Jmtjx5544T4smrit9Eroe4PCrRkpDeKjP",
1900
+ # "extra": ''
1901
+ # }
1902
+ tag = self.safe_string(response, 'extra')
1903
+ address = self.safe_string(response, 'address')
1904
+ self.check_address(address)
1905
+ return {
1906
+ 'currency': code,
1907
+ 'address': address,
1908
+ 'tag': tag,
1909
+ 'network': networkCode,
1910
+ 'info': response,
1911
+ }
1912
+
1913
+ async def get_asset_history_rows(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> Any:
1914
+ await self.load_markets()
1915
+ request: dict = {}
1916
+ currency: Currency = None
1917
+ if code is not None:
1918
+ currency = self.currency(code)
1919
+ request['balance_token'] = currency['id']
1920
+ if since is not None:
1921
+ request['start_t'] = since
1922
+ if limit is not None:
1923
+ request['pageSize'] = limit
1924
+ transactionType = self.safe_string(params, 'type')
1925
+ params = self.omit(params, 'type')
1926
+ if transactionType is not None:
1927
+ request['type'] = transactionType
1928
+ response = await self.v1PrivateGetAssetHistory(self.extend(request, params))
1929
+ # {
1930
+ # "rows": [
1931
+ # {
1932
+ # "id": "22010508193900165",
1933
+ # "token": "TRON_USDT",
1934
+ # "extra": '',
1935
+ # "amount": "13.75848500",
1936
+ # "status": "COMPLETED",
1937
+ # "account": null,
1938
+ # "description": null,
1939
+ # "user_id": "42222",
1940
+ # "application_id": "6ad2b303-f354-45c0-8105-9f5f19d0e335",
1941
+ # "external_id": "220105081900134",
1942
+ # "target_address": "TXnyFSnAYad3YCaqtwMw9jvXKkeU39NLnK",
1943
+ # "source_address": "TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6",
1944
+ # "type": "BALANCE",
1945
+ # "token_side": "DEPOSIT",
1946
+ # "tx_id": "35b0004022f6b3ad07f39a0b7af199f6b258c2c3e2c7cdc93c67efa74fd625ee",
1947
+ # "fee_token": '',
1948
+ # "fee_amount": "0.00000000",
1949
+ # "created_time": "1641370779.442",
1950
+ # "updated_time": "1641370779.465",
1951
+ # "is_new_target_address": null,
1952
+ # "confirmed_number": "29",
1953
+ # "confirming_threshold": "27",
1954
+ # "audit_tag": "1",
1955
+ # "audit_result": "0",
1956
+ # "balance_token": null, # TODO -write to support, that self seems broken. here should be the token id
1957
+ # "network_name": null # TODO -write to support, that self seems broken. here should be the network id
1958
+ # }
1959
+ # ],
1960
+ # "meta": {total: '1', records_per_page: "25", current_page: "1"},
1961
+ # "success": True
1962
+ # }
1963
+ return [currency, self.safe_list(response, 'rows', [])]
1964
+
1965
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1966
+ """
1967
+ fetch the history of changes, actions done by the user or operations that altered balance of the user
1968
+ :see: https://docs.woo.org/#get-asset-history
1969
+ :param str code: unified currency code, default is None
1970
+ :param int [since]: timestamp in ms of the earliest ledger entry, default is None
1971
+ :param int [limit]: max number of ledger entrys to return, default is None
1972
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1973
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
1974
+ """
1975
+ currency, rows = await self.get_asset_history_rows(code, since, limit, params)
1976
+ return self.parse_ledger(rows, currency, since, limit, params)
1977
+
1978
+ def parse_ledger_entry(self, item: dict, currency: Currency = None):
1979
+ networkizedCode = self.safe_string(item, 'token')
1980
+ currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
1981
+ code = currencyDefined['code']
1982
+ amount = self.safe_number(item, 'amount')
1983
+ side = self.safe_string(item, 'token_side')
1984
+ direction = 'in' if (side == 'DEPOSIT') else 'out'
1985
+ timestamp = self.safe_timestamp(item, 'created_time')
1986
+ fee = self.parse_token_and_fee_temp(item, 'fee_token', 'fee_amount')
1987
+ return {
1988
+ 'id': self.safe_string(item, 'id'),
1989
+ 'currency': code,
1990
+ 'account': self.safe_string(item, 'account'),
1991
+ 'referenceAccount': None,
1992
+ 'referenceId': self.safe_string(item, 'tx_id'),
1993
+ 'status': self.parse_transaction_status(self.safe_string(item, 'status')),
1994
+ 'amount': amount,
1995
+ 'before': None,
1996
+ 'after': None,
1997
+ 'fee': fee,
1998
+ 'direction': direction,
1999
+ 'timestamp': timestamp,
2000
+ 'datetime': self.iso8601(timestamp),
2001
+ 'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
2002
+ 'info': item,
2003
+ }
2004
+
2005
+ def parse_ledger_entry_type(self, type):
2006
+ types: dict = {
2007
+ 'BALANCE': 'transaction', # Funds moved in/out wallet
2008
+ 'COLLATERAL': 'transfer', # Funds moved between portfolios
2009
+ }
2010
+ return self.safe_string(types, type, type)
2011
+
2012
+ def get_currency_from_chaincode(self, networkizedCode, currency):
2013
+ if currency is not None:
2014
+ return currency
2015
+ else:
2016
+ parts = networkizedCode.split('_')
2017
+ partsLength = len(parts)
2018
+ firstPart = self.safe_string(parts, 0)
2019
+ currencyId = self.safe_string(parts, 1, firstPart)
2020
+ if partsLength > 2:
2021
+ currencyId += '_' + self.safe_string(parts, 2)
2022
+ currency = self.safe_currency(currencyId)
2023
+ return currency
2024
+
2025
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2026
+ """
2027
+ fetch all deposits made to an account
2028
+ :see: https://docs.woo.org/#get-asset-history
2029
+ :param str code: unified currency code
2030
+ :param int [since]: the earliest time in ms to fetch deposits for
2031
+ :param int [limit]: the maximum number of deposits structures to retrieve
2032
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2033
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2034
+ """
2035
+ request: dict = {
2036
+ 'token_side': 'DEPOSIT',
2037
+ }
2038
+ return await self.fetch_deposits_withdrawals(code, since, limit, self.extend(request, params))
2039
+
2040
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2041
+ """
2042
+ fetch all withdrawals made from an account
2043
+ :see: https://docs.woo.org/#get-asset-history
2044
+ :param str code: unified currency code
2045
+ :param int [since]: the earliest time in ms to fetch withdrawals for
2046
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
2047
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2048
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2049
+ """
2050
+ request: dict = {
2051
+ 'token_side': 'WITHDRAW',
2052
+ }
2053
+ return await self.fetch_deposits_withdrawals(code, since, limit, self.extend(request, params))
2054
+
2055
+ async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2056
+ """
2057
+ fetch history of deposits and withdrawals
2058
+ :see: https://docs.woo.org/#get-asset-history
2059
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2060
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2061
+ :param int [limit]: max number of deposit/withdrawals to return, default is None
2062
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2063
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2064
+ """
2065
+ request: dict = {
2066
+ 'type': 'BALANCE',
2067
+ }
2068
+ currency, rows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2069
+ #
2070
+ # {
2071
+ # "rows":[],
2072
+ # "meta":{
2073
+ # "total":0,
2074
+ # "records_per_page":25,
2075
+ # "current_page":1
2076
+ # },
2077
+ # "success":true
2078
+ # }
2079
+ #
2080
+ return self.parse_transactions(rows, currency, since, limit, params)
2081
+
2082
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2083
+ # example in fetchLedger
2084
+ networkizedCode = self.safe_string(transaction, 'token')
2085
+ currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
2086
+ code = currencyDefined['code']
2087
+ movementDirection = self.safe_string_lower(transaction, 'token_side')
2088
+ if movementDirection == 'withdraw':
2089
+ movementDirection = 'withdrawal'
2090
+ fee = self.parse_token_and_fee_temp(transaction, 'fee_token', 'fee_amount')
2091
+ addressTo = self.safe_string(transaction, 'target_address')
2092
+ addressFrom = self.safe_string(transaction, 'source_address')
2093
+ timestamp = self.safe_timestamp(transaction, 'created_time')
2094
+ return {
2095
+ 'info': transaction,
2096
+ 'id': self.safe_string_2(transaction, 'id', 'withdraw_id'),
2097
+ 'txid': self.safe_string(transaction, 'tx_id'),
2098
+ 'timestamp': timestamp,
2099
+ 'datetime': self.iso8601(timestamp),
2100
+ 'address': None,
2101
+ 'addressFrom': addressFrom,
2102
+ 'addressTo': addressTo,
2103
+ 'tag': self.safe_string(transaction, 'extra'),
2104
+ 'tagFrom': None,
2105
+ 'tagTo': None,
2106
+ 'type': movementDirection,
2107
+ 'amount': self.safe_number(transaction, 'amount'),
2108
+ 'currency': code,
2109
+ 'status': self.parse_transaction_status(self.safe_string(transaction, 'status')),
2110
+ 'updated': self.safe_timestamp(transaction, 'updated_time'),
2111
+ 'comment': None,
2112
+ 'internal': None,
2113
+ 'fee': fee,
2114
+ 'network': None,
2115
+ }
2116
+
2117
+ def parse_transaction_status(self, status: Str):
2118
+ statuses: dict = {
2119
+ 'NEW': 'pending',
2120
+ 'CONFIRMING': 'pending',
2121
+ 'PROCESSING': 'pending',
2122
+ 'COMPLETED': 'ok',
2123
+ 'CANCELED': 'canceled',
2124
+ }
2125
+ return self.safe_string(statuses, status, status)
2126
+
2127
+ async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2128
+ """
2129
+ transfer currency internally between wallets on the same account
2130
+ :see: https://docs.woo.org/#get-transfer-history
2131
+ :param str code: unified currency code
2132
+ :param float amount: amount to transfer
2133
+ :param str fromAccount: account to transfer from
2134
+ :param str toAccount: account to transfer to
2135
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2136
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2137
+ """
2138
+ await self.load_markets()
2139
+ currency = self.currency(code)
2140
+ request: dict = {
2141
+ 'token': currency['id'],
2142
+ 'amount': self.parse_to_numeric(amount),
2143
+ 'from_application_id': fromAccount,
2144
+ 'to_application_id': toAccount,
2145
+ }
2146
+ response = await self.v1PrivatePostAssetMainSubTransfer(self.extend(request, params))
2147
+ #
2148
+ # {
2149
+ # "success": True,
2150
+ # "id": 200
2151
+ # }
2152
+ #
2153
+ transfer = self.parse_transfer(response, currency)
2154
+ transferOptions = self.safe_dict(self.options, 'transfer', {})
2155
+ fillResponseFromRequest = self.safe_bool(transferOptions, 'fillResponseFromRequest', True)
2156
+ if fillResponseFromRequest:
2157
+ transfer['amount'] = amount
2158
+ transfer['fromAccount'] = fromAccount
2159
+ transfer['toAccount'] = toAccount
2160
+ return transfer
2161
+
2162
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
2163
+ """
2164
+ fetch a history of internal transfers made on an account
2165
+ :see: https://docs.woo.org/#get-transfer-history
2166
+ :param str code: unified currency code of the currency transferred
2167
+ :param int [since]: the earliest time in ms to fetch transfers for
2168
+ :param int [limit]: the maximum number of transfers structures to retrieve
2169
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2170
+ :param int [params.until]: the latest time in ms to fetch entries for
2171
+ :returns dict[]: a list of `transfer structures <https://docs.ccxt.com/#/?id=transfer-structure>`
2172
+ """
2173
+ request: dict = {}
2174
+ if limit is not None:
2175
+ request['size'] = limit
2176
+ if since is not None:
2177
+ request['start_t'] = since
2178
+ until = self.safe_integer(params, 'until') # unified in milliseconds
2179
+ params = self.omit(params, ['until'])
2180
+ if until is not None:
2181
+ request['end_t'] = until
2182
+ response = await self.v1PrivateGetAssetMainSubTransferHistory(self.extend(request, params))
2183
+ #
2184
+ # {
2185
+ # "rows": [
2186
+ # {
2187
+ # "id": 46704,
2188
+ # "token": "USDT",
2189
+ # "amount": 30000.00000000,
2190
+ # "status": "COMPLETED",
2191
+ # "from_application_id": "0f1bd3cd-dba2-4563-b8bb-0adb1bfb83a3",
2192
+ # "to_application_id": "c01e6940-a735-4022-9b6c-9d3971cdfdfa",
2193
+ # "from_user": "LeverageLow",
2194
+ # "to_user": "dev",
2195
+ # "created_time": "1709022325.427",
2196
+ # "updated_time": "1709022325.542"
2197
+ # }
2198
+ # ],
2199
+ # "meta": {
2200
+ # "total": 50,
2201
+ # "records_per_page": 25,
2202
+ # "current_page": 1
2203
+ # },
2204
+ # "success": True
2205
+ # }
2206
+ #
2207
+ data = self.safe_list(response, 'rows', [])
2208
+ return self.parse_transfers(data, None, since, limit, params)
2209
+
2210
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2211
+ #
2212
+ # fetchTransfers
2213
+ # {
2214
+ # "id": 46704,
2215
+ # "token": "USDT",
2216
+ # "amount": 30000.00000000,
2217
+ # "status": "COMPLETED",
2218
+ # "from_application_id": "0f1bd3cd-dba2-4563-b8bb-0adb1bfb83a3",
2219
+ # "to_application_id": "c01e6940-a735-4022-9b6c-9d3971cdfdfa",
2220
+ # "from_user": "LeverageLow",
2221
+ # "to_user": "dev",
2222
+ # "created_time": "1709022325.427",
2223
+ # "updated_time": "1709022325.542"
2224
+ # }
2225
+ #
2226
+ # transfer
2227
+ # {
2228
+ # "success": True,
2229
+ # "id": 200
2230
+ # }
2231
+ #
2232
+ networkizedCode = self.safe_string(transfer, 'token')
2233
+ currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
2234
+ code = currencyDefined['code']
2235
+ timestamp = self.safe_timestamp(transfer, 'created_time')
2236
+ success = self.safe_bool(transfer, 'success')
2237
+ status: Str = None
2238
+ if success is not None:
2239
+ status = 'ok' if success else 'failed'
2240
+ return {
2241
+ 'id': self.safe_string(transfer, 'id'),
2242
+ 'timestamp': timestamp,
2243
+ 'datetime': self.iso8601(timestamp),
2244
+ 'currency': code,
2245
+ 'amount': self.safe_number(transfer, 'amount'),
2246
+ 'fromAccount': self.safe_string(transfer, 'from_application_id'),
2247
+ 'toAccount': self.safe_string(transfer, 'to_application_id'),
2248
+ 'status': self.parse_transfer_status(self.safe_string(transfer, 'status', status)),
2249
+ 'info': transfer,
2250
+ }
2251
+
2252
+ def parse_transfer_status(self, status: Str) -> Str:
2253
+ statuses: dict = {
2254
+ 'NEW': 'pending',
2255
+ 'CONFIRMING': 'pending',
2256
+ 'PROCESSING': 'pending',
2257
+ 'COMPLETED': 'ok',
2258
+ 'CANCELED': 'canceled',
2259
+ }
2260
+ return self.safe_string(statuses, status, status)
2261
+
2262
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2263
+ """
2264
+ make a withdrawal
2265
+ :see: https://docs.woo.org/#token-withdraw
2266
+ :param str code: unified currency code
2267
+ :param float amount: the amount to withdraw
2268
+ :param str address: the address to withdraw to
2269
+ :param str tag:
2270
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2271
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2272
+ """
2273
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
2274
+ await self.load_markets()
2275
+ self.check_address(address)
2276
+ currency = self.currency(code)
2277
+ request: dict = {
2278
+ 'amount': amount,
2279
+ 'address': address,
2280
+ }
2281
+ if tag is not None:
2282
+ request['extra'] = tag
2283
+ networks = self.safe_dict(self.options, 'networks', {})
2284
+ currencyNetworks = self.safe_dict(currency, 'networks', {})
2285
+ network = self.safe_string_upper(params, 'network')
2286
+ networkId = self.safe_string(networks, network, network)
2287
+ coinNetwork = self.safe_dict(currencyNetworks, networkId, {})
2288
+ coinNetworkId = self.safe_string(coinNetwork, 'id')
2289
+ if coinNetworkId is None:
2290
+ raise BadRequest(self.id + ' withdraw() require network parameter')
2291
+ request['token'] = coinNetworkId
2292
+ response = await self.v1PrivatePostAssetWithdraw(self.extend(request, params))
2293
+ #
2294
+ # {
2295
+ # "success": True,
2296
+ # "withdraw_id": "20200119145703654"
2297
+ # }
2298
+ #
2299
+ return self.parse_transaction(response, currency)
2300
+
2301
+ async def repay_margin(self, code: str, amount, symbol: Str = None, params={}):
2302
+ """
2303
+ repay borrowed margin and interest
2304
+ :see: https://docs.woo.org/#repay-interest
2305
+ :param str code: unified currency code of the currency to repay
2306
+ :param float amount: the amount to repay
2307
+ :param str symbol: not used by woo.repayMargin()
2308
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2309
+ :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
2310
+ """
2311
+ await self.load_markets()
2312
+ market: Market = None
2313
+ if symbol is not None:
2314
+ market = self.market(symbol)
2315
+ symbol = market['symbol']
2316
+ currency = self.currency(code)
2317
+ request: dict = {
2318
+ 'token': currency['id'], # interest token that you want to repay
2319
+ 'amount': self.currency_to_precision(code, amount),
2320
+ }
2321
+ response = await self.v1PrivatePostInterestRepay(self.extend(request, params))
2322
+ #
2323
+ # {
2324
+ # "success": True,
2325
+ # }
2326
+ #
2327
+ transaction = self.parse_margin_loan(response, currency)
2328
+ return self.extend(transaction, {
2329
+ 'amount': amount,
2330
+ 'symbol': symbol,
2331
+ })
2332
+
2333
+ def parse_margin_loan(self, info, currency: Currency = None):
2334
+ #
2335
+ # {
2336
+ # "success": True,
2337
+ # }
2338
+ #
2339
+ return {
2340
+ 'id': None,
2341
+ 'currency': self.safe_currency_code(None, currency),
2342
+ 'amount': None,
2343
+ 'symbol': None,
2344
+ 'timestamp': None,
2345
+ 'datetime': None,
2346
+ 'info': info,
2347
+ }
2348
+
2349
+ def nonce(self):
2350
+ return self.milliseconds()
2351
+
2352
+ def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
2353
+ version = section[0]
2354
+ access = section[1]
2355
+ pathWithParams = self.implode_params(path, params)
2356
+ url = self.implode_hostname(self.urls['api'][access])
2357
+ url += '/' + version + '/'
2358
+ params = self.omit(params, self.extract_params(path))
2359
+ params = self.keysort(params)
2360
+ if access == 'public':
2361
+ url += access + '/' + pathWithParams
2362
+ if params:
2363
+ url += '?' + self.urlencode(params)
2364
+ else:
2365
+ self.check_required_credentials()
2366
+ if method == 'POST' and (path == 'algo/order' or path == 'order'):
2367
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
2368
+ if not isSandboxMode:
2369
+ applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad'
2370
+ brokerId = self.safe_string(self.options, 'brokerId', applicationId)
2371
+ isStop = path.find('algo') > -1
2372
+ if isStop:
2373
+ params['brokerId'] = brokerId
2374
+ else:
2375
+ params['broker_id'] = brokerId
2376
+ params = self.keysort(params)
2377
+ auth = ''
2378
+ ts = str(self.nonce())
2379
+ url += pathWithParams
2380
+ headers = {
2381
+ 'x-api-key': self.apiKey,
2382
+ 'x-api-timestamp': ts,
2383
+ }
2384
+ if version == 'v3':
2385
+ auth = ts + method + '/' + version + '/' + pathWithParams
2386
+ if method == 'POST' or method == 'PUT' or method == 'DELETE':
2387
+ body = self.json(params)
2388
+ auth += body
2389
+ else:
2390
+ if params:
2391
+ query = self.urlencode(params)
2392
+ url += '?' + query
2393
+ auth += '?' + query
2394
+ headers['content-type'] = 'application/json'
2395
+ else:
2396
+ auth = self.urlencode(params)
2397
+ if method == 'POST' or method == 'PUT' or method == 'DELETE':
2398
+ body = auth
2399
+ else:
2400
+ if params:
2401
+ url += '?' + auth
2402
+ auth += '|' + ts
2403
+ headers['content-type'] = 'application/x-www-form-urlencoded'
2404
+ headers['x-api-signature'] = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
2405
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
2406
+
2407
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2408
+ if not response:
2409
+ return None # fallback to default error handler
2410
+ #
2411
+ # 400 Bad Request {"success":false,"code":-1012,"message":"Amount is required for buy market orders when margin disabled."}
2412
+ # {"code":"-1011","message":"The system is under maintenance.","success":false}
2413
+ #
2414
+ success = self.safe_bool(response, 'success')
2415
+ errorCode = self.safe_string(response, 'code')
2416
+ if not success:
2417
+ feedback = self.id + ' ' + self.json(response)
2418
+ self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
2419
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
2420
+ return None
2421
+
2422
+ def parse_income(self, income, market: Market = None):
2423
+ #
2424
+ # {
2425
+ # "id":666666,
2426
+ # "symbol":"PERP_BTC_USDT",
2427
+ # "funding_rate":0.00001198,
2428
+ # "mark_price":28941.04000000,
2429
+ # "funding_fee":0.00069343,
2430
+ # "payment_type":"Pay",
2431
+ # "status":"COMPLETED",
2432
+ # "created_time":"1653616000.666",
2433
+ # "updated_time":"1653616000.605"
2434
+ # }
2435
+ #
2436
+ marketId = self.safe_string(income, 'symbol')
2437
+ symbol = self.safe_symbol(marketId, market)
2438
+ amount = self.safe_number(income, 'funding_fee')
2439
+ code = self.safe_currency_code('USD')
2440
+ id = self.safe_string(income, 'id')
2441
+ timestamp = self.safe_timestamp(income, 'updated_time')
2442
+ rate = self.safe_number(income, 'funding_rate')
2443
+ return {
2444
+ 'info': income,
2445
+ 'symbol': symbol,
2446
+ 'code': code,
2447
+ 'timestamp': timestamp,
2448
+ 'datetime': self.iso8601(timestamp),
2449
+ 'id': id,
2450
+ 'amount': amount,
2451
+ 'rate': rate,
2452
+ }
2453
+
2454
+ async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2455
+ await self.load_markets()
2456
+ request: dict = {}
2457
+ market: Market = None
2458
+ if symbol is not None:
2459
+ market = self.market(symbol)
2460
+ request['symbol'] = market['id']
2461
+ if since is not None:
2462
+ request['start_t'] = since
2463
+ response = await self.v1PrivateGetFundingFeeHistory(self.extend(request, params))
2464
+ #
2465
+ # {
2466
+ # "rows":[
2467
+ # {
2468
+ # "id":666666,
2469
+ # "symbol":"PERP_BTC_USDT",
2470
+ # "funding_rate":0.00001198,
2471
+ # "mark_price":28941.04000000,
2472
+ # "funding_fee":0.00069343,
2473
+ # "payment_type":"Pay",
2474
+ # "status":"COMPLETED",
2475
+ # "created_time":"1653616000.666",
2476
+ # "updated_time":"1653616000.605"
2477
+ # }
2478
+ # ],
2479
+ # "meta":{
2480
+ # "total":235,
2481
+ # "records_per_page":25,
2482
+ # "current_page":1
2483
+ # },
2484
+ # "success":true
2485
+ # }
2486
+ #
2487
+ result = self.safe_list(response, 'rows', [])
2488
+ return self.parse_incomes(result, market, since, limit)
2489
+
2490
+ def parse_funding_rate(self, fundingRate, market: Market = None):
2491
+ #
2492
+ # {
2493
+ # "symbol":"PERP_AAVE_USDT",
2494
+ # "est_funding_rate":-0.00003447,
2495
+ # "est_funding_rate_timestamp":1653633959001,
2496
+ # "last_funding_rate":-0.00002094,
2497
+ # "last_funding_rate_timestamp":1653631200000,
2498
+ # "next_funding_time":1653634800000
2499
+ # }
2500
+ #
2501
+ #
2502
+ symbol = self.safe_string(fundingRate, 'symbol')
2503
+ market = self.market(symbol)
2504
+ nextFundingTimestamp = self.safe_integer(fundingRate, 'next_funding_time')
2505
+ estFundingRateTimestamp = self.safe_integer(fundingRate, 'est_funding_rate_timestamp')
2506
+ lastFundingRateTimestamp = self.safe_integer(fundingRate, 'last_funding_rate_timestamp')
2507
+ return {
2508
+ 'info': fundingRate,
2509
+ 'symbol': market['symbol'],
2510
+ 'markPrice': None,
2511
+ 'indexPrice': None,
2512
+ 'interestRate': self.parse_number('0'),
2513
+ 'estimatedSettlePrice': None,
2514
+ 'timestamp': estFundingRateTimestamp,
2515
+ 'datetime': self.iso8601(estFundingRateTimestamp),
2516
+ 'fundingRate': self.safe_number(fundingRate, 'est_funding_rate'),
2517
+ 'fundingTimestamp': nextFundingTimestamp,
2518
+ 'fundingDatetime': self.iso8601(nextFundingTimestamp),
2519
+ 'nextFundingRate': None,
2520
+ 'nextFundingTimestamp': None,
2521
+ 'nextFundingDatetime': None,
2522
+ 'previousFundingRate': self.safe_number(fundingRate, 'last_funding_rate'),
2523
+ 'previousFundingTimestamp': lastFundingRateTimestamp,
2524
+ 'previousFundingDatetime': self.iso8601(lastFundingRateTimestamp),
2525
+ }
2526
+
2527
+ async def fetch_funding_rate(self, symbol: str, params={}):
2528
+ await self.load_markets()
2529
+ market = self.market(symbol)
2530
+ request: dict = {
2531
+ 'symbol': market['id'],
2532
+ }
2533
+ response = await self.v1PublicGetFundingRateSymbol(self.extend(request, params))
2534
+ #
2535
+ # {
2536
+ # "success":true,
2537
+ # "timestamp":1653640572711,
2538
+ # "symbol":"PERP_BTC_USDT",
2539
+ # "est_funding_rate":0.00000738,
2540
+ # "est_funding_rate_timestamp":1653640559003,
2541
+ # "last_funding_rate":0.00000629,
2542
+ # "last_funding_rate_timestamp":1653638400000,
2543
+ # "next_funding_time":1653642000000
2544
+ # }
2545
+ #
2546
+ return self.parse_funding_rate(response, market)
2547
+
2548
+ async def fetch_funding_rates(self, symbols: Strings = None, params={}):
2549
+ await self.load_markets()
2550
+ symbols = self.market_symbols(symbols)
2551
+ response = await self.v1PublicGetFundingRates(params)
2552
+ #
2553
+ # {
2554
+ # "success":true,
2555
+ # "rows":[
2556
+ # {
2557
+ # "symbol":"PERP_AAVE_USDT",
2558
+ # "est_funding_rate":-0.00003447,
2559
+ # "est_funding_rate_timestamp":1653633959001,
2560
+ # "last_funding_rate":-0.00002094,
2561
+ # "last_funding_rate_timestamp":1653631200000,
2562
+ # "next_funding_time":1653634800000
2563
+ # }
2564
+ # ],
2565
+ # "timestamp":1653633985646
2566
+ # }
2567
+ #
2568
+ rows = self.safe_list(response, 'rows', [])
2569
+ result = self.parse_funding_rates(rows)
2570
+ return self.filter_by_array(result, 'symbol', symbols)
2571
+
2572
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2573
+ """
2574
+ fetches historical funding rate prices
2575
+ :see: https://docs.woo.org/#get-funding-rate-history-for-one-market-public
2576
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2577
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
2578
+ :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
2579
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2580
+ :param int [params.until]: timestamp in ms of the latest funding rate
2581
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2582
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2583
+ """
2584
+ await self.load_markets()
2585
+ paginate = False
2586
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2587
+ if paginate:
2588
+ return await self.fetch_paginated_call_incremental('fetchFundingRateHistory', symbol, since, limit, params, 'page', 25)
2589
+ request: dict = {}
2590
+ if symbol is not None:
2591
+ market = self.market(symbol)
2592
+ symbol = market['symbol']
2593
+ request['symbol'] = market['id']
2594
+ if since is not None:
2595
+ request['start_t'] = self.parse_to_int(since / 1000)
2596
+ request, params = self.handle_until_option('end_t', request, params, 0.001)
2597
+ response = await self.v1PublicGetFundingRateHistory(self.extend(request, params))
2598
+ #
2599
+ # {
2600
+ # "success":true,
2601
+ # "meta":{
2602
+ # "total":2464,
2603
+ # "records_per_page":25,
2604
+ # "current_page":1
2605
+ # },
2606
+ # "rows":[
2607
+ # {
2608
+ # "symbol":"PERP_BTC_USDT",
2609
+ # "funding_rate":0.00000629,
2610
+ # "funding_rate_timestamp":1653638400000,
2611
+ # "next_funding_time":1653642000000
2612
+ # }
2613
+ # ],
2614
+ # "timestamp":1653640814885
2615
+ # }
2616
+ #
2617
+ result = self.safe_list(response, 'rows')
2618
+ rates = []
2619
+ for i in range(0, len(result)):
2620
+ entry = result[i]
2621
+ marketId = self.safe_string(entry, 'symbol')
2622
+ timestamp = self.safe_integer(entry, 'funding_rate_timestamp')
2623
+ rates.append({
2624
+ 'info': entry,
2625
+ 'symbol': self.safe_symbol(marketId),
2626
+ 'fundingRate': self.safe_number(entry, 'funding_rate'),
2627
+ 'timestamp': timestamp,
2628
+ 'datetime': self.iso8601(timestamp),
2629
+ })
2630
+ sorted = self.sort_by(rates, 'timestamp')
2631
+ return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
2632
+
2633
+ async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
2634
+ """
2635
+ set hedged to True or False for a market
2636
+ :see: https://docs.woo.org/#update-position-mode
2637
+ :param bool hedged: set to True to use HEDGE_MODE, False for ONE_WAY
2638
+ :param str symbol: not used by woo setPositionMode
2639
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2640
+ :returns dict: response from the exchange
2641
+ """
2642
+ hedgeMode = None
2643
+ if hedged:
2644
+ hedgeMode = 'HEDGE_MODE'
2645
+ else:
2646
+ hedgeMode = 'ONE_WAY'
2647
+ request: dict = {
2648
+ 'position_mode': hedgeMode,
2649
+ }
2650
+ response = await self.v1PrivatePostClientPositionMode(self.extend(request, params))
2651
+ #
2652
+ # {
2653
+ # "success": True,
2654
+ # "data": {},
2655
+ # "timestamp": "1709195608551"
2656
+ # }
2657
+ #
2658
+ return response
2659
+
2660
+ async def fetch_leverage(self, symbol: str, params={}) -> Leverage:
2661
+ """
2662
+ fetch the set leverage for a market
2663
+ :see: https://docs.woo.org/#get-account-information-new
2664
+ :param str symbol: unified market symbol
2665
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2666
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
2667
+ """
2668
+ await self.load_markets()
2669
+ market = self.market(symbol)
2670
+ response = await self.v3PrivateGetAccountinfo(params)
2671
+ #
2672
+ # {
2673
+ # "success": True,
2674
+ # "data": {
2675
+ # "applicationId": "dsa",
2676
+ # "account": "dsa",
2677
+ # "alias": "haha",
2678
+ # "accountMode": "MARGIN",
2679
+ # "leverage": 1,
2680
+ # "takerFeeRate": 1,
2681
+ # "makerFeeRate": 1,
2682
+ # "interestRate": 1,
2683
+ # "futuresTakerFeeRate": 1,
2684
+ # "futuresMakerFeeRate": 1,
2685
+ # "otpauth": True,
2686
+ # "marginRatio": 1,
2687
+ # "openMarginRatio": 1,
2688
+ # "initialMarginRatio": 1,
2689
+ # "maintenanceMarginRatio": 1,
2690
+ # "totalCollateral": 1,
2691
+ # "freeCollateral": 1,
2692
+ # "totalAccountValue": 1,
2693
+ # "totalVaultValue": 1,
2694
+ # "totalStakingValue": 1
2695
+ # },
2696
+ # "timestamp": 1673323685109
2697
+ # }
2698
+ #
2699
+ data = self.safe_dict(response, 'data', {})
2700
+ return self.parse_leverage(data, market)
2701
+
2702
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
2703
+ leverageValue = self.safe_integer(leverage, 'leverage')
2704
+ return {
2705
+ 'info': leverage,
2706
+ 'symbol': market['symbol'],
2707
+ 'marginMode': None,
2708
+ 'longLeverage': leverageValue,
2709
+ 'shortLeverage': leverageValue,
2710
+ }
2711
+
2712
+ async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2713
+ await self.load_markets()
2714
+ if (leverage < 1) or (leverage > 20):
2715
+ raise BadRequest(self.id + ' leverage should be between 1 and 20')
2716
+ request: dict = {
2717
+ 'leverage': leverage,
2718
+ }
2719
+ return await self.v1PrivatePostClientLeverage(self.extend(request, params))
2720
+
2721
+ async def fetch_position(self, symbol: Str = None, params={}):
2722
+ await self.load_markets()
2723
+ market = self.market(symbol)
2724
+ request: dict = {
2725
+ 'symbol': market['id'],
2726
+ }
2727
+ response = await self.v1PrivateGetPositionSymbol(self.extend(request, params))
2728
+ #
2729
+ # {
2730
+ # "symbol":"PERP_ETC_USDT",
2731
+ # "holding":0.0,
2732
+ # "pnl_24_h":0,
2733
+ # "settle_price":0.0,
2734
+ # "average_open_price":0,
2735
+ # "success":true,
2736
+ # "mark_price":22.6955,
2737
+ # "pending_short_qty":0.0,
2738
+ # "pending_long_qty":0.0,
2739
+ # "fee_24_h":0,
2740
+ # "timestamp":"1652231044.920"
2741
+ # }
2742
+ #
2743
+ return self.parse_position(response, market)
2744
+
2745
+ async def fetch_positions(self, symbols: Strings = None, params={}):
2746
+ await self.load_markets()
2747
+ response = await self.v3PrivateGetPositions(params)
2748
+ #
2749
+ # {
2750
+ # "success": True,
2751
+ # "data": {
2752
+ # "positions": [
2753
+ # {
2754
+ # "symbol": "0_symbol",
2755
+ # "holding": 1,
2756
+ # "pendingLongQty": 0,
2757
+ # "pendingShortQty": 1,
2758
+ # "settlePrice": 1,
2759
+ # "averageOpenPrice": 1,
2760
+ # "pnl24H": 1,
2761
+ # "fee24H": 1,
2762
+ # "markPrice": 1,
2763
+ # "estLiqPrice": 1,
2764
+ # "timestamp": 12321321
2765
+ # }
2766
+ # ]
2767
+ # },
2768
+ # "timestamp": 1673323880342
2769
+ # }
2770
+ #
2771
+ result = self.safe_dict(response, 'data', {})
2772
+ positions = self.safe_list(result, 'positions', [])
2773
+ return self.parse_positions(positions, symbols)
2774
+
2775
+ def parse_position(self, position: dict, market: Market = None):
2776
+ #
2777
+ # {
2778
+ # "symbol": "0_symbol",
2779
+ # "holding": 1,
2780
+ # "pendingLongQty": 0,
2781
+ # "pendingShortQty": 1,
2782
+ # "settlePrice": 1,
2783
+ # "averageOpenPrice": 1,
2784
+ # "pnl24H": 1,
2785
+ # "fee24H": 1,
2786
+ # "markPrice": 1,
2787
+ # "estLiqPrice": 1,
2788
+ # "timestamp": 12321321
2789
+ # }
2790
+ #
2791
+ contract = self.safe_string(position, 'symbol')
2792
+ market = self.safe_market(contract, market)
2793
+ size = self.safe_string(position, 'holding')
2794
+ side: Str = None
2795
+ if Precise.string_gt(size, '0'):
2796
+ side = 'long'
2797
+ else:
2798
+ side = 'short'
2799
+ contractSize = self.safe_string(market, 'contractSize')
2800
+ markPrice = self.safe_string(position, 'markPrice')
2801
+ timestamp = self.safe_timestamp(position, 'timestamp')
2802
+ entryPrice = self.safe_string(position, 'averageOpenPrice')
2803
+ priceDifference = Precise.string_sub(markPrice, entryPrice)
2804
+ unrealisedPnl = Precise.string_mul(priceDifference, size)
2805
+ size = Precise.string_abs(size)
2806
+ notional = Precise.string_mul(size, markPrice)
2807
+ return self.safe_position({
2808
+ 'info': position,
2809
+ 'id': None,
2810
+ 'symbol': self.safe_string(market, 'symbol'),
2811
+ 'timestamp': timestamp,
2812
+ 'datetime': self.iso8601(timestamp),
2813
+ 'lastUpdateTimestamp': None,
2814
+ 'initialMargin': None,
2815
+ 'initialMarginPercentage': None,
2816
+ 'maintenanceMargin': None,
2817
+ 'maintenanceMarginPercentage': None,
2818
+ 'entryPrice': self.parse_number(entryPrice),
2819
+ 'notional': self.parse_number(notional),
2820
+ 'leverage': None,
2821
+ 'unrealizedPnl': self.parse_number(unrealisedPnl),
2822
+ 'contracts': self.parse_number(size),
2823
+ 'contractSize': self.parse_number(contractSize),
2824
+ 'marginRatio': None,
2825
+ 'liquidationPrice': self.safe_number(position, 'estLiqPrice'),
2826
+ 'markPrice': self.parse_number(markPrice),
2827
+ 'lastPrice': None,
2828
+ 'collateral': None,
2829
+ 'marginMode': 'cross',
2830
+ 'marginType': None,
2831
+ 'side': side,
2832
+ 'percentage': None,
2833
+ 'hedged': None,
2834
+ 'stopLossPrice': None,
2835
+ 'takeProfitPrice': None,
2836
+ })
2837
+
2838
+ async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
2839
+ """
2840
+ fetch a quote for converting from one currency to another
2841
+ :see: https://docs.woo.org/#get-quote-rfq
2842
+ :param str fromCode: the currency that you want to sell and convert from
2843
+ :param str toCode: the currency that you want to buy and convert into
2844
+ :param float [amount]: how much you want to trade in units of the from currency
2845
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2846
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
2847
+ """
2848
+ await self.load_markets()
2849
+ request: dict = {
2850
+ 'sellToken': fromCode.upper(),
2851
+ 'buyToken': toCode.upper(),
2852
+ 'sellQuantity': self.number_to_string(amount),
2853
+ }
2854
+ response = await self.v3PrivateGetConvertRfq(self.extend(request, params))
2855
+ #
2856
+ # {
2857
+ # "success": True,
2858
+ # "data": {
2859
+ # "quoteId": 123123123,
2860
+ # "counterPartyId": "",
2861
+ # "sellToken": "ETH",
2862
+ # "sellQuantity": "0.0445",
2863
+ # "buyToken": "USDT",
2864
+ # "buyQuantity": "33.45",
2865
+ # "buyPrice": "6.77",
2866
+ # "expireTimestamp": 1659084466000,
2867
+ # "message": 1659084466000
2868
+ # }
2869
+ # }
2870
+ #
2871
+ data = self.safe_dict(response, 'data', {})
2872
+ fromCurrencyId = self.safe_string(data, 'sellToken', fromCode)
2873
+ fromCurrency = self.currency(fromCurrencyId)
2874
+ toCurrencyId = self.safe_string(data, 'buyToken', toCode)
2875
+ toCurrency = self.currency(toCurrencyId)
2876
+ return self.parse_conversion(data, fromCurrency, toCurrency)
2877
+
2878
+ async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
2879
+ """
2880
+ convert from one currency to another
2881
+ :see: https://docs.woo.org/#send-quote-rft
2882
+ :param str id: the id of the trade that you want to make
2883
+ :param str fromCode: the currency that you want to sell and convert from
2884
+ :param str toCode: the currency that you want to buy and convert into
2885
+ :param float [amount]: how much you want to trade in units of the from currency
2886
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2887
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
2888
+ """
2889
+ await self.load_markets()
2890
+ request: dict = {
2891
+ 'quoteId': id,
2892
+ }
2893
+ response = await self.v3PrivatePostConvertRft(self.extend(request, params))
2894
+ #
2895
+ # {
2896
+ # "success": True,
2897
+ # "data": {
2898
+ # "quoteId": 123123123,
2899
+ # "counterPartyId": "",
2900
+ # "rftAccepted": 1 # 1 -> success; 2 -> processing; 3 -> fail
2901
+ # }
2902
+ # }
2903
+ #
2904
+ data = self.safe_dict(response, 'data', {})
2905
+ return self.parse_conversion(data)
2906
+
2907
+ async def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
2908
+ """
2909
+ fetch the data for a conversion trade
2910
+ :see: https://docs.woo.org/#get-quote-trade
2911
+ :param str id: the id of the trade that you want to fetch
2912
+ :param str [code]: the unified currency code of the conversion trade
2913
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2914
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
2915
+ """
2916
+ await self.load_markets()
2917
+ request: dict = {
2918
+ 'quoteId': id,
2919
+ }
2920
+ response = await self.v3PrivateGetConvertTrade(self.extend(request, params))
2921
+ #
2922
+ # {
2923
+ # "success": True,
2924
+ # "data": {
2925
+ # "quoteId": 12,
2926
+ # "buyAsset": "",
2927
+ # "sellAsset": "",
2928
+ # "buyAmount": 12.11,
2929
+ # "sellAmount": 12.11,
2930
+ # "tradeStatus": 12,
2931
+ # "createdTime": ""
2932
+ # }
2933
+ # }
2934
+ #
2935
+ data = self.safe_dict(response, 'data', {})
2936
+ fromCurrencyId = self.safe_string(data, 'sellAsset')
2937
+ toCurrencyId = self.safe_string(data, 'buyAsset')
2938
+ fromCurrency = None
2939
+ toCurrency = None
2940
+ if fromCurrencyId is not None:
2941
+ fromCurrency = self.currency(fromCurrencyId)
2942
+ if toCurrencyId is not None:
2943
+ toCurrency = self.currency(toCurrencyId)
2944
+ return self.parse_conversion(data, fromCurrency, toCurrency)
2945
+
2946
+ async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
2947
+ """
2948
+ fetch the users history of conversion trades
2949
+ :see: https://docs.woo.org/#get-quote-trades
2950
+ :param str [code]: the unified currency code
2951
+ :param int [since]: the earliest time in ms to fetch conversions for
2952
+ :param int [limit]: the maximum number of conversion structures to retrieve
2953
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2954
+ :param int [params.until]: timestamp in ms of the latest conversion to fetch
2955
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
2956
+ """
2957
+ await self.load_markets()
2958
+ request: dict = {}
2959
+ request, params = self.handle_until_option('endTime', request, params)
2960
+ if since is not None:
2961
+ request['startTime'] = since
2962
+ if limit is not None:
2963
+ request['size'] = limit
2964
+ response = await self.v3PrivateGetConvertTrades(self.extend(request, params))
2965
+ #
2966
+ # {
2967
+ # "success": True,
2968
+ # "data": {
2969
+ # "count": 12,
2970
+ # "tradeVos":[
2971
+ # {
2972
+ # "quoteId": 12,
2973
+ # "buyAsset": "",
2974
+ # "sellAsset": "",
2975
+ # "buyAmount": 12.11,
2976
+ # "sellAmount": 12.11,
2977
+ # "tradeStatus": 12,
2978
+ # "createdTime": ""
2979
+ # }
2980
+ # ...
2981
+ # ]
2982
+ # }
2983
+ # }
2984
+ #
2985
+ data = self.safe_dict(response, 'data', {})
2986
+ rows = self.safe_list(data, 'tradeVos', [])
2987
+ return self.parse_conversions(rows, code, 'sellAsset', 'buyAsset', since, limit)
2988
+
2989
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
2990
+ #
2991
+ # fetchConvertQuote
2992
+ #
2993
+ # {
2994
+ # "quoteId": 123123123,
2995
+ # "counterPartyId": "",
2996
+ # "sellToken": "ETH",
2997
+ # "sellQuantity": "0.0445",
2998
+ # "buyToken": "USDT",
2999
+ # "buyQuantity": "33.45",
3000
+ # "buyPrice": "6.77",
3001
+ # "expireTimestamp": 1659084466000,
3002
+ # "message": 1659084466000
3003
+ # }
3004
+ #
3005
+ # createConvertTrade
3006
+ #
3007
+ # {
3008
+ # "quoteId": 123123123,
3009
+ # "counterPartyId": "",
3010
+ # "rftAccepted": 1 # 1 -> success; 2 -> processing; 3 -> fail
3011
+ # }
3012
+ #
3013
+ # fetchConvertTrade, fetchConvertTradeHistory
3014
+ #
3015
+ # {
3016
+ # "quoteId": 12,
3017
+ # "buyAsset": "",
3018
+ # "sellAsset": "",
3019
+ # "buyAmount": 12.11,
3020
+ # "sellAmount": 12.11,
3021
+ # "tradeStatus": 12,
3022
+ # "createdTime": ""
3023
+ # }
3024
+ #
3025
+ timestamp = self.safe_integer_2(conversion, 'expireTimestamp', 'createdTime')
3026
+ fromCurr = self.safe_string_2(conversion, 'sellToken', 'buyAsset')
3027
+ fromCode = self.safe_currency_code(fromCurr, fromCurrency)
3028
+ to = self.safe_string_2(conversion, 'buyToken', 'sellAsset')
3029
+ toCode = self.safe_currency_code(to, toCurrency)
3030
+ return {
3031
+ 'info': conversion,
3032
+ 'timestamp': timestamp,
3033
+ 'datetime': self.iso8601(timestamp),
3034
+ 'id': self.safe_string(conversion, 'quoteId'),
3035
+ 'fromCurrency': fromCode,
3036
+ 'fromAmount': self.safe_number_2(conversion, 'sellQuantity', 'sellAmount'),
3037
+ 'toCurrency': toCode,
3038
+ 'toAmount': self.safe_number_2(conversion, 'buyQuantity', 'buyAmount'),
3039
+ 'price': self.safe_number(conversion, 'buyPrice'),
3040
+ 'fee': None,
3041
+ }
3042
+
3043
+ async def fetch_convert_currencies(self, params={}) -> Currencies:
3044
+ """
3045
+ fetches all available currencies that can be converted
3046
+ :see: https://docs.woo.org/#get-quote-asset-info
3047
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3048
+ :returns dict: an associative dictionary of currencies
3049
+ """
3050
+ await self.load_markets()
3051
+ response = await self.v3PrivateGetConvertAssetInfo(params)
3052
+ #
3053
+ # {
3054
+ # "success": True,
3055
+ # "rows": [
3056
+ # {
3057
+ # "token": "BTC",
3058
+ # "tick": 0.0001,
3059
+ # "createdTime": "1575014248.99", # Unix epoch time in seconds
3060
+ # "updatedTime": "1575014248.99" # Unix epoch time in seconds
3061
+ # },
3062
+ # ]
3063
+ # }
3064
+ #
3065
+ result: dict = {}
3066
+ data = self.safe_list(response, 'rows', [])
3067
+ for i in range(0, len(data)):
3068
+ entry = data[i]
3069
+ id = self.safe_string(entry, 'token')
3070
+ code = self.safe_currency_code(id)
3071
+ result[code] = {
3072
+ 'info': entry,
3073
+ 'id': id,
3074
+ 'code': code,
3075
+ 'networks': None,
3076
+ 'type': None,
3077
+ 'name': None,
3078
+ 'active': None,
3079
+ 'deposit': None,
3080
+ 'withdraw': None,
3081
+ 'fee': None,
3082
+ 'precision': self.safe_number(entry, 'tick'),
3083
+ 'limits': {
3084
+ 'amount': {
3085
+ 'min': None,
3086
+ 'max': None,
3087
+ },
3088
+ 'withdraw': {
3089
+ 'min': None,
3090
+ 'max': None,
3091
+ },
3092
+ 'deposit': {
3093
+ 'min': None,
3094
+ 'max': None,
3095
+ },
3096
+ },
3097
+ 'created': self.safe_timestamp(entry, 'createdTime'),
3098
+ }
3099
+ return result
3100
+
3101
+ def default_network_code_for_currency(self, code):
3102
+ currencyItem = self.currency(code)
3103
+ networks = currencyItem['networks']
3104
+ networkKeys = list(networks.keys())
3105
+ for i in range(0, len(networkKeys)):
3106
+ network = networkKeys[i]
3107
+ if network == 'ETH':
3108
+ return network
3109
+ # if it was not returned according to above options, then return the first network of currency
3110
+ return self.safe_value(networkKeys, 0)
3111
+
3112
+ def set_sandbox_mode(self, enable: bool):
3113
+ super(woo, self).set_sandbox_mode(enable)
3114
+ self.options['sandboxMode'] = enable