ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__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 (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/async_support/woo.py CHANGED
@@ -5,16 +5,17 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.woo import ImplicitAPI
8
+ import asyncio
8
9
  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 ccxt.base.types import Account, Any, Balances, Bool, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Leverage, MarginModification, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
11
  from typing import List
11
- from typing import Any
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
14
14
  from ccxt.base.errors import ArgumentsRequired
15
15
  from ccxt.base.errors import BadRequest
16
16
  from ccxt.base.errors import InvalidOrder
17
17
  from ccxt.base.errors import NotSupported
18
+ from ccxt.base.errors import OperationFailed
18
19
  from ccxt.base.errors import RateLimitExceeded
19
20
  from ccxt.base.errors import OnMaintenance
20
21
  from ccxt.base.decimal_to_precision import TICK_SIZE
@@ -23,7 +24,7 @@ from ccxt.base.precise import Precise
23
24
 
24
25
  class woo(Exchange, ImplicitAPI):
25
26
 
26
- def describe(self):
27
+ def describe(self) -> Any:
27
28
  return self.deep_extend(super(woo, self).describe(), {
28
29
  'id': 'woo',
29
30
  'name': 'WOO X',
@@ -32,7 +33,7 @@ class woo(Exchange, ImplicitAPI):
32
33
  'version': 'v1',
33
34
  'certified': True,
34
35
  'pro': True,
35
- 'hostname': 'woo.org',
36
+ 'hostname': 'woox.io',
36
37
  'has': {
37
38
  'CORS': None,
38
39
  'spot': True,
@@ -40,11 +41,11 @@ class woo(Exchange, ImplicitAPI):
40
41
  'swap': True,
41
42
  'future': False,
42
43
  'option': False,
43
- 'addMargin': False,
44
+ 'addMargin': True,
44
45
  'cancelAllOrders': True,
45
46
  'cancelAllOrdersAfter': True,
46
47
  '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
+ 'cancelWithdraw': False, # exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://docx.woo.io/wootrade-documents/#cancel-withdraw-request
48
49
  'closeAllPositions': False,
49
50
  'closePosition': False,
50
51
  'createConvertTrade': True,
@@ -52,7 +53,7 @@ class woo(Exchange, ImplicitAPI):
52
53
  'createMarketBuyOrderWithCost': True,
53
54
  'createMarketOrder': False,
54
55
  'createMarketOrderWithCost': False,
55
- 'createMarketSellOrderWithCost': False,
56
+ 'createMarketSellOrderWithCost': True,
56
57
  'createOrder': True,
57
58
  'createOrderWithTakeProfitAndStopLoss': True,
58
59
  'createReduceOnlyOrder': True,
@@ -75,9 +76,13 @@ class woo(Exchange, ImplicitAPI):
75
76
  'fetchConvertTradeHistory': True,
76
77
  'fetchCurrencies': True,
77
78
  'fetchDepositAddress': True,
79
+ 'fetchDepositAddresses': False,
80
+ 'fetchDepositAddressesByNetwork': False,
78
81
  'fetchDeposits': True,
79
82
  'fetchDepositsWithdrawals': True,
80
83
  'fetchFundingHistory': True,
84
+ 'fetchFundingInterval': True,
85
+ 'fetchFundingIntervals': False,
81
86
  'fetchFundingRate': True,
82
87
  'fetchFundingRateHistory': True,
83
88
  'fetchFundingRates': True,
@@ -108,7 +113,7 @@ class woo(Exchange, ImplicitAPI):
108
113
  'fetchTickers': False,
109
114
  'fetchTime': True,
110
115
  'fetchTrades': True,
111
- 'fetchTradingFee': False,
116
+ 'fetchTradingFee': True,
112
117
  'fetchTradingFees': True,
113
118
  'fetchTransactions': 'emulated',
114
119
  'fetchTransfers': True,
@@ -119,7 +124,7 @@ class woo(Exchange, ImplicitAPI):
119
124
  'setMargin': False,
120
125
  'setPositionMode': True,
121
126
  '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
127
+ 'withdraw': True, # exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://docx.woo.io/wootrade-documents/#token-withdraw
123
128
  },
124
129
  'timeframes': {
125
130
  '1m': '1m',
@@ -137,24 +142,24 @@ class woo(Exchange, ImplicitAPI):
137
142
  'urls': {
138
143
  'logo': 'https://user-images.githubusercontent.com/1294454/150730761-1a00e5e0-d28c-480f-9e65-089ce3e6ef3b.jpg',
139
144
  'api': {
140
- 'pub': 'https://api-pub.woo.org',
145
+ 'pub': 'https://api-pub.woox.io',
141
146
  'public': 'https://api.{hostname}',
142
147
  'private': 'https://api.{hostname}',
143
148
  },
144
149
  'test': {
145
- 'pub': 'https://api-pub.staging.woo.org',
146
- 'public': 'https://api.staging.woo.org',
147
- 'private': 'https://api.staging.woo.org',
150
+ 'pub': 'https://api-pub.staging.woox.io',
151
+ 'public': 'https://api.staging.woox.io',
152
+ 'private': 'https://api.staging.woox.io',
148
153
  },
149
- 'www': 'https://woo.org/',
154
+ 'www': 'https://woox.io/',
150
155
  'doc': [
151
- 'https://docs.woo.org/',
156
+ 'https://docs.woox.io/',
152
157
  ],
153
158
  'fees': [
154
- 'https://support.woo.org/hc/en-001/articles/4404611795353--Trading-Fees',
159
+ 'https://support.woox.io/hc/en-001/articles/4404611795353--Trading-Fees',
155
160
  ],
156
161
  'referral': {
157
- 'url': 'https://x.woo.org/register?ref=YWOWC96B',
162
+ 'url': 'https://woox.io/register?ref=DIJT0CNL',
158
163
  'discount': 0.35,
159
164
  },
160
165
  },
@@ -163,7 +168,7 @@ class woo(Exchange, ImplicitAPI):
163
168
  'pub': {
164
169
  'get': {
165
170
  'hist/kline': 10,
166
- 'hist/trades': 1,
171
+ 'hist/trades': 10,
167
172
  },
168
173
  },
169
174
  'public': {
@@ -210,24 +215,27 @@ class woo(Exchange, ImplicitAPI):
210
215
  'positions': 3.33, # 30 requests per 10 seconds
211
216
  'position/{symbol}': 3.33,
212
217
  'client/transaction_history': 60,
218
+ 'client/futures_leverage': 60,
213
219
  },
214
220
  'post': {
215
- 'order': 5, # 2 requests per 1 second per symbol
221
+ 'order': 1, # 10 requests per 1 second per symbol
216
222
  'order/cancel_all_after': 1,
217
223
  'asset/main_sub_transfer': 30, # 20 requests per 60 seconds
218
224
  'asset/ltv': 30,
219
- 'asset/withdraw': 30, # implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#token-withdraw
225
+ 'asset/withdraw': 30, # implemented in ccxt, disabled on the exchange side https://docx.woo.io/wootrade-documents/#token-withdraw
220
226
  'asset/internal_withdraw': 30,
221
227
  'interest/repay': 60,
222
228
  'client/account_mode': 120,
223
229
  'client/position_mode': 5,
224
230
  'client/leverage': 120,
231
+ 'client/futures_leverage': 30,
232
+ 'client/isolated_margin': 30,
225
233
  },
226
234
  'delete': {
227
235
  'order': 1,
228
236
  'client/order': 1,
229
237
  'orders': 1,
230
- 'asset/withdraw': 120, # implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
238
+ 'asset/withdraw': 120, # implemented in ccxt, disabled on the exchange side https://docx.woo.io/wootrade-documents/#cancel-withdraw-request
231
239
  },
232
240
  },
233
241
  },
@@ -241,19 +249,56 @@ class woo(Exchange, ImplicitAPI):
241
249
  'v3': {
242
250
  'public': {
243
251
  'get': {
244
- 'insuranceFund': 3,
252
+ 'systemInfo': 1, # 10/1s
253
+ 'instruments': 1, # 10/1s
254
+ 'token': 1, # 10/1s
255
+ 'tokenNetwork': 1, # 10/1s
256
+ 'tokenInfo': 1, # 10/1s
257
+ 'marketTrades': 1, # 10/1s
258
+ 'marketTradesHistory': 1, # 10/1s
259
+ 'orderbook': 1, # 10/1s
260
+ 'kline': 1, # 10/1s
261
+ 'klineHistory': 1, # 10/1s
262
+ 'futures': 1, # 10/1s
263
+ 'fundingRate': 1, # 10/1s
264
+ 'fundingRateHistory': 1, # 10/1s
265
+ 'insuranceFund': 1, # 10/1s
245
266
  },
246
267
  },
247
268
  'private': {
248
269
  'get': {
270
+ 'trade/order': 2, # 5/1s
271
+ 'trade/orders': 1, # 10/1s
272
+ 'trade/algoOrder': 1, # 10/1s
273
+ 'trade/algoOrders': 1, # 10/1s
274
+ 'trade/transaction': 1, # 10/1s
275
+ 'trade/transactionHistory': 5, # 2/1s
276
+ 'trade/tradingFee': 5, # 2/1s
277
+ 'account/info': 60, # 10/60s
278
+ 'account/tokenConfig': 1, # 10/1s
279
+ 'account/symbolConfig': 1, # 10/1s
280
+ 'account/subAccounts/all': 60, # 10/60s
281
+ 'account/referral/summary': 60, # 10/60s
282
+ 'account/referral/rewardHistory': 60, # 10/60s
283
+ 'account/credentials': 60, # 10/60s
284
+ 'asset/balances': 1, # 10/1s
285
+ 'asset/token/history': 60, # 10/60s
286
+ 'asset/transfer/history': 30, # 20/60s
287
+ 'asset/wallet/history': 60, # 10/60s
288
+ 'asset/wallet/deposit': 60, # 10/60s
289
+ 'asset/staking/yieldHistory': 60, # 10/60s
290
+ 'futures/positions': 3.33, # 30/10s
291
+ 'futures/leverage': 60, # 10/60s
292
+ 'futures/defaultMarginMode': 60, # 10/60s
293
+ 'futures/fundingFee/history': 30, # 20/60s
294
+ 'spotMargin/interestRate': 60, # 10/60s
295
+ 'spotMargin/interestHistory': 60, # 10/60s
296
+ 'spotMargin/maxMargin': 60, # 10/60s
249
297
  'algo/order/{oid}': 1,
250
298
  'algo/orders': 1,
251
299
  'balances': 1,
252
- 'accountinfo': 60,
253
300
  'positions': 3.33,
254
301
  'buypower': 1,
255
- 'referrals': 60,
256
- 'referral_rewards': 60,
257
302
  'convert/exchangeInfo': 1,
258
303
  'convert/assetInfo': 1,
259
304
  'convert/rfq': 60,
@@ -261,16 +306,34 @@ class woo(Exchange, ImplicitAPI):
261
306
  'convert/trades': 1,
262
307
  },
263
308
  'post': {
309
+ 'trade/order': 2, # 5/1s
310
+ 'trade/algoOrder': 5, # 2/1s
311
+ 'trade/cancelAllAfter': 1, # 10/1s
312
+ 'account/tradingMode': 120, # 5/60s
313
+ 'account/listenKey': 20, # 5/10s
314
+ 'asset/transfer': 30, # 20/60s
315
+ 'asset/wallet/withdraw': 60, # 10/60s
316
+ 'spotMargin/leverage': 120, # 5/60s
317
+ 'spotMargin/interestRepay': 60, # 10/60s
264
318
  'algo/order': 5,
265
319
  'convert/rft': 60,
266
320
  },
267
321
  'put': {
322
+ 'trade/order': 2, # 5/1s
323
+ 'trade/algoOrder': 2, # 5/1s
324
+ 'futures/leverage': 60, # 10/60s
325
+ 'futures/positionMode': 120, # 5/60s
268
326
  'order/{oid}': 2,
269
327
  'order/client/{client_order_id}': 2,
270
328
  'algo/order/{oid}': 2,
271
329
  'algo/order/client/{client_order_id}': 2,
272
330
  },
273
331
  'delete': {
332
+ 'trade/order': 1, # 10/1s
333
+ 'trade/orders': 1, # 10/1s
334
+ 'trade/algoOrder': 1, # 10/1s
335
+ 'trade/algoOrders': 1, # 10/1s
336
+ 'trade/allOrders': 1, # 10/1s
274
337
  'algo/order/{order_id}': 1,
275
338
  'algo/orders/pending': 1,
276
339
  'algo/orders/pending/{symbol}': 1,
@@ -288,6 +351,8 @@ class woo(Exchange, ImplicitAPI):
288
351
  },
289
352
  },
290
353
  'options': {
354
+ 'timeDifference': 0, # the difference between system clock and exchange clock
355
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
291
356
  'sandboxMode': False,
292
357
  'createMarketBuyOrderRequiresPrice': True,
293
358
  # these network aliases require manual mapping here
@@ -302,6 +367,11 @@ class woo(Exchange, ImplicitAPI):
302
367
  'TRC20': 'TRON',
303
368
  'ERC20': 'ETH',
304
369
  'BEP20': 'BSC',
370
+ 'ARB': 'Arbitrum',
371
+ },
372
+ 'networksById': {
373
+ 'TRX': 'TRC20',
374
+ 'TRON': 'TRC20',
305
375
  },
306
376
  # override defaultNetworkCodePriorities for a specific currency
307
377
  'defaultNetworkCodeForCurrencies': {
@@ -313,10 +383,103 @@ class woo(Exchange, ImplicitAPI):
313
383
  },
314
384
  'brokerId': 'bc830de7-50f3-460b-9ee0-f430f83f9dad',
315
385
  },
386
+ 'features': {
387
+ 'default': {
388
+ 'sandbox': True,
389
+ 'createOrder': {
390
+ 'marginMode': True,
391
+ 'triggerPrice': True,
392
+ 'triggerPriceType': {
393
+ 'last': True,
394
+ 'mark': True,
395
+ 'index': False,
396
+ },
397
+ 'triggerDirection': False,
398
+ 'stopLossPrice': False, # todo by triggerPrice
399
+ 'takeProfitPrice': False, # todo by triggerPrice
400
+ 'attachedStopLossTakeProfit': None,
401
+ 'timeInForce': {
402
+ 'IOC': True,
403
+ 'FOK': True,
404
+ 'PO': True,
405
+ 'GTD': True,
406
+ },
407
+ 'hedged': False,
408
+ 'trailing': True,
409
+ 'leverage': False,
410
+ 'marketBuyByCost': True,
411
+ 'marketBuyRequiresPrice': False,
412
+ 'selfTradePrevention': False,
413
+ 'iceberg': True, # todo implement
414
+ },
415
+ 'createOrders': None,
416
+ 'fetchMyTrades': {
417
+ 'marginMode': False,
418
+ 'limit': 500,
419
+ 'daysBack': 90,
420
+ 'untilDays': 10000,
421
+ 'symbolRequired': False,
422
+ },
423
+ 'fetchOrder': {
424
+ 'marginMode': False,
425
+ 'trigger': True,
426
+ 'trailing': False,
427
+ 'symbolRequired': False,
428
+ },
429
+ 'fetchOpenOrders': {
430
+ 'marginMode': False,
431
+ 'limit': 500,
432
+ 'trigger': True,
433
+ 'trailing': True,
434
+ 'symbolRequired': False,
435
+ },
436
+ 'fetchOrders': {
437
+ 'marginMode': False,
438
+ 'limit': 500,
439
+ 'daysBack': None,
440
+ 'untilDays': 100000,
441
+ 'trigger': True,
442
+ 'trailing': True,
443
+ 'symbolRequired': False,
444
+ },
445
+ 'fetchClosedOrders': {
446
+ 'marginMode': False,
447
+ 'limit': 500,
448
+ 'daysBack': None,
449
+ 'daysBackCanceled': None,
450
+ 'untilDays': 100000,
451
+ 'trigger': True,
452
+ 'trailing': True,
453
+ 'symbolRequired': False,
454
+ },
455
+ 'fetchOHLCV': {
456
+ 'limit': 1000,
457
+ },
458
+ },
459
+ 'spot': {
460
+ 'extends': 'default',
461
+ },
462
+ 'forSwap': {
463
+ 'extends': 'default',
464
+ 'createOrder': {
465
+ 'hedged': True,
466
+ },
467
+ },
468
+ 'swap': {
469
+ 'linear': {
470
+ 'extends': 'forSwap',
471
+ },
472
+ 'inverse': None,
473
+ },
474
+ 'future': {
475
+ 'linear': None,
476
+ 'inverse': None,
477
+ },
478
+ },
316
479
  'commonCurrencies': {},
317
480
  'exceptions': {
318
481
  'exact': {
319
- '-1000': ExchangeError, # {"code": -1000, "message": "An unknown error occurred while processing the request"}
482
+ '-1000': OperationFailed, # {"code": -1000, "message": "An unknown error occurred while processing the request"} or {"success":false,"code":"-1000","message":"An internal error has occurred. We are unable to process your request. Please try again later."}
320
483
  '-1001': AuthenticationError, # {"code": -1001, "message": "The api key or secret is in wrong format"}
321
484
  '-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
485
  '-1003': RateLimitExceeded, # {"code": -1003, "message": "Rate limit exceed."}
@@ -348,19 +511,22 @@ class woo(Exchange, ImplicitAPI):
348
511
  async def fetch_status(self, params={}):
349
512
  """
350
513
  the latest known information on the availability of the exchange API
351
- :see: https://docs.woo.org/#get-system-maintenance-status-public
514
+
515
+ https://developer.woox.io/api-reference/endpoint/public_data/systemInfo
516
+
352
517
  :param dict [params]: extra parameters specific to the exchange API endpoint
353
518
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
354
519
  """
355
- response = await self.v1PublicGetSystemInfo(params)
520
+ response = await self.v3PublicGetSystemInfo(params)
356
521
  #
357
522
  # {
358
523
  # "success": True,
359
524
  # "data": {
360
- # "status": "0",
361
- # "msg": "System is functioning properly."
525
+ # "status": 0,
526
+ # "msg": "System is functioning properly.",
527
+ # "estimatedEndTime": 1749963600362
362
528
  # },
363
- # "timestamp": "1709274106602"
529
+ # "timestamp": 1751442989564
364
530
  # }
365
531
  #
366
532
  data = self.safe_dict(response, 'data', {})
@@ -379,22 +545,25 @@ class woo(Exchange, ImplicitAPI):
379
545
  'info': response,
380
546
  }
381
547
 
382
- async def fetch_time(self, params={}):
548
+ async def fetch_time(self, params={}) -> Int:
383
549
  """
384
550
  fetches the current integer timestamp in milliseconds from the exchange server
385
- :see: https://docs.woo.org/#get-system-maintenance-status-public
551
+
552
+ https://developer.woox.io/api-reference/endpoint/public_data/systemInfo
553
+
386
554
  :param dict [params]: extra parameters specific to the exchange API endpoint
387
555
  :returns int: the current integer timestamp in milliseconds from the exchange server
388
556
  """
389
- response = await self.v1PublicGetSystemInfo(params)
557
+ response = await self.v3PublicGetSystemInfo(params)
390
558
  #
391
559
  # {
392
560
  # "success": True,
393
561
  # "data": {
394
- # "status": "0",
395
- # "msg": "System is functioning properly."
562
+ # "status": 0,
563
+ # "msg": "System is functioning properly.",
564
+ # "estimatedEndTime": 1749963600362
396
565
  # },
397
- # "timestamp": "1709274106602"
566
+ # "timestamp": 1751442989564
398
567
  # }
399
568
  #
400
569
  return self.safe_integer(response, 'timestamp')
@@ -402,34 +571,50 @@ class woo(Exchange, ImplicitAPI):
402
571
  async def fetch_markets(self, params={}) -> List[Market]:
403
572
  """
404
573
  retrieves data on all markets for woo
405
- :see: https://docs.woo.org/#exchange-information
574
+
575
+ https://developer.woox.io/api-reference/endpoint/public_data/instruments
576
+
406
577
  :param dict [params]: extra parameters specific to the exchange API endpoint
407
578
  :returns dict[]: an array of objects representing market data
408
579
  """
409
- response = await self.v1PublicGetInfo(params)
580
+ if self.options['adjustForTimeDifference']:
581
+ await self.load_time_difference()
582
+ response = await self.v3PublicGetInstruments(params)
410
583
  #
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
584
+ # {
585
+ # "success": True,
586
+ # "data": {
587
+ # "rows": [
588
+ # {
589
+ # "symbol": "SPOT_AAVE_USDT",
590
+ # "status": "TRADING",
591
+ # "baseAsset": "AAVE",
592
+ # "baseAssetMultiplier": 1,
593
+ # "quoteAsset": "USDT",
594
+ # "quoteMin": "0",
595
+ # "quoteMax": "100000",
596
+ # "quoteTick": "0.01",
597
+ # "baseMin": "0.005",
598
+ # "baseMax": "5000",
599
+ # "baseTick": "0.0001",
600
+ # "minNotional": "1",
601
+ # "bidCapRatio": "1.1",
602
+ # "bidFloorRatio": null,
603
+ # "askCapRatio": null,
604
+ # "askFloorRatio": "0.9",
605
+ # "orderMode": "NORMAL",
606
+ # "impactNotional": null,
607
+ # "isAllowedRpi": False,
608
+ # "tickGranularity": null
609
+ # }
610
+ # ]
426
611
  # },
427
- # ...
428
- # "success": True
429
- # }
612
+ # "timestamp": 1751512951338
613
+ # }
430
614
  #
431
- data = self.safe_list(response, 'rows', [])
432
- return self.parse_markets(data)
615
+ data = self.safe_dict(response, 'data', {})
616
+ rows = self.safe_list(data, 'rows', [])
617
+ return self.parse_markets(rows)
433
618
 
434
619
  def parse_market(self, market: dict) -> Market:
435
620
  marketId = self.safe_string(market, 'symbol')
@@ -453,6 +638,7 @@ class woo(Exchange, ImplicitAPI):
453
638
  symbol = base + '/' + quote
454
639
  contractSize: Num = None
455
640
  linear: Bool = None
641
+ inverse: Bool = None
456
642
  margin = True
457
643
  contract = swap
458
644
  if contract:
@@ -462,6 +648,8 @@ class woo(Exchange, ImplicitAPI):
462
648
  symbol = base + '/' + quote + ':' + settle
463
649
  contractSize = self.parse_number('1')
464
650
  linear = True
651
+ inverse = False
652
+ active = self.safe_string(market, 'status') == 'TRADING'
465
653
  return {
466
654
  'id': marketId,
467
655
  'symbol': symbol,
@@ -477,18 +665,18 @@ class woo(Exchange, ImplicitAPI):
477
665
  'swap': swap,
478
666
  'future': False,
479
667
  'option': False,
480
- 'active': None,
668
+ 'active': active,
481
669
  'contract': contract,
482
670
  'linear': linear,
483
- 'inverse': None,
671
+ 'inverse': inverse,
484
672
  'contractSize': contractSize,
485
673
  'expiry': None,
486
674
  'expiryDatetime': None,
487
675
  'strike': None,
488
676
  'optionType': None,
489
677
  'precision': {
490
- 'amount': self.safe_number(market, 'base_tick'),
491
- 'price': self.safe_number(market, 'quote_tick'),
678
+ 'amount': self.safe_number(market, 'baseTick'),
679
+ 'price': self.safe_number(market, 'quoteTick'),
492
680
  },
493
681
  'limits': {
494
682
  'leverage': {
@@ -496,26 +684,28 @@ class woo(Exchange, ImplicitAPI):
496
684
  'max': None,
497
685
  },
498
686
  'amount': {
499
- 'min': self.safe_number(market, 'base_min'),
500
- 'max': self.safe_number(market, 'base_max'),
687
+ 'min': self.safe_number(market, 'baseMin'),
688
+ 'max': self.safe_number(market, 'baseMax'),
501
689
  },
502
690
  'price': {
503
- 'min': self.safe_number(market, 'quote_min'),
504
- 'max': self.safe_number(market, 'quote_max'),
691
+ 'min': self.safe_number(market, 'quoteMin'),
692
+ 'max': self.safe_number(market, 'quoteMax'),
505
693
  },
506
694
  'cost': {
507
- 'min': self.safe_number(market, 'min_notional'),
695
+ 'min': self.safe_number(market, 'minNotional'),
508
696
  'max': None,
509
697
  },
510
698
  },
511
- 'created': self.safe_timestamp(market, 'created_time'),
699
+ 'created': None,
512
700
  'info': market,
513
701
  }
514
702
 
515
703
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
516
704
  """
517
705
  get the list of most recent trades for a particular symbol
518
- :see: https://docs.woo.org/#market-trades-public
706
+
707
+ https://developer.woox.io/api-reference/endpoint/public_data/marketTrades
708
+
519
709
  :param str symbol: unified symbol of the market to fetch trades for
520
710
  :param int [since]: timestamp in ms of the earliest trade to fetch
521
711
  :param int [limit]: the maximum amount of trades to fetch
@@ -529,38 +719,28 @@ class woo(Exchange, ImplicitAPI):
529
719
  }
530
720
  if limit is not None:
531
721
  request['limit'] = limit
532
- response = await self.v1PublicGetMarketTrades(self.extend(request, params))
722
+ response = await self.v3PublicGetMarketTrades(self.extend(request, params))
533
723
  #
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"
724
+ # {
725
+ # "success": True,
726
+ # "data": {
727
+ # "rows": [
728
+ # {
729
+ # "symbol": "SPOT_BTC_USDT",
730
+ # "side": "SELL",
731
+ # "source": 0,
732
+ # "executedPrice": "108741.01",
733
+ # "executedQuantity": "0.02477",
734
+ # "executedTimestamp": 1751513940144
735
+ # }
736
+ # ]
557
737
  # },
558
- # ...
559
- # ]
560
- # }
738
+ # "timestamp": 1751513988543
739
+ # }
561
740
  #
562
- resultResponse = self.safe_list(response, 'rows', [])
563
- return self.parse_trades(resultResponse, market, since, limit)
741
+ data = self.safe_dict(response, 'data', {})
742
+ rows = self.safe_list(data, 'rows', [])
743
+ return self.parse_trades(rows, market, since, limit)
564
744
 
565
745
  def parse_trade(self, trade: dict, market: Market = None) -> Trade:
566
746
  #
@@ -569,42 +749,53 @@ class woo(Exchange, ImplicitAPI):
569
749
  # {
570
750
  # "symbol": "SPOT_BTC_USDT",
571
751
  # "side": "SELL",
572
- # "executed_price": 46222.35,
573
- # "executed_quantity": 0.0012,
574
- # "executed_timestamp": "1641241162.329"
752
+ # "source": 0,
753
+ # "executedPrice": "108741.01",
754
+ # "executedQuantity": "0.02477",
755
+ # "executedTimestamp": 1751513940144
575
756
  # }
576
757
  #
577
758
  # fetchOrderTrades, fetchOrder
578
759
  #
579
760
  # {
580
- # "id": "99119876",
581
- # "symbol": "SPOT_WOO_USDT",
582
- # "fee": "0.0024",
761
+ # "id": 1734947821,
762
+ # "symbol": "SPOT_LTC_USDT",
763
+ # "orderId": 60780383217,
764
+ # "executedPrice": 87.86,
765
+ # "executedQuantity": 0.1,
766
+ # "fee": 0.0001,
767
+ # "realizedPnl": null,
768
+ # "feeAsset": "LTC",
769
+ # "orderTag": "default",
583
770
  # "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"
771
+ # "executedTimestamp": "1752055173.630",
772
+ # "isMaker": 0
591
773
  # }
592
774
  #
593
775
  isFromFetchOrder = ('id' in trade)
594
- timestamp = self.safe_timestamp(trade, 'executed_timestamp')
776
+ timestampString = self.safe_string_2(trade, 'executed_timestamp', 'executedTimestamp')
777
+ timestamp = None
778
+ if timestampString is not None:
779
+ if timestampString.find('.') > -1:
780
+ timestamp = self.safe_timestamp_2(trade, 'executed_timestamp', 'executedTimestamp')
781
+ else:
782
+ timestamp = self.safe_integer(trade, 'executedTimestamp')
595
783
  marketId = self.safe_string(trade, 'symbol')
596
784
  market = self.safe_market(marketId, market)
597
785
  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')
786
+ price = self.safe_string_2(trade, 'executed_price', 'executedPrice')
787
+ amount = self.safe_string_2(trade, 'executed_quantity', 'executedQuantity')
788
+ order_id = self.safe_string_2(trade, 'order_id', 'orderId')
789
+ fee = self.parse_token_and_fee_temp(trade, ['fee_asset', 'feeAsset'], ['fee'])
790
+ feeCost = self.safe_string(fee, 'cost')
791
+ if feeCost is not None:
792
+ fee['cost'] = feeCost
602
793
  cost = Precise.string_mul(price, amount)
603
794
  side = self.safe_string_lower(trade, 'side')
604
795
  id = self.safe_string(trade, 'id')
605
796
  takerOrMaker: Str = None
606
797
  if isFromFetchOrder:
607
- isMaker = self.safe_string(trade, 'is_maker') == '1'
798
+ isMaker = self.safe_string_2(trade, 'is_maker', 'isMaker') == '1'
608
799
  takerOrMaker = 'maker' if isMaker else 'taker'
609
800
  return self.safe_trade({
610
801
  'id': id,
@@ -622,11 +813,11 @@ class woo(Exchange, ImplicitAPI):
622
813
  'info': trade,
623
814
  }, market)
624
815
 
625
- def parse_token_and_fee_temp(self, item, feeTokenKey, feeAmountKey):
626
- feeCost = self.safe_string(item, feeAmountKey)
816
+ def parse_token_and_fee_temp(self, item, feeTokenKeys, feeAmountKeys):
817
+ feeCost = self.safe_string_n(item, feeAmountKeys)
627
818
  fee = None
628
819
  if feeCost is not None:
629
- feeCurrencyId = self.safe_string(item, feeTokenKey)
820
+ feeCurrencyId = self.safe_string_n(item, feeTokenKeys)
630
821
  feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
631
822
  fee = {
632
823
  'cost': feeCost,
@@ -634,41 +825,90 @@ class woo(Exchange, ImplicitAPI):
634
825
  }
635
826
  return fee
636
827
 
828
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
829
+ marketId = self.safe_string(fee, 'symbol')
830
+ symbol = self.safe_symbol(marketId, market)
831
+ return {
832
+ 'info': fee,
833
+ 'symbol': symbol,
834
+ 'maker': self.parse_number(Precise.string_div(self.safe_string(fee, 'makerFee'), '100')),
835
+ 'taker': self.parse_number(Precise.string_div(self.safe_string(fee, 'takerFee'), '100')),
836
+ 'percentage': None,
837
+ 'tierBased': None,
838
+ }
839
+
840
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
841
+ """
842
+ fetch the trading fees for a market
843
+
844
+ https://developer.woox.io/api-reference/endpoint/trading/get_tradingFee
845
+
846
+ :param str symbol: unified market symbol
847
+ :param dict [params]: extra parameters specific to the exchange API endpoint
848
+ :param boolean [params.portfolioMargin]: set to True if you would like to fetch trading fees in a portfolio margin account
849
+ :param str [params.subType]: "linear" or "inverse"
850
+ :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
851
+ """
852
+ await self.load_markets()
853
+ market = self.market(symbol)
854
+ request: dict = {
855
+ 'symbol': market['id'],
856
+ }
857
+ response = await self.v3PrivateGetTradeTradingFee(self.extend(request, params))
858
+ #
859
+ # {
860
+ # "success": True,
861
+ # "data": {
862
+ # "symbol": "SPOT_BTC_USDT",
863
+ # "takerFee": "10",
864
+ # "makerFee": "8"
865
+ # },
866
+ # "timestamp": 1751858977368
867
+ # }
868
+ #
869
+ data = self.safe_dict(response, 'data', {})
870
+ return self.parse_trading_fee(data, market)
871
+
637
872
  async def fetch_trading_fees(self, params={}) -> TradingFees:
638
873
  """
639
874
  fetch the trading fees for multiple markets
640
- :see: https://docs.woo.org/#get-account-information-new
875
+
876
+ https://developer.woox.io/api-reference/endpoint/account/get_account_info
877
+
641
878
  :param dict [params]: extra parameters specific to the exchange API endpoint
642
879
  :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
643
880
  """
644
881
  await self.load_markets()
645
- response = await self.v3PrivateGetAccountinfo(params)
882
+ response = await self.v3PrivateGetAccountInfo(params)
646
883
  #
647
884
  # {
648
885
  # "success": True,
649
886
  # "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,
887
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
888
+ # "account": "carlos_jose_lima@yahoo.com",
889
+ # "alias": "carlos_jose_lima@yahoo.com",
660
890
  # "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
891
+ # "accountMode": "FUTURES",
892
+ # "positionMode": "ONE_WAY",
893
+ # "leverage": 0,
894
+ # "makerFeeRate": 0,
895
+ # "takerFeeRate": 0,
896
+ # "marginRatio": "10",
897
+ # "openMarginRatio": "10",
898
+ # "initialMarginRatio": "10",
899
+ # "maintenanceMarginRatio": "0.03",
900
+ # "totalCollateral": "165.55629469",
901
+ # "freeCollateral": "165.55629469",
902
+ # "totalAccountValue": "167.32418611",
903
+ # "totalTradingValue": "167.32418611",
904
+ # "totalVaultValue": "0",
905
+ # "totalStakingValue": "0",
906
+ # "totalLaunchpadValue": "0",
907
+ # "totalEarnValue": "0",
908
+ # "referrerID": null,
909
+ # "accountType": "Main"
670
910
  # },
671
- # "timestamp": 1673323685109
911
+ # "timestamp": 1752062807915
672
912
  # }
673
913
  #
674
914
  data = self.safe_dict(response, 'data', {})
@@ -690,38 +930,52 @@ class woo(Exchange, ImplicitAPI):
690
930
  async def fetch_currencies(self, params={}) -> Currencies:
691
931
  """
692
932
  fetches all available currencies on an exchange
693
- :see: https://docs.woo.org/#available-token-public
933
+
934
+ https://docs.woox.io/#available-token-public
935
+
694
936
  :param dict [params]: extra parameters specific to the exchange API endpoint
695
937
  :returns dict: an associative dictionary of currencies
696
938
  """
697
939
  result: dict = {}
698
- tokenResponse = await self.v1PublicGetToken(params)
940
+ tokenResponsePromise = self.v1PublicGetToken(params)
699
941
  #
700
- # {
701
- # "rows": [
942
+ # {
943
+ # "rows": [
702
944
  # {
703
945
  # "token": "ETH_USDT",
704
946
  # "fullname": "Tether",
705
- # "decimals": 6,
947
+ # "network": "ETH",
948
+ # "decimals": "6",
949
+ # "delisted": False,
706
950
  # "balance_token": "USDT",
707
- # "created_time": "0",
708
- # "updated_time": "0"
951
+ # "created_time": "1710123398",
952
+ # "updated_time": "1746528481",
953
+ # "can_collateral": True,
954
+ # "can_short": True
709
955
  # },
710
956
  # {
711
957
  # "token": "BSC_USDT",
712
958
  # "fullname": "Tether",
713
- # "decimals": 18,
959
+ # "network": "BSC",
960
+ # "decimals": "18",
961
+ # "delisted": False,
714
962
  # "balance_token": "USDT",
715
- # "created_time": "0",
716
- # "updated_time": "0"
963
+ # "created_time": "1710123395",
964
+ # "updated_time": "1746528601",
965
+ # "can_collateral": True,
966
+ # "can_short": True
717
967
  # },
718
968
  # {
719
- # "token": "ZEC",
720
- # "fullname": "ZCash",
721
- # "decimals": 8,
722
- # "balance_token": "ZEC",
723
- # "created_time": "0",
724
- # "updated_time": "0"
969
+ # "token": "ALGO",
970
+ # "fullname": "Algorand",
971
+ # "network": "ALGO",
972
+ # "decimals": "6",
973
+ # "delisted": False,
974
+ # "balance_token": "ALGO",
975
+ # "created_time": "1710123394",
976
+ # "updated_time": "1723087518",
977
+ # "can_collateral": True,
978
+ # "can_short": True
725
979
  # },
726
980
  # ...
727
981
  # ],
@@ -729,58 +983,66 @@ class woo(Exchange, ImplicitAPI):
729
983
  # }
730
984
  #
731
985
  # only make one request for currrencies...
732
- # tokenNetworkResponse = await self.v1PublicGetTokenNetwork(params)
986
+ tokenNetworkResponsePromise = self.v1PublicGetTokenNetwork(params)
733
987
  #
734
988
  # {
735
989
  # "rows": [
736
990
  # {
737
991
  # "protocol": "ERC20",
992
+ # "network": "ETH",
738
993
  # "token": "USDT",
739
- # "name": "Ethereum",
740
- # "minimum_withdrawal": 30,
741
- # "withdrawal_fee": 25,
742
- # "allow_deposit": 1,
743
- # "allow_withdraw": 1
994
+ # "name": "Ethereum(ERC20)",
995
+ # "minimum_withdrawal": "10.00000000",
996
+ # "withdrawal_fee": "2.00000000",
997
+ # "allow_deposit": "1",
998
+ # "allow_withdraw": "1"
744
999
  # },
745
1000
  # {
746
1001
  # "protocol": "TRC20",
1002
+ # "network": "TRX",
747
1003
  # "token": "USDT",
748
- # "name": "Tron",
749
- # "minimum_withdrawal": 30,
750
- # "withdrawal_fee": 1,
751
- # "allow_deposit": 1,
752
- # "allow_withdraw": 1
1004
+ # "name": "Tron(TRC20)",
1005
+ # "minimum_withdrawal": "10.00000000",
1006
+ # "withdrawal_fee": "4.50000000",
1007
+ # "allow_deposit": "1",
1008
+ # "allow_withdraw": "1"
753
1009
  # },
754
1010
  # ...
755
1011
  # ],
756
1012
  # "success": True
757
1013
  # }
758
1014
  #
1015
+ tokenResponse, tokenNetworkResponse = await asyncio.gather(*[tokenResponsePromise, tokenNetworkResponsePromise])
759
1016
  tokenRows = self.safe_list(tokenResponse, 'rows', [])
760
- networksByCurrencyId = self.group_by(tokenRows, 'balance_token')
761
- currencyIds = list(networksByCurrencyId.keys())
1017
+ tokenNetworkRows = self.safe_list(tokenNetworkResponse, 'rows', [])
1018
+ networksById = self.group_by(tokenNetworkRows, 'token')
1019
+ tokensById = self.group_by(tokenRows, 'balance_token')
1020
+ currencyIds = list(tokensById.keys())
762
1021
  for i in range(0, len(currencyIds)):
763
1022
  currencyId = currencyIds[i]
764
- networks = networksByCurrencyId[currencyId]
765
1023
  code = self.safe_currency_code(currencyId)
766
- name: Str = None
767
- minPrecision = None
1024
+ tokensByNetworkId = self.index_by(tokensById[currencyId], 'network')
1025
+ chainsByNetworkId = self.index_by(networksById[currencyId], 'network')
1026
+ keys = list(chainsByNetworkId.keys())
768
1027
  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] = {
1028
+ for j in range(0, len(keys)):
1029
+ networkId = keys[j]
1030
+ tokenEntry = self.safe_dict(tokensByNetworkId, networkId, {})
1031
+ networkEntry = self.safe_dict(chainsByNetworkId, networkId, {})
1032
+ networkCode = self.network_id_to_code(networkId, code)
1033
+ specialNetworkId = self.safe_string(tokenEntry, 'token')
1034
+ resultingNetworks[networkCode] = {
779
1035
  'id': networkId,
780
- 'network': unifiedNetwork,
1036
+ 'currencyNetworkId': specialNetworkId, # exchange uses special crrency-ids(coin + network junction)
1037
+ 'network': networkCode,
1038
+ 'active': None,
1039
+ 'deposit': self.safe_string(networkEntry, 'allow_deposit') == '1',
1040
+ 'withdraw': self.safe_string(networkEntry, 'allow_withdraw') == '1',
1041
+ 'fee': self.safe_number(networkEntry, 'withdrawal_fee'),
1042
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(tokenEntry, 'decimals'))),
781
1043
  'limits': {
782
1044
  'withdraw': {
783
- 'min': None,
1045
+ 'min': self.safe_number(networkEntry, 'minimum_withdrawal'),
784
1046
  'max': None,
785
1047
  },
786
1048
  'deposit': {
@@ -788,23 +1050,19 @@ class woo(Exchange, ImplicitAPI):
788
1050
  'max': None,
789
1051
  },
790
1052
  },
791
- 'active': None,
792
- 'deposit': None,
793
- 'withdraw': None,
794
- 'fee': None,
795
- 'precision': self.parse_number(precision),
796
- 'info': network,
1053
+ 'info': [networkEntry, tokenEntry],
797
1054
  }
798
- result[code] = {
1055
+ result[code] = self.safe_currency_structure({
799
1056
  'id': currencyId,
800
- 'name': name,
1057
+ 'name': None,
801
1058
  'code': code,
802
- 'precision': self.parse_number(minPrecision),
1059
+ 'precision': None,
803
1060
  'active': None,
804
1061
  'fee': None,
805
1062
  'networks': resultingNetworks,
806
1063
  'deposit': None,
807
1064
  'withdraw': None,
1065
+ 'type': 'crypto',
808
1066
  'limits': {
809
1067
  'deposit': {
810
1068
  'min': None,
@@ -815,14 +1073,16 @@ class woo(Exchange, ImplicitAPI):
815
1073
  'max': None,
816
1074
  },
817
1075
  },
818
- 'info': networks,
819
- }
1076
+ 'info': [tokensByNetworkId, chainsByNetworkId],
1077
+ })
820
1078
  return result
821
1079
 
822
1080
  async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
823
1081
  """
824
1082
  create a market buy order by providing the symbol and cost
825
- :see: https://docs.woo.org/#send-order
1083
+
1084
+ https://docs.woox.io/#send-order
1085
+
826
1086
  :param str symbol: unified symbol of the market to create an order in
827
1087
  :param float cost: how much you want to trade in units of the quote currency
828
1088
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -832,13 +1092,31 @@ class woo(Exchange, ImplicitAPI):
832
1092
  market = self.market(symbol)
833
1093
  if not market['spot']:
834
1094
  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)
1095
+ return await self.create_order(symbol, 'market', 'buy', cost, 1, params)
1096
+
1097
+ async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
1098
+ """
1099
+ create a market sell order by providing the symbol and cost
1100
+
1101
+ https://docs.woox.io/#send-order
1102
+
1103
+ :param str symbol: unified symbol of the market to create an order in
1104
+ :param float cost: how much you want to trade in units of the quote currency
1105
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1106
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1107
+ """
1108
+ await self.load_markets()
1109
+ market = self.market(symbol)
1110
+ if not market['spot']:
1111
+ raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot orders only')
1112
+ return await self.create_order(symbol, 'market', 'sell', cost, 1, params)
837
1113
 
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:
1114
+ async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount: Num = None, trailingTriggerPrice: Num = None, params={}) -> Order:
839
1115
  """
840
1116
  create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
841
- :see: https://docs.woo.org/#send-algo-order
1117
+
1118
+ https://docs.woox.io/#send-algo-order
1119
+
842
1120
  :param str symbol: unified symbol of the market to create an order in
843
1121
  :param str type: 'market' or 'limit'
844
1122
  :param str side: 'buy' or 'sell'
@@ -857,10 +1135,12 @@ class woo(Exchange, ImplicitAPI):
857
1135
  params['trailingTriggerPrice'] = trailingTriggerPrice
858
1136
  return await self.create_order(symbol, type, side, amount, price, params)
859
1137
 
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:
1138
+ async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent: Num = None, trailingTriggerPrice: Num = None, params={}) -> Order:
861
1139
  """
862
1140
  create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
863
- :see: https://docs.woo.org/#send-algo-order
1141
+
1142
+ https://docs.woox.io/#send-algo-order
1143
+
864
1144
  :param str symbol: unified symbol of the market to create an order in
865
1145
  :param str type: 'market' or 'limit'
866
1146
  :param str side: 'buy' or 'sell'
@@ -882,24 +1162,28 @@ class woo(Exchange, ImplicitAPI):
882
1162
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
883
1163
  """
884
1164
  create a trade order
885
- :see: https://docs.woo.org/#send-order
886
- :see: https://docs.woo.org/#send-algo-order
1165
+
1166
+ https://developer.woox.io/api-reference/endpoint/trading/post_order
1167
+ https://developer.woox.io/api-reference/endpoint/trading/post_algo_order
1168
+
887
1169
  :param str symbol: unified symbol of the market to create an order in
888
1170
  :param str type: 'market' or 'limit'
889
1171
  :param str side: 'buy' or 'sell'
890
1172
  :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
1173
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
892
1174
  :param dict [params]: extra parameters specific to the exchange API endpoint
1175
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated', default 'cross'
893
1176
  :param float [params.triggerPrice]: The price a trigger order is triggered at
894
1177
  :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
1178
  :param float [params.takeProfit.triggerPrice]: take profit trigger price
896
1179
  :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
1180
  :param float [params.stopLoss.triggerPrice]: stop loss trigger price
898
- :param float [params.algoType]: 'STOP'or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
1181
+ :param float [params.algoType]: 'STOP' or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
899
1182
  :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
900
1183
  :param str [params.trailingAmount]: the quote amount to trail away from the current market price
901
1184
  :param str [params.trailingPercent]: the percent to trail away from the current market price
902
1185
  :param str [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
1186
+ :param str [params.position_side]: 'SHORT' or 'LONG' - if position mode is HEDGE_MODE and the trading involves futures, then is required, otherwise self parameter is not required
903
1187
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
904
1188
  """
905
1189
  reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
@@ -912,7 +1196,11 @@ class woo(Exchange, ImplicitAPI):
912
1196
  'symbol': market['id'],
913
1197
  'side': orderSide,
914
1198
  }
