ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/kucoin.py CHANGED
@@ -8,7 +8,7 @@ from ccxt.abstract.kucoin import ImplicitAPI
8
8
  import hashlib
9
9
  import math
10
10
  import json
11
- from ccxt.base.types import Account, Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
11
+ from ccxt.base.types import Account, Any, Balances, BorrowInterest, Bool, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import AuthenticationError
@@ -32,7 +32,7 @@ from ccxt.base.precise import Precise
32
32
 
33
33
  class kucoin(Exchange, ImplicitAPI):
34
34
 
35
- def describe(self):
35
+ def describe(self) -> Any:
36
36
  return self.deep_extend(super(kucoin, self).describe(), {
37
37
  'id': 'kucoin',
38
38
  'name': 'KuCoin',
@@ -78,6 +78,7 @@ class kucoin(Exchange, ImplicitAPI):
78
78
  'fetchCrossBorrowRates': False,
79
79
  'fetchCurrencies': True,
80
80
  'fetchDepositAddress': True,
81
+ 'fetchDepositAddresses': False,
81
82
  'fetchDepositAddressesByNetwork': True,
82
83
  'fetchDeposits': True,
83
84
  'fetchDepositWithdrawFee': True,
@@ -97,6 +98,8 @@ class kucoin(Exchange, ImplicitAPI):
97
98
  'fetchMarketLeverageTiers': False,
98
99
  'fetchMarkets': True,
99
100
  'fetchMarkOHLCV': False,
101
+ 'fetchMarkPrice': True,
102
+ 'fetchMarkPrices': True,
100
103
  'fetchMyTrades': True,
101
104
  'fetchOHLCV': True,
102
105
  'fetchOpenInterest': False,
@@ -123,7 +126,7 @@ class kucoin(Exchange, ImplicitAPI):
123
126
  'fetchWithdrawals': True,
124
127
  'repayCrossMargin': True,
125
128
  'repayIsolatedMargin': True,
126
- 'setLeverage': False,
129
+ 'setLeverage': True,
127
130
  'setMarginMode': False,
128
131
  'setPositionMode': False,
129
132
  'signIn': False,
@@ -178,7 +181,9 @@ class kucoin(Exchange, ImplicitAPI):
178
181
  'status': 4.5, # 3PW
179
182
  # margin trading
180
183
  'mark-price/{symbol}/current': 3, # 2PW
184
+ 'mark-price/all-symbols': 3,
181
185
  'margin/config': 25, # 25SW
186
+ 'announcements': 20, # 20W
182
187
  },
183
188
  'post': {
184
189
  # ws
@@ -217,8 +222,10 @@ class kucoin(Exchange, ImplicitAPI):
217
222
  'market/orderbook/level{level}': 3, # 3SW
218
223
  'market/orderbook/level2': 3, # 3SW
219
224
  'market/orderbook/level3': 3, # 3SW
225
+ 'hf/accounts/opened': 2, #
220
226
  'hf/orders/active': 2, # 2SW
221
227
  'hf/orders/active/symbols': 2, # 2SW
228
+ 'hf/margin/order/active/symbols': 2, # 2SW
222
229
  'hf/orders/done': 2, # 2SW
223
230
  'hf/orders/{orderId}': 2, # 2SW
224
231
  'hf/orders/client-order/{clientOid}': 2, # 2SW
@@ -247,6 +254,7 @@ class kucoin(Exchange, ImplicitAPI):
247
254
  'margin/currencies': 20, # 20SW
248
255
  'risk/limit/strategy': 20, # 20SW(Deprecate)
249
256
  'isolated/symbols': 20, # 20SW
257
+ 'margin/symbols': 5,
250
258
  'isolated/account/{symbol}': 50, # 50SW
251
259
  'margin/borrow': 15, # 15SW
252
260
  'margin/repay': 15, # 15SW
@@ -257,6 +265,9 @@ class kucoin(Exchange, ImplicitAPI):
257
265
  'purchase/orders': 10, # 10SW
258
266
  # broker
259
267
  'broker/api/rebase/download': 3,
268
+ 'migrate/user/account/status': 3,
269
+ # affiliate
270
+ 'affiliate/inviter/statistics': 30,
260
271
  },
261
272
  'post': {
262
273
  # account
@@ -296,6 +307,8 @@ class kucoin(Exchange, ImplicitAPI):
296
307
  'lend/purchase/update': 10, # 10SW
297
308
  # ws
298
309
  'bullet-private': 10, # 10SW
310
+ 'position/update-user-leverage': 5,
311
+ 'deposit-address/create': 20,
299
312
  },
300
313
  'delete': {
301
314
  # account
@@ -408,6 +421,7 @@ class kucoin(Exchange, ImplicitAPI):
408
421
  'broker/nd/account': 2,
409
422
  'broker/nd/account/apikey': 2,
410
423
  'broker/nd/rebase/download': 3,
424
+ 'asset/ndbroker/deposit/list': 1,
411
425
  'broker/nd/transfer/detail': 1,
412
426
  'broker/nd/deposit/detail': 1,
413
427
  'broker/nd/withdraw/detail': 1,
@@ -461,6 +475,7 @@ class kucoin(Exchange, ImplicitAPI):
461
475
  'precisionMode': TICK_SIZE,
462
476
  'exceptions': {
463
477
  'exact': {
478
+ 'The order does not exist.': OrderNotFound,
464
479
  'order not exist': OrderNotFound,
465
480
  'order not exist.': OrderNotFound, # duplicated error temporarily
466
481
  'order_not_exist': OrderNotFound, # {"code":"order_not_exist","msg":"order_not_exist"} ¯\_(ツ)_/¯
@@ -561,6 +576,7 @@ class kucoin(Exchange, ImplicitAPI):
561
576
  '400008': NotSupported,
562
577
  '400100': InsufficientFunds, # {"msg":"account.available.amount","code":"400100"} or {"msg":"Withdrawal amount is below the minimum requirement.","code":"400100"}
563
578
  '400200': InvalidOrder, # {"code":"400200","msg":"Forbidden to place an order"}
579
+ '400330': InvalidOrder, # {"msg":"Order price can't deviate from NAV by 50%","code":"400330"}
564
580
  '400350': InvalidOrder, # {"code":"400350","msg":"Upper limit for holding: 10,000USDT, you can still buy 10,000USDT worth of coin."}
565
581
  '400370': InvalidOrder, # {"code":"400370","msg":"Max. price: 0.02500000000000000000"}
566
582
  '400400': BadRequest, # Parameter error
@@ -575,6 +591,8 @@ class kucoin(Exchange, ImplicitAPI):
575
591
  '400303': PermissionDenied, # {"msg":"To enjoy the full range of our products and services, we kindly request you complete the identity verification process.","code":"400303"}
576
592
  '500000': ExchangeNotAvailable, # {"code":"500000","msg":"Internal Server Error"}
577
593
  '260220': InvalidAddress, # {"code": "260220", "msg": "deposit.address.not.exists"}
594
+ '600100': InsufficientFunds, # {"msg":"Funds below the minimum requirement.","code":"600100"}
595
+ '600101': InvalidOrder, # {"msg":"The order funds should more then 0.1 USDT.","code":"600101"}
578
596
  '900014': BadRequest, # {"code":"900014","msg":"Invalid chainId"}
579
597
  },
580
598
  'broad': {
@@ -634,11 +652,15 @@ class kucoin(Exchange, ImplicitAPI):
634
652
  'WAX': 'WAXP',
635
653
  'ALT': 'APTOSLAUNCHTOKEN',
636
654
  'KALT': 'ALT', # ALTLAYER
655
+ 'FUD': 'FTX Users\' Debt',
637
656
  },
638
657
  'options': {
658
+ 'hf': None, # would be auto set to `true/false` after first load
639
659
  'version': 'v1',
640
660
  'symbolSeparator': '-',
641
661
  'fetchMyTradesMethod': 'private_get_fills',
662
+ 'timeDifference': 0, # the difference between system clock and Binance clock
663
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
642
664
  'fetchCurrencies': {
643
665
  'webApiEnable': True, # fetches from WEB
644
666
  'webApiRetries': 1,
@@ -658,6 +680,8 @@ class kucoin(Exchange, ImplicitAPI):
658
680
  'currencies': 'v3',
659
681
  'currencies/{currency}': 'v3',
660
682
  'symbols': 'v2',
683
+ 'mark-price/all-symbols': 'v3',
684
+ 'announcements': 'v3',
661
685
  },
662
686
  },
663
687
  'private': {
@@ -682,6 +706,7 @@ class kucoin(Exchange, ImplicitAPI):
682
706
  'oco/orders': 'v3',
683
707
  # margin trading
684
708
  'hf/margin/orders/active': 'v3',
709
+ 'hf/margin/order/active/symbols': 'v3',
685
710
  'hf/margin/orders/done': 'v3',
686
711
  'hf/margin/orders/{orderId}': 'v3',
687
712
  'hf/margin/orders/client-order/{clientOid}': 'v3',
@@ -695,6 +720,10 @@ class kucoin(Exchange, ImplicitAPI):
695
720
  'project/marketInterestRate': 'v3',
696
721
  'redeem/orders': 'v3',
697
722
  'purchase/orders': 'v3',
723
+ 'migrate/user/account/status': 'v3',
724
+ 'margin/symbols': 'v3',
725
+ 'affiliate/inviter/statistics': 'v2',
726
+ 'asset/ndbroker/deposit/list': 'v1',
698
727
  },
699
728
  'POST': {
700
729
  # account
@@ -704,6 +733,7 @@ class kucoin(Exchange, ImplicitAPI):
704
733
  'accounts/sub-transfer': 'v2',
705
734
  'accounts/inner-transfer': 'v2',
706
735
  'transfer-out': 'v3',
736
+ 'deposit-address/create': 'v3',
707
737
  # spot trading
708
738
  'oco/order': 'v3',
709
739
  # margin trading
@@ -714,6 +744,8 @@ class kucoin(Exchange, ImplicitAPI):
714
744
  'purchase': 'v3',
715
745
  'redeem': 'v3',
716
746
  'lend/purchase/update': 'v3',
747
+ 'position/update-user-leverage': 'v3',
748
+ 'withdrawals': 'v3',
717
749
  },
718
750
  'DELETE': {
719
751
  # account
@@ -761,7 +793,7 @@ class kucoin(Exchange, ImplicitAPI):
761
793
  'hf': 'trade_hf',
762
794
  },
763
795
  'networks': {
764
- 'BTC': 'btc',
796
+ 'BRC20': 'btc',
765
797
  'BTCNATIVESEGWIT': 'bech32',
766
798
  'ERC20': 'eth',
767
799
  'TRC20': 'trx',
@@ -898,6 +930,8 @@ class kucoin(Exchange, ImplicitAPI):
898
930
  'TRUE': 'true',
899
931
  'CS': 'cs',
900
932
  'ORAI': 'orai',
933
+ 'BASE': 'base',
934
+ 'TARA': 'tara',
901
935
  # below will be uncommented after consensus
902
936
  # 'BITCOINDIAMON': 'bcd',
903
937
  # 'BITCOINGOLD': 'btg',
@@ -973,15 +1007,89 @@ class kucoin(Exchange, ImplicitAPI):
973
1007
  'spot': 'TRADE',
974
1008
  },
975
1009
  },
1010
+ 'features': {
1011
+ 'spot': {
1012
+ 'sandbox': False,
1013
+ 'createOrder': {
1014
+ 'marginMode': True,
1015
+ 'triggerPrice': True,
1016
+ 'triggerPriceType': None,
1017
+ 'triggerDirection': False,
1018
+ 'stopLossPrice': True,
1019
+ 'takeProfitPrice': True,
1020
+ 'attachedStopLossTakeProfit': None, # not supported
1021
+ 'timeInForce': {
1022
+ 'IOC': True,
1023
+ 'FOK': True,
1024
+ 'PO': True,
1025
+ 'GTD': True,
1026
+ },
1027
+ 'hedged': False,
1028
+ 'trailing': False,
1029
+ 'leverage': False,
1030
+ 'marketBuyByCost': True,
1031
+ 'marketBuyRequiresPrice': False,
1032
+ 'selfTradePrevention': True, # todo implement
1033
+ 'iceberg': True, # todo implement
1034
+ },
1035
+ 'createOrders': {
1036
+ 'max': 5,
1037
+ },
1038
+ 'fetchMyTrades': {
1039
+ 'marginMode': True,
1040
+ 'limit': None,
1041
+ 'daysBack': None,
1042
+ 'untilDays': 7, # per implementation comments
1043
+ 'symbolRequired': True,
1044
+ },
1045
+ 'fetchOrder': {
1046
+ 'marginMode': False,
1047
+ 'trigger': True,
1048
+ 'trailing': False,
1049
+ 'symbolRequired': True,
1050
+ },
1051
+ 'fetchOpenOrders': {
1052
+ 'marginMode': True,
1053
+ 'limit': 500,
1054
+ 'trigger': True,
1055
+ 'trailing': False,
1056
+ 'symbolRequired': True,
1057
+ },
1058
+ 'fetchOrders': None,
1059
+ 'fetchClosedOrders': {
1060
+ 'marginMode': True,
1061
+ 'limit': 500,
1062
+ 'daysBack': None,
1063
+ 'daysBackCanceled': None,
1064
+ 'untilDays': 7,
1065
+ 'trigger': True,
1066
+ 'trailing': False,
1067
+ 'symbolRequired': True,
1068
+ },
1069
+ 'fetchOHLCV': {
1070
+ 'limit': 1500,
1071
+ },
1072
+ },
1073
+ 'swap': {
1074
+ 'linear': None,
1075
+ 'inverse': None,
1076
+ },
1077
+ 'future': {
1078
+ 'linear': None,
1079
+ 'inverse': None,
1080
+ },
1081
+ },
976
1082
  })
