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