915
- stopPrice = self.safe_number_2(params, 'triggerPrice', 'stopPrice')
1199
+ marginMode: Str = None
1200
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
1201
+ if marginMode is not None:
1202
+ request['marginMode'] = self.encode_margin_mode(marginMode)
1203
+ triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
916
1204
  stopLoss = self.safe_value(params, 'stopLoss')
917
1205
  takeProfit = self.safe_value(params, 'takeProfit')
918
1206
  algoType = self.safe_string(params, 'algoType')
@@ -922,52 +1210,42 @@ class woo(Exchange, ImplicitAPI):
922
1210
  isTrailingAmountOrder = trailingAmount is not None
923
1211
  isTrailingPercentOrder = trailingPercent is not None
924
1212
  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)
1213
+ isConditional = isTrailing or triggerPrice is not None or stopLoss is not None or takeProfit is not None or (self.safe_value(params, 'childOrders') is not None)
926
1214
  isMarket = orderType == 'MARKET'
927
1215
  timeInForce = self.safe_string_lower(params, 'timeInForce')
928
1216
  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:
1217
+ clientOrderIdKey = 'clientAlgoOrderId' if isConditional else 'clientOrderId'
1218
+ request['type'] = orderType # LIMIT/MARKET/IOC/FOK/POST_ONLY/ASK/BID
1219
+ if not isConditional:
936
1220
  if postOnly:
937
- request['order_type'] = 'POST_ONLY'
1221
+ request['type'] = 'POST_ONLY'
938
1222
  elif timeInForce == 'fok':
939
- request['order_type'] = 'FOK'
1223
+ request['type'] = 'FOK'
940
1224
  elif timeInForce == 'ioc':
941
- request['order_type'] = 'IOC'
1225
+ request['type'] = 'IOC'
942
1226
  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:
1227
+ request['reduceOnly'] = reduceOnly
1228
+ if not isMarket and price is not None:
1229
+ request['price'] = self.price_to_precision(symbol, price)
1230
+ if isMarket and not isConditional:
947
1231
  # for market buy it requires the amount of quote currency to spend
948
- if market['spot'] and orderSide == 'BUY':
1232
+ cost = self.safe_string_n(params, ['cost', 'order_amount', 'orderAmount'])
1233
+ params = self.omit(params, ['cost', 'order_amount', 'orderAmount'])
1234
+ isPriceProvided = price is not None
1235
+ if market['spot'] and (isPriceProvided or (cost is not None)):
949
1236
  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
1237
  if cost is not None:
955
1238
  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
1239
  else:
965
- quoteAmount = self.cost_to_precision(symbol, amount)
966
- request['order_amount'] = quoteAmount
1240
+ amountString = self.number_to_string(amount)
1241
+ priceString = self.number_to_string(price)
1242
+ costRequest = Precise.string_mul(amountString, priceString)
1243
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1244
+ request['amount'] = quoteAmount
967
1245
  else:
968
- request['order_quantity'] = self.amount_to_precision(symbol, amount)
1246
+ request['quantity'] = self.amount_to_precision(symbol, amount)
969
1247
  elif algoType != 'POSITIONAL_TP_SL':
970
- request[orderQtyKey] = self.amount_to_precision(symbol, amount)
1248
+ request['quantity'] = self.amount_to_precision(symbol, amount)
971
1249
  clientOrderId = self.safe_string_n(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
972
1250
  if clientOrderId is not None:
973
1251
  request[clientOrderIdKey] = clientOrderId
@@ -981,9 +1259,9 @@ class woo(Exchange, ImplicitAPI):
981
1259
  elif isTrailingPercentOrder:
982
1260
  convertedTrailingPercent = Precise.string_div(trailingPercent, '100')
983
1261
  request['callbackRate'] = convertedTrailingPercent
984
- elif stopPrice is not None:
1262
+ elif triggerPrice is not None:
985
1263
  if algoType != 'TRAILING_STOP':
986
- request['triggerPrice'] = self.price_to_precision(symbol, stopPrice)
1264
+ request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
987
1265
  request['algoType'] = 'STOP'
988
1266
  elif (stopLoss is not None) or (takeProfit is not None):
989
1267
  request['algoType'] = 'BRACKET'
@@ -993,9 +1271,10 @@ class woo(Exchange, ImplicitAPI):
993
1271
  'algoType': 'POSITIONAL_TP_SL',
994
1272
  'childOrders': [],
995
1273
  }
1274
+ childOrders = outterOrder['childOrders']
996
1275
  closeSide = 'SELL' if (orderSide == 'BUY') else 'BUY'
997
1276
  if stopLoss is not None:
998
- stopLossPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'price', stopLoss)
1277
+ stopLossPrice = self.safe_string(stopLoss, 'triggerPrice', stopLoss)
999
1278
  stopLossOrder: dict = {
1000
1279
  'side': closeSide,
1001
1280
  'algoType': 'STOP_LOSS',
@@ -1003,9 +1282,9 @@ class woo(Exchange, ImplicitAPI):
1003
1282
  'type': 'CLOSE_POSITION',
1004
1283
  'reduceOnly': True,
1005
1284
  }
1006
- outterOrder['childOrders'].append(stopLossOrder)
1285
+ childOrders.append(stopLossOrder)
1007
1286
  if takeProfit is not None:
1008
- takeProfitPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'price', takeProfit)
1287
+ takeProfitPrice = self.safe_string(takeProfit, 'triggerPrice', takeProfit)
1009
1288
  takeProfitOrder: dict = {
1010
1289
  'side': closeSide,
1011
1290
  'algoType': 'TAKE_PROFIT',
@@ -1013,60 +1292,72 @@ class woo(Exchange, ImplicitAPI):
1013
1292
  'type': 'CLOSE_POSITION',
1014
1293
  'reduceOnly': True,
1015
1294
  }
1016
- outterOrder['childOrders'].append(takeProfitOrder)
1295
+ childOrders.append(takeProfitOrder)
1017
1296
  request['childOrders'] = [outterOrder]
1018
1297
  params = self.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingPercent', 'trailingAmount', 'trailingTriggerPrice'])
1019
1298
  response = None
1020
- if isStop:
1021
- response = await self.v3PrivatePostAlgoOrder(self.extend(request, params))
1299
+ if isConditional:
1300
+ response = await self.v3PrivatePostTradeAlgoOrder(self.extend(request, params))
1301
+ #
1302
+ # {
1303
+ # "success": True,
1304
+ # "data": {
1305
+ # "rows": [
1306
+ # {
1307
+ # "orderId": "1578938",
1308
+ # "clientOrderId": "0",
1309
+ # "algoType": "STOP_LOSS",
1310
+ # "quantity": "0.1"
1311
+ # }
1312
+ # ]
1313
+ # },
1314
+ # "timestamp": "1686149372216"
1315
+ # }
1316
+ #
1022
1317
  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
1318
+ response = await self.v3PrivatePostTradeOrder(self.extend(request, params))
1319
+ #
1320
+ # {
1321
+ # "success": True,
1322
+ # "data": {
1323
+ # "orderId": 60667653330,
1324
+ # "clientOrderId": 0,
1325
+ # "type": "LIMIT",
1326
+ # "price": 60,
1327
+ # "quantity": 0.1,
1328
+ # "amount": null,
1329
+ # "bidAskLevel": null
1330
+ # },
1331
+ # "timestamp": 1751871779855
1332
+ # }
1333
+ #
1334
+ data = self.safe_dict(response, 'data', {})
1335
+ data = self.safe_dict(self.safe_list(data, 'rows'), 0, data)
1336
+ data['timestamp'] = self.safe_string(response, 'timestamp')
1337
+ return self.parse_order(data, market)
1338
+
1339
+ def encode_margin_mode(self, mode):
1340
+ modes = {
1341
+ 'cross': 'CROSS',
1342
+ 'isolated': 'ISOLATED',
1343
+ }
1344
+ return self.safe_string(modes, mode, mode)
1056
1345
 
1057
1346
  async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1058
1347
  """
1059
1348
  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
1349
+
1350
+ https://docs.woox.io/#edit-order
1351
+ https://docs.woox.io/#edit-order-by-client_order_id
1352
+ https://docs.woox.io/#edit-algo-order
1353
+ https://docs.woox.io/#edit-algo-order-by-client_order_id
1354
+
1064
1355
  :param str id: order id
1065
1356
  :param str symbol: unified symbol of the market to create an order in
1066
1357
  :param str type: 'market' or 'limit'
1067
1358
  :param str side: 'buy' or 'sell'
1068
1359
  :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
1360
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1070
1361
  :param dict [params]: extra parameters specific to the exchange API endpoint
1071
1362
  :param float [params.triggerPrice]: The price a trigger order is triggered at
1072
1363
  :param float [params.stopLossPrice]: price to trigger stop-loss orders
@@ -1089,9 +1380,9 @@ class woo(Exchange, ImplicitAPI):
1089
1380
  clientOrderIdUnified = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1090
1381
  clientOrderIdExchangeSpecific = self.safe_string(params, 'client_order_id', clientOrderIdUnified)
1091
1382
  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)
1383
+ triggerPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'takeProfitPrice', 'stopLossPrice'])
1384
+ if triggerPrice is not None:
1385
+ request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
1095
1386
  trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activatedPrice', self.number_to_string(price))
1096
1387
  trailingAmount = self.safe_string_2(params, 'trailingAmount', 'callbackValue')
1097
1388
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
@@ -1107,17 +1398,17 @@ class woo(Exchange, ImplicitAPI):
1107
1398
  convertedTrailingPercent = Precise.string_div(trailingPercent, '100')
1108
1399
  request['callbackRate'] = convertedTrailingPercent
1109
1400
  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)
1401
+ isConditional = isTrailing or (triggerPrice is not None) or (self.safe_value(params, 'childOrders') is not None)
1111
1402
  response = None
1112
1403
  if isByClientOrder:
1113
1404
  request['client_order_id'] = clientOrderIdExchangeSpecific
1114
- if isStop:
1405
+ if isConditional:
1115
1406
  response = await self.v3PrivatePutAlgoOrderClientClientOrderId(self.extend(request, params))
1116
1407
  else:
1117
1408
  response = await self.v3PrivatePutOrderClientClientOrderId(self.extend(request, params))
1118
1409
  else:
1119
1410
  request['oid'] = id
1120
- if isStop:
1411
+ if isConditional:
1121
1412
  response = await self.v3PrivatePutAlgoOrderOid(self.extend(request, params))
1122
1413
  else:
1123
1414
  response = await self.v3PrivatePutOrderOid(self.extend(request, params))
@@ -1138,19 +1429,20 @@ class woo(Exchange, ImplicitAPI):
1138
1429
 
1139
1430
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
1140
1431
  """
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
1432
+
1433
+ https://developer.woox.io/api-reference/endpoint/trading/cancel_order
1434
+ https://developer.woox.io/api-reference/endpoint/trading/cancel_algo_order
1435
+
1144
1436
  cancels an open order
1145
1437
  :param str id: order id
1146
1438
  :param str symbol: unified symbol of the market the order was made in
1147
1439
  :param dict [params]: extra parameters specific to the exchange API endpoint