977
1083
 
978
1084
  def nonce(self):
979
- return self.milliseconds()
1085
+ return self.milliseconds() - self.options['timeDifference']
980
1086
 
981
- def fetch_time(self, params={}):
1087
+ def fetch_time(self, params={}) -> Int:
982
1088
  """
983
1089
  fetches the current integer timestamp in milliseconds from the exchange server
984
- :see: https://docs.kucoin.com/#server-time
1090
+
1091
+ https://docs.kucoin.com/#server-time
1092
+
985
1093
  :param dict [params]: extra parameters specific to the exchange API endpoint
986
1094
  :returns int: the current integer timestamp in milliseconds from the exchange server
987
1095
  """
@@ -998,7 +1106,9 @@ class kucoin(Exchange, ImplicitAPI):
998
1106
  def fetch_status(self, params={}):
999
1107
  """
1000
1108
  the latest known information on the availability of the exchange API
1001
- :see: https://docs.kucoin.com/#service-status
1109
+
1110
+ https://docs.kucoin.com/#service-status
1111
+
1002
1112
  :param dict [params]: extra parameters specific to the exchange API endpoint
1003
1113
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
1004
1114
  """
@@ -1025,12 +1135,17 @@ class kucoin(Exchange, ImplicitAPI):
1025
1135
  def fetch_markets(self, params={}) -> List[Market]:
1026
1136
  """
1027
1137
  retrieves data on all markets for kucoin
1028
- :see: https://docs.kucoin.com/#get-symbols-list-deprecated
1029
- :see: https://docs.kucoin.com/#get-all-tickers
1138
+
1139
+ https://docs.kucoin.com/#get-symbols-list-deprecated
1140
+ https://docs.kucoin.com/#get-all-tickers
1141
+
1030
1142
  :param dict [params]: extra parameters specific to the exchange API endpoint
1031
1143
  :returns dict[]: an array of objects representing market data
1032
1144
  """
1033
- response = self.publicGetSymbols(params)
1145
+ fetchTickersFees = None
1146
+ fetchTickersFees, params = self.handle_option_and_params(params, 'fetchMarkets', 'fetchTickersFees', True)
1147
+ promises = []
1148
+ promises.append(self.publicGetSymbols(params))
1034
1149
  #
1035
1150
  # {
1036
1151
  # "code": "200000",
@@ -1053,59 +1168,102 @@ class kucoin(Exchange, ImplicitAPI):
1053
1168
  # "isMarginEnabled": True,
1054
1169
  # "enableTrading": True
1055
1170
  # },
1056
- # ]
1057
- # }
1058
1171
  #
1059
- data = self.safe_list(response, 'data')
1060
- options = self.safe_dict(self.options, 'fetchMarkets', {})
1061
- fetchTickersFees = self.safe_bool(options, 'fetchTickersFees', True)
1062
- tickersResponse: dict = {}
1172
+ credentialsSet = self.check_required_credentials(False)
1173
+ requestMarginables = credentialsSet and self.safe_bool(params, 'marginables', True)
1174
+ if requestMarginables:
1175
+ promises.append(self.privateGetMarginSymbols(params)) # cross margin symbols
1176
+ #
1177
+ # {
1178
+ # "code": "200000",
1179
+ # "data": {
1180
+ # "timestamp": 1719393213421,
1181
+ # "items": [
1182
+ # {
1183
+ # # same object market, with one additional field:
1184
+ # "minFunds": "0.1"
1185
+ # },
1186
+ #
1187
+ promises.append(self.privateGetIsolatedSymbols(params)) # isolated margin symbols
1188
+ #
1189
+ # {
1190
+ # "code": "200000",
1191
+ # "data": [
1192
+ # {
1193
+ # "symbol": "NKN-USDT",
1194
+ # "symbolName": "NKN-USDT",
1195
+ # "baseCurrency": "NKN",
1196
+ # "quoteCurrency": "USDT",
1197
+ # "maxLeverage": 5,
1198
+ # "flDebtRatio": "0.97",
1199
+ # "tradeEnable": True,
1200
+ # "autoRenewMaxDebtRatio": "0.96",
1201
+ # "baseBorrowEnable": True,
1202
+ # "quoteBorrowEnable": True,
1203
+ # "baseTransferInEnable": True,
1204
+ # "quoteTransferInEnable": True,
1205
+ # "baseBorrowCoefficient": "1",
1206
+ # "quoteBorrowCoefficient": "1"
1207
+ # },
1208
+ #
1063
1209
  if fetchTickersFees:
1064
- tickersResponse = self.publicGetMarketAllTickers(params)
1065
- #
1066
- # {
1067
- # "code": "200000",
1068
- # "data": {
1069
- # "time":1602832092060,
1070
- # "ticker":[
1071
- # {
1072
- # "symbol": "BTC-USDT", # symbol
1073
- # "symbolName":"BTC-USDT", # Name of trading pairs, it would change after renaming
1074
- # "buy": "11328.9", # bestAsk
1075
- # "sell": "11329", # bestBid
1076
- # "changeRate": "-0.0055", # 24h change rate
1077
- # "changePrice": "-63.6", # 24h change price
1078
- # "high": "11610", # 24h highest price
1079
- # "low": "11200", # 24h lowest price
1080
- # "vol": "2282.70993217", # 24h volume,the aggregated trading volume in BTC
1081
- # "volValue": "25984946.157790431", # 24h total, the trading volume in quote currency of last 24 hours
1082
- # "last": "11328.9", # last price
1083
- # "averagePrice": "11360.66065903", # 24h average transaction price yesterday
1084
- # "takerFeeRate": "0.001", # Basic Taker Fee
1085
- # "makerFeeRate": "0.001", # Basic Maker Fee
1086
- # "takerCoefficient": "1", # Taker Fee Coefficient
1087
- # "makerCoefficient": "1" # Maker Fee Coefficient
1088
- # }
1089
- # ]
1090
- # }
1091
- # }
1092
- #
1093
- tickersData = self.safe_dict(tickersResponse, 'data', {})
1094
- tickers = self.safe_list(tickersData, 'ticker', [])
1095
- tickersByMarketId = self.index_by(tickers, 'symbol')
1210
+ promises.append(self.publicGetMarketAllTickers(params))
1211
+ #
1212
+ # {
1213
+ # "code": "200000",
1214
+ # "data": {
1215
+ # "time":1602832092060,
1216
+ # "ticker":[
1217
+ # {
1218
+ # "symbol": "BTC-USDT", # symbol
1219
+ # "symbolName":"BTC-USDT", # Name of trading pairs, it would change after renaming
1220
+ # "buy": "11328.9", # bestAsk
1221
+ # "sell": "11329", # bestBid
1222
+ # "changeRate": "-0.0055", # 24h change rate
1223
+ # "changePrice": "-63.6", # 24h change price
1224
+ # "high": "11610", # 24h highest price
1225
+ # "low": "11200", # 24h lowest price
1226
+ # "vol": "2282.70993217", # 24h volume,the aggregated trading volume in BTC
1227
+ # "volValue": "25984946.157790431", # 24h total, the trading volume in quote currency of last 24 hours
1228
+ # "last": "11328.9", # last price
1229
+ # "averagePrice": "11360.66065903", # 24h average transaction price yesterday
1230
+ # "takerFeeRate": "0.001", # Basic Taker Fee
1231
+ # "makerFeeRate": "0.001", # Basic Maker Fee
1232
+ # "takerCoefficient": "1", # Taker Fee Coefficient
1233
+ # "makerCoefficient": "1" # Maker Fee Coefficient
1234
+ # }
1235
+ #
1236
+ if credentialsSet:
1237
+ # load migration status for account
1238
+ promises.append(self.load_migration_status())
1239
+ responses = promises
1240
+ symbolsData = self.safe_list(responses[0], 'data')
1241
+ crossData = self.safe_dict(responses[1], 'data', {}) if requestMarginables else {}
1242
+ crossItems = self.safe_list(crossData, 'items', [])
1243
+ crossById = self.index_by(crossItems, 'symbol')
1244
+ isolatedData = responses[2] if requestMarginables else {}
1245
+ isolatedItems = self.safe_list(isolatedData, 'data', [])
1246
+ isolatedById = self.index_by(isolatedItems, 'symbol')
1247
+ tickersIdx = 3 if requestMarginables else 1
1248
+ tickersResponse = self.safe_dict(responses, tickersIdx, {})
1249
+ tickerItems = self.safe_list(self.safe_dict(tickersResponse, 'data', {}), 'ticker', [])
1250
+ tickersById = self.index_by(tickerItems, 'symbol')
1096
1251
  result = []
1097
- for i in range(0, len(data)):
1098
- market = data[i]
1252
+ for i in range(0, len(symbolsData)):
1253
+ market = symbolsData[i]
1099
1254
  id = self.safe_string(market, 'symbol')
1100
1255
  baseId, quoteId = id.split('-')
1101
1256
  base = self.safe_currency_code(baseId)
1102
1257
  quote = self.safe_currency_code(quoteId)
1103
1258
  # quoteIncrement = self.safe_number(market, 'quoteIncrement')
1104
- ticker = self.safe_dict(tickersByMarketId, id, {})
1259
+ ticker = self.safe_dict(tickersById, id, {})
1105
1260
  makerFeeRate = self.safe_string(ticker, 'makerFeeRate')
1106
1261
  takerFeeRate = self.safe_string(ticker, 'takerFeeRate')
1107
1262
  makerCoefficient = self.safe_string(ticker, 'makerCoefficient')
1108
1263
  takerCoefficient = self.safe_string(ticker, 'takerCoefficient')
1264
+ hasCrossMargin = (id in crossById)
1265
+ hasIsolatedMargin = (id in isolatedById)
1266
+ isMarginable = self.safe_bool(market, 'isMarginEnabled', False) or hasCrossMargin or hasIsolatedMargin
1109
1267
  result.append({
1110
1268
  'id': id,
1111
1269
  'symbol': base + '/' + quote,
@@ -1117,7 +1275,11 @@ class kucoin(Exchange, ImplicitAPI):
1117
1275
  'settleId': None,
1118
1276
  'type': 'spot',
1119
1277
  'spot': True,
1120
- 'margin': self.safe_bool(market, 'isMarginEnabled'),
1278
+ 'margin': isMarginable,
1279
+ 'marginModes': {
1280
+ 'cross': hasCrossMargin,
1281
+ 'isolated': hasIsolatedMargin,
1282
+ },
1121
1283
  'swap': False,
1122
1284
  'future': False,
1123
1285
  'option': False,
@@ -1157,17 +1319,46 @@ class kucoin(Exchange, ImplicitAPI):
1157
1319
  'created': None,
1158
1320
  'info': market,
1159
1321
  })
1322
+ if self.options['adjustForTimeDifference']:
1323
+ self.load_time_difference()
1160
1324
  return result
1161
1325
 
1326
+ def load_migration_status(self, force: bool = False):
1327
+ """
1328
+ :param boolean force: load account state for non hf
1329
+ loads the migration status for the account(hf or not)
1330
+
1331
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/get-user-type
1332
+
1333
+ :returns any: ignore
1334
+ """
1335
+ if not ('hf' in self.options) or (self.options['hf'] is None) or force:
1336
+ result: dict = self.privateGetHfAccountsOpened()
1337
+ self.options['hf'] = self.safe_bool(result, 'data')
1338
+ return True
1339
+
1340
+ def handle_hf_and_params(self, params={}):
1341
+ migrated: Bool = self.safe_bool(self.options, 'hf', False)
1342
+ loadedHf: Bool = None
1343
+ if migrated is not None:
1344
+ if migrated:
1345
+ loadedHf = True
1346
+ else:
1347
+ loadedHf = False
1348
+ hf: Bool = self.safe_bool(params, 'hf', loadedHf)
1349
+ params = self.omit(params, 'hf')
1350
+ return [hf, params]
1351
+
1162
1352
  def fetch_currencies(self, params={}) -> Currencies:
1163
1353
  """
1164
1354
  fetches all available currencies on an exchange
1165
- :see: https://docs.kucoin.com/#get-currencies
1355
+
1356
+ https://docs.kucoin.com/#get-currencies
1357
+
1166
1358
  :param dict params: extra parameters specific to the exchange API endpoint
1167
1359
  :returns dict: an associative dictionary of currencies
1168
1360
  """
1169
- promises = []
1170
- promises.append(self.publicGetCurrencies(params))
1361
+ response = self.publicGetCurrencies(params)
1171
1362
  #
1172
1363
  # {
1173
1364
  # "code":"200000",
@@ -1193,130 +1384,82 @@ class kucoin(Exchange, ImplicitAPI):
1193
1384
  # "isDepositEnabled":false,
1194
1385
  # "confirms":12,
1195
1386
  # "preConfirms":12,
1387
+ # "withdrawPrecision": 8,
1388
+ # "maxWithdraw": null,
1389
+ # "maxDeposit": null,
1390
+ # "needTag": False,
1196
1391
  # "contractAddress":"0xa6446d655a0c34bc4f05042ee88170d056cbaf45",
1197
1392
  # "depositFeeRate": "0.001", # present for some currencies/networks
1198
1393
  # }
1199
1394
  # ]
1200
1395
  # },
1201
- # }
1202
- #
1203
- promises.append(self.fetch_web_endpoint('fetchCurrencies', 'webExchangeGetCurrencyCurrencyChainInfo', True))
1204
- #
1205
- # {
1206
- # "success": True,
1207
- # "code": "200",
1208
- # "msg": "success",
1209
- # "retry": False,
1210
- # "data": [
1211
- # {
1212
- # "status": "enabled",
1213
- # "currency": "BTC",
1214
- # "isChainEnabled": "true",
1215
- # "chain": "btc",
1216
- # "chainName": "BTC",
1217
- # "chainFullName": "Bitcoin",
1218
- # "walletPrecision": "8",
1219
- # "isDepositEnabled": "true",
1220
- # "depositMinSize": "0.00005",
1221
- # "confirmationCount": "2",
1222
- # "isWithdrawEnabled": "true",
1223
- # "withdrawMinSize": "0.001",
1224
- # "withdrawMinFee": "0.0005",
1225
- # "withdrawFeeRate": "0",
1226
- # "depositDisabledTip": "Wallet Maintenance",
1227
- # "preDepositTipEnabled": "true",
1228
- # "preDepositTip": "Do not transfer from ETH network directly",
1229
- # "withdrawDisabledTip": "",
1230
- # "preWithdrawTipEnabled": "false",
1231
- # "preWithdrawTip": "",
1232
- # "orgAddress": "",
1233
- # "userAddressName": "Memo",
1234
- # },
1235
1396
  # ]
1236
1397
  # }
1237
1398
  #
1238
- responses = promises
1239
- currenciesResponse = self.safe_dict(responses, 0, {})
1240
- currenciesData = self.safe_list(currenciesResponse, 'data', [])
1241
- additionalResponse = self.safe_dict(responses, 1, {})
1242
- additionalData = self.safe_list(additionalResponse, 'data', [])
1243
- additionalDataGrouped = self.group_by(additionalData, 'currency')
1399
+ currenciesData = self.safe_list(response, 'data', [])
1400
+ brokenCurrencies = self.safe_list(self.options, 'brokenCurrencies', ['00', 'OPEN_ERROR', 'HUF', 'BDT'])
1401
+ otherFiats = self.safe_list(self.options, 'fiats', ['KWD', 'IRR', 'PKR'])
1244
1402
  result: dict = {}
1245
1403
  for i in range(0, len(currenciesData)):
1246
1404
  entry = currenciesData[i]
1247
1405
  id = self.safe_string(entry, 'currency')
1248
- name = self.safe_string(entry, 'fullName')
1406
+ if self.in_array(id, brokenCurrencies):
1407
+ continue # skip buggy entries: https://t.me/KuCoin_API/217798
1249
1408
  code = self.safe_currency_code(id)
1250
- isWithdrawEnabled = None
1251
- isDepositEnabled = None
1252
1409
  networks: dict = {}
1253
1410
  chains = self.safe_list(entry, 'chains', [])
1254
- extraChainsData = self.index_by(self.safe_list(additionalDataGrouped, id, []), 'chain')
1255
- rawPrecision = self.safe_string(entry, 'precision')
1256
- precision = self.parse_number(self.parse_precision(rawPrecision))
1257
1411
  chainsLength = len(chains)
1258
- if not chainsLength:
1259
- # https://t.me/KuCoin_API/173118
1260
- isWithdrawEnabled = False
1261
- isDepositEnabled = False
1262
1412
  for j in range(0, chainsLength):
1263
1413
  chain = chains[j]
1264
1414
  chainId = self.safe_string(chain, 'chainId')
1265
- networkCode = self.network_id_to_code(chainId)
1266
- chainWithdrawEnabled = self.safe_bool(chain, 'isWithdrawEnabled', False)
1267
- if isWithdrawEnabled is None:
1268
- isWithdrawEnabled = chainWithdrawEnabled
1269
- else:
1270
- isWithdrawEnabled = isWithdrawEnabled or chainWithdrawEnabled
1271
- chainDepositEnabled = self.safe_bool(chain, 'isDepositEnabled', False)
1272
- if isDepositEnabled is None:
1273
- isDepositEnabled = chainDepositEnabled
1274
- else:
1275
- isDepositEnabled = isDepositEnabled or chainDepositEnabled
1276
- chainExtraData = self.safe_dict(extraChainsData, chainId, {})
1415
+ networkCode = self.network_id_to_code(chainId, code)
1277
1416
  networks[networkCode] = {
1278
1417
  'info': chain,
1279
1418
  'id': chainId,
1280
1419
  'name': self.safe_string(chain, 'chainName'),
1281
1420
  'code': networkCode,
1282
- 'active': chainWithdrawEnabled and chainDepositEnabled,
1421
+ 'active': None,
1283
1422
  'fee': self.safe_number(chain, 'withdrawalMinFee'),
1284
- 'deposit': chainDepositEnabled,
1285
- 'withdraw': chainWithdrawEnabled,
1286
- 'precision': self.parse_number(self.parse_precision(self.safe_string(chainExtraData, 'walletPrecision'))),
1423
+ 'deposit': self.safe_bool(chain, 'isDepositEnabled'),
1424
+ 'withdraw': self.safe_bool(chain, 'isWithdrawEnabled'),
1425
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(chain, 'withdrawPrecision'))),
1287
1426
  'limits': {
1288
1427
  'withdraw': {
1289
1428
  'min': self.safe_number(chain, 'withdrawalMinSize'),
1290
- 'max': None,
1429
+ 'max': self.safe_number(chain, 'maxWithdraw'),
1291
1430
  },
1292
1431
  'deposit': {
1293
1432
  'min': self.safe_number(chain, 'depositMinSize'),
1294
- 'max': None,
1433
+ 'max': self.safe_number(chain, 'maxDeposit'),
1295
1434
  },
1296
1435
  },
1297
1436
  }
1298
1437
  # kucoin has determined 'fiat' currencies with below logic
1299
- isFiat = (rawPrecision == '2') and (chainsLength == 0)
1300
- result[code] = {
1438
+ rawPrecision = self.safe_string(entry, 'precision')
1439
+ precision = self.parse_number(self.parse_precision(rawPrecision))
1440
+ isFiat = self.in_array(id, otherFiats) or ((rawPrecision == '2') and (chainsLength == 0))
1441
+ result[code] = self.safe_currency_structure({
1301
1442
  'id': id,
1302
- 'name': name,
1443
+ 'name': self.safe_string(entry, 'fullName'),
1303
1444
  'code': code,
1304
1445
  'type': 'fiat' if isFiat else 'crypto',
1305
1446
  'precision': precision,
1306
1447
  'info': entry,
1307
- 'active': (isDepositEnabled or isWithdrawEnabled),
1308
- 'deposit': isDepositEnabled,
1309
- 'withdraw': isWithdrawEnabled,
1310
- 'fee': None,
1311
- 'limits': self.limits,
1312
1448
  'networks': networks,
1313
- }
1449
+ 'deposit': None,
1450
+ 'withdraw': None,
1451
+ 'active': None,
1452
+ 'fee': None,
1453
+ 'limits': None,
1454
+ })
1314
1455
  return result
1315
1456
 
1316
1457
  def fetch_accounts(self, params={}) -> List[Account]:
1317
1458
  """
1318
1459
  fetch all the accounts associated with a profile
1319
- :see: https://docs.kucoin.com/#list-accounts
1460
+
1461
+ https://docs.kucoin.com/#list-accounts
1462
+
1320
1463
  :param dict [params]: extra parameters specific to the exchange API endpoint
1321
1464
  :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
1322
1465
  """
@@ -1364,7 +1507,9 @@ class kucoin(Exchange, ImplicitAPI):
1364
1507
  def fetch_transaction_fee(self, code: str, params={}):
1365
1508
  """
1366
1509
  *DEPRECATED* please use fetchDepositWithdrawFee instead
1367
- :see: https://docs.kucoin.com/#get-withdrawal-quotas
1510
+
1511
+ https://docs.kucoin.com/#get-withdrawal-quotas
1512
+
1368
1513
  :param str code: unified currency code
1369
1514
  :param dict params: extra parameters specific to the exchange API endpoint
1370
1515
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -1391,7 +1536,9 @@ class kucoin(Exchange, ImplicitAPI):
1391
1536
  def fetch_deposit_withdraw_fee(self, code: str, params={}):
1392
1537
  """
1393
1538
  fetch the fee for deposits and withdrawals
1394
- :see: https://docs.kucoin.com/#get-withdrawal-quotas
1539
+
1540
+ https://docs.kucoin.com/#get-withdrawal-quotas
1541
+
1395
1542
  :param str code: unified currency code
1396
1543
  :param dict [params]: extra parameters specific to the exchange API endpoint
1397
1544
  :param str [params.network]: The chain of currency. This only apply for multi-chain currency, and there is no need for single chain currency; you can query the chain through the response of the GET /api/v2/currencies/{currency} interface
@@ -1444,32 +1591,57 @@ class kucoin(Exchange, ImplicitAPI):
1444
1591
  # "chain": "ERC20"
1445
1592
  # }
1446
1593
  #
1594
+ if 'chains' in fee:
1595
+ # if data obtained through `currencies` endpoint
1596
+ resultNew: dict = {
1597
+ 'info': fee,
1598
+ 'withdraw': {
1599
+ 'fee': None,
1600
+ 'percentage': False,
1601
+ },
1602
+ 'deposit': {
1603
+ 'fee': None,
1604
+ 'percentage': None,
1605
+ },
1606
+ 'networks': {},
1607
+ }
1608
+ chains = self.safe_list(fee, 'chains', [])
1609
+ for i in range(0, len(chains)):
1610
+ chain = chains[i]
1611
+ networkCodeNew = self.network_id_to_code(self.safe_string(chain, 'chainId'), self.safe_string(currency, 'code'))
1612
+ resultNew['networks'][networkCodeNew] = {
1613
+ 'withdraw': {
1614
+ 'fee': self.safe_number(chain, 'withdrawMinFee'),
1615
+ 'percentage': False,
1616
+ },
1617
+ 'deposit': {
1618
+ 'fee': None,
1619
+ 'percentage': None,
1620
+ },
1621
+ }
1622
+ return resultNew
1623
+ minWithdrawFee = self.safe_number(fee, 'withdrawMinFee')
1447
1624
  result: dict = {
1448
1625
  'info': fee,
1449
1626
  'withdraw': {
1627
+ 'fee': minWithdrawFee,
1628
+ 'percentage': False,
1629
+ },
1630
+ 'deposit': {
1450
1631
  'fee': None,
1451
1632
  'percentage': None,
1452
1633
  },
1634
+ 'networks': {},
1635
+ }
1636
+ networkId = self.safe_string(fee, 'chain')
1637
+ networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
1638
+ result['networks'][networkCode] = {
1639
+ 'withdraw': minWithdrawFee,
1453
1640
  'deposit': {
1454
1641
  'fee': None,
1455
1642
  'percentage': None,
1456
1643
  },
1457
- 'networks': {},
1458
1644
  }
1459
- isWithdrawEnabled = self.safe_bool(fee, 'isWithdrawEnabled')
1460
- if isWithdrawEnabled:
1461
- result['withdraw']['fee'] = self.safe_number_2(fee, 'withdrawalMinFee', 'withdrawMinFee')
1462
- result['withdraw']['percentage'] = False
1463
- networkId = self.safe_string(fee, 'chain')
1464
- if networkId:
1465
- networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
1466
- result['networks'][networkCode] = {
1467
- 'withdraw': result['withdraw'],
1468
- 'deposit': {
1469
- 'fee': None,
1470
- 'percentage': None,
1471
- },
1472
- }
1473
1645
  return result
1474
1646
 
1475
1647
  def is_futures_method(self, methodName, params):
@@ -1555,7 +1727,7 @@ class kucoin(Exchange, ImplicitAPI):
1555
1727
  symbol = market['symbol']
1556
1728
  baseVolume = self.safe_string(ticker, 'vol')
1557
1729
  quoteVolume = self.safe_string(ticker, 'volValue')
1558
- timestamp = self.safe_integer_2(ticker, 'time', 'datetime')
1730
+ timestamp = self.safe_integer_n(ticker, ['time', 'datetime', 'timePoint'])
1559
1731
  return self.safe_ticker({
1560
1732
  'symbol': symbol,
1561
1733
  'timestamp': timestamp,
@@ -1576,13 +1748,16 @@ class kucoin(Exchange, ImplicitAPI):
1576
1748
  'average': self.safe_string(ticker, 'averagePrice'),
1577
1749
  'baseVolume': baseVolume,
1578
1750
  'quoteVolume': quoteVolume,
1751
+ 'markPrice': self.safe_string(ticker, 'value'),
1579
1752
  'info': ticker,
1580
1753
  }, market)
1581
1754
 