1148
- :param boolean [params.stop]: whether the order is a stop/algo order
1440
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1149
1441
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1150
1442
  """
1151
- stop = self.safe_bool(params, 'stop', False)
1152
- params = self.omit(params, 'stop')
1153
- if not stop and (symbol is None):
1443
+ isTrigger = self.safe_bool_2(params, 'trigger', 'stop', False)
1444
+ params = self.omit(params, ['trigger', 'stop'])
1445
+ if not isTrigger and (symbol is None):
1154
1446
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
1155
1447
  await self.load_markets()
1156
1448
  market: Market = None
@@ -1159,167 +1451,219 @@ class woo(Exchange, ImplicitAPI):
1159
1451
  request: dict = {}
1160
1452
  clientOrderIdUnified = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1161
1453
  clientOrderIdExchangeSpecific = self.safe_string(params, 'client_order_id', clientOrderIdUnified)
1454
+ params = self.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
1162
1455
  isByClientOrder = clientOrderIdExchangeSpecific is not None
1163
1456
  response = None
1164
- if stop:
1165
- request['order_id'] = id
1166
- response = await self.v3PrivateDeleteAlgoOrderOrderId(self.extend(request, params))
1457
+ if isTrigger:
1458
+ if isByClientOrder:
1459
+ request['clientAlgoOrderId'] = clientOrderIdExchangeSpecific
1460
+ else:
1461
+ request['algoOrderId'] = id
1462
+ response = await self.v3PrivateDeleteTradeAlgoOrder(self.extend(request, params))
1167
1463
  else:
1168
1464
  request['symbol'] = market['id']
1169
1465
  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))
1466
+ request['clientOrderId'] = clientOrderIdExchangeSpecific
1173
1467
  else:
1174
- request['order_id'] = id
1175
- response = await self.v1PrivateDeleteOrder(self.extend(request, params))
1468
+ request['orderId'] = id
1469
+ response = await self.v3PrivateDeleteTradeOrder(self.extend(request, params))
1176
1470
  #
1177
- # {success: True, status: "CANCEL_SENT"}
1471
+ # {
1472
+ # "success": True,
1473
+ # "data": {
1474
+ # "status": "CANCEL_SENT"
1475
+ # },
1476
+ # "timestamp": 1751940315838
1477
+ # }
1178
1478
  #
1179
- extendParams: dict = {'symbol': symbol}
1479
+ data = self.safe_dict(response, 'data', {})
1480
+ data['timestamp'] = self.safe_string(response, 'timestamp')
1180
1481
  if isByClientOrder:
1181
- extendParams['client_order_id'] = clientOrderIdExchangeSpecific
1482
+ data['clientOrderId'] = clientOrderIdExchangeSpecific
1182
1483
  else:
1183
- extendParams['id'] = id
1184
- return self.extend(self.parse_order(response), extendParams)
1484
+ data['orderId'] = id
1485
+ return self.parse_order(data, market)
1185
1486
 
1186
1487
  async def cancel_all_orders(self, symbol: Str = None, params={}):
1187
1488
  """
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
1489
+
1490
+ https://developer.woox.io/api-reference/endpoint/trading/cancel_all_order
1491
+ https://developer.woox.io/api-reference/endpoint/trading/cancel_algo_orders
1492
+
1191
1493
  cancel all open orders in a market
1192
1494
  :param str symbol: unified market symbol
1193
1495
  :param dict [params]: extra parameters specific to the exchange API endpoint
1194
- :param boolean [params.stop]: whether the order is a stop/algo order
1496
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1195
1497
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1196
1498
  """
1197
1499
  await self.load_markets()
1198
- stop = self.safe_bool_2(params, 'stop', 'trigger')
1500
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
1199
1501
  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))
1502
+ request: dict = {}
1503
+ if symbol is not None:
1504
+ market = self.market(symbol)
1505
+ request['symbol'] = market['id']
1506
+ response = None
1507
+ if trigger:
1508
+ response = await self.v3PrivateDeleteTradeAlgoOrders(params)
1509
+ else:
1510
+ response = await self.v3PrivateDeleteTradeOrders(self.extend(request, params))
1209
1511
  #
1210
1512
  # {
1211
- # "success":true,
1212
- # "status":"CANCEL_ALL_SENT"
1513
+ # "success": True,
1514
+ # "data": {
1515
+ # "status": "CANCEL_ALL_SENT"
1516
+ # },
1517
+ # "timestamp": 1751941988134
1213
1518
  # }
1214
1519
  #
1215
- return [
1216
- self.safe_order(response),
1217
- ]
1520
+ data = self.safe_dict(response, 'data', {})
1521
+ return [self.safe_order({'info': data})]
1218
1522
 
1219
1523
  async def cancel_all_orders_after(self, timeout: Int, params={}):
1220
1524
  """
1221
1525
  dead man's switch, cancel all orders after the given timeout
1222
- :see: https://docs.woo.org/#cancel-all-after
1526
+
1527
+ https://developer.woox.io/api-reference/endpoint/trading/cancel_all_after
1528
+
1223
1529
  :param number timeout: time in milliseconds, 0 represents cancel the timer
1224
- :param boolean activated: countdown
1225
1530
  :param dict [params]: extra parameters specific to the exchange API endpoint
1226
1531
  :returns dict: the api result
1227
1532
  """
1228
1533
  await self.load_markets()
1229
1534
  request: dict = {
1230
- 'trigger_after': timeout if (timeout > 0) else 0,
1535
+ 'triggerAfter': min(timeout, 900000) if (timeout > 0) else 0,
1231
1536
  }
1232
- response = await self.v1PrivatePostOrderCancelAllAfter(self.extend(request, params))
1537
+ response = await self.v3PrivatePostTradeCancelAllAfter(self.extend(request, params))
1233
1538
  #
1234
- # {
1235
- # "success": True,
1236
- # "data": {
1237
- # "expected_trigger_time": 1711534302938
1238
- # },
1239
- # "timestamp": 1711534302943
1539
+ # {
1540
+ # "success": True,
1541
+ # "timestamp": 123,
1542
+ # "data": {
1543
+ # "expectedTriggerTime": 123
1240
1544
  # }
1545
+ # }
1241
1546
  #
1242
- return [
1243
- self.safe_order(response),
1244
- ]
1547
+ return response
1245
1548
 
1246
1549
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
1247
1550
  """
1248
- :see: https://docs.woo.org/#get-algo-order
1249
- :see: https://docs.woo.org/#get-order
1551
+
1552
+ https://developer.woox.io/api-reference/endpoint/trading/get_order
1553
+ https://developer.woox.io/api-reference/endpoint/trading/get_algo_order
1554
+
1250
1555
  fetches information on an order made by the user
1556
+ :param str id: the order id
1251
1557
  :param str symbol: unified symbol of the market the order was made in
1252
1558
  :param dict [params]: extra parameters specific to the exchange API endpoint
1253
- :param boolean [params.stop]: whether the order is a stop/algo order
1559
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1254
1560
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1255
1561
  """
1256
1562
  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')
1563
+ market = None
1564
+ if symbol is not None:
1565
+ market = self.market(symbol)
1566
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
1259
1567
  params = self.omit(params, ['stop', 'trigger'])
1260
1568
  request: dict = {}
1261
1569
  clientOrderId = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1262
1570
  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))
1571
+ if trigger:
1572
+ if clientOrderId is not None:
1573
+ request['clientAlgoOrderId'] = id
1574
+ else:
1575
+ request['algoOrderId'] = id
1576
+ response = await self.v3PrivateGetTradeAlgoOrder(self.extend(request, params))
1577
+ #
1578
+ # {
1579
+ # "success": True,
1580
+ # "data": {
1581
+ # "algoOrderId": 10399260,
1582
+ # "clientAlgoOrderId": 0,
1583
+ # "rootAlgoOrderId": 10399260,
1584
+ # "parentAlgoOrderId": 0,
1585
+ # "symbol": "SPOT_LTC_USDT",
1586
+ # "algoOrderTag": "default",
1587
+ # "algoType": "TAKE_PROFIT",
1588
+ # "side": "BUY",
1589
+ # "quantity": 0.1,
1590
+ # "isTriggered": False,
1591
+ # "triggerPrice": 65,
1592
+ # "triggerStatus": "USELESS",
1593
+ # "type": "LIMIT",
1594
+ # "rootAlgoStatus": "NEW",
1595
+ # "algoStatus": "NEW",
1596
+ # "triggerPriceType": "MARKET_PRICE",
1597
+ # "price": 60,
1598
+ # "triggerTime": "0",
1599
+ # "totalExecutedQuantity": 0,
1600
+ # "visibleQuantity": 0.1,
1601
+ # "averageExecutedPrice": 0,
1602
+ # "totalFee": 0,
1603
+ # "feeAsset": "",
1604
+ # "totalRebate": 0,
1605
+ # "rebateAsset": "",
1606
+ # "reduceOnly": False,
1607
+ # "createdTime": "1752049747.732",
1608
+ # "updatedTime": "1752049747.732",
1609
+ # "positionSide": "BOTH"
1610
+ # },
1611
+ # "timestamp": 1752049767550
1612
+ # }
1613
+ #
1269
1614
  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)
1615
+ if clientOrderId is not None:
1616
+ request['clientOrderId'] = clientOrderId
1617
+ else:
1618
+ request['orderId'] = id
1619
+ response = await self.v3PrivateGetTradeOrder(self.extend(request, params))
1620
+ #
1621
+ # {
1622
+ # "success": True,
1623
+ # "data": {
1624
+ # "orderId": 60780315704,
1625
+ # "clientOrderId": 0,
1626
+ # "symbol": "SPOT_LTC_USDT",
1627
+ # "orderTag": "default",
1628
+ # "side": "BUY",
1629
+ # "quantity": 0.1,
1630
+ # "amount": null,
1631
+ # "type": "LIMIT",
1632
+ # "status": "NEW",
1633
+ # "price": 60,
1634
+ # "executed": 0,
1635
+ # "visible": 0.1,
1636
+ # "averageExecutedPrice": 0,
1637
+ # "totalFee": 0,
1638
+ # "feeAsset": "LTC",
1639
+ # "totalRebate": 0,
1640
+ # "rebateAsset": "USDT",
1641
+ # "reduceOnly": False,
1642
+ # "createdTime": "1752049062.496",
1643
+ # "realizedPnl": null,
1644
+ # "positionSide": "BOTH",
1645
+ # "bidAskLevel": null
1646
+ # },
1647
+ # "timestamp": 1752049393466
1648
+ # }
1649
+ #
1650
+ data = self.safe_dict(response, 'data', {})
1651
+ return self.parse_order(data, market)
1309
1652
 
1310
1653
  async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1311
1654
  """
1312
1655
  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
1656
+
1657
+ https://developer.woox.io/api-reference/endpoint/trading/get_orders
1658
+ https://developer.woox.io/api-reference/endpoint/trading/get_algo_orders
1659
+
1315
1660
  :param str symbol: unified market symbol of the market orders were made in
1316
1661
  :param int [since]: the earliest time in ms to fetch orders for
1317
1662
  :param int [limit]: the maximum number of order structures to retrieve
1318
1663
  :param dict [params]: extra parameters specific to the exchange API endpoint
1319
- :param boolean [params.stop]: whether the order is a stop/algo order
1664
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1320
1665
  :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1321
1666
  :param str [params.side]: 'buy' or 'sell'
1322
- :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1323
1667
  :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1324
1668
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1325
1669
  """
@@ -1330,75 +1674,125 @@ class woo(Exchange, ImplicitAPI):
1330
1674
  return await self.fetch_paginated_call_incremental('fetchOrders', symbol, since, limit, params, 'page', 500)
1331
1675
  request: dict = {}
1332
1676
  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'])
1677
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
1678
+ params = self.omit(params, ['stop', 'trigger'])
1336
1679
  if symbol is not None:
1337
1680
  market = self.market(symbol)
1338
1681
  request['symbol'] = market['id']
1339
1682
  if since is not None:
1340
- if stop or trailing:
1341
- request['createdTimeStart'] = since
1342
- else:
1343
- request['start_t'] = since
1683
+ request['startTime'] = since
1684
+ until = self.safe_integer(params, 'until') # unified in milliseconds
1685
+ params = self.omit(params, ['until'])
1686
+ if until is not None:
1687
+ request['endTime'] = until
1344
1688
  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'
1689
+ request['size'] = min(limit, 500)
1352
1690
  response = None
1353
- if stop or trailing:
1354
- response = await self.v3PrivateGetAlgoOrders(self.extend(request, params))
1691
+ if trigger:
1692
+ response = await self.v3PrivateGetTradeAlgoOrders(self.extend(request, params))
1693
+ #
1694
+ # {
1695
+ # "success": True,
1696
+ # "data": {
1697
+ # "rows": [
1698
+ # {
1699
+ # "algoOrderId": 10399260,
1700
+ # "clientAlgoOrderId": 0,
1701
+ # "rootAlgoOrderId": 10399260,
1702
+ # "parentAlgoOrderId": 0,
1703
+ # "symbol": "SPOT_LTC_USDT",
1704
+ # "algoOrderTag": "default",
1705
+ # "algoType": "TAKE_PROFIT",
1706
+ # "side": "BUY",
1707
+ # "quantity": 0.1,
1708
+ # "isTriggered": False,
1709
+ # "triggerPrice": 65,
1710
+ # "triggerStatus": "USELESS",
1711
+ # "type": "LIMIT",
1712
+ # "rootAlgoStatus": "NEW",
1713
+ # "algoStatus": "NEW",
1714
+ # "triggerPriceType": "MARKET_PRICE",
1715
+ # "price": 60,
1716
+ # "triggerTime": "0",
1717
+ # "totalExecutedQuantity": 0,
1718
+ # "visibleQuantity": 0.1,
1719
+ # "averageExecutedPrice": 0,
1720
+ # "totalFee": 0,
1721
+ # "feeAsset": "",
1722
+ # "totalRebate": 0,
1723
+ # "rebateAsset": "",
1724
+ # "reduceOnly": False,
1725
+ # "createdTime": "1752049747.730",
1726
+ # "updatedTime": "1752049747.730",
1727
+ # "positionSide": "BOTH"
1728
+ # }
1729
+ # ],
1730
+ # "meta": {
1731
+ # "total": 7,
1732
+ # "recordsPerPage": 1,
1733
+ # "currentPage": 1
1734
+ # }
1735
+ # },
1736
+ # "timestamp": 1752053127448
1737
+ # }
1738
+ #
1355
1739
  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')
1740
+ response = await self.v3PrivateGetTradeOrders(self.extend(request, params))
1741
+ #
1742
+ # {
1743
+ # "success": True,
1744
+ # "data": {
1745
+ # "rows": [
1746
+ # {
1747
+ # "orderId": 60780315704,
1748
+ # "clientOrderId": 0,
1749
+ # "symbol": "SPOT_LTC_USDT",
1750
+ # "orderTag": "default",
1751
+ # "side": "BUY",
1752
+ # "quantity": 0.1,
1753
+ # "amount": null,
1754
+ # "type": "LIMIT",
1755
+ # "status": "NEW",
1756
+ # "price": 60,
1757
+ # "executed": 0,
1758
+ # "visible": 0.1,
1759
+ # "averageExecutedPrice": 0,
1760
+ # "totalFee": 0,
1761
+ # "feeAsset": "LTC",
1762
+ # "totalRebate": 0,
1763
+ # "rebateAsset": "USDT",
1764
+ # "reduceOnly": False,
1765
+ # "createdTime": "1752049062.496",
1766
+ # "realizedPnl": null,
1767
+ # "positionSide": "BOTH",
1768
+ # "bidAskLevel": null
1769
+ # }
1770
+ # ],
1771
+ # "meta": {
1772
+ # "total": 11,
1773
+ # "recordsPerPage": 1,
1774
+ # "currentPage": 1
1775
+ # }
1776
+ # },
1777
+ # "timestamp": 1752053061236
1778
+ # }
1779
+ #
1780
+ data = self.safe_value(response, 'data', {})
1781
+ orders = self.safe_list(data, 'rows', [])
1390
1782
  return self.parse_orders(orders, market, since, limit)
1391
1783
 
1392
1784
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1393
1785
  """
1394
1786
  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
1787
+
1788
+ https://developer.woox.io/api-reference/endpoint/trading/get_orders
1789
+ https://developer.woox.io/api-reference/endpoint/trading/get_algo_orders
1790
+
1397
1791
  :param str symbol: unified market symbol of the market orders were made in
1398
1792
  :param int [since]: the earliest time in ms to fetch orders for
1399
1793
  :param int [limit]: the maximum number of order structures to retrieve
1400
1794
  :param dict [params]: extra parameters specific to the exchange API endpoint
1401
- :param boolean [params.stop]: whether the order is a stop/algo order
1795
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1402
1796
  :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1403
1797
  :param str [params.side]: 'buy' or 'sell'
1404
1798
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
@@ -1412,13 +1806,15 @@ class woo(Exchange, ImplicitAPI):
1412
1806
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1413
1807
  """
1414
1808
  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
1809
+
1810
+ https://developer.woox.io/api-reference/endpoint/trading/get_orders
1811
+ https://developer.woox.io/api-reference/endpoint/trading/get_algo_orders
1812
+
1417
1813
  :param str symbol: unified market symbol of the market orders were made in
1418
1814
  :param int [since]: the earliest time in ms to fetch orders for
1419
1815
  :param int [limit]: the maximum number of order structures to retrieve
1420
1816
  :param dict [params]: extra parameters specific to the exchange API endpoint
1421
- :param boolean [params.stop]: whether the order is a stop/algo order
1817
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1422
1818
  :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1423
1819
  :param str [params.side]: 'buy' or 'sell'
1424
1820
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
@@ -1439,81 +1835,107 @@ class woo(Exchange, ImplicitAPI):
1439
1835
 
1440
1836
  def parse_order(self, order: dict, market: Market = None) -> Order:
1441
1837
  #
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
1838
+ # createOrder
1839
+ # {
1840
+ # "orderId": 60667653330,
1841
+ # "clientOrderId": 0,
1842
+ # "type": "LIMIT",
1843
+ # "price": 60,
1844
+ # "quantity": 0.1,
1845
+ # "amount": null,
1846
+ # "bidAskLevel": null,
1847
+ # "timestamp": 1751871779855
1848
+ # }
1849
+ #
1850
+ # createOrder - algo
1851
+ # {
1852
+ # "orderId": "1578938",
1853
+ # "clientOrderId": "0",
1854
+ # "algoType": "STOP_LOSS",
1855
+ # "quantity": "0.1",
1856
+ # "timestamp": "1686149372216"
1857
+ # }
1858
+ #
1859
+ # fetchOrder
1860
+ # {
1861
+ # "orderId": 60780315704,
1862
+ # "clientOrderId": 0,
1863
+ # "symbol": "SPOT_LTC_USDT",
1864
+ # "orderTag": "default",
1865
+ # "side": "BUY",
1866
+ # "quantity": 0.1,
1867
+ # "amount": null,
1868
+ # "type": "LIMIT",
1869
+ # "status": "NEW",
1870
+ # "price": 60,
1871
+ # "executed": 0,
1872
+ # "visible": 0.1,
1873
+ # "averageExecutedPrice": 0,
1874
+ # "totalFee": 0,
1875
+ # "feeAsset": "LTC",
1876
+ # "totalRebate": 0,
1877
+ # "rebateAsset": "USDT",
1878
+ # "reduceOnly": False,
1879
+ # "createdTime": "1752049062.496",
1880
+ # "realizedPnl": null,
1881
+ # "positionSide": "BOTH",
1882
+ # "bidAskLevel": null
1883
+ # }
1884
+ #
1885
+ # fetchOrder - algo
1886
+ # {
1887
+ # "algoOrderId": 10399260,
1888
+ # "clientAlgoOrderId": 0,
1889
+ # "rootAlgoOrderId": 10399260,
1890
+ # "parentAlgoOrderId": 0,
1891
+ # "symbol": "SPOT_LTC_USDT",
1892
+ # "algoOrderTag": "default",
1893
+ # "algoType": "TAKE_PROFIT",
1894
+ # "side": "BUY",
1895
+ # "quantity": 0.1,
1896
+ # "isTriggered": False,
1897
+ # "triggerPrice": 65,
1898
+ # "triggerStatus": "USELESS",
1899
+ # "type": "LIMIT",
1900
+ # "rootAlgoStatus": "NEW",
1901
+ # "algoStatus": "NEW",
1902
+ # "triggerPriceType": "MARKET_PRICE",
1903
+ # "price": 60,
1904
+ # "triggerTime": "0",
1905
+ # "totalExecutedQuantity": 0,
1906
+ # "visibleQuantity": 0.1,
1907
+ # "averageExecutedPrice": 0,
1908
+ # "totalFee": 0,
1909
+ # "feeAsset": "",
1910
+ # "totalRebate": 0,
1911
+ # "rebateAsset": "",
1912
+ # "reduceOnly": False,
1913
+ # "createdTime": "1752049747.732",
1914
+ # "updatedTime": "1752049747.732",
1915
+ # "positionSide": "BOTH"
1916
+ # }
1917
+ #
1918
+ timestamp = self.safe_timestamp(order, 'createdTime')
1919
+ if timestamp is None:
1920
+ timestamp = self.safe_integer(order, 'timestamp')
1921
+ orderId = self.safe_string_2(order, 'orderId', 'algoOrderId')
1922
+ clientOrderId = self.omit_zero(self.safe_string_2(order, 'clientOrderId', 'clientAlgoOrderId')) # Somehow, self always returns 0 for limit order
1488
1923
  marketId = self.safe_string(order, 'symbol')
1489
1924
  market = self.safe_market(marketId, market)
1490
1925
  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')
1926
+ price = self.safe_string(order, 'price')
1927
+ amount = self.safe_string(order, 'quantity') # This is base amount
1928
+ cost = self.safe_string(order, 'amount') # This is quote amount
1929
+ orderType = self.safe_string_lower(order, 'type')
1495
1930
  status = self.safe_value_2(order, 'status', 'algoStatus')
1496
1931
  side = self.safe_string_lower(order, 'side')
1497
1932
  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')
1933
+ average = self.omit_zero(self.safe_string(order, 'averageExecutedPrice'))
1934
+ # remaining = Precise.string_sub(cost, filled)
1935
+ fee = self.safe_number(order, 'totalFee')
1936
+ feeCurrency = self.safe_string(order, 'feeAsset')
1937
+ triggerPrice = self.safe_number(order, 'triggerPrice')
1938
+ lastUpdateTimestamp = self.safe_timestamp(order, 'updatedTime')
1517
1939
  return self.safe_order({
1518
1940
  'id': orderId,
1519
1941
  'clientOrderId': clientOrderId,
@@ -1526,19 +1948,18 @@ class woo(Exchange, ImplicitAPI):
1526
1948
  'type': orderType,
1527
1949
  'timeInForce': self.parse_time_in_force(orderType),
1528
1950
  'postOnly': None, # TO_DO
1529
- 'reduceOnly': self.safe_bool(order, 'reduce_only'),
1951
+ 'reduceOnly': self.safe_bool(order, 'reduceOnly'),
1530
1952
  'side': side,
1531
1953
  'price': price,
1532
- 'stopPrice': stopPrice,
1533
- 'triggerPrice': stopPrice,
1534
- 'takeProfitPrice': takeProfitPrice,
1535
- 'stopLossPrice': stopLossPrice,
1954
+ 'triggerPrice': triggerPrice,
1955
+ 'takeProfitPrice': None,
1956
+ 'stopLossPrice': None,
1536
1957
  'average': average,
1537
1958
  'amount': amount,
1538
1959
  'filled': filled,
1539
- 'remaining': remaining, # TO_DO
1960
+ 'remaining': None, # TO_DO
1540
1961
  'cost': cost,
1541
- 'trades': transactions,
1962
+ 'trades': None,
1542
1963
  'fee': {
1543
1964
  'cost': fee,
1544
1965
  'currency': feeCurrency,
@@ -1565,7 +1986,9 @@ class woo(Exchange, ImplicitAPI):
1565
1986
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1566
1987
  """