1582
1755
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1583
1756
  """
1584
1757
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1585
- :see: https://docs.kucoin.com/#get-all-tickers
1758
+
1759
+ https://docs.kucoin.com/#get-all-tickers
1760
+
1586
1761
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1587
1762
  :param dict [params]: extra parameters specific to the exchange API endpoint
1588
1763
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1630,10 +1805,28 @@ class kucoin(Exchange, ImplicitAPI):
1630
1805
  result[symbol] = ticker
1631
1806
  return self.filter_by_array_tickers(result, 'symbol', symbols)
1632
1807
 
1808
+ def fetch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1809
+ """
1810
+ fetches the mark price for multiple markets
1811
+
1812
+ https://www.kucoin.com/docs/rest/margin-trading/margin-info/get-all-margin-trading-pairs-mark-prices
1813
+
1814
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1815
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1816
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1817
+ """
1818
+ self.load_markets()
1819
+ symbols = self.market_symbols(symbols)
1820
+ response = self.publicGetMarkPriceAllSymbols(params)
1821
+ data = self.safe_list(response, 'data', [])
1822
+ return self.parse_tickers(data)
1823
+
1633
1824
  def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1634
1825
  """
1635
1826
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1636
- :see: https://docs.kucoin.com/#get-24hr-stats
1827
+
1828
+ https://docs.kucoin.com/#get-24hr-stats
1829
+
1637
1830
  :param str symbol: unified symbol of the market to fetch the ticker for
1638
1831
  :param dict [params]: extra parameters specific to the exchange API endpoint
1639
1832
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1667,7 +1860,28 @@ class kucoin(Exchange, ImplicitAPI):
1667
1860
  # }
1668
1861
  # }
1669
1862
  #
1670
- return self.parse_ticker(response['data'], market)
1863
+ data = self.safe_dict(response, 'data', {})
1864
+ return self.parse_ticker(data, market)
1865
+
1866
+ def fetch_mark_price(self, symbol: str, params={}) -> Ticker:
1867
+ """
1868
+ fetches the mark price for a specific market
1869
+
1870
+ https://www.kucoin.com/docs/rest/margin-trading/margin-info/get-mark-price
1871
+
1872
+ :param str symbol: unified symbol of the market to fetch the ticker for
1873
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1874
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1875
+ """
1876
+ self.load_markets()
1877
+ market = self.market(symbol)
1878
+ request: dict = {
1879
+ 'symbol': market['id'],
1880
+ }
1881
+ response = self.publicGetMarkPriceSymbolCurrent(self.extend(request, params))
1882
+ #
1883
+ data = self.safe_dict(response, 'data', {})
1884
+ return self.parse_ticker(data, market)
1671
1885
 
1672
1886
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1673
1887
  #
@@ -1693,7 +1907,9 @@ class kucoin(Exchange, ImplicitAPI):
1693
1907
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1694
1908
  """
1695
1909
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1696
- :see: https://docs.kucoin.com/#get-klines
1910
+
1911
+ https://docs.kucoin.com/#get-klines
1912
+
1697
1913
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1698
1914
  :param str timeframe: the length of time each candle represents
1699
1915
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -1742,9 +1958,11 @@ class kucoin(Exchange, ImplicitAPI):
1742
1958
  data = self.safe_list(response, 'data', [])
1743
1959
  return self.parse_ohlcvs(data, market, timeframe, since, limit)
1744
1960
 
1745
- def create_deposit_address(self, code: str, params={}):
1961
+ def create_deposit_address(self, code: str, params={}) -> DepositAddress:
1746
1962
  """
1747
- :see: https://docs.kucoin.com/#create-deposit-address
1963
+
1964
+ https://www.kucoin.com/docs/rest/funding/deposit/create-deposit-address-v3-
1965
+
1748
1966
  create a currency deposit address
1749
1967
  :param str code: unified currency code of the currency for the deposit address
1750
1968
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1759,18 +1977,32 @@ class kucoin(Exchange, ImplicitAPI):
1759
1977
  networkCode = None
1760
1978
  networkCode, params = self.handle_network_code_and_params(params)
1761
1979
  if networkCode is not None:
1762
- request['chain'] = self.network_code_to_id(networkCode).lower()
1763
- response = self.privatePostDepositAddresses(self.extend(request, params))
1980
+ request['chain'] = self.network_code_to_id(networkCode) # docs mention "chain-name", but seems "chain-id" is used, like in "fetchDepositAddress"
1981
+ response = self.privatePostDepositAddressCreate(self.extend(request, params))
1764
1982
  # {"code":"260000","msg":"Deposit address already exists."}
1765
- # BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
1766
- # BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
1983
+ #
1984
+ # {
1985
+ # "code": "200000",
1986
+ # "data": {
1987
+ # "address": "0x2336d1834faab10b2dac44e468f2627138417431",
1988
+ # "memo": null,
1989
+ # "chainId": "bsc",
1990
+ # "to": "MAIN",
1991
+ # "expirationDate": 0,
1992
+ # "currency": "BNB",
1993
+ # "chainName": "BEP20"
1994
+ # }
1995
+ # }
1996
+ #
1767
1997
  data = self.safe_dict(response, 'data', {})
1768
1998
  return self.parse_deposit_address(data, currency)
1769
1999
 
1770
- def fetch_deposit_address(self, code: str, params={}):
2000
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1771
2001
  """
1772
2002
  fetch the deposit address for a currency associated with self account
1773
- :see: https://docs.kucoin.com/#get-deposit-addresses-v2
2003
+
2004
+ https://docs.kucoin.com/#get-deposit-addresses-v2
2005
+
1774
2006
  :param str code: unified currency code
1775
2007
  :param dict [params]: extra parameters specific to the exchange API endpoint
1776
2008
  :param str [params.network]: the blockchain network name
@@ -1799,7 +2031,7 @@ class kucoin(Exchange, ImplicitAPI):
1799
2031
  raise ExchangeError(self.id + ' fetchDepositAddress() returned an empty response, you might try to run createDepositAddress() first and try again')
1800
2032
  return self.parse_deposit_address(data, currency)
1801
2033
 
1802
- def parse_deposit_address(self, depositAddress, currency: Currency = None):
2034
+ def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
1803
2035
  address = self.safe_string(depositAddress, 'address')
1804
2036
  # BCH/BSV is returned with a "bitcoincash:" prefix, which we cut off here and only keep the address
1805
2037
  if address is not None:
@@ -1813,14 +2045,16 @@ class kucoin(Exchange, ImplicitAPI):
1813
2045
  return {
1814
2046
  'info': depositAddress,
1815
2047
  'currency': code,
2048
+ 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chainId')),
1816
2049
  'address': address,
1817
2050
  'tag': self.safe_string(depositAddress, 'memo'),
1818
- 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chain')),
1819
2051
  }
1820
2052
 
1821
- def fetch_deposit_addresses_by_network(self, code: str, params={}):
2053
+ def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
1822
2054
  """
1823
- :see: https://docs.kucoin.com/#get-deposit-addresses-v2
2055
+
2056
+ https://docs.kucoin.com/#get-deposit-addresses-v2
2057
+
1824
2058
  fetch the deposit address for a currency associated with self account
1825
2059
  :param str code: unified currency code
1826
2060
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1859,8 +2093,10 @@ class kucoin(Exchange, ImplicitAPI):
1859
2093
  def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1860
2094
  """
1861
2095
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1862
- :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-part-order-book-aggregated-
1863
- :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-full-order-book-aggregated-
2096
+
2097
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-part-order-book-aggregated-
2098
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-full-order-book-aggregated-
2099
+
1864
2100
  :param str symbol: unified symbol of the market to fetch the order book for
1865
2101
  :param int [limit]: the maximum amount of order book entries to return
1866
2102
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1934,49 +2170,56 @@ class kucoin(Exchange, ImplicitAPI):
1934
2170
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1935
2171
  """
1936
2172
  Create an order on the exchange
1937
- :see: https://docs.kucoin.com/spot#place-a-new-order
1938
- :see: https://docs.kucoin.com/spot#place-a-new-order-2
1939
- :see: https://docs.kucoin.com/spot#place-a-margin-order
1940
- :see: https://docs.kucoin.com/spot-hf/#place-hf-order
1941
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order-test
1942
- :see: https://www.kucoin.com/docs/rest/margin-trading/orders/place-margin-order-test
2173
+
2174
+ https://docs.kucoin.com/spot#place-a-new-order
2175
+ https://docs.kucoin.com/spot#place-a-new-order-2
2176
+ https://docs.kucoin.com/spot#place-a-margin-order
2177
+ https://docs.kucoin.com/spot-hf/#place-hf-order
2178
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order-test
2179
+ https://www.kucoin.com/docs/rest/margin-trading/orders/place-margin-order-test
2180
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-place-hf-order
2181
+
1943
2182
  :param str symbol: Unified CCXT market symbol
1944
2183
  :param str type: 'limit' or 'market'
1945
2184
  :param str side: 'buy' or 'sell'
1946
2185
  :param float amount: the amount of currency to trade
1947
- :param float [price]: *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
2186
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1948
2187
  :param dict [params]: extra parameters specific to the exchange API endpoint
1949
2188
  :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1950
2189
  :param str [params.marginMode]: 'cross', # cross(cross mode) and isolated(isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned
1951
2190
  :param str [params.timeInForce]: GTC, GTT, IOC, or FOK, default is GTC, limit orders only
1952
2191
  :param str [params.postOnly]: Post only flag, invalid when timeInForce is IOC or FOK
1953
- *
1954
- * EXCHANGE SPECIFIC PARAMETERS
2192
+
2193
+ EXCHANGE SPECIFIC PARAMETERS
1955
2194
  :param str [params.clientOid]: client order id, defaults to uuid if not passed
1956
2195
  :param str [params.remark]: remark for the order, length cannot exceed 100 utf8 characters
1957
2196
  :param str [params.tradeType]: 'TRADE', # TRADE, MARGIN_TRADE # not used with margin orders
1958
- * limit orders ---------------------------------------------------
2197
+ limit orders ---------------------------------------------------
1959
2198
  :param float [params.cancelAfter]: long, # cancel after n seconds, requires timeInForce to be GTT
1960
2199
  :param bool [params.hidden]: False, # Order will not be displayed in the order book
1961
2200
  :param bool [params.iceberg]: False, # Only a portion of the order is displayed in the order book
1962
2201
  :param str [params.visibleSize]: self.amount_to_precision(symbol, visibleSize), # The maximum visible size of an iceberg order
1963
- * market orders --------------------------------------------------
2202
+ market orders --------------------------------------------------
1964
2203
  :param str [params.funds]: # Amount of quote currency to use
1965
- * stop orders ----------------------------------------------------
1966
- :param str [params.stop]: Either loss or entry, the default is loss. Requires stopPrice to be defined
1967
- * margin orders --------------------------------------------------
2204
+ stop orders ----------------------------------------------------
2205
+ :param str [params.stop]: Either loss or entry, the default is loss. Requires triggerPrice to be defined
2206
+ margin orders --------------------------------------------------
1968
2207
  :param float [params.leverage]: Leverage size of the order
1969
2208
  :param str [params.stp]: '', # self trade prevention, CN, CO, CB or DC
1970
2209
  :param bool [params.autoBorrow]: False, # The system will first borrow you funds at the optimal interest rate and then place an order for you
1971
2210
  :param bool [params.hf]: False, # True for hf order
1972
2211
  :param bool [params.test]: set to True to test an order, no order will be created but the request will be validated
2212
+ :param bool [params.sync]: set to True to use the hf sync call
1973
2213
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1974
2214
  """
1975
2215
  self.load_markets()
1976
2216
  market = self.market(symbol)
1977
2217
  testOrder = self.safe_bool(params, 'test', False)
1978
2218
  params = self.omit(params, 'test')
1979
- isHf = self.safe_bool(params, 'hf', False)
2219
+ hf = None
2220
+ hf, params = self.handle_hf_and_params(params)
2221
+ useSync = False
2222
+ useSync, params = self.handle_option_and_params(params, 'createOrder', 'sync', False)
1980
2223
  triggerPrice, stopLossPrice, takeProfitPrice = self.handle_trigger_prices(params)
1981
2224
  tradeType = self.safe_string(params, 'tradeType') # keep it for backward compatibility
1982
2225
  isTriggerOrder = (triggerPrice or stopLossPrice or takeProfitPrice)
@@ -1989,14 +2232,18 @@ class kucoin(Exchange, ImplicitAPI):
1989
2232
  if testOrder:
1990
2233
  if isMarginOrder:
1991
2234
  response = self.privatePostMarginOrderTest(orderRequest)
2235
+ elif hf:
2236
+ response = self.privatePostHfOrdersTest(orderRequest)
1992
2237
  else:
1993
2238
  response = self.privatePostOrdersTest(orderRequest)
1994
- elif isHf:
1995
- response = self.privatePostHfOrders(orderRequest)
1996
2239
  elif isTriggerOrder:
1997
2240
  response = self.privatePostStopOrder(orderRequest)
1998
2241
  elif isMarginOrder:
1999
2242
  response = self.privatePostMarginOrder(orderRequest)
2243
+ elif useSync:
2244
+ response = self.privatePostHfOrdersSync(orderRequest)
2245
+ elif hf:
2246
+ response = self.privatePostHfOrders(orderRequest)
2000
2247
  else:
2001
2248
  response = self.privatePostOrders(orderRequest)
2002
2249
  #
@@ -2013,7 +2260,9 @@ class kucoin(Exchange, ImplicitAPI):
2013
2260
  def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
2014
2261
  """
2015
2262
  create a market order by providing the symbol, side and cost
2016
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2263
+
2264
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2265
+
2017
2266
  :param str symbol: unified symbol of the market to create an order in
2018
2267
  :param str side: 'buy' or 'sell'
2019
2268
  :param float cost: how much you want to trade in units of the quote currency
@@ -2021,13 +2270,17 @@ class kucoin(Exchange, ImplicitAPI):
2021
2270
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2022
2271
  """
2023
2272
  self.load_markets()
2024
- params['cost'] = cost
2025
- return self.create_order(symbol, 'market', side, cost, None, params)
2273
+ req = {
2274
+ 'cost': cost,
2275
+ }
2276
+ return self.create_order(symbol, 'market', side, cost, None, self.extend(req, params))
2026
2277
 
2027
2278
  def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
2028
2279
  """
2029
2280
  create a market buy order by providing the symbol and cost
2030
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2281
+
2282
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2283
+
2031
2284
  :param str symbol: unified symbol of the market to create an order in
2032
2285
  :param float cost: how much you want to trade in units of the quote currency
2033
2286
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2039,7 +2292,9 @@ class kucoin(Exchange, ImplicitAPI):
2039
2292
  def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
2040
2293
  """
2041
2294
  create a market sell order by providing the symbol and cost
2042
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2295
+
2296
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2297
+
2043
2298
  :param str symbol: unified symbol of the market to create an order in
2044
2299
  :param float cost: how much you want to trade in units of the quote currency
2045
2300
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2051,11 +2306,15 @@ class kucoin(Exchange, ImplicitAPI):
2051
2306
  def create_orders(self, orders: List[OrderRequest], params={}):
2052
2307
  """
2053
2308
  create a list of trade orders
2054
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-multiple-orders
2055
- :see: https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-multiple-hf-orders
2309
+
2310
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-multiple-orders
2311
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-multiple-hf-orders
2312
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-place-multiple-hf-orders
2313
+
2056
2314
  :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2057
2315
  :param dict [params]: extra parameters specific to the exchange API endpoint
2058
2316
  :param bool [params.hf]: False, # True for hf orders
2317
+ :param bool [params.sync]: False, # True to use the hf sync call
2059
2318
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2060
2319
  """
2061
2320
  self.load_markets()
@@ -2083,10 +2342,14 @@ class kucoin(Exchange, ImplicitAPI):
2083
2342
  'symbol': market['id'],
2084
2343
  'orderList': ordersRequests,
2085
2344
  }
2086
- hf = self.safe_bool(params, 'hf', False)
2087
- params = self.omit(params, 'hf')
2345
+ hf = None
2346
+ hf, params = self.handle_hf_and_params(params)
2347
+ useSync = False
2348
+ useSync, params = self.handle_option_and_params(params, 'createOrders', 'sync', False)
2088
2349
  response = None
2089
- if hf:
2350
+ if useSync:
2351
+ response = self.privatePostHfOrdersMultiSync(self.extend(request, params))
2352
+ elif hf:
2090
2353
  response = self.privatePostHfOrdersMulti(self.extend(request, params))
2091
2354
  else:
2092
2355
  response = self.privatePostOrdersMulti(self.extend(request, params))
@@ -2191,13 +2454,15 @@ class kucoin(Exchange, ImplicitAPI):
2191
2454
  def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
2192
2455
  """
2193
2456
  edit an order, kucoin currently only supports the modification of HF orders
2194
- :see: https://docs.kucoin.com/spot-hf/#modify-order
2457
+
2458
+ https://docs.kucoin.com/spot-hf/#modify-order
2459
+
2195
2460
  :param str id: order id
2196
2461
  :param str symbol: unified symbol of the market to create an order in
2197
2462
  :param str type: not used
2198
2463
  :param str side: not used
2199
2464
  :param float amount: how much of the currency you want to trade in units of the base currency
2200
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2465
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2201
2466
  :param dict [params]: extra parameters specific to the exchange API endpoint
2202
2467
  :param str [params.clientOrderId]: client order id, defaults to id if not passed
2203
2468
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2231,34 +2496,42 @@ class kucoin(Exchange, ImplicitAPI):
2231
2496
  def cancel_order(self, id: str, symbol: Str = None, params={}):
2232
2497
  """
2233
2498
  cancels an open order
2234
- :see: https://docs.kucoin.com/spot#cancel-an-order
2235
- :see: https://docs.kucoin.com/spot#cancel-an-order-2
2236
- :see: https://docs.kucoin.com/spot#cancel-single-order-by-clientoid
2237
- :see: https://docs.kucoin.com/spot#cancel-single-order-by-clientoid-2
2238
- :see: https://docs.kucoin.com/spot-hf/#cancel-orders-by-orderid
2239
- :see: https://docs.kucoin.com/spot-hf/#cancel-order-by-clientoid
2499
+
2500
+ https://docs.kucoin.com/spot#cancel-an-order
2501
+ https://docs.kucoin.com/spot#cancel-an-order-2
2502
+ https://docs.kucoin.com/spot#cancel-single-order-by-clientoid
2503
+ https://docs.kucoin.com/spot#cancel-single-order-by-clientoid-2
2504
+ https://docs.kucoin.com/spot-hf/#cancel-orders-by-orderid
2505
+ https://docs.kucoin.com/spot-hf/#cancel-order-by-clientoid
2506
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-cancel-hf-order-by-orderid
2507
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-cancel-hf-order-by-clientoid
2508
+
2240
2509
  :param str id: order id
2241
2510
  :param str symbol: unified symbol of the market the order was made in
2242
2511
  :param dict [params]: extra parameters specific to the exchange API endpoint
2243
- :param bool [params.stop]: True if cancelling a stop order
2512
+ :param bool [params.trigger]: True if cancelling a stop order
2244
2513
  :param bool [params.hf]: False, # True for hf order
2514
+ :param bool [params.sync]: False, # True to use the hf sync call
2245
2515
  :returns: Response from the exchange
2246
2516
  """
2247
2517
  self.load_markets()
2248
2518
  request: dict = {}
2249
2519
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
2250
- stop = self.safe_bool_2(params, 'stop', 'trigger', False)
2251
- hf = self.safe_bool(params, 'hf', False)
2252
- if hf:
2520
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2521
+ hf = None
2522
+ hf, params = self.handle_hf_and_params(params)
2523
+ useSync = False
2524
+ useSync, params = self.handle_option_and_params(params, 'cancelOrder', 'sync', False)
2525
+ if hf or useSync:
2253
2526
  if symbol is None:
2254
2527
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol parameter for hf orders')
2255
2528
  market = self.market(symbol)
2256
2529
  request['symbol'] = market['id']
2257
2530
  response = None
2258
- params = self.omit(params, ['clientOid', 'clientOrderId', 'stop', 'hf', 'trigger'])
2531
+ params = self.omit(params, ['clientOid', 'clientOrderId', 'stop', 'trigger'])
2259
2532
  if clientOrderId is not None:
2260
2533
  request['clientOid'] = clientOrderId
2261
- if stop:
2534
+ if trigger:
2262
2535
  response = self.privateDeleteStopOrderCancelOrderByClientOid(self.extend(request, params))
2263
2536
  #
2264
2537
  # {
@@ -2269,6 +2542,8 @@ class kucoin(Exchange, ImplicitAPI):
2269
2542
  # }
2270
2543
  # }
2271
2544
  #
2545
+ elif useSync:
2546
+ response = self.privateDeleteHfOrdersSyncClientOrderClientOid(self.extend(request, params))
2272
2547
  elif hf:
2273
2548
  response = self.privateDeleteHfOrdersClientOrderClientOid(self.extend(request, params))
2274
2549
  #
@@ -2295,7 +2570,7 @@ class kucoin(Exchange, ImplicitAPI):
2295
2570
  return self.parse_order(response)
2296
2571
  else:
2297
2572
  request['orderId'] = id
2298
- if stop:
2573
+ if trigger:
2299
2574
  response = self.privateDeleteStopOrderOrderId(self.extend(request, params))
2300
2575
  #
2301
2576
  # {
@@ -2303,6 +2578,8 @@ class kucoin(Exchange, ImplicitAPI):
2303
2578
  # data: {cancelledOrderIds: ['vs8lgpiuaco91qk8003vebu9']}
2304
2579
  # }
2305
2580
  #
2581
+ elif useSync:
2582
+ response = self.privateDeleteHfOrdersSyncOrderId(self.extend(request, params))
2306
2583
  elif hf:
2307
2584
  response = self.privateDeleteHfOrdersOrderId(self.extend(request, params))
2308
2585
  #
@@ -2334,32 +2611,34 @@ class kucoin(Exchange, ImplicitAPI):
2334
2611
  def cancel_all_orders(self, symbol: Str = None, params={}):
2335
2612
  """
2336
2613
  cancel all open orders
2337
- :see: https://docs.kucoin.com/spot#cancel-all-orders
2338
- :see: https://docs.kucoin.com/spot#cancel-orders
2339
- :see: https://docs.kucoin.com/spot-hf/#cancel-all-hf-orders-by-symbol
2614
+
2615
+ https://docs.kucoin.com/spot#cancel-all-orders
2616
+ https://docs.kucoin.com/spot#cancel-orders
2617
+ https://docs.kucoin.com/spot-hf/#cancel-all-hf-orders-by-symbol
2618
+
2340
2619
  :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
2341
2620
  :param dict [params]: extra parameters specific to the exchange API endpoint
2342
- :param bool [params.stop]: *invalid for isolated margin* True if cancelling all stop orders
2621
+ :param bool [params.trigger]: *invalid for isolated margin* True if cancelling all stop orders
2343
2622
  :param str [params.marginMode]: 'cross' or 'isolated'
2344
2623
  :param str [params.orderIds]: *stop orders only* Comma seperated order IDs
2345
- :param bool [params.stop]: True if cancelling a stop order
2346
2624
  :param bool [params.hf]: False, # True for hf order
2347
2625
  :returns: Response from the exchange
2348
2626
  """
2349
2627
  self.load_markets()
2350
2628
  request: dict = {}
2351
- stop = self.safe_bool(params, 'stop', False)
2352
- hf = self.safe_bool(params, 'hf', False)
2353
- params = self.omit(params, ['stop', 'hf'])
2629
+ trigger = self.safe_bool_2(params, 'trigger', 'stop', False)
2630
+ hf = None
2631
+ hf, params = self.handle_hf_and_params(params)
2632
+ params = self.omit(params, 'stop')
2354
2633
  marginMode, query = self.handle_margin_mode_and_params('cancelAllOrders', params)
2355
2634
  if symbol is not None:
2356
2635
  request['symbol'] = self.market_id(symbol)
2357
2636
  if marginMode is not None:
2358
2637
  request['tradeType'] = self.options['marginModes'][marginMode]
2359
- if marginMode == 'isolated' and stop:
2638
+ if marginMode == 'isolated' and trigger:
2360
2639
  raise BadRequest(self.id + ' cancelAllOrders does not support isolated margin for stop orders')
2361
2640
  response = None
2362
- if stop:
2641
+ if trigger:
2363
2642
  response = self.privateDeleteStopOrderCancel(self.extend(request, query))
2364
2643
  elif hf:
2365
2644
  if symbol is None:
@@ -2368,37 +2647,41 @@ class kucoin(Exchange, ImplicitAPI):
2368
2647
  response = self.privateDeleteHfOrders(self.extend(request, query))
2369
2648
  else:
2370
2649
  response = self.privateDeleteOrders(self.extend(request, query))
2371
- return response
2650
+ return [self.safe_order({'info': response})]
2372
2651
 
2373
2652
  def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2374
2653
  """
2375
2654
  fetch a list of orders
2376
- :see: https://docs.kucoin.com/spot#list-orders
2377
- :see: https://docs.kucoin.com/spot#list-stop-orders
2378
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2379
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2655
+
2656
+ https://docs.kucoin.com/spot#list-orders
2657
+ https://docs.kucoin.com/spot#list-stop-orders
2658
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2659
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2660
+
2380
2661
  :param str status: *not used for stop orders* 'open' or 'closed'
2381
2662
  :param str symbol: unified market symbol
2382
2663
  :param int [since]: timestamp in ms of the earliest order
2383
2664
  :param int [limit]: max number of orders to return
2384
2665
  :param dict [params]: exchange specific params
2385
2666
  :param int [params.until]: end time in ms
2386
- :param bool [params.stop]: True if fetching stop orders
2387
2667
  :param str [params.side]: buy or sell
2388
2668
  :param str [params.type]: limit, market, limit_stop or market_stop
2389
2669
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2390
- :param int [params.currentPage]: *stop orders only* current page
2391
- :param str [params.orderIds]: *stop orders only* comma seperated order ID list
2392
- :param bool [params.stop]: True if fetching a stop order
2670
+ :param int [params.currentPage]: *trigger orders only* current page
2671
+ :param str [params.orderIds]: *trigger orders only* comma seperated order ID list
2672
+ :param bool [params.trigger]: True if fetching a trigger order
2393
2673
  :param bool [params.hf]: False, # True for hf order
2394
2674
  :returns: An `array of order structures <https://docs.ccxt.com/#/?id=order-structure>`
2395
2675
  """