1567
1988
  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
1989
+
1990
+ https://developer.woox.io/api-reference/endpoint/public_data/orderbook
1991
+
1569
1992
  :param str symbol: unified symbol of the market to fetch the order book for
1570
1993
  :param int [limit]: the maximum amount of order book entries to return
1571
1994
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1577,38 +2000,45 @@ class woo(Exchange, ImplicitAPI):
1577
2000
  'symbol': market['id'],
1578
2001
  }
1579
2002
  if limit is not None:
1580
- limit = min(limit, 1000)
1581
- request['max_level'] = limit
1582
- response = await self.v1PublicGetOrderbookSymbol(self.extend(request, params))
2003
+ request['maxLevel'] = limit
2004
+ response = await self.v3PublicGetOrderbook(self.extend(request, params))
1583
2005
  #
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
2006
  # }
2007
+ # {
2008
+ # "success": True,
2009
+ # "timestamp": 1751620923344,
2010
+ # "data": {
2011
+ # "asks": [
2012
+ # {
2013
+ # "price": "108924.86",
2014
+ # "quantity": "0.032126"
2015
+ # }
2016
+ # ],
2017
+ # "bids": [
2018
+ # {
2019
+ # "price": "108924.85",
2020
+ # "quantity": "1.714147"
2021
+ # }
2022
+ # ]
2023
+ # }
2024
+ # }
1598
2025
  #
2026
+ data = self.safe_dict(response, 'data', {})
1599
2027
  timestamp = self.safe_integer(response, 'timestamp')
1600
- return self.parse_order_book(response, symbol, timestamp, 'bids', 'asks', 'price', 'quantity')
2028
+ return self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 'price', 'quantity')
1601
2029
 
1602
2030
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1603
2031
  """
1604
- :see: https://docs.woo.org/#kline-public
1605
- :see: https://docs.woo.org/#kline-historical-data-public
2032
+
2033
+ https://developer.woox.io/api-reference/endpoint/public_data/klineHistory
2034
+
1606
2035
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1607
2036
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1608
2037
  :param str timeframe: the length of time each candle represents
1609
2038
  :param int [since]: timestamp in ms of the earliest candle to fetch
1610
2039
  :param int [limit]: max=1000, max=100 when since is defined and is less than(now - (999 * (timeframe in ms)))
1611
2040
  :param dict [params]: extra parameters specific to the exchange API endpoint
2041
+ :param int [params.until]: the latest time in ms to fetch entries for
1612
2042
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1613
2043
  """
1614
2044
  await self.load_markets()
@@ -1617,70 +2047,44 @@ class woo(Exchange, ImplicitAPI):
1617
2047
  'symbol': market['id'],
1618
2048
  'type': self.safe_string(self.timeframes, timeframe, timeframe),
1619
2049
  }
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
2050
+ if limit is not None:
1628
2051
  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', [])
2052
+ if since is not None:
2053
+ request['after'] = since
2054
+ until = self.safe_integer(params, 'until')
2055
+ params = self.omit(params, 'until')
2056
+ if until is not None:
2057
+ request['before'] = until
2058
+ response = await self.v3PublicGetKlineHistory(self.extend(request, params))
2059
+ #
2060
+ # {
2061
+ # "success": True,
2062
+ # "data": {
2063
+ # "rows": [
2064
+ # {
2065
+ # "symbol": "SPOT_BTC_USDT",
2066
+ # "open": "108994.16",
2067
+ # "close": "108994.16",
2068
+ # "high": "108994.16",
2069
+ # "low": "108994.16",
2070
+ # "volume": "0",
2071
+ # "amount": "0",
2072
+ # "type": "1m",
2073
+ # "startTimestamp": 1751622120000,
2074
+ # "endTimestamp": 1751622180000
2075
+ # }
2076
+ # ]
2077
+ # },
2078
+ # "timestamp": 1751622205410
2079
+ # }
2080
+ #
2081
+ data = self.safe_dict(response, 'data', {})
2082
+ rows = self.safe_list(data, 'rows', [])
1678
2083
  return self.parse_ohlcvs(rows, market, timeframe, since, limit)
1679
2084
 