2396
2676
  self.load_markets()
2397
2677
  lowercaseStatus = status.lower()
2398
2678
  until = self.safe_integer(params, 'until')
2399
- stop = self.safe_bool(params, 'stop', False)
2400
- hf = self.safe_bool(params, 'hf', False)
2401
- params = self.omit(params, ['stop', 'hf', 'until'])
2679
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2680
+ hf = None
2681
+ hf, params = self.handle_hf_and_params(params)
2682
+ if hf and (symbol is None):
2683
+ raise ArgumentsRequired(self.id + ' fetchOrdersByStatus() requires a symbol parameter for hf orders')
2684
+ params = self.omit(params, ['stop', 'trigger', 'till', 'until'])
2402
2685
  marginMode, query = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
2403
2686
  if lowercaseStatus == 'open':
2404
2687
  lowercaseStatus = 'active'
@@ -2419,7 +2702,7 @@ class kucoin(Exchange, ImplicitAPI):
2419
2702
  request['endAt'] = until
2420
2703
  request['tradeType'] = self.safe_string(self.options['marginModes'], marginMode, 'TRADE')
2421
2704
  response = None
2422
- if stop:
2705
+ if trigger:
2423
2706
  response = self.privateGetStopOrder(self.extend(request, query))
2424
2707
  elif hf:
2425
2708
  if lowercaseStatus == 'active':
@@ -2481,10 +2764,12 @@ class kucoin(Exchange, ImplicitAPI):
2481
2764
  def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2482
2765
  """
2483
2766
  fetches information on multiple closed orders made by the user
2484
- :see: https://docs.kucoin.com/spot#list-orders
2485
- :see: https://docs.kucoin.com/spot#list-stop-orders
2486
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2487
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2767
+
2768
+ https://docs.kucoin.com/spot#list-orders
2769
+ https://docs.kucoin.com/spot#list-stop-orders
2770
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2771
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2772
+
2488
2773
  :param str symbol: unified market symbol of the market orders were made in
2489
2774
  :param int [since]: the earliest time in ms to fetch orders for
2490
2775
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2493,7 +2778,7 @@ class kucoin(Exchange, ImplicitAPI):
2493
2778
  :param str [params.side]: buy or sell
2494
2779
  :param str [params.type]: limit, market, limit_stop or market_stop
2495
2780
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2496
- :param bool [params.stop]: True if fetching a stop order
2781
+ :param bool [params.trigger]: True if fetching a trigger order
2497
2782
  :param bool [params.hf]: False, # True for hf order
2498
2783
  :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)
2499
2784
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2508,22 +2793,23 @@ class kucoin(Exchange, ImplicitAPI):
2508
2793
  def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2509
2794
  """
2510
2795
  fetch all unfilled currently open orders
2511
- :see: https://docs.kucoin.com/spot#list-orders
2512
- :see: https://docs.kucoin.com/spot#list-stop-orders
2513
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2514
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2796
+
2797
+ https://docs.kucoin.com/spot#list-orders
2798
+ https://docs.kucoin.com/spot#list-stop-orders
2799
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2800
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2801
+
2515
2802
  :param str symbol: unified market symbol
2516
2803
  :param int [since]: the earliest time in ms to fetch open orders for
2517
2804
  :param int [limit]: the maximum number of open orders structures to retrieve
2518
2805
  :param dict [params]: extra parameters specific to the exchange API endpoint
2519
2806
  :param int [params.until]: end time in ms
2520
- :param bool [params.stop]: True if fetching stop orders
2807
+ :param bool [params.trigger]: True if fetching trigger orders
2521
2808
  :param str [params.side]: buy or sell
2522
2809
  :param str [params.type]: limit, market, limit_stop or market_stop
2523
2810
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2524
- :param int [params.currentPage]: *stop orders only* current page
2525
- :param str [params.orderIds]: *stop orders only* comma seperated order ID list
2526
- :param bool [params.stop]: True if fetching a stop order
2811
+ :param int [params.currentPage]: *trigger orders only* current page
2812
+ :param str [params.orderIds]: *trigger orders only* comma seperated order ID list
2527
2813
  :param bool [params.hf]: False, # True for hf order
2528
2814
  :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)
2529
2815
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2538,16 +2824,18 @@ class kucoin(Exchange, ImplicitAPI):
2538
2824
  def fetch_order(self, id: str, symbol: Str = None, params={}):
2539
2825
  """
2540
2826
  fetch an order
2541
- :see: https://docs.kucoin.com/spot#get-an-order
2542
- :see: https://docs.kucoin.com/spot#get-single-active-order-by-clientoid
2543
- :see: https://docs.kucoin.com/spot#get-single-order-info
2544
- :see: https://docs.kucoin.com/spot#get-single-order-by-clientoid
2545
- :see: https://docs.kucoin.com/spot-hf/#details-of-a-single-hf-order
2546
- :see: https://docs.kucoin.com/spot-hf/#obtain-details-of-a-single-hf-order-using-clientoid
2827
+
2828
+ https://docs.kucoin.com/spot#get-an-order
2829
+ https://docs.kucoin.com/spot#get-single-active-order-by-clientoid
2830
+ https://docs.kucoin.com/spot#get-single-order-info
2831
+ https://docs.kucoin.com/spot#get-single-order-by-clientoid
2832
+ https://docs.kucoin.com/spot-hf/#details-of-a-single-hf-order
2833
+ https://docs.kucoin.com/spot-hf/#obtain-details-of-a-single-hf-order-using-clientoid
2834
+
2547
2835
  :param str id: Order id
2548
- :param str symbol: not sent to exchange except for stop orders with clientOid, but used internally by CCXT to filter
2836
+ :param str symbol: not sent to exchange except for trigger orders with clientOid, but used internally by CCXT to filter
2549
2837
  :param dict [params]: exchange specific parameters
2550
- :param bool [params.stop]: True if fetching a stop order
2838
+ :param bool [params.trigger]: True if fetching a trigger order
2551
2839
  :param bool [params.hf]: False, # True for hf order
2552
2840
  :param bool [params.clientOid]: unique order id created by users to identify their orders
2553
2841
  :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2555,8 +2843,9 @@ class kucoin(Exchange, ImplicitAPI):
2555
2843
  self.load_markets()
2556
2844
  request: dict = {}
2557
2845
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
2558
- stop = self.safe_bool(params, 'stop', False)
2559
- hf = self.safe_bool(params, 'hf', False)
2846
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2847
+ hf = None
2848
+ hf, params = self.handle_hf_and_params(params)
2560
2849
  market = None
2561
2850
  if symbol is not None:
2562
2851
  market = self.market(symbol)
@@ -2564,11 +2853,11 @@ class kucoin(Exchange, ImplicitAPI):
2564
2853
  if symbol is None:
2565
2854
  raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol parameter for hf orders')
2566
2855
  request['symbol'] = market['id']
2567
- params = self.omit(params, ['stop', 'hf', 'clientOid', 'clientOrderId'])
2856
+ params = self.omit(params, ['stop', 'clientOid', 'clientOrderId', 'trigger'])
2568
2857
  response = None
2569
2858
  if clientOrderId is not None:
2570
2859
  request['clientOid'] = clientOrderId
2571
- if stop:
2860
+ if trigger:
2572
2861
  if symbol is not None:
2573
2862
  request['symbol'] = market['id']
2574
2863
  response = self.privateGetStopOrderQueryOrderByClientOid(self.extend(request, params))
@@ -2583,7 +2872,7 @@ class kucoin(Exchange, ImplicitAPI):
2583
2872
  if id is None:
2584
2873
  raise InvalidOrder(self.id + ' fetchOrder() requires an order id')
2585
2874
  request['orderId'] = id
2586
- if stop:
2875
+ if trigger:
2587
2876
  response = self.privateGetStopOrderOrderId(self.extend(request, params))
2588
2877
  elif hf:
2589
2878
  response = self.privateGetHfOrdersOrderId(self.extend(request, params))
@@ -2721,7 +3010,7 @@ class kucoin(Exchange, ImplicitAPI):
2721
3010
  feeCurrencyId = self.safe_string(order, 'feeCurrency')
2722
3011
  cancelExist = self.safe_bool(order, 'cancelExist', False)
2723
3012
  responseStop = self.safe_string(order, 'stop')
2724
- stop = responseStop is not None
3013
+ trigger = responseStop is not None
2725
3014
  stopTriggered = self.safe_bool(order, 'stopTriggered', False)
2726
3015
  isActive = self.safe_bool_2(order, 'isActive', 'active')
2727
3016
  responseStatus = self.safe_string(order, 'status')
@@ -2731,7 +3020,7 @@ class kucoin(Exchange, ImplicitAPI):
2731
3020
  status = 'open'
2732
3021
  else:
2733
3022
  status = 'closed'
2734
- if stop:
3023
+ if trigger:
2735
3024
  if responseStatus == 'NEW':
2736
3025
  status = 'open'
2737
3026
  elif not isActive and not stopTriggered:
@@ -2740,7 +3029,6 @@ class kucoin(Exchange, ImplicitAPI):
2740
3029
  status = 'canceled'
2741
3030
  if responseStatus == 'fail':
2742
3031
  status = 'rejected'
2743
- stopPrice = self.safe_number(order, 'stopPrice')
2744
3032
  return self.safe_order({
2745
3033
  'info': order,
2746
3034
  'id': self.safe_string_n(order, ['id', 'orderId', 'newOrderId', 'cancelledOrderId']),
@@ -2752,8 +3040,7 @@ class kucoin(Exchange, ImplicitAPI):
2752
3040
  'side': self.safe_string(order, 'side'),
2753
3041
  'amount': self.safe_string(order, 'size'),
2754
3042
  'price': self.safe_string(order, 'price'), # price is zero for market order, omitZero is called in safeOrder2
2755
- 'stopPrice': stopPrice,
2756
- 'triggerPrice': stopPrice,
3043
+ 'triggerPrice': self.safe_number(order, 'stopPrice'),
2757
3044
  'cost': self.safe_string(order, 'dealFunds'),
2758
3045
  'filled': self.safe_string(order, 'dealSize'),
2759
3046
  'remaining': None,
@@ -2765,15 +3052,17 @@ class kucoin(Exchange, ImplicitAPI):
2765
3052
  },
2766
3053
  'status': status,
2767
3054
  'lastTradeTimestamp': None,
2768
- 'average': None,
3055
+ 'average': self.safe_string(order, 'avgDealPrice'),
2769
3056
  'trades': None,
2770
3057
  }, market)
2771
3058
 
2772
3059
  def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2773
3060
  """
2774
3061
  fetch all the trades made from a single order
2775
- :see: https://docs.kucoin.com/#list-fills
2776
- :see: https://docs.kucoin.com/spot-hf/#transaction-details
3062
+
3063
+ https://docs.kucoin.com/#list-fills
3064
+ https://docs.kucoin.com/spot-hf/#transaction-details
3065
+
2777
3066
  :param str id: order id
2778
3067
  :param str symbol: unified market symbol
2779
3068
  :param int [since]: the earliest time in ms to fetch trades for
@@ -2788,8 +3077,10 @@ class kucoin(Exchange, ImplicitAPI):
2788
3077
 
2789
3078
  def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2790
3079
  """
2791
- :see: https://docs.kucoin.com/#list-fills
2792
- :see: https://docs.kucoin.com/spot-hf/#transaction-details
3080
+
3081
+ https://docs.kucoin.com/#list-fills
3082
+ https://docs.kucoin.com/spot-hf/#transaction-details
3083
+
2793
3084
  fetch all trades made by the user
2794
3085
  :param str symbol: unified market symbol
2795
3086
  :param int [since]: the earliest time in ms to fetch trades for
@@ -2806,20 +3097,25 @@ class kucoin(Exchange, ImplicitAPI):
2806
3097
  if paginate:
2807
3098
  return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
2808
3099
  request: dict = {}
2809
- hf = self.safe_bool(params, 'hf', False)
3100
+ hf = None
3101
+ hf, params = self.handle_hf_and_params(params)
2810
3102
  if hf and symbol is None:
2811
3103
  raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol parameter for hf orders')
2812
3104
  market = None
2813
3105
  if symbol is not None:
2814
3106
  market = self.market(symbol)
2815
3107
  request['symbol'] = market['id']
2816
- if limit is not None:
2817
- request['pageSize'] = limit
2818
3108
  method = self.options['fetchMyTradesMethod']
2819
3109
  parseResponseData = False
2820
3110
  response = None
2821
3111
  request, params = self.handle_until_option('endAt', request, params)
2822
3112
  if hf:
3113
+ # does not return trades earlier than 2019-02-18T00:00:00Z
3114
+ if limit is not None:
3115
+ request['limit'] = limit
3116
+ if since is not None:
3117
+ # only returns trades up to one week after the since param
3118
+ request['startAt'] = since
2823
3119
  response = self.privateGetHfFills(self.extend(request, params))
2824
3120
  elif method == 'private_get_fills':
2825
3121
  # does not return trades earlier than 2019-02-18T00:00:00Z
@@ -2886,7 +3182,9 @@ class kucoin(Exchange, ImplicitAPI):
2886
3182
  def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
2887
3183
  """
2888
3184
  get the list of most recent trades for a particular symbol