1680
2085
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1681
- # example response in fetchOHLCV
1682
2086
  return [
1683
- self.safe_integer(ohlcv, 'start_timestamp'),
2087
+ self.safe_integer(ohlcv, 'startTimestamp'),
1684
2088
  self.safe_number(ohlcv, 'open'),
1685
2089
  self.safe_number(ohlcv, 'high'),
1686
2090
  self.safe_number(ohlcv, 'low'),
@@ -1691,7 +2095,9 @@ class woo(Exchange, ImplicitAPI):
1691
2095
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1692
2096
  """
1693
2097
  fetch all the trades made from a single order
1694
- :see: https://docs.woo.org/#get-trades
2098
+
2099
+ https://docs.woox.io/#get-trades
2100
+
1695
2101
  :param str id: order id
1696
2102
  :param str symbol: unified market symbol
1697
2103
  :param int [since]: the earliest time in ms to fetch trades for
@@ -1731,7 +2137,9 @@ class woo(Exchange, ImplicitAPI):
1731
2137
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1732
2138
  """
1733
2139
  fetch all trades made by the user
1734
- :see: https://docs.woo.org/#get-trades
2140
+
2141
+ https://developer.woox.io/api-reference/endpoint/trading/get_transactions
2142
+
1735
2143
  :param str symbol: unified market symbol
1736
2144
  :param int [since]: the earliest time in ms to fetch trades for
1737
2145
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -1750,86 +2158,157 @@ class woo(Exchange, ImplicitAPI):
1750
2158
  market = self.market(symbol)
1751
2159
  request['symbol'] = market['id']
1752
2160
  if since is not None:
1753
- request['start_t'] = since
2161
+ request['startTime'] = since
2162
+ until = self.safe_integer(params, 'until') # unified in milliseconds
2163
+ params = self.omit(params, ['until'])
2164
+ if until is not None:
2165
+ request['endTime'] = until
1754
2166
  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"
2167
+ request['limit'] = limit
2168
+ response = await self.v3PrivateGetTradeTransactionHistory(self.extend(request, params))
2169
+ #
2170
+ # {
2171
+ # "success": True,
2172
+ # "data": {
2173
+ # "rows": [
2174
+ # {
2175
+ # "id": 1734947821,
2176
+ # "symbol": "SPOT_LTC_USDT",
2177
+ # "orderId": 60780383217,
2178
+ # "executedPrice": 87.86,
2179
+ # "executedQuantity": 0.1,
2180
+ # "fee": 0.0001,
2181
+ # "realizedPnl": null,
2182
+ # "feeAsset": "LTC",
2183
+ # "orderTag": "default",
2184
+ # "side": "BUY",
2185
+ # "executedTimestamp": "1752055173.630",
2186
+ # "isMaker": 0
2187
+ # }
2188
+ # ],
2189
+ # "meta": {
2190
+ # "total": 1,
2191
+ # "recordsPerPage": 100,
2192
+ # "currentPage": 1
2193
+ # }
1778
2194
  # },
1779
- # ...
1780
- # ]
1781
- # }
1782
- trades = self.safe_list(response, 'rows', [])
2195
+ # "timestamp": 1752055545121
2196
+ # }
2197
+ #
2198
+ data = self.safe_dict(response, 'data', {})
2199
+ trades = self.safe_list(data, 'rows', [])
1783
2200
  return self.parse_trades(trades, market, since, limit, params)
1784
2201
 
1785
2202
  async def fetch_accounts(self, params={}) -> List[Account]:
1786
2203
  """
1787
2204
  fetch all the accounts associated with a profile
1788
- :see: https://docs.woo.org/#get-assets-of-subaccounts
2205
+
2206
+ https://developer.woox.io/api-reference/endpoint/account/get_account_info
2207
+ https://developer.woox.io/api-reference/endpoint/account/sub_accounts
2208
+
1789
2209
  :param dict [params]: extra parameters specific to the exchange API endpoint
1790
2210
  :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
1791
2211
  """
1792
- response = await self.v1PrivateGetSubAccountAssets(params)
2212
+ mainAccountPromise = self.v3PrivateGetAccountInfo(params)
1793
2213
  #
1794
2214
  # {
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
2215
+ # "success": True,
2216
+ # "data": {
2217
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
2218
+ # "account": "carlos_jose_lima@yahoo.com",
2219
+ # "alias": "carlos_jose_lima@yahoo.com",
2220
+ # "otpauth": True,
2221
+ # "accountMode": "FUTURES",
2222
+ # "positionMode": "ONE_WAY",
2223
+ # "leverage": 0,
2224
+ # "marginRatio": "10",
2225
+ # "openMarginRatio": "10",
2226
+ # "initialMarginRatio": "10",
2227
+ # "maintenanceMarginRatio": "0.03",
2228
+ # "totalCollateral": "165.55629469",
2229
+ # "freeCollateral": "165.55629469",
2230
+ # "totalAccountValue": "167.32418611",
2231
+ # "totalTradingValue": "167.32418611",
2232
+ # "totalVaultValue": "0",
2233
+ # "totalStakingValue": "0",
2234
+ # "totalLaunchpadValue": "0",
2235
+ # "totalEarnValue": "0",
2236
+ # "referrerID": null,
2237
+ # "accountType": "Main"
2238
+ # },
2239
+ # "timestamp": 1752062807915
2240
+ # }
2241
+ #
2242
+ subAccountPromise = self.v3PrivateGetAccountSubAccountsAll(params)
2243
+ #
2244
+ # {
2245
+ # "success": True,
2246
+ # "data": {
2247
+ # "rows": [
2248
+ # {
2249
+ # "applicationId": "6b43de5c-0955-4887-9862-d84e4689f9fe",
2250
+ # "name": "sub_account_2",
2251
+ # "createdTime": "1606897264.994"
2252
+ # },
2253
+ # ]
2254
+ # },
2255
+ # "timestamp": 1721295317627
1807
2256
  # }
1808
2257
  #
1809
- rows = self.safe_list(response, 'rows', [])
2258
+ mainAccountResponse, subAccountResponse = await asyncio.gather(*[mainAccountPromise, subAccountPromise])
2259
+ mainData = self.safe_dict(mainAccountResponse, 'data', {})
2260
+ mainRows = [mainData]
2261
+ subData = self.safe_dict(subAccountResponse, 'data', {})
2262
+ subRows = self.safe_list(subData, 'rows', [])
2263
+ rows = self.array_concat(mainRows, subRows)
1810
2264
  return self.parse_accounts(rows, params)
1811
2265
 
1812
2266
  def parse_account(self, account):
1813
2267
  #
1814
2268
  # {
1815
- # "application_id": "336952aa-a401-4e26-aff6-972920aebba3",
1816
- # "account": "subaccount",
1817
- # "usdt_balance": "1.0",
2269
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
2270
+ # "account": "carlos_jose_lima@yahoo.com",
2271
+ # "alias": "carlos_jose_lima@yahoo.com",
2272
+ # "otpauth": True,
2273
+ # "accountMode": "FUTURES",
2274
+ # "positionMode": "ONE_WAY",
2275
+ # "leverage": 0,
2276
+ # "marginRatio": "10",
2277
+ # "openMarginRatio": "10",
2278
+ # "initialMarginRatio": "10",
2279
+ # "maintenanceMarginRatio": "0.03",
2280
+ # "totalCollateral": "165.55629469",
2281
+ # "freeCollateral": "165.55629469",
2282
+ # "totalAccountValue": "167.32418611",
2283
+ # "totalTradingValue": "167.32418611",
2284
+ # "totalVaultValue": "0",
2285
+ # "totalStakingValue": "0",
2286
+ # "totalLaunchpadValue": "0",
2287
+ # "totalEarnValue": "0",
2288
+ # "referrerID": null,
2289
+ # "accountType": "Main"
2290
+ # }
2291
+ #
2292
+ # {
2293
+ # "applicationId": "6b43de5c-0955-4887-9862-d84e4689f9fe",
2294
+ # "name": "sub_account_2",
2295
+ # "createdTime": "1606897264.994"
1818
2296
  # }
1819
2297
  #
1820
- accountId = self.safe_string(account, 'account')
1821
2298
  return {
1822
2299
  'info': account,
1823
- 'id': self.safe_string(account, 'application_id'),
1824
- 'name': accountId,
2300
+ 'id': self.safe_string(account, 'applicationId'),
2301
+ 'name': self.safe_string_n(account, ['name', 'account', 'alias']),
1825
2302
  'code': None,
1826
- 'type': accountId == 'main' if 'Main' else 'subaccount',
2303
+ 'type': self.safe_string_lower(account, 'accountType', 'subaccount'),
1827
2304
  }
1828
2305
 
1829
2306
  async def fetch_balance(self, params={}) -> Balances:
1830
2307
  """
1831
2308
  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
2309
+
2310
+ https://docs.woox.io/#get-current-holding-get-balance-new
2311
+
1833
2312
  :param dict [params]: extra parameters specific to the exchange API endpoint
1834
2313
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1835
2314
  """
@@ -1875,10 +2354,12 @@ class woo(Exchange, ImplicitAPI):
1875
2354
  result[code] = account
1876
2355
  return self.safe_balance(result)
1877
2356
 
1878
- async def fetch_deposit_address(self, code: str, params={}):
2357
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1879
2358
  """
1880
2359
  fetch the deposit address for a currency associated with self account
1881
- :see: https://docs.woo.org/#get-token-deposit-address
2360
+
2361
+ https://developer.woox.io/api-reference/endpoint/assets/get_wallet_deposit
2362
+
1882
2363
  :param str code: unified currency code
1883
2364
  :param dict [params]: extra parameters specific to the exchange API endpoint
1884
2365
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
@@ -1886,28 +2367,46 @@ class woo(Exchange, ImplicitAPI):
1886
2367
  # self method is TODO because of networks unification
1887
2368
  await self.load_markets()
1888
2369
  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']
2370
+ networkCode = None
2371
+ networkCode, params = self.handle_network_code_and_params(params)
1893
2372
  request: dict = {
1894
- 'token': codeForExchange,
2373
+ 'token': currency['id'],
2374
+ 'network': self.network_code_to_id(networkCode),
1895
2375
  }
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')
2376
+ response = await self.v3PrivateGetAssetWalletDeposit(self.extend(request, params))
2377
+ #
2378
+ # {
2379
+ # "success": True,
2380
+ # "data": {
2381
+ # "address": "0x31d64B3230f8baDD91dE1710A65DF536aF8f7cDa",
2382
+ # "extra": ""
2383
+ # },
2384
+ # "timestamp": 1721300689532
2385
+ # }
2386
+ #
2387
+ data = self.safe_dict(response, 'data', {})
2388
+ return self.parse_deposit_address(data, currency)
2389
+
2390
+ def get_dedicated_network_id(self, currency, params: dict) -> Any:
2391
+ networkCode = None
2392
+ networkCode, params = self.handle_network_code_and_params(params)
2393
+ networkCode = self.network_id_to_code(networkCode, currency['code'])
2394
+ networkEntry = self.safe_dict(currency['networks'], networkCode)
2395
+ if networkEntry is None:
2396
+ supportedNetworks = list(currency['networks'].keys())
2397
+ raise BadRequest(self.id + ' can not determine a network code, please provide unified "network" param, one from the following: ' + self.json(supportedNetworks))
2398
+ currentyNetworkId = self.safe_string(networkEntry, 'currencyNetworkId')
2399
+ return [currentyNetworkId, params]
2400
+
2401
+ def parse_deposit_address(self, depositEntry, currency: Currency = None) -> DepositAddress:
2402
+ address = self.safe_string(depositEntry, 'address')
1904
2403
  self.check_address(address)
1905
2404
  return {
1906
- 'currency': code,
2405
+ 'info': depositEntry,
2406
+ 'currency': self.safe_string(currency, 'code'),
2407
+ 'network': None,
1907
2408
  'address': address,
1908
- 'tag': tag,
1909
- 'network': networkCode,
1910
- 'info': response,
2409
+ 'tag': self.safe_string(depositEntry, 'extra'),
1911
2410
  }
1912
2411
 
1913
2412
  async def get_asset_history_rows(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> Any:
@@ -1916,91 +2415,123 @@ class woo(Exchange, ImplicitAPI):
1916
2415
  currency: Currency = None
1917
2416
  if code is not None:
1918
2417
  currency = self.currency(code)
1919
- request['balance_token'] = currency['id']
2418
+ request['token'] = currency['id']
2419
+ networkCode = None
2420
+ networkCode, params = self.handle_network_code_and_params(params)
2421
+ if networkCode is not None:
2422
+ request['network'] = self.network_code_to_id(networkCode)
1920
2423
  if since is not None:
1921
- request['start_t'] = since
2424
+ request['startTime'] = since
1922
2425
  if limit is not None:
1923
- request['pageSize'] = limit
2426
+ request['size'] = min(limit, 1000)
1924
2427
  transactionType = self.safe_string(params, 'type')
1925
2428
  params = self.omit(params, 'type')
1926
2429
  if transactionType is not None:
1927
2430
  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', [])]
2431
+ response = await self.v3PrivateGetAssetWalletHistory(self.extend(request, params))
2432
+ #
2433
+ # {
2434
+ # "success": True,
2435
+ # "data": {
2436
+ # "rows": [
2437
+ # {
2438
+ # "createdTime": "1734964440.523",
2439
+ # "updatedTime": "1734964614.081",
2440
+ # "id": "24122314340000585",
2441
+ # "externalId": "241223143600621",
2442
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
2443
+ # "token": "ARB_USDCNATIVE",
2444
+ # "targetAddress": "0x4d6802d2736daa85e6242ef0dc0f00aa0e68f635",
2445
+ # "sourceAddress": "0x63DFE4e34A3bFC00eB0220786238a7C6cEF8Ffc4",
2446
+ # "extra": "",
2447
+ # "type": "BALANCE",
2448
+ # "tokenSide": "WITHDRAW",
2449
+ # "amount": "10.00000000",
2450
+ # "txId": "0x891ade0a47fd55466bb9d06702bea4edcb75ed9367d9afbc47b93a84f496d2e6",
2451
+ # "feeToken": "USDC",
2452
+ # "feeAmount": "2",
2453
+ # "status": "COMPLETED",
2454
+ # "confirmingThreshold": null,
2455
+ # "confirmedNumber": null
2456
+ # }
2457
+ # ],
2458
+ # "meta": {
2459
+ # "total": 1,
2460
+ # "records_per_page": 25,
2461
+ # "current_page": 1
2462
+ # }
2463
+ # },
2464
+ # "timestamp": 1752485344719
2465
+ # }
2466
+ #
2467
+ data = self.safe_dict(response, 'data', {})
2468
+ return [currency, self.safe_list(data, 'rows', [])]
1964
2469
 
1965
- async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
2470
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
1966
2471
  """
1967
2472
  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
2473
+
2474
+ https://developer.woox.io/api-reference/endpoint/assets/get_wallet_history
2475
+
2476
+ :param str [code]: unified currency code, default is None
1970
2477
  :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
2478
+ :param int [limit]: max number of ledger entries to return, default is None
1972
2479
  :param dict [params]: extra parameters specific to the exchange API endpoint
1973
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
2480
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
1974
2481
  """
1975
- currency, rows = await self.get_asset_history_rows(code, since, limit, params)
2482
+ currencyRows = await self.get_asset_history_rows(code, since, limit, params)
2483
+ currency = self.safe_value(currencyRows, 0)
2484
+ rows = self.safe_list(currencyRows, 1)
1976
2485
  return self.parse_ledger(rows, currency, since, limit, params)
1977
2486
 
1978
- def parse_ledger_entry(self, item: dict, currency: Currency = None):
2487
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
2488
+ #
2489
+ # {
2490
+ # "createdTime": "1734964440.523",
2491
+ # "updatedTime": "1734964614.081",
2492
+ # "id": "24122314340000585",
2493
+ # "externalId": "241223143600621",
2494
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
2495
+ # "token": "ARB_USDCNATIVE",
2496
+ # "targetAddress": "0x4d6802d2736daa85e6242ef0dc0f00aa0e68f635",
2497
+ # "sourceAddress": "0x63DFE4e34A3bFC00eB0220786238a7C6cEF8Ffc4",
2498
+ # "extra": "",
2499
+ # "type": "BALANCE",
2500
+ # "tokenSide": "WITHDRAW",
2501
+ # "amount": "10.00000000",
2502
+ # "txId": "0x891ade0a47fd55466bb9d06702bea4edcb75ed9367d9afbc47b93a84f496d2e6",
2503
+ # "feeToken": "USDC",
2504
+ # "feeAmount": "2",
2505
+ # "status": "COMPLETED",
2506
+ # "confirmingThreshold": null,
2507
+ # "confirmedNumber": null
2508
+ # }
2509
+ #
1979
2510
  networkizedCode = self.safe_string(item, 'token')
1980
- currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
1981
- code = currencyDefined['code']
2511
+ code = self.safe_currency_code(networkizedCode, currency)
2512
+ currency = self.safe_currency(code, currency)
1982
2513
  amount = self.safe_number(item, 'amount')
1983
- side = self.safe_string(item, 'token_side')
2514
+ side = self.safe_string(item, 'tokenSide')
1984
2515
  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 {
2516
+ timestamp = self.safe_timestamp(item, 'createdTime')
2517
+ fee = self.parse_token_and_fee_temp(item, ['feeToken'], ['feeAmount'])
2518
+ return self.safe_ledger_entry({
2519
+ 'info': item,
1988
2520
  'id': self.safe_string(item, 'id'),
1989
2521
  'currency': code,
1990
2522
  'account': self.safe_string(item, 'account'),
1991
2523
  'referenceAccount': None,
1992
- 'referenceId': self.safe_string(item, 'tx_id'),
2524
+ 'referenceId': self.safe_string(item, 'txId'),
1993
2525
  'status': self.parse_transaction_status(self.safe_string(item, 'status')),
1994
2526
  'amount': amount,
1995
2527
  'before': None,
1996
2528
  'after': None,
1997
- 'fee': fee,
1998
2529
  'direction': direction,
1999
2530
  'timestamp': timestamp,
2000
2531
  'datetime': self.iso8601(timestamp),
2001
2532
  'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
2002
- 'info': item,
2003
- }
2533
+ 'fee': fee,
2534
+ }, currency)
2004
2535
 
2005
2536
  def parse_ledger_entry_type(self, type):
2006
2537
  types: dict = {
@@ -2025,7 +2556,9 @@ class woo(Exchange, ImplicitAPI):
2025
2556
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2026
2557
  """
2027
2558
  fetch all deposits made to an account
2028
- :see: https://docs.woo.org/#get-asset-history
2559
+
2560
+ https://developer.woox.io/api-reference/endpoint/assets/get_wallet_history
2561
+
2029
2562
  :param str code: unified currency code
2030
2563
  :param int [since]: the earliest time in ms to fetch deposits for
2031
2564
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -2033,14 +2566,16 @@ class woo(Exchange, ImplicitAPI):
2033
2566
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2034
2567
  """
2035
2568
  request: dict = {
2036
- 'token_side': 'DEPOSIT',
2569
+ 'tokenSide': 'DEPOSIT',
2037
2570
  }
2038
2571
  return await self.fetch_deposits_withdrawals(code, since, limit, self.extend(request, params))
2039
2572
 
2040
2573
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2041
2574
  """
2042
2575
  fetch all withdrawals made from an account
2043
- :see: https://docs.woo.org/#get-asset-history
2576
+
2577
+ https://developer.woox.io/api-reference/endpoint/assets/get_wallet_history
2578
+
2044
2579
  :param str code: unified currency code
2045
2580
  :param int [since]: the earliest time in ms to fetch withdrawals for
2046
2581
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -2048,14 +2583,16 @@ class woo(Exchange, ImplicitAPI):
2048
2583
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2049
2584
  """
2050
2585
  request: dict = {
2051
- 'token_side': 'WITHDRAW',
2586
+ 'tokenSide': 'WITHDRAW',
2052
2587
  }
2053
2588
  return await self.fetch_deposits_withdrawals(code, since, limit, self.extend(request, params))
2054
2589
 
2055
2590
  async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2056
2591
  """
2057
2592
  fetch history of deposits and withdrawals
2058
- :see: https://docs.woo.org/#get-asset-history
2593
+
2594
+ https://developer.woox.io/api-reference/endpoint/assets/get_wallet_history
2595
+
2059
2596
  :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2060
2597
  :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2061
2598
  :param int [limit]: max number of deposit/withdrawals to return, default is None
@@ -2065,36 +2602,48 @@ class woo(Exchange, ImplicitAPI):
2065
2602
  request: dict = {
2066
2603
  'type': 'BALANCE',
2067
2604
  }
2068
- currency, rows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2605
+ currencyRows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2606
+ currency = self.safe_value(currencyRows, 0)
2607
+ rows = self.safe_list(currencyRows, 1)
2608
+ return self.parse_transactions(rows, currency, since, limit, params)
2609
+
2610
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2069
2611
  #
2070
2612
  # {
2071
- # "rows":[],
2072
- # "meta":{
2073
- # "total":0,
2074
- # "records_per_page":25,
2075
- # "current_page":1
2076
- # },
2077
- # "success":true
2613
+ # "createdTime": "1734964440.523",
2614
+ # "updatedTime": "1734964614.081",
2615
+ # "id": "24122314340000585",
2616
+ # "externalId": "241223143600621",
2617
+ # "applicationId": "251bf5c4-f3c8-4544-bb8b-80001007c3c0",
2618
+ # "token": "ARB_USDCNATIVE",
2619
+ # "targetAddress": "0x4d6802d2736daa85e6242ef0dc0f00aa0e68f635",
2620
+ # "sourceAddress": "0x63DFE4e34A3bFC00eB0220786238a7C6cEF8Ffc4",
2621
+ # "extra": "",
2622
+ # "type": "BALANCE",
2623
+ # "tokenSide": "WITHDRAW",
2624
+ # "amount": "10.00000000",
2625
+ # "txId": "0x891ade0a47fd55466bb9d06702bea4edcb75ed9367d9afbc47b93a84f496d2e6",
2626
+ # "feeToken": "USDC",
2627
+ # "feeAmount": "2",
2628
+ # "status": "COMPLETED",
2629
+ # "confirmingThreshold": null,
2630
+ # "confirmedNumber": null
2078
2631
  # }
2079
2632
  #
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
2633
  networkizedCode = self.safe_string(transaction, 'token')
2085
2634
  currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
2086
2635
  code = currencyDefined['code']
2087
- movementDirection = self.safe_string_lower(transaction, 'token_side')
2636
+ movementDirection = self.safe_string_lower_2(transaction, 'token_side', 'tokenSide')
2088
2637
  if movementDirection == 'withdraw':
2089
2638
  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')
2639
+ fee = self.parse_token_and_fee_temp(transaction, ['fee_token', 'feeToken'], ['fee_amount', 'feeAmount'])
2640
+ addressTo = self.safe_string_2(transaction, 'target_address', 'targetAddress')
2641
+ addressFrom = self.safe_string_2(transaction, 'source_address', 'sourceAddress')
2642
+ timestamp = self.safe_timestamp_2(transaction, 'created_time', 'createdTime')
2094
2643
  return {
2095
2644
  'info': transaction,
2096
- 'id': self.safe_string_2(transaction, 'id', 'withdraw_id'),
2097
- 'txid': self.safe_string(transaction, 'tx_id'),
2645
+ 'id': self.safe_string_n(transaction, ['id', 'withdraw_id', 'withdrawId']),
2646
+ 'txid': self.safe_string_2(transaction, 'tx_id', 'txId'),
2098
2647
  'timestamp': timestamp,
2099
2648
  'datetime': self.iso8601(timestamp),
2100
2649
  'address': None,
@@ -2107,7 +2656,7 @@ class woo(Exchange, ImplicitAPI):
2107
2656
  'amount': self.safe_number(transaction, 'amount'),
2108
2657
  'currency': code,
2109
2658
  'status': self.parse_transaction_status(self.safe_string(transaction, 'status')),
2110
- 'updated': self.safe_timestamp(transaction, 'updated_time'),
2659
+ 'updated': self.safe_timestamp_2(transaction, 'updated_time', 'updatedTime'),
2111
2660
  'comment': None,
2112
2661
  'internal': None,
2113
2662
  'fee': fee,
@@ -2127,7 +2676,9 @@ class woo(Exchange, ImplicitAPI):
2127
2676
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2128
2677
  """
2129
2678
  transfer currency internally between wallets on the same account
2130
- :see: https://docs.woo.org/#get-transfer-history
2679
+
2680
+ https://docs.woox.io/#get-transfer-history
2681
+
2131
2682
  :param str code: unified currency code
2132
2683
  :param float amount: amount to transfer
2133
2684
  :param str fromAccount: account to transfer from
@@ -2159,10 +2710,12 @@ class woo(Exchange, ImplicitAPI):
2159
2710
  transfer['toAccount'] = toAccount
2160
2711
  return transfer
2161
2712
 
2162
- async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
2713
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
2163
2714
  """
2164
2715
  fetch a history of internal transfers made on an account
2165
- :see: https://docs.woo.org/#get-transfer-history
2716
+
2717
+ https://developer.woox.io/api-reference/endpoint/assets/get_transfer_history
2718
+
2166
2719
  :param str code: unified currency code of the currency transferred
2167
2720
  :param int [since]: the earliest time in ms to fetch transfers for
2168
2721
  :param int [limit]: the maximum number of transfers structures to retrieve
@@ -2171,41 +2724,52 @@ class woo(Exchange, ImplicitAPI):
2171
2724
  :returns dict[]: a list of `transfer structures <https://docs.ccxt.com/#/?id=transfer-structure>`
2172
2725
  """
2173
2726
  request: dict = {}
2727
+ currency = None
2728
+ if code is not None:
2729
+ currency = self.currency(code)
2174
2730
  if limit is not None:
2175
2731
  request['size'] = limit
2176
2732
  if since is not None:
2177
- request['start_t'] = since
2733
+ request['startTime'] = since
2178
2734
  until = self.safe_integer(params, 'until') # unified in milliseconds
2179
2735
  params = self.omit(params, ['until'])
2180
2736
  if until is not None:
2181
- request['end_t'] = until
2182
- response = await self.v1PrivateGetAssetMainSubTransferHistory(self.extend(request, params))
2737
+ request['endTime'] = until
2738
+ response = await self.v3PrivateGetAssetTransferHistory(self.extend(request, params))
2183
2739
  #
2184
2740
  # {
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"
2741
+ # "success": True,
2742
+ # "data": {
2743
+ # "rows": [
2744
+ # {
2745
+ # "id": 225,
2746
+ # "token": "USDT",
2747
+ # "amount": "1000000",
2748
+ # "status": "COMPLETED",
2749
+ # "from": {
2750
+ # "applicationId": "046b5c5c-5b44-4d27-9593-ddc32c0a08ae",
2751
+ # "accountName": "Main"
2752
+ # },
2753
+ # "to": {
2754
+ # "applicationId": "082ae5ae-e26a-4fb1-be5b-03e5b4867663",
2755
+ # "accountName": "sub001"
2756
+ # },
2757
+ # "createdTime": "1642660941.534",
2758
+ # "updatedTime": "1642660941.950"
2759
+ # }
2760
+ # ],
2761
+ # "meta": {
2762
+ # "total": 46,
2763
+ # "recordsPerPage": 1,
2764
+ # "currentPage": 1
2197
2765
  # }
2198
- # ],
2199
- # "meta": {
2200
- # "total": 50,
2201
- # "records_per_page": 25,
2202
- # "current_page": 1
2203
2766
  # },
2204
- # "success": True
2767
+ # "timestamp": 1721295317627
2205
2768
  # }
2206
2769
  #
2207
- data = self.safe_list(response, 'rows', [])
2208
- return self.parse_transfers(data, None, since, limit, params)
2770
+ data = self.safe_dict(response, 'data', {})
2771
+ rows = self.safe_list(data, 'rows', [])
2772
+ return self.parse_transfers(rows, currency, since, limit, params)
2209
2773
 
2210
2774
  def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2211
2775
  #
@@ -2222,6 +2786,22 @@ class woo(Exchange, ImplicitAPI):
2222
2786
  # "created_time": "1709022325.427",
2223
2787
  # "updated_time": "1709022325.542"
2224
2788
  # }
2789
+ # {
2790
+ # "id": 225,
2791
+ # "token": "USDT",
2792
+ # "amount": "1000000",
2793
+ # "status": "COMPLETED",
2794
+ # "from": {
2795
+ # "applicationId": "046b5c5c-5b44-4d27-9593-ddc32c0a08ae",
2796
+ # "accountName": "Main"
2797
+ # },
2798
+ # "to": {
2799
+ # "applicationId": "082ae5ae-e26a-4fb1-be5b-03e5b4867663",
2800
+ # "accountName": "sub001"
2801
+ # },
2802
+ # "createdTime": "1642660941.534",
2803
+ # "updatedTime": "1642660941.950"
2804
+ # }
2225
2805
  #
2226
2806
  # transfer
2227
2807
  # {
@@ -2229,22 +2809,22 @@ class woo(Exchange, ImplicitAPI):
2229
2809
  # "id": 200
2230
2810
  # }
2231
2811
  #
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')
2812
+ code = self.safe_currency_code(self.safe_string(transfer, 'token'), currency)
2813
+ timestamp = self.safe_timestamp(transfer, 'createdTime')
2236
2814
  success = self.safe_bool(transfer, 'success')
2237
2815
  status: Str = None
2238
2816
  if success is not None:
2239
2817
  status = 'ok' if success else 'failed'
2818
+ fromAccount = self.safe_dict(transfer, 'from', {})
2819
+ toAccount = self.safe_dict(transfer, 'to', {})
2240
2820
  return {
2241
2821
  'id': self.safe_string(transfer, 'id'),
2242
2822
  'timestamp': timestamp,
2243
2823
  'datetime': self.iso8601(timestamp),
2244
2824
  'currency': code,
2245
2825
  'amount': self.safe_number(transfer, 'amount'),
2246
- 'fromAccount': self.safe_string(transfer, 'from_application_id'),
2247
- 'toAccount': self.safe_string(transfer, 'to_application_id'),
2826
+ 'fromAccount': self.safe_string(fromAccount, 'applicationId'),
2827
+ 'toAccount': self.safe_string(toAccount, 'applicationId'),
2248
2828
  'status': self.parse_transfer_status(self.safe_string(transfer, 'status', status)),
2249
2829
  'info': transfer,
2250
2830
  }
@@ -2259,10 +2839,12 @@ class woo(Exchange, ImplicitAPI):
2259
2839
  }
2260
2840
  return self.safe_string(statuses, status, status)
2261
2841
 
2262
- async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2842
+ async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
2263
2843
  """
2264
2844
  make a withdrawal
2265
- :see: https://docs.woo.org/#token-withdraw
2845
+
2846
+ https://docs.woox.io/#token-withdraw
2847
+
2266
2848
  :param str code: unified currency code
2267
2849
  :param float amount: the amount to withdraw
2268
2850
  :param str address: the address to withdraw to
@@ -2280,15 +2862,9 @@ class woo(Exchange, ImplicitAPI):
2280
2862
  }
2281
2863
  if tag is not None:
2282
2864
  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
2865
+ specialNetworkId: Str = None
2866
+ specialNetworkId, params = self.get_dedicated_network_id(currency, params)
2867
+ request['token'] = specialNetworkId
2292
2868
  response = await self.v1PrivatePostAssetWithdraw(self.extend(request, params))
2293
2869
  #
2294
2870
  # {
@@ -2298,10 +2874,12 @@ class woo(Exchange, ImplicitAPI):
2298
2874
  #
2299
2875
  return self.parse_transaction(response, currency)
2300
2876
 
2301
- async def repay_margin(self, code: str, amount, symbol: Str = None, params={}):
2877
+ async def repay_margin(self, code: str, amount: float, symbol: Str = None, params={}):
2302
2878
  """
2303
2879
  repay borrowed margin and interest
2304
- :see: https://docs.woo.org/#repay-interest
2880
+
2881
+ https://docs.woox.io/#repay-interest
2882
+
2305
2883
  :param str code: unified currency code of the currency to repay
2306
2884
  :param float amount: the amount to repay
2307
2885
  :param str symbol: not used by woo.repayMargin()
@@ -2347,7 +2925,7 @@ class woo(Exchange, ImplicitAPI):
2347
2925
  }
2348
2926
 
2349
2927
  def nonce(self):
2350
- return self.milliseconds()
2928
+ return self.milliseconds() - self.options['timeDifference']
2351
2929
 
2352
2930
  def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
2353
2931
  version = section[0]
@@ -2361,15 +2939,19 @@ class woo(Exchange, ImplicitAPI):
2361
2939
  url += access + '/' + pathWithParams
2362
2940
  if params:
2363
2941
  url += '?' + self.urlencode(params)
2942
+ elif access == 'pub':
2943
+ url += pathWithParams
2944
+ if params:
2945
+ url += '?' + self.urlencode(params)
2364
2946
  else:
2365
2947
  self.check_required_credentials()
2366
- if method == 'POST' and (path == 'algo/order' or path == 'order'):
2948
+ if method == 'POST' and (path == 'trade/algoOrder' or path == 'trade/order'):
2367
2949
  isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
2368
2950
  if not isSandboxMode:
2369
2951
  applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad'
2370
2952
  brokerId = self.safe_string(self.options, 'brokerId', applicationId)
2371
- isStop = path.find('algo') > -1
2372
- if isStop:
2953
+ isTrigger = path.find('algo') > -1
2954
+ if isTrigger:
2373
2955
  params['brokerId'] = brokerId
2374
2956
  else:
2375
2957
  params['broker_id'] = brokerId
@@ -2383,15 +2965,15 @@ class woo(Exchange, ImplicitAPI):
2383
2965
  }
2384
2966
  if version == 'v3':
2385
2967
  auth = ts + method + '/' + version + '/' + pathWithParams
2386
- if method == 'POST' or method == 'PUT' or method == 'DELETE':
2968
+ if method == 'POST' or method == 'PUT':
2387
2969
  body = self.json(params)
2388
2970
  auth += body
2971
+ headers['content-type'] = 'application/json'
2389
2972
  else:
2390
2973
  if params:
2391
2974
  query = self.urlencode(params)
2392
2975
  url += '?' + query
2393
2976
  auth += '?' + query
2394
- headers['content-type'] = 'application/json'
2395
2977
  else:
2396
2978
  auth = self.urlencode(params)
2397
2979
  if method == 'POST' or method == 'PUT' or method == 'DELETE':
@@ -2422,24 +3004,27 @@ class woo(Exchange, ImplicitAPI):
2422
3004
  def parse_income(self, income, market: Market = None):
2423
3005
  #
2424
3006
  # {
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"
3007
+ # "id": 1286360,
3008
+ # "symbol": "PERP_BTC_USDT",
3009
+ # "fundingRate": -0.00001445,
3010
+ # "markPrice": "26930.60000000",
3011
+ # "fundingFee": "9.56021744",
3012
+ # "fundingIntervalHours": 8,
3013
+ # "paymentType": "Pay",
3014
+ # "status": "COMPLETED",
3015
+ # "createdTime": 1696060873259,
3016
+ # "updatedTime": 1696060873286
2434
3017
  # }
2435
3018
  #
2436
3019
  marketId = self.safe_string(income, 'symbol')
2437
3020
  symbol = self.safe_symbol(marketId, market)
2438
- amount = self.safe_number(income, 'funding_fee')
3021
+ amount = self.safe_string(income, 'fundingFee')
2439
3022
  code = self.safe_currency_code('USD')
2440
3023
  id = self.safe_string(income, 'id')
2441
- timestamp = self.safe_timestamp(income, 'updated_time')
2442
- rate = self.safe_number(income, 'funding_rate')
3024
+ timestamp = self.safe_integer(income, 'updatedTime')
3025
+ rate = self.safe_number(income, 'fundingRate')
3026
+ paymentType = self.safe_string(income, 'paymentType')
3027
+ amount = Precise.string_neg(amount) if (paymentType == 'Pay') else amount
2443
3028
  return {
2444
3029
  'info': income,
2445
3030
  'symbol': symbol,
@@ -2447,63 +3032,92 @@ class woo(Exchange, ImplicitAPI):
2447
3032
  'timestamp': timestamp,
2448
3033
  'datetime': self.iso8601(timestamp),
2449
3034
  'id': id,
2450
- 'amount': amount,
3035
+ 'amount': self.parse_number(amount),
2451
3036
  'rate': rate,
2452
3037
  }
2453
3038
 
2454
3039
  async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3040
+ """
3041
+ fetch the history of funding payments paid and received on self account
3042
+
3043
+ https://developer.woox.io/api-reference/endpoint/futures/get_fundingFee_history
3044
+
3045
+ :param str [symbol]: unified market symbol
3046
+ :param int [since]: the earliest time in ms to fetch funding history for
3047
+ :param int [limit]: the maximum number of funding history structures to retrieve
3048
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3049
+ :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)
3050
+ :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
3051
+ """
2455
3052
  await self.load_markets()
3053
+ paginate = False
3054
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingHistory', 'paginate')
3055
+ if paginate:
3056
+ return await self.fetch_paginated_call_incremental('fetchFundingHistory', symbol, since, limit, params, 'page', 500)
2456
3057
  request: dict = {}
2457
3058
  market: Market = None
2458
3059
  if symbol is not None:
2459
3060
  market = self.market(symbol)
2460
3061
  request['symbol'] = market['id']
2461
3062
  if since is not None:
2462
- request['start_t'] = since
2463
- response = await self.v1PrivateGetFundingFeeHistory(self.extend(request, params))
3063
+ request['startTime'] = since
3064
+ until = self.safe_integer(params, 'until') # unified in milliseconds
3065
+ params = self.omit(params, ['until'])
3066
+ if until is not None:
3067
+ request['endTime'] = until
3068
+ if limit is not None:
3069
+ request['size'] = min(limit, 500)
3070
+ response = await self.v3PrivateGetFuturesFundingFeeHistory(self.extend(request, params))
2464
3071
  #
2465
3072
  # {
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
3073
+ # "success": True,
3074
+ # "data": {
3075
+ # "meta": {
3076
+ # "total": 670,
3077
+ # "recordsPerPage": 25,
3078
+ # "currentPage": 1
3079
+ # },
3080
+ # "rows": [
3081
+ # {
3082
+ # "id": 1286360,
3083
+ # "symbol": "PERP_BTC_USDT",
3084
+ # "fundingRate": -0.00001445,
3085
+ # "markPrice": "26930.60000000",
3086
+ # "fundingFee": "9.56021744",
3087
+ # "fundingIntervalHours": 8,
3088
+ # "paymentType": "Pay",
3089
+ # "status": "COMPLETED",
3090
+ # "createdTime": 1696060873259,
3091
+ # "updatedTime": 1696060873286
3092
+ # }
3093
+ # ]
2483
3094
  # },
2484
- # "success":true
3095
+ # "timestamp": 1721351502594
2485
3096
  # }
2486
3097
  #
2487
- result = self.safe_list(response, 'rows', [])
2488
- return self.parse_incomes(result, market, since, limit)
3098
+ data = self.safe_dict(response, 'data', {})
3099
+ rows = self.safe_list(data, 'rows', [])
3100
+ return self.parse_incomes(rows, market, since, limit)
2489
3101
 
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
- # }
3102
+ def parse_funding_rate(self, fundingRate, market: Market = None) -> FundingRate:
2500
3103
  #
3104
+ # {
3105
+ # "symbol": "PERP_BTC_USDT",
3106
+ # "estFundingRate": "-0.00000441",
3107
+ # "estFundingRateTimestamp": 1751623979022,
3108
+ # "lastFundingRate": "-0.00004953",
3109
+ # "lastFundingRateTimestamp": 1751616000000,
3110
+ # "nextFundingTime": 1751644800000,
3111
+ # "lastFundingIntervalHours": 8,
3112
+ # "estFundingIntervalHours": 8
3113
+ # }
2501
3114
  #
2502
3115
  symbol = self.safe_string(fundingRate, 'symbol')
2503
3116
  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')
3117
+ nextFundingTimestamp = self.safe_integer(fundingRate, 'nextFundingTime')
3118
+ estFundingRateTimestamp = self.safe_integer(fundingRate, 'estFundingRateTimestamp')
3119
+ lastFundingRateTimestamp = self.safe_integer(fundingRate, 'lastFundingRateTimestamp')
3120
+ intervalString = self.safe_string(fundingRate, 'estFundingIntervalHours')
2507
3121
  return {
2508
3122
  'info': fundingRate,
2509
3123
  'symbol': market['symbol'],
@@ -2513,66 +3127,114 @@ class woo(Exchange, ImplicitAPI):
2513
3127
  'estimatedSettlePrice': None,
2514
3128
  'timestamp': estFundingRateTimestamp,
2515
3129
  'datetime': self.iso8601(estFundingRateTimestamp),
2516
- 'fundingRate': self.safe_number(fundingRate, 'est_funding_rate'),
3130
+ 'fundingRate': self.safe_number(fundingRate, 'estFundingRate'),
2517
3131
  'fundingTimestamp': nextFundingTimestamp,
2518
3132
  'fundingDatetime': self.iso8601(nextFundingTimestamp),
2519
3133
  'nextFundingRate': None,
2520
3134
  'nextFundingTimestamp': None,
2521
3135
  'nextFundingDatetime': None,
2522
- 'previousFundingRate': self.safe_number(fundingRate, 'last_funding_rate'),
3136
+ 'previousFundingRate': self.safe_number(fundingRate, 'lastFundingRate'),
2523
3137
  'previousFundingTimestamp': lastFundingRateTimestamp,
2524
3138
  'previousFundingDatetime': self.iso8601(lastFundingRateTimestamp),
3139
+ 'interval': intervalString + 'h',
2525
3140
  }
2526
3141
 
2527
- async def fetch_funding_rate(self, symbol: str, params={}):
3142
+ async def fetch_funding_interval(self, symbol: str, params={}) -> FundingRate:
3143
+ """
3144
+ fetch the current funding rate interval
3145
+
3146
+ https://developer.woox.io/api-reference/endpoint/public_data/fundingRate
3147
+
3148
+ :param str symbol: unified market symbol
3149
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3150
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3151
+ """
3152
+ return await self.fetch_funding_rate(symbol, params)
3153
+
3154
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
3155
+ """
3156
+ fetch the current funding rate
3157
+
3158
+ https://developer.woox.io/api-reference/endpoint/public_data/fundingRate
3159
+
3160
+ :param str symbol: unified market symbol
3161
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3162
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3163
+ """
2528
3164
  await self.load_markets()
2529
3165
  market = self.market(symbol)
2530
3166
  request: dict = {
2531
3167
  'symbol': market['id'],
2532
3168
  }
2533
- response = await self.v1PublicGetFundingRateSymbol(self.extend(request, params))
3169
+ response = await self.v3PublicGetFundingRate(self.extend(request, params))
2534
3170
  #
2535
3171
  # {
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
3172
+ # "success": True,
3173
+ # "data": {
3174
+ # "rows": [
3175
+ # {
3176
+ # "symbol": "PERP_BTC_USDT",
3177
+ # "estFundingRate": "-0.00000441",
3178
+ # "estFundingRateTimestamp": 1751623979022,
3179
+ # "lastFundingRate": "-0.00004953",
3180
+ # "lastFundingRateTimestamp": 1751616000000,
3181
+ # "nextFundingTime": 1751644800000,
3182
+ # "lastFundingIntervalHours": 8,
3183
+ # "estFundingIntervalHours": 8
3184
+ # }
3185
+ # ]
3186
+ # },
3187
+ # "timestamp": 1751624037798
2544
3188
  # }
2545
3189
  #
2546
- return self.parse_funding_rate(response, market)
3190
+ data = self.safe_dict(response, 'data', {})
3191
+ rows = self.safe_list(data, 'rows', [])
3192
+ first = self.safe_dict(rows, 0, {})
3193
+ return self.parse_funding_rate(first, market)
3194
+
3195
+ async def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
3196
+ """
3197
+ fetch the funding rate for multiple markets
3198
+
3199
+ https://developer.woox.io/api-reference/endpoint/public_data/fundingRate
2547
3200
 
2548
- async def fetch_funding_rates(self, symbols: Strings = None, params={}):
3201
+ :param str[]|None symbols: list of unified market symbols
3202
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3203
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexed by market symbols
3204
+ """
2549
3205
  await self.load_markets()
2550
3206
  symbols = self.market_symbols(symbols)
2551
- response = await self.v1PublicGetFundingRates(params)
3207
+ response = await self.v3PublicGetFundingRate(params)
2552
3208
  #
2553
3209
  # {
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
3210
+ # "success": True,
3211
+ # "data": {
3212
+ # "rows": [
3213
+ # {
3214
+ # "symbol": "PERP_BTC_USDT",
3215
+ # "estFundingRate": "-0.00000441",
3216
+ # "estFundingRateTimestamp": 1751623979022,
3217
+ # "lastFundingRate": "-0.00004953",
3218
+ # "lastFundingRateTimestamp": 1751616000000,
3219
+ # "nextFundingTime": 1751644800000,
3220
+ # "lastFundingIntervalHours": 8,
3221
+ # "estFundingIntervalHours": 8
3222
+ # }
3223
+ # ]
3224
+ # },
3225
+ # "timestamp": 1751624037798
2566
3226
  # }
2567
3227
  #
2568
- rows = self.safe_list(response, 'rows', [])
2569
- result = self.parse_funding_rates(rows)
2570
- return self.filter_by_array(result, 'symbol', symbols)
3228
+ data = self.safe_dict(response, 'data', {})
3229
+ rows = self.safe_list(data, 'rows', [])
3230
+ return self.parse_funding_rates(rows, symbols)
2571
3231
 
2572
3232
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2573
3233
  """
2574
3234
  fetches historical funding rate prices
2575
- :see: https://docs.woo.org/#get-funding-rate-history-for-one-market-public
3235
+
3236
+ https://developer.woox.io/api-reference/endpoint/public_data/fundingRateHistory
3237
+
2576
3238
  :param str symbol: unified symbol of the market to fetch the funding rate history for
2577
3239
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
2578
3240
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
@@ -2586,44 +3248,50 @@ class woo(Exchange, ImplicitAPI):
2586
3248
  paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2587
3249
  if paginate:
2588
3250
  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']
3251
+ if symbol is None:
3252
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
3253
+ market = self.market(symbol)
3254
+ symbol = market['symbol']
3255
+ request: dict = {
3256
+ 'symbol': market['id'],
3257
+ }
2594
3258
  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))
3259
+ request['startTime'] = since
3260
+ request, params = self.handle_until_option('endTime', request, params)
3261
+ response = await self.v3PublicGetFundingRateHistory(self.extend(request, params))
2598
3262
  #
2599
3263
  # {
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
3264
+ # "success": True,
3265
+ # "data": {
3266
+ # "rows": [
3267
+ # {
3268
+ # "symbol": "PERP_BTC_USDT",
3269
+ # "fundingRate": "-0.00004953",
3270
+ # "fundingRateTimestamp": 1751616000000,
3271
+ # "nextFundingTime": 1751644800000,
3272
+ # "markPrice": "108708"
3273
+ # }
3274
+ # ],
3275
+ # "meta": {
3276
+ # "total": 11690,
3277
+ # "recordsPerPage": 25,
3278
+ # "currentPage": 1
2612
3279
  # }
2613
- # ],
2614
- # "timestamp":1653640814885
3280
+ # },
3281
+ # "timestamp": 1751632390031
2615
3282
  # }
2616
3283
  #
2617
- result = self.safe_list(response, 'rows')
3284
+ data = self.safe_dict(response, 'data', {})
3285
+ rows = self.safe_list(data, 'rows', [])
2618
3286
  rates = []
2619
- for i in range(0, len(result)):
2620
- entry = result[i]
3287
+ for i in range(0, len(rows)):
3288
+ entry = rows[i]
2621
3289
  marketId = self.safe_string(entry, 'symbol')
2622
- timestamp = self.safe_integer(entry, 'funding_rate_timestamp')
3290
+ timestamp = self.safe_integer(entry, 'fundingRateTimestamp')
2623
3291
  rates.append({
2624
3292
  'info': entry,
2625
3293
  'symbol': self.safe_symbol(marketId),
2626
- 'fundingRate': self.safe_number(entry, 'funding_rate'),
3294
+ 'fundingRate': self.safe_number(entry, 'fundingRate'),
2627
3295
  'timestamp': timestamp,
2628
3296
  'datetime': self.iso8601(timestamp),
2629
3297
  })
@@ -2633,7 +3301,9 @@ class woo(Exchange, ImplicitAPI):
2633
3301
  async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
2634
3302
  """
2635
3303
  set hedged to True or False for a market
2636
- :see: https://docs.woo.org/#update-position-mode
3304
+
3305
+ https://developer.woox.io/api-reference/endpoint/futures/position_mode
3306
+
2637
3307
  :param bool hedged: set to True to use HEDGE_MODE, False for ONE_WAY
2638
3308
  :param str symbol: not used by woo setPositionMode
2639
3309
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2645,14 +3315,13 @@ class woo(Exchange, ImplicitAPI):
2645
3315
  else:
2646
3316
  hedgeMode = 'ONE_WAY'
2647
3317
  request: dict = {
2648
- 'position_mode': hedgeMode,
3318
+ 'positionMode': hedgeMode,
2649
3319
  }
2650
- response = await self.v1PrivatePostClientPositionMode(self.extend(request, params))
3320
+ response = await self.v3PrivatePutFuturesPositionMode(self.extend(request, params))
2651
3321
  #
2652
3322
  # {
2653
3323
  # "success": True,
2654
- # "data": {},
2655
- # "timestamp": "1709195608551"
3324
+ # "timestamp": 1752550492845
2656
3325
  # }
2657
3326
  #
2658
3327
  return response
@@ -2660,112 +3329,296 @@ class woo(Exchange, ImplicitAPI):
2660
3329
  async def fetch_leverage(self, symbol: str, params={}) -> Leverage:
2661
3330
  """
2662
3331
  fetch the set leverage for a market
2663
- :see: https://docs.woo.org/#get-account-information-new
3332
+
3333
+ https://developer.woox.io/api-reference/endpoint/account/get_account_info
3334
+ https://developer.woox.io/api-reference/endpoint/futures/get_leverage
3335
+
2664
3336
  :param str symbol: unified market symbol
2665
3337
  :param dict [params]: extra parameters specific to the exchange API endpoint
3338
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated'
3339
+ :param str [params.positionMode]: *for swap markets only* 'ONE_WAY' or 'HEDGE_MODE'
2666
3340
  :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