2889
- :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-trade-histories
3185
+
3186
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-trade-histories
3187
+
2890
3188
  :param str symbol: unified symbol of the market to fetch trades for
2891
3189
  :param int [since]: timestamp in ms of the earliest trade to fetch
2892
3190
  :param int [limit]: the maximum amount of trades to fetch
@@ -3051,7 +3349,9 @@ class kucoin(Exchange, ImplicitAPI):
3051
3349
  def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
3052
3350
  """
3053
3351
  fetch the trading fees for a market
3054
- :see: https://www.kucoin.com/docs/rest/funding/trade-fee/trading-pair-actual-fee-spot-margin-trade_hf
3352
+
3353
+ https://www.kucoin.com/docs/rest/funding/trade-fee/trading-pair-actual-fee-spot-margin-trade_hf
3354
+
3055
3355
  :param str symbol: unified market symbol
3056
3356
  :param dict [params]: extra parameters specific to the exchange API endpoint
3057
3357
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -3086,10 +3386,12 @@ class kucoin(Exchange, ImplicitAPI):
3086
3386
  'tierBased': True,
3087
3387
  }
3088
3388
 
3089
- def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
3389
+ def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
3090
3390
  """
3091
3391
  make a withdrawal
3092
- :see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw
3392
+
3393
+ https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw-v3-
3394
+
3093
3395
  :param str code: unified currency code
3094
3396
  :param float amount: the amount to withdraw
3095
3397
  :param str address: the address to withdraw to
@@ -3103,7 +3405,8 @@ class kucoin(Exchange, ImplicitAPI):
3103
3405
  currency = self.currency(code)
3104
3406
  request: dict = {
3105
3407
  'currency': currency['id'],
3106
- 'address': address,
3408
+ 'toAddress': address,
3409
+ 'withdrawType': 'ADDRESS',
3107
3410
  # 'memo': tag,
3108
3411
  # 'isInner': False, # internal transfer or external withdrawal
3109
3412
  # 'remark': 'optional',
@@ -3115,15 +3418,14 @@ class kucoin(Exchange, ImplicitAPI):
3115
3418
  networkCode, params = self.handle_network_code_and_params(params)
3116
3419
  if networkCode is not None:
3117
3420
  request['chain'] = self.network_code_to_id(networkCode).lower()
3118
- self.load_currency_precision(currency, networkCode)
3119
- request['amount'] = self.currency_to_precision(code, amount, networkCode)
3421
+ request['amount'] = float(self.currency_to_precision(code, amount, networkCode))
3120
3422
  includeFee = None
3121
3423
  includeFee, params = self.handle_option_and_params(params, 'withdraw', 'includeFee', False)
3122
3424
  if includeFee:
3123
3425
  request['feeDeductType'] = 'INTERNAL'
3124
3426
  response = self.privatePostWithdrawals(self.extend(request, params))
3125
3427
  #
3126
- # https://github.com/ccxt/ccxt/issues/5558
3428
+ # the id is inside "data"
3127
3429
  #
3128
3430
  # {
3129
3431
  # "code": 200000,
@@ -3135,51 +3437,6 @@ class kucoin(Exchange, ImplicitAPI):
3135
3437
  data = self.safe_dict(response, 'data', {})
3136
3438
  return self.parse_transaction(data, currency)
3137
3439
 
3138
- def load_currency_precision(self, currency, networkCode: Str = None):
3139
- # might not have network specific precisions defined in fetchCurrencies(because of webapi failure)
3140
- # we should check and refetch precision once-per-instance for that specific currency & network
3141
- # so avoids thorwing exceptions and burden to users
3142
- # Note: self needs to be executed only if networkCode was provided
3143
- if networkCode is not None:
3144
- networks = currency['networks']
3145
- network = self.safe_dict(networks, networkCode)
3146
- if self.safe_number(network, 'precision') is not None:
3147
- # if precision exists, no need to refetch
3148
- return
3149
- # otherwise try to fetch and store in instance
3150
- request: dict = {
3151
- 'currency': currency['id'],
3152
- 'chain': self.network_code_to_id(networkCode).lower(),
3153
- }
3154
- response = self.privateGetWithdrawalsQuotas(request)
3155
- #
3156
- # {
3157
- # "code": "200000",
3158
- # "data": {
3159
- # "currency": "USDT",
3160
- # "limitBTCAmount": "14.24094850",
3161
- # "usedBTCAmount": "0.00000000",
3162
- # "quotaCurrency": "USDT",
3163
- # "limitQuotaCurrencyAmount": "999999.00000000",
3164
- # "usedQuotaCurrencyAmount": "0",
3165
- # "remainAmount": "999999.0000",
3166
- # "availableAmount": "10.77545071",
3167
- # "withdrawMinFee": "1",
3168
- # "innerWithdrawMinFee": "0",
3169
- # "withdrawMinSize": "10",
3170
- # "isWithdrawEnabled": True,
3171
- # "precision": 4,
3172
- # "chain": "EOS",
3173
- # "reason": null,
3174
- # "lockedAmount": "0"
3175
- # }
3176
- # }
3177
- #
3178
- data = self.safe_dict(response, 'data', {})
3179
- precision = self.parse_number(self.parse_precision(self.safe_string(data, 'precision')))
3180
- code = currency['code']
3181
- self.currencies[code]['networks'][networkCode]['precision'] = precision
3182
-
3183
3440
  def parse_transaction_status(self, status: Str):
3184
3441
  statuses: dict = {
3185
3442
  'SUCCESS': 'ok',
@@ -3296,8 +3553,10 @@ class kucoin(Exchange, ImplicitAPI):
3296
3553
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3297
3554
  """
3298
3555
  fetch all deposits made to an account
3299
- :see: https://www.kucoin.com/docs/rest/funding/deposit/get-deposit-list
3300
- :see: https://www.kucoin.com/docs/rest/funding/deposit/get-v1-historical-deposits-list
3556
+
3557
+ https://www.kucoin.com/docs/rest/funding/deposit/get-deposit-list
3558
+ https://www.kucoin.com/docs/rest/funding/deposit/get-v1-historical-deposits-list
3559
+
3301
3560
  :param str code: unified currency code
3302
3561
  :param int [since]: the earliest time in ms to fetch deposits for
3303
3562
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -3366,14 +3625,17 @@ class kucoin(Exchange, ImplicitAPI):
3366
3625
  # }
3367
3626
  # }
3368
3627
  #
3369
- responseData = response['data']['items']
3370
- return self.parse_transactions(responseData, currency, since, limit, {'type': 'deposit'})
3628
+ data = self.safe_dict(response, 'data', {})
3629
+ items = self.safe_list(data, 'items', [])
3630
+ return self.parse_transactions(items, currency, since, limit, {'type': 'deposit'})
3371
3631
 
3372
3632
  def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3373
3633
  """
3374
3634
  fetch all withdrawals made from an account
3375
- :see: https://www.kucoin.com/docs/rest/funding/withdrawals/get-withdrawals-list
3376
- :see: https://www.kucoin.com/docs/rest/funding/withdrawals/get-v1-historical-withdrawals-list
3635
+
3636
+ https://www.kucoin.com/docs/rest/funding/withdrawals/get-withdrawals-list
3637
+ https://www.kucoin.com/docs/rest/funding/withdrawals/get-v1-historical-withdrawals-list
3638
+
3377
3639
  :param str code: unified currency code
3378
3640
  :param int [since]: the earliest time in ms to fetch withdrawals for
3379
3641
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -3443,8 +3705,9 @@ class kucoin(Exchange, ImplicitAPI):
3443
3705
  # }
3444
3706
  # }
3445
3707
  #
3446
- responseData = response['data']['items']
3447
- return self.parse_transactions(responseData, currency, since, limit, {'type': 'withdrawal'})
3708
+ data = self.safe_dict(response, 'data', {})
3709
+ items = self.safe_list(data, 'items', [])
3710
+ return self.parse_transactions(items, currency, since, limit, {'type': 'withdrawal'})
3448
3711
 
3449
3712
  def parse_balance_helper(self, entry):
3450
3713
  account = self.account()
@@ -3459,9 +3722,11 @@ class kucoin(Exchange, ImplicitAPI):
3459
3722
  def fetch_balance(self, params={}) -> Balances:
3460
3723
  """
3461
3724
  query for balance and get the amount of funds available for trading or funds locked in orders
3462
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3463
- :see: https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-margin
3464
- :see: https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-isolated-margin
3725
+
3726
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3727
+ https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-margin
3728
+ https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-isolated-margin
3729
+
3465
3730
  :param dict [params]: extra parameters specific to the exchange API endpoint
3466
3731
  :param dict [params.marginMode]: 'cross' or 'isolated', margin type for fetching margin balance
3467
3732
  :param dict [params.type]: extra parameters specific to the exchange API endpoint
@@ -3478,10 +3743,10 @@ class kucoin(Exchange, ImplicitAPI):
3478
3743
  accountsByType = self.safe_dict(self.options, 'accountsByType')
3479
3744
  type = self.safe_string(accountsByType, requestedType, requestedType)
3480
3745
  params = self.omit(params, 'type')
3481
- isHf = self.safe_bool(params, 'hf', False)
3482
- if isHf:
3746
+ hf = None
3747
+ hf, params = self.handle_hf_and_params(params)
3748
+ if hf and (type != 'main'):
3483
3749
  type = 'trade_hf'
3484
- params = self.omit(params, 'hf')
3485
3750
  marginMode, query = self.handle_margin_mode_and_params('fetchBalance', params)
3486
3751
  response = None
3487
3752
  request: dict = {}
@@ -3617,15 +3882,19 @@ class kucoin(Exchange, ImplicitAPI):
3617
3882
  account['free'] = self.safe_string(balance, 'available')
3618
3883
  account['used'] = self.safe_string(balance, 'holds')
3619
3884
  result[codeInner2] = account
3620
- returnType = result if isolated else self.safe_balance(result)
3885
+ returnType = result
3886
+ if not isolated:
3887
+ returnType = self.safe_balance(result)
3621
3888
  return returnType
3622
3889
 
3623
3890
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
3624
3891
  """
3625
3892
  transfer currency internally between wallets on the same account
3626
- :see: https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
3627
- :see: https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3628
- :see: https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3893
+
3894
+ https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
3895
+ https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3896
+ https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3897
+
3629
3898
  :param str code: unified currency code
3630
3899
  :param float amount: amount to transfer
3631
3900
  :param str fromAccount: account to transfer from
@@ -3810,7 +4079,7 @@ class kucoin(Exchange, ImplicitAPI):
3810
4079
  }
3811
4080
  return self.safe_string(types, type, type)
3812
4081
 
3813
- def parse_ledger_entry(self, item: dict, currency: Currency = None):
4082
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
3814
4083
  #
3815
4084
  # {
3816
4085
  # "id": "611a1e7c6a053300067a88d9", #unique key for each ledger entry
@@ -3828,6 +4097,7 @@ class kucoin(Exchange, ImplicitAPI):
3828
4097
  id = self.safe_string(item, 'id')
3829
4098
  currencyId = self.safe_string(item, 'currency')
3830
4099
  code = self.safe_currency_code(currencyId, currency)
4100
+ currency = self.safe_currency(currencyId, currency)
3831
4101
  amount = self.safe_number(item, 'amount')
3832
4102
  balanceAfter = None
3833
4103
  # balanceAfter = self.safe_number(item, 'balance'); only returns zero string
@@ -3870,7 +4140,8 @@ class kucoin(Exchange, ImplicitAPI):
3870
4140
  if feeCost != '0':
3871
4141
  feeCurrency = code
3872
4142
  fee = {'cost': self.parse_number(feeCost), 'currency': feeCurrency}
3873
- return {
4143
+ return self.safe_ledger_entry({
4144
+ 'info': item,
3874
4145
  'id': id,
3875
4146
  'direction': direction,
3876
4147
  'account': account,
@@ -3885,30 +4156,31 @@ class kucoin(Exchange, ImplicitAPI):
3885
4156
  'after': balanceAfter, # None
3886
4157
  'status': None,
3887
4158
  'fee': fee,
3888
- 'info': item,
3889
- }
4159
+ }, currency)
3890
4160
 
3891
- def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4161
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
3892
4162
  """
3893
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-spot-margin
3894
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
3895
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
3896
- fetch the history of changes, actions done by the user or operations that altered balance of the user
3897
- :param str code: unified currency code, default is None
4163
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
4164
+
4165
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-spot-margin
4166
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
4167
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
4168
+
4169
+ :param str [code]: unified currency code, default is None
3898
4170
  :param int [since]: timestamp in ms of the earliest ledger entry, default is None
3899
- :param int [limit]: max number of ledger entrys to return, default is None
4171
+ :param int [limit]: max number of ledger entries to return, default is None
3900
4172
  :param dict [params]: extra parameters specific to the exchange API endpoint
3901
4173
  :param boolean [params.hf]: default False, when True will fetch ledger entries for the high frequency trading account
3902
4174
  :param int [params.until]: the latest time in ms to fetch entries for
3903
- :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)
3904
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
4175
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4176
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
3905
4177
  """
3906
4178
  self.load_markets()
3907
4179
  self.load_accounts()
3908
4180
  paginate = False
3909
4181
  paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
3910
- isHf = self.safe_bool(params, 'hf')
3911
- params = self.omit(params, 'hf')
4182
+ hf = None
4183
+ hf, params = self.handle_hf_and_params(params)
3912
4184
  if paginate:
3913
4185
  return self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params)