2667
3341
  """
2668
3342
  await self.load_markets()
2669
3343
  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
- #
3344
+ response: dict = None
3345
+ if market['spot']:
3346
+ response = await self.v3PrivateGetAccountInfo(params)
3347
+ #
3348
+ # {
3349
+ # "success": True,
3350
+ # "data": {
3351
+ # "applicationId": "dsa",
3352
+ # "account": "dsa",
3353
+ # "alias": "haha",
3354
+ # "otpauth": True,
3355
+ # "accountMode": "FUTURES",
3356
+ # "positionMode": "ONE_WAY",
3357
+ # "leverage": 0,
3358
+ # "marginRatio": "10",
3359
+ # "openMarginRatio": "10",
3360
+ # "initialMarginRatio": "10",
3361
+ # "maintenanceMarginRatio": "0.03",
3362
+ # "totalCollateral": "165.6115334",
3363
+ # "freeCollateral": "165.6115334",
3364
+ # "totalAccountValue": "167.52723093",
3365
+ # "totalTradingValue": "167.52723093",
3366
+ # "totalVaultValue": "0",
3367
+ # "totalStakingValue": "0",
3368
+ # "totalLaunchpadValue": "0",
3369
+ # "totalEarnValue": "0",
3370
+ # "referrerID": null,
3371
+ # "accountType": "Main"
3372
+ # },
3373
+ # "timestamp": 1752645129054
3374
+ # }
3375
+ #
3376
+ elif market['swap']:
3377
+ request: dict = {
3378
+ 'symbol': market['id'],
3379
+ }
3380
+ marginMode: Str = None
3381
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params, 'cross')
3382
+ request['marginMode'] = self.encode_margin_mode(marginMode)
3383
+ response = await self.v3PrivateGetFuturesLeverage(self.extend(request, params))
3384
+ #
3385
+ # HEDGE_MODE
3386
+ # {
3387
+ # "success": True,
3388
+ # "data":
3389
+ # {
3390
+ # "symbol": "PERP_ETH_USDT",
3391
+ # "marginMode": "CROSS",
3392
+ # "positionMode": "HEDGE_MODE",
3393
+ # "details": [
3394
+ # {
3395
+ # "positionSide": "LONG",
3396
+ # "leverage": 10
3397
+ # },
3398
+ # {
3399
+ # "positionSide": "SHORT",
3400
+ # "leverage": 10
3401
+ # }
3402
+ # ]
3403
+ # },
3404
+ # "timestamp": 1720886470482
3405
+ # }
3406
+ #
3407
+ # ONE_WAY
3408
+ # {
3409
+ # "success": True,
3410
+ # "data": {
3411
+ # "symbol": "PERP_ETH_USDT",
3412
+ # "marginMode": "ISOLATED",
3413
+ # "positionMode": "ONE_WAY",
3414
+ # "details": [
3415
+ # {
3416
+ # "positionSide": "BOTH",
3417
+ # "leverage": 10
3418
+ # }
3419
+ # ]
3420
+ # },
3421
+ # "timestamp": 1720886810317
3422
+ # }
3423
+ #
3424
+ else:
3425
+ raise NotSupported(self.id + ' fetchLeverage() is not supported for ' + market['type'] + ' markets')
2699
3426
  data = self.safe_dict(response, 'data', {})
2700
3427
  return self.parse_leverage(data, market)
2701
3428
 
2702
3429
  def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
2703
- leverageValue = self.safe_integer(leverage, 'leverage')
3430
+ marketId = self.safe_string(leverage, 'symbol')
3431
+ market = self.safe_market(marketId, market)
3432
+ marginMode = self.safe_string_lower(leverage, 'marginMode')
3433
+ spotLeverage = self.safe_integer(leverage, 'leverage')
3434
+ if spotLeverage == 0:
3435
+ spotLeverage = None
3436
+ longLeverage = spotLeverage
3437
+ shortLeverage = spotLeverage
3438
+ details = self.safe_list(leverage, 'details', [])
3439
+ for i in range(0, len(details)):
3440
+ position = self.safe_dict(details, i, {})
3441
+ positionLeverage = self.safe_integer(position, 'leverage')
3442
+ side = self.safe_string(position, 'positionSide')
3443
+ if side == 'BOTH':
3444
+ longLeverage = positionLeverage
3445
+ shortLeverage = positionLeverage
3446
+ elif side == 'LONG':
3447
+ longLeverage = positionLeverage
3448
+ elif side == 'SHORT':
3449
+ shortLeverage = positionLeverage
2704
3450
  return {
2705
3451
  'info': leverage,
2706
3452
  'symbol': market['symbol'],
2707
- 'marginMode': None,
2708
- 'longLeverage': leverageValue,
2709
- 'shortLeverage': leverageValue,
3453
+ 'marginMode': marginMode,
3454
+ 'longLeverage': longLeverage,
3455
+ 'shortLeverage': shortLeverage,
2710
3456
  }
2711
3457
 
2712
- async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
3458
+ async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
3459
+ """
3460
+ set the level of leverage for a market
3461
+
3462
+ https://developer.woox.io/api-reference/endpoint/spot_margin/set_leverage
3463
+ https://developer.woox.io/api-reference/endpoint/futures/set_leverage
3464
+
3465
+ :param float leverage: the rate of leverage(1, 2, 3, 4 or 5 for spot markets, 1, 2, 3, 4, 5, 10, 15, 20 for swap markets)
3466
+ :param str [symbol]: unified market symbol(is mandatory for swap markets)
3467
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3468
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated'
3469
+ :param str [params.positionMode]: *for swap markets only* 'ONE_WAY' or 'HEDGE_MODE'
3470
+ :returns dict: response from the exchange
3471
+ """
2713
3472
  await self.load_markets()
2714
- if (leverage < 1) or (leverage > 20):
2715
- raise BadRequest(self.id + ' leverage should be between 1 and 20')
2716
3473
  request: dict = {
2717
3474
  'leverage': leverage,
2718
3475
  }
2719
- return await self.v1PrivatePostClientLeverage(self.extend(request, params))
3476
+ market: Market = None
3477
+ if symbol is not None:
3478
+ market = self.market(symbol)
3479
+ if (symbol is None) or market['spot']:
3480
+ return await self.v3PrivatePostSpotMarginLeverage(self.extend(request, params))
3481
+ elif market['swap']:
3482
+ request['symbol'] = market['id']
3483
+ marginMode: Str = None
3484
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params, 'cross')
3485
+ request['marginMode'] = self.encode_margin_mode(marginMode)
3486
+ return await self.v3PrivatePutFuturesLeverage(self.extend(request, params))
3487
+ else:
3488
+ raise NotSupported(self.id + ' fetchLeverage() is not supported for ' + market['type'] + ' markets')
3489
+
3490
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3491
+ """
3492
+ add margin
3493
+
3494
+ https://docs.woox.io/#update-isolated-margin-setting
3495
+
3496
+ :param str symbol: unified market symbol
3497
+ :param float amount: amount of margin to add
3498
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3499
+ :param str [params.position_side]: 'LONG' or 'SHORT' in hedge mode, 'BOTH' in one way mode
3500
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
3501
+ """
3502
+ return await self.modify_margin_helper(symbol, amount, 'ADD', params)
3503
+
3504
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3505
+ """
3506
+ remove margin from a position
3507
+
3508
+ https://docs.woox.io/#update-isolated-margin-setting
3509
+
3510
+ :param str symbol: unified market symbol
3511
+ :param float amount: amount of margin to remove
3512
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3513
+ :param str [params.position_side]: 'LONG' or 'SHORT' in hedge mode, 'BOTH' in one way mode
3514
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
3515
+ """
3516
+ return await self.modify_margin_helper(symbol, amount, 'REDUCE', params)
3517
+
3518
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
3519
+ await self.load_markets()
3520
+ market = self.market(symbol)
3521
+ request: dict = {
3522
+ 'symbol': market['id'],
3523
+ 'adjust_token': 'USDT', # todo check
3524
+ 'adjust_amount': amount,
3525
+ 'action': type,
3526
+ }
3527
+ return await self.v1PrivatePostClientIsolatedMargin(self.extend(request, params))
2720
3528
 
2721
- async def fetch_position(self, symbol: Str = None, params={}):
3529
+ async def fetch_position(self, symbol: Str, params={}):
3530
+ """
3531
+ fetch data on an open position
3532
+
3533
+ https://developer.woox.io/api-reference/endpoint/futures/get_positions
3534
+
3535
+ :param str symbol: unified market symbol of the market the position is held in
3536
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3537
+ :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3538
+ """
2722
3539
  await self.load_markets()
2723
3540
  market = self.market(symbol)
2724
3541
  request: dict = {
2725
3542
  'symbol': market['id'],
2726
3543
  }
2727
- response = await self.v1PrivateGetPositionSymbol(self.extend(request, params))
3544
+ response = await self.v3PrivateGetFuturesPositions(self.extend(request, params))
2728
3545
  #
2729
3546
  # {
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"
3547
+ # "success": True,
3548
+ # "data": {
3549
+ # "positions": [
3550
+ # {
3551
+ # "symbol": "PERP_LTC_USDT",
3552
+ # "holding": "0.1",
3553
+ # "pendingLongQty": "0",
3554
+ # "pendingShortQty": "0",
3555
+ # "settlePrice": "96.87",
3556
+ # "averageOpenPrice": "96.87",
3557
+ # "pnl24H": "0",
3558
+ # "fee24H": "0.0048435",
3559
+ # "markPrice": "96.83793449",
3560
+ # "estLiqPrice": "0",
3561
+ # "timestamp": 1752500555823,
3562
+ # "adlQuantile": 2,
3563
+ # "positionSide": "BOTH",
3564
+ # "marginMode": "CROSS",
3565
+ # "isolatedMarginToken": "",
3566
+ # "isolatedMarginAmount": "0",
3567
+ # "isolatedFrozenLong": "0",
3568
+ # "isolatedFrozenShort": "0",
3569
+ # "leverage": 10
3570
+ # }
3571
+ # ]
3572
+ # },
3573
+ # "timestamp": 1752500579848
2741
3574
  # }
2742
3575
  #
2743
- return self.parse_position(response, market)
3576
+ result = self.safe_dict(response, 'data', {})
3577
+ positions = self.safe_list(result, 'positions', [])
3578
+ first = self.safe_dict(positions, 0, {})
3579
+ return self.parse_position(first, market)
3580
+
3581
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3582
+ """
3583
+ fetch all open positions
2744
3584
 
2745
- async def fetch_positions(self, symbols: Strings = None, params={}):
3585
+ https://developer.woox.io/api-reference/endpoint/futures/get_positions
3586
+
3587
+ :param str[] [symbols]: list of unified market symbols
3588
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3589
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3590
+ """
2746
3591
  await self.load_markets()
2747
- response = await self.v3PrivateGetPositions(params)
3592
+ response = await self.v3PrivateGetFuturesPositions(params)
2748
3593
  #
2749
3594
  # {
2750
3595
  # "success": True,
2751
3596
  # "data": {
2752
3597
  # "positions": [
2753
3598
  # {
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
3599
+ # "symbol": "PERP_LTC_USDT",
3600
+ # "holding": "0.1",
3601
+ # "pendingLongQty": "0",
3602
+ # "pendingShortQty": "0",
3603
+ # "settlePrice": "96.87",
3604
+ # "averageOpenPrice": "96.87",
3605
+ # "pnl24H": "0",
3606
+ # "fee24H": "0.0048435",
3607
+ # "markPrice": "96.83793449",
3608
+ # "estLiqPrice": "0",
3609
+ # "timestamp": 1752500555823,
3610
+ # "adlQuantile": 2,
3611
+ # "positionSide": "BOTH",
3612
+ # "marginMode": "CROSS",
3613
+ # "isolatedMarginToken": "",
3614
+ # "isolatedMarginAmount": "0",
3615
+ # "isolatedFrozenLong": "0",
3616
+ # "isolatedFrozenShort": "0",
3617
+ # "leverage": 10
2765
3618
  # }
2766
3619
  # ]
2767
3620
  # },
2768
- # "timestamp": 1673323880342
3621
+ # "timestamp": 1752500579848
2769
3622
  # }
2770
3623
  #
2771
3624
  result = self.safe_dict(response, 'data', {})
@@ -2774,18 +3627,51 @@ class woo(Exchange, ImplicitAPI):
2774
3627
 
2775
3628
  def parse_position(self, position: dict, market: Market = None):
2776
3629
  #
3630
+ # v1PrivateGetPositionSymbol
3631
+ # {
3632
+ # "symbol": "PERP_ETH_USDT",
3633
+ # "position_side": "BOTH",
3634
+ # "leverage": 10,
3635
+ # "margin_mode": "CROSS",
3636
+ # "average_open_price": 3139.9,
3637
+ # "isolated_margin_amount": 0.0,
3638
+ # "isolated_margin_token": "",
3639
+ # "opening_time": "1720627963.094",
3640
+ # "mark_price": 3155.19169891,
3641
+ # "pending_short_qty": 0.0,
3642
+ # "pending_long_qty": 0.0,
3643
+ # "holding": -0.7,
3644
+ # "pnl_24_h": 0.0,
3645
+ # "est_liq_price": 9107.40055552,
3646
+ # "settle_price": 3151.0319904,
3647
+ # "success": True,
3648
+ # "fee_24_h": 0.0,
3649
+ # "isolated_frozen_long": 0.0,
3650
+ # "isolated_frozen_short": 0.0,
3651
+ # "timestamp": "1720867502.544"
3652
+ # }
3653
+ #
3654
+ # v3PrivateGetPositions
2777
3655
  # {
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
3656
+ # "symbol": "PERP_LTC_USDT",
3657
+ # "holding": "0.1",
3658
+ # "pendingLongQty": "0",
3659
+ # "pendingShortQty": "0",
3660
+ # "settlePrice": "96.87",
3661
+ # "averageOpenPrice": "96.87",
3662
+ # "pnl24H": "0",
3663
+ # "fee24H": "0.0048435",
3664
+ # "markPrice": "96.83793449",
3665
+ # "estLiqPrice": "0",
3666
+ # "timestamp": 1752500555823,
3667
+ # "adlQuantile": 2,
3668
+ # "positionSide": "BOTH",
3669
+ # "marginMode": "CROSS",
3670
+ # "isolatedMarginToken": "",
3671
+ # "isolatedMarginAmount": "0",
3672
+ # "isolatedFrozenLong": "0",
3673
+ # "isolatedFrozenShort": "0",
3674
+ # "leverage": 10
2789
3675
  # }
2790
3676
  #
2791
3677
  contract = self.safe_string(position, 'symbol')
@@ -2797,13 +3683,20 @@ class woo(Exchange, ImplicitAPI):
2797
3683
  else:
2798
3684
  side = 'short'
2799
3685
  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')
3686
+ markPrice = self.safe_string_2(position, 'markPrice', 'mark_price')
3687
+ timestampString = self.safe_string(position, 'timestamp')
3688
+ timestamp = None
3689
+ if timestampString is not None:
3690
+ if timestampString.find('.') > -1:
3691
+ timestamp = self.safe_timestamp(position, 'timestamp')
3692
+ else:
3693
+ timestamp = self.safe_integer(position, 'timestamp')
3694
+ entryPrice = self.safe_string_2(position, 'averageOpenPrice', 'average_open_price')
2803
3695
  priceDifference = Precise.string_sub(markPrice, entryPrice)
2804
3696
  unrealisedPnl = Precise.string_mul(priceDifference, size)
2805
3697
  size = Precise.string_abs(size)
2806
3698
  notional = Precise.string_mul(size, markPrice)
3699
+ positionSide = self.safe_string(position, 'positionSide') # 'SHORT' or 'LONG' for hedged, 'BOTH' for non-hedged
2807
3700
  return self.safe_position({
2808
3701
  'info': position,
2809
3702
  'id': None,
@@ -2817,20 +3710,19 @@ class woo(Exchange, ImplicitAPI):
2817
3710
  'maintenanceMarginPercentage': None,
2818
3711
  'entryPrice': self.parse_number(entryPrice),
2819
3712
  'notional': self.parse_number(notional),
2820
- 'leverage': None,
3713
+ 'leverage': self.safe_number(position, 'leverage'),
2821
3714
  'unrealizedPnl': self.parse_number(unrealisedPnl),
2822
3715
  'contracts': self.parse_number(size),
2823
3716
  'contractSize': self.parse_number(contractSize),
2824
3717
  'marginRatio': None,
2825
- 'liquidationPrice': self.safe_number(position, 'estLiqPrice'),
3718
+ 'liquidationPrice': self.safe_number_2(position, 'estLiqPrice', 'est_liq_price'),
2826
3719
  'markPrice': self.parse_number(markPrice),
2827
3720
  'lastPrice': None,
2828
3721
  'collateral': None,
2829
- 'marginMode': 'cross',
2830
- 'marginType': None,
3722
+ 'marginMode': self.safe_string_lower_2(position, 'marginMode', 'margin_mode'),
2831
3723
  'side': side,
2832
3724
  'percentage': None,
2833
- 'hedged': None,
3725
+ 'hedged': positionSide != 'BOTH',
2834
3726
  'stopLossPrice': None,
2835
3727
  'takeProfitPrice': None,
2836
3728
  })
@@ -2838,7 +3730,9 @@ class woo(Exchange, ImplicitAPI):
2838
3730
  async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
2839
3731
  """
2840
3732
  fetch a quote for converting from one currency to another
2841
- :see: https://docs.woo.org/#get-quote-rfq
3733
+
3734
+ https://docs.woox.io/#get-quote-rfq
3735
+
2842
3736
  :param str fromCode: the currency that you want to sell and convert from
2843
3737
  :param str toCode: the currency that you want to buy and convert into
2844
3738
  :param float [amount]: how much you want to trade in units of the from currency
@@ -2878,7 +3772,9 @@ class woo(Exchange, ImplicitAPI):
2878
3772
  async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
2879
3773
  """
2880
3774
  convert from one currency to another
2881
- :see: https://docs.woo.org/#send-quote-rft
3775
+
3776
+ https://docs.woox.io/#send-quote-rft
3777
+
2882
3778
  :param str id: the id of the trade that you want to make
2883
3779
  :param str fromCode: the currency that you want to sell and convert from
2884
3780
  :param str toCode: the currency that you want to buy and convert into
@@ -2907,7 +3803,9 @@ class woo(Exchange, ImplicitAPI):
2907
3803
  async def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
2908
3804
  """
2909
3805
  fetch the data for a conversion trade
2910
- :see: https://docs.woo.org/#get-quote-trade
3806
+
3807
+ https://docs.woox.io/#get-quote-trade
3808
+
2911
3809
  :param str id: the id of the trade that you want to fetch
2912
3810
  :param str [code]: the unified currency code of the conversion trade
2913
3811
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2946,7 +3844,9 @@ class woo(Exchange, ImplicitAPI):
2946
3844
  async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
2947
3845
  """
2948
3846
  fetch the users history of conversion trades
2949
- :see: https://docs.woo.org/#get-quote-trades
3847
+
3848
+ https://docs.woox.io/#get-quote-trades
3849
+
2950
3850
  :param str [code]: the unified currency code
2951
3851
  :param int [since]: the earliest time in ms to fetch conversions for
2952
3852
  :param int [limit]: the maximum number of conversion structures to retrieve
@@ -3043,7 +3943,9 @@ class woo(Exchange, ImplicitAPI):
3043
3943
  async def fetch_convert_currencies(self, params={}) -> Currencies:
3044
3944
  """
3045
3945
  fetches all available currencies that can be converted
3046
- :see: https://docs.woo.org/#get-quote-asset-info
3946
+
3947
+ https://docs.woox.io/#get-quote-asset-info
3948
+
3047
3949
  :param dict [params]: extra parameters specific to the exchange API endpoint
3048
3950
  :returns dict: an associative dictionary of currencies
3049
3951
  """