3914
4186
  request: dict = {
@@ -3929,7 +4201,7 @@ class kucoin(Exchange, ImplicitAPI):
3929
4201
  marginMode = None
3930
4202
  marginMode, params = self.handle_margin_mode_and_params('fetchLedger', params)
3931
4203
  response = None
3932
- if isHf:
4204
+ if hf:
3933
4205
  if marginMode is not None:
3934
4206
  response = self.privateGetHfMarginAccountLedgers(self.extend(request, params))
3935
4207
  else:
@@ -3994,15 +4266,6 @@ class kucoin(Exchange, ImplicitAPI):
3994
4266
  return config['v1']
3995
4267
  return self.safe_value(config, 'cost', 1)
3996
4268
 
3997
- def parse_borrow_rate_history(self, response, code, since, limit):
3998
- result = []
3999
- for i in range(0, len(response)):
4000
- item = response[i]
4001
- borrowRate = self.parse_borrow_rate(item)
4002
- result.append(borrowRate)
4003
- sorted = self.sort_by(result, 'timestamp')
4004
- return self.filter_by_currency_since_limit(sorted, code, since, limit)
4005
-
4006
4269
  def parse_borrow_rate(self, info, currency: Currency = None):
4007
4270
  #
4008
4271
  # {
@@ -4033,13 +4296,15 @@ class kucoin(Exchange, ImplicitAPI):
4033
4296
  'info': info,
4034
4297
  }
4035
4298
 
4036
- def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4299
+ def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
4037
4300
  """
4038
4301
  fetch the interest owed by the user for borrowing currency for margin trading
4039
- :see: https://docs.kucoin.com/#get-repay-record
4040
- :see: https://docs.kucoin.com/#query-isolated-margin-account-info
4041
- :param str code: unified currency code
4042
- :param str symbol: unified market symbol, required for isolated margin
4302
+
4303
+ https://docs.kucoin.com/#get-repay-record
4304
+ https://docs.kucoin.com/#query-isolated-margin-account-info
4305
+
4306
+ :param str [code]: unified currency code
4307
+ :param str [symbol]: unified market symbol, required for isolated margin
4043
4308
  :param int [since]: the earliest time in ms to fetch borrrow interest for
4044
4309
  :param int [limit]: the maximum number of structures to retrieve
4045
4310
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4048,14 +4313,19 @@ class kucoin(Exchange, ImplicitAPI):
4048
4313
  """
4049
4314
  self.load_markets()
4050
4315
  marginMode = None
4051
- marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params)
4052
- if marginMode is None:
4053
- marginMode = 'cross' # cross marginMode
4316
+ marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params, 'cross')
4054
4317
  request: dict = {}
4055
- response = None
4318
+ currency = None
4056
4319
  if code is not None:
4057
4320
  currency = self.currency(code)
4058
- request['quoteCurrency'] = currency['id']
4321
+ if marginMode == 'isolated':
4322
+ request['balanceCurrency'] = currency['id']
4323
+ else:
4324
+ request['quoteCurrency'] = currency['id']
4325
+ market = None
4326
+ if symbol is not None:
4327
+ market = self.market(symbol)
4328
+ response = None
4059
4329
  if marginMode == 'isolated':
4060
4330
  response = self.privateGetIsolatedAccounts(self.extend(request, params))
4061
4331
  else:
@@ -4126,9 +4396,11 @@ class kucoin(Exchange, ImplicitAPI):
4126
4396
  #
4127
4397
  data = self.safe_dict(response, 'data', {})
4128
4398
  assets = self.safe_list(data, 'assets', []) if (marginMode == 'isolated') else self.safe_list(data, 'accounts', [])
4129
- return self.parse_borrow_interests(assets, None)
4399
+ interest = self.parse_borrow_interests(assets, market)
4400
+ filteredByCurrency = self.filter_by_currency_since_limit(interest, code, since, limit)
4401
+ return self.filter_by_symbol_since_limit(filteredByCurrency, symbol, since, limit)
4130
4402
 
4131
- def parse_borrow_interest(self, info: dict, market: Market = None):
4403
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
4132
4404
  #
4133
4405
  # Cross
4134
4406
  #
@@ -4191,21 +4463,23 @@ class kucoin(Exchange, ImplicitAPI):
4191
4463
  interest = self.safe_number(info, 'accruedInterest')
4192
4464
  currencyId = self.safe_string(info, 'currency')
4193
4465
  return {
4466
+ 'info': info,
4194
4467
  'symbol': symbol,
4195
- 'marginMode': marginMode,
4196
4468
  'currency': self.safe_currency_code(currencyId),
4197
4469
  'interest': interest,
4198
4470
  'interestRate': self.safe_number(info, 'dailyIntRate'),
4199
4471
  'amountBorrowed': amountBorrowed,
4472
+ 'marginMode': marginMode,
4200
4473
  'timestamp': timestamp, # create time
4201
4474
  'datetime': self.iso8601(timestamp),
4202
- 'info': info,
4203
4475
  }
4204
4476
 
4205
4477
  def fetch_borrow_rate_histories(self, codes=None, since: Int = None, limit: Int = None, params={}):
4206
4478
  """
4207
4479
  retrieves a history of a multiple currencies borrow interest rate at specific time slots, returns all currencies if no symbols passed, default is None
4208
- :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4480
+
4481
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4482
+
4209
4483
  :param str[]|None codes: list of unified currency codes, default is None
4210
4484
  :param int [since]: timestamp in ms of the earliest borrowRate, default is None
4211
4485
  :param int [limit]: max number of borrow rate prices to return, default is None
@@ -4248,13 +4522,15 @@ class kucoin(Exchange, ImplicitAPI):
4248
4522
  # }
4249
4523
  #
4250
4524
  data = self.safe_dict(response, 'data')
4251
- rows = self.safe_list(data, 'items')
4525
+ rows = self.safe_list(data, 'items', [])
4252
4526
  return self.parse_borrow_rate_histories(rows, codes, since, limit)
4253
4527
 
4254
4528
  def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
4255
4529
  """
4256
4530
  retrieves a history of a currencies borrow interest rate at specific time slots
4257
- :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4531
+
4532
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4533
+
4258
4534
  :param str code: unified currency code
4259
4535
  :param int [since]: timestamp for the earliest borrow rate
4260
4536
  :param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
@@ -4299,7 +4575,7 @@ class kucoin(Exchange, ImplicitAPI):
4299
4575
  # }
4300
4576
  #
4301
4577
  data = self.safe_dict(response, 'data')
4302
- rows = self.safe_list(data, 'items')
4578
+ rows = self.safe_list(data, 'items', [])
4303
4579
  return self.parse_borrow_rate_history(rows, code, since, limit)
4304
4580
 
4305
4581
  def parse_borrow_rate_histories(self, response, codes, since, limit):
@@ -4321,7 +4597,8 @@ class kucoin(Exchange, ImplicitAPI):
4321
4597
  if not (code in borrowRateHistories):
4322
4598
  borrowRateHistories[code] = []
4323
4599
  borrowRateStructure = self.parse_borrow_rate(item)
4324
- borrowRateHistories[code].append(borrowRateStructure)
4600
+ borrowRateHistoriesCode = borrowRateHistories[code]
4601
+ borrowRateHistoriesCode.append(borrowRateStructure)
4325
4602
  keys = list(borrowRateHistories.keys())
4326
4603
  for i in range(0, len(keys)):
4327
4604
  code = keys[i]
@@ -4331,7 +4608,9 @@ class kucoin(Exchange, ImplicitAPI):
4331
4608
  def borrow_cross_margin(self, code: str, amount: float, params={}):
4332
4609
  """
4333
4610
  create a loan to borrow margin
4334
- :see: https://docs.kucoin.com/#1-margin-borrowing
4611
+
4612
+ https://docs.kucoin.com/#1-margin-borrowing
4613
+
4335
4614
  :param str code: unified currency code of the currency to borrow
4336
4615
  :param float amount: the amount to borrow
4337
4616
  :param dict [params]: extra parameters specific to the exchange API endpoints
@@ -4364,7 +4643,9 @@ class kucoin(Exchange, ImplicitAPI):
4364
4643
  def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
4365
4644
  """
4366
4645
  create a loan to borrow margin
4367
- :see: https://docs.kucoin.com/#1-margin-borrowing
4646
+
4647
+ https://docs.kucoin.com/#1-margin-borrowing
4648
+
4368
4649
  :param str symbol: unified market symbol, required for isolated margin
4369
4650
  :param str code: unified currency code of the currency to borrow
4370
4651
  :param float amount: the amount to borrow
@@ -4401,7 +4682,9 @@ class kucoin(Exchange, ImplicitAPI):
4401
4682
  def repay_cross_margin(self, code: str, amount, params={}):
4402
4683
  """
4403
4684
  repay borrowed margin and interest
4404
- :see: https://docs.kucoin.com/#2-repayment
4685
+
4686
+ https://docs.kucoin.com/#2-repayment
4687
+
4405
4688
  :param str code: unified currency code of the currency to repay
4406
4689
  :param float amount: the amount to repay
4407
4690
  :param dict [params]: extra parameters specific to the exchange API endpoints
@@ -4432,7 +4715,9 @@ class kucoin(Exchange, ImplicitAPI):
4432
4715
  def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
4433
4716
  """
4434
4717
  repay borrowed margin and interest
4435
- :see: https://docs.kucoin.com/#2-repayment
4718
+
4719
+ https://docs.kucoin.com/#2-repayment
4720
+
4436
4721
  :param str symbol: unified market symbol
4437
4722
  :param str code: unified currency code of the currency to repay
4438
4723
  :param float amount: the amount to repay
@@ -4486,7 +4771,9 @@ class kucoin(Exchange, ImplicitAPI):
4486
4771
  def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
4487
4772
  """
4488
4773
  fetch deposit and withdraw fees - *IMPORTANT* use fetchDepositWithdrawFee to get more in-depth info
4489
- :see: https://docs.kucoin.com/#get-currencies
4774
+
4775
+ https://docs.kucoin.com/#get-currencies
4776
+
4490
4777
  :param str[]|None codes: list of unified currency codes
4491
4778
  :param dict [params]: extra parameters specific to the exchange API endpoint
4492
4779
  :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -4514,6 +4801,38 @@ class kucoin(Exchange, ImplicitAPI):
4514
4801
  data = self.safe_list(response, 'data', [])
4515
4802
  return self.parse_deposit_withdraw_fees(data, codes, 'currency')
4516
4803
 
4804
+ def set_leverage(self, leverage: int, symbol: Str = None, params={}):
4805
+ """
4806
+ set the level of leverage for a market
4807
+
4808
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/modify-leverage-multiplier
4809
+
4810
+ :param int [leverage]: New leverage multiplier. Must be greater than 1 and up to two decimal places, and cannot be less than the user's current debt leverage or greater than the system's maximum leverage
4811
+ :param str [symbol]: unified market symbol
4812
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4813
+ :returns dict: response from the exchange
4814
+ """
4815
+ self.load_markets()
4816
+ market = None
4817
+ marketType: Str = None
4818
+ marketType, params = self.handle_market_type_and_params('setLeverage', None, params)
4819
+ if (symbol is not None) or marketType != 'spot':
4820
+ market = self.market(symbol)
4821
+ if market['contract']:
4822
+ raise NotSupported(self.id + ' setLeverage currently supports only spot margin')
4823
+ marginMode: Str = None
4824
+ marginMode, params = self.handle_margin_mode_and_params('setLeverage', params)
4825
+ if marginMode is None:
4826
+ raise ArgumentsRequired(self.id + ' setLeverage requires a marginMode parameter')
4827
+ request: dict = {}
4828
+ if marginMode == 'isolated' and symbol is None:
4829
+ raise ArgumentsRequired(self.id + ' setLeverage requires a symbol parameter for isolated margin')
4830
+ if symbol is not None:
4831
+ request['symbol'] = market['id']
4832
+ request['leverage'] = str(leverage)
4833
+ request['isIsolated'] = (marginMode == 'isolated')
4834
+ return self.privatePostPositionUpdateUserLeverage(self.extend(request, params))
4835
+
4517
4836
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4518
4837
  #
4519
4838
  # the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint
@@ -4536,7 +4855,7 @@ class kucoin(Exchange, ImplicitAPI):
4536
4855
  headers = headers if (headers is not None) else {}
4537
4856
  url = self.urls['api'][api]
4538
4857
  if not self.is_empty(query):
4539
- if (method == 'GET') or (method == 'DELETE'):
4858
+ if ((method == 'GET') or (method == 'DELETE')) and (path != 'orders/multi-cancel'):
4540
4859
  endpoint += '?' + self.rawencode(query)
4541
4860
  else:
4542
4861
  body = self.json(query)
@@ -4592,7 +4911,7 @@ class kucoin(Exchange, ImplicitAPI):
4592
4911
  #
4593
4912
  errorCode = self.safe_string(response, 'code')
4594
4913
  message = self.safe_string_2(response, 'msg', 'data', '')
4595
- feedback = self.id + ' ' + message
4914
+ feedback = self.id + ' ' + body
4596
4915
  self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
4597
4916
  self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
4598
4917
  self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)