ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3205 -937
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1525 -573
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +223 -97
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3205 -937
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1525 -573
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +223 -97
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +143 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
@@ -9,9 +9,10 @@ import asyncio
9
9
  import hashlib
10
10
  import math
11
11
  import json
12
- from ccxt.base.types import Account, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
12
+ from ccxt.base.types import Account, Balances, BorrowInterest, Bool, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
13
13
  from typing import List
14
14
  from ccxt.base.errors import ExchangeError
15
+ from ccxt.base.errors import AuthenticationError
15
16
  from ccxt.base.errors import PermissionDenied
16
17
  from ccxt.base.errors import AccountSuspended
17
18
  from ccxt.base.errors import ArgumentsRequired
@@ -25,7 +26,7 @@ from ccxt.base.errors import NotSupported
25
26
  from ccxt.base.errors import RateLimitExceeded
26
27
  from ccxt.base.errors import ExchangeNotAvailable
27
28
  from ccxt.base.errors import InvalidNonce
28
- from ccxt.base.errors import AuthenticationError
29
+ from ccxt.base.decimal_to_precision import TRUNCATE
29
30
  from ccxt.base.decimal_to_precision import TICK_SIZE
30
31
  from ccxt.base.precise import Precise
31
32
 
@@ -78,6 +79,7 @@ class kucoin(Exchange, ImplicitAPI):
78
79
  'fetchCrossBorrowRates': False,
79
80
  'fetchCurrencies': True,
80
81
  'fetchDepositAddress': True,
82
+ 'fetchDepositAddresses': False,
81
83
  'fetchDepositAddressesByNetwork': True,
82
84
  'fetchDeposits': True,
83
85
  'fetchDepositWithdrawFee': True,
@@ -92,10 +94,13 @@ class kucoin(Exchange, ImplicitAPI):
92
94
  'fetchL3OrderBook': True,
93
95
  'fetchLedger': True,
94
96
  'fetchLeverageTiers': False,
97
+ 'fetchMarginAdjustmentHistory': False,
95
98
  'fetchMarginMode': False,
96
99
  'fetchMarketLeverageTiers': False,
97
100
  'fetchMarkets': True,
98
101
  'fetchMarkOHLCV': False,
102
+ 'fetchMarkPrice': True,
103
+ 'fetchMarkPrices': True,
99
104
  'fetchMyTrades': True,
100
105
  'fetchOHLCV': True,
101
106
  'fetchOpenInterest': False,
@@ -106,7 +111,9 @@ class kucoin(Exchange, ImplicitAPI):
106
111
  'fetchOrderBooks': False,
107
112
  'fetchOrdersByStatus': True,
108
113
  'fetchOrderTrades': True,
114
+ 'fetchPositionHistory': False,
109
115
  'fetchPositionMode': False,
116
+ 'fetchPositionsHistory': False,
110
117
  'fetchPremiumIndexOHLCV': False,
111
118
  'fetchStatus': True,
112
119
  'fetchTicker': True,
@@ -120,7 +127,7 @@ class kucoin(Exchange, ImplicitAPI):
120
127
  'fetchWithdrawals': True,
121
128
  'repayCrossMargin': True,
122
129
  'repayIsolatedMargin': True,
123
- 'setLeverage': False,
130
+ 'setLeverage': True,
124
131
  'setMarginMode': False,
125
132
  'setPositionMode': False,
126
133
  'signIn': False,
@@ -137,6 +144,7 @@ class kucoin(Exchange, ImplicitAPI):
137
144
  'futuresPublic': 'https://api-futures.kucoin.com',
138
145
  'webExchange': 'https://kucoin.com/_api',
139
146
  'broker': 'https://api-broker.kucoin.com',
147
+ 'earn': 'https://api.kucoin.com',
140
148
  },
141
149
  'www': 'https://www.kucoin.com',
142
150
  'doc': [
@@ -174,7 +182,9 @@ class kucoin(Exchange, ImplicitAPI):
174
182
  'status': 4.5, # 3PW
175
183
  # margin trading
176
184
  'mark-price/{symbol}/current': 3, # 2PW
185
+ 'mark-price/all-symbols': 3,
177
186
  'margin/config': 25, # 25SW
187
+ 'announcements': 20, # 20W
178
188
  },
179
189
  'post': {
180
190
  # ws
@@ -213,8 +223,10 @@ class kucoin(Exchange, ImplicitAPI):
213
223
  'market/orderbook/level{level}': 3, # 3SW
214
224
  'market/orderbook/level2': 3, # 3SW
215
225
  'market/orderbook/level3': 3, # 3SW
226
+ 'hf/accounts/opened': 2, #
216
227
  'hf/orders/active': 2, # 2SW
217
228
  'hf/orders/active/symbols': 2, # 2SW
229
+ 'hf/margin/order/active/symbols': 2, # 2SW
218
230
  'hf/orders/done': 2, # 2SW
219
231
  'hf/orders/{orderId}': 2, # 2SW
220
232
  'hf/orders/client-order/{clientOid}': 2, # 2SW
@@ -243,6 +255,7 @@ class kucoin(Exchange, ImplicitAPI):
243
255
  'margin/currencies': 20, # 20SW
244
256
  'risk/limit/strategy': 20, # 20SW(Deprecate)
245
257
  'isolated/symbols': 20, # 20SW
258
+ 'margin/symbols': 5,
246
259
  'isolated/account/{symbol}': 50, # 50SW
247
260
  'margin/borrow': 15, # 15SW
248
261
  'margin/repay': 15, # 15SW
@@ -253,6 +266,9 @@ class kucoin(Exchange, ImplicitAPI):
253
266
  'purchase/orders': 10, # 10SW
254
267
  # broker
255
268
  'broker/api/rebase/download': 3,
269
+ 'migrate/user/account/status': 3,
270
+ # affiliate
271
+ 'affiliate/inviter/statistics': 30,
256
272
  },
257
273
  'post': {
258
274
  # account
@@ -292,6 +308,8 @@ class kucoin(Exchange, ImplicitAPI):
292
308
  'lend/purchase/update': 10, # 10SW
293
309
  # ws
294
310
  'bullet-private': 10, # 10SW
311
+ 'position/update-user-leverage': 5,
312
+ 'deposit-address/create': 20,
295
313
  },
296
314
  'delete': {
297
315
  # account
@@ -404,6 +422,10 @@ class kucoin(Exchange, ImplicitAPI):
404
422
  'broker/nd/account': 2,
405
423
  'broker/nd/account/apikey': 2,
406
424
  'broker/nd/rebase/download': 3,
425
+ 'asset/ndbroker/deposit/list': 1,
426
+ 'broker/nd/transfer/detail': 1,
427
+ 'broker/nd/deposit/detail': 1,
428
+ 'broker/nd/withdraw/detail': 1,
407
429
  },
408
430
  'post': {
409
431
  'broker/nd/transfer': 1,
@@ -415,6 +437,25 @@ class kucoin(Exchange, ImplicitAPI):
415
437
  'broker/nd/account/apikey': 3,
416
438
  },
417
439
  },
440
+ 'earn': {
441
+ 'get': {
442
+ 'otc-loan/loan': 1,
443
+ 'otc-loan/accounts': 1,
444
+ 'earn/redeem-preview': 7.5, # 5EW
445
+ 'earn/saving/products': 7.5, # 5EW
446
+ 'earn/hold-assets': 7.5, # 5EW
447
+ 'earn/promotion/products': 7.5, # 5EW
448
+ 'earn/kcs-staking/products': 7.5, # 5EW
449
+ 'earn/staking/products': 7.5, # 5EW
450
+ 'earn/eth-staking/products': 7.5, # 5EW
451
+ },
452
+ 'post': {
453
+ 'earn/orders': 7.5, # 5EW
454
+ },
455
+ 'delete': {
456
+ 'earn/orders': 7.5, # 5EW
457
+ },
458
+ },
418
459
  },
419
460
  'timeframes': {
420
461
  '1m': '1min',
@@ -435,6 +476,7 @@ class kucoin(Exchange, ImplicitAPI):
435
476
  'precisionMode': TICK_SIZE,
436
477
  'exceptions': {
437
478
  'exact': {
479
+ 'The order does not exist.': OrderNotFound,
438
480
  'order not exist': OrderNotFound,
439
481
  'order not exist.': OrderNotFound, # duplicated error temporarily
440
482
  'order_not_exist': OrderNotFound, # {"code":"order_not_exist","msg":"order_not_exist"} ¯\_(ツ)_/¯
@@ -442,6 +484,8 @@ class kucoin(Exchange, ImplicitAPI):
442
484
  'Order size below the minimum requirement.': InvalidOrder, # {"code":"400100","msg":"Order size below the minimum requirement."}
443
485
  'The withdrawal amount is below the minimum requirement.': ExchangeError, # {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."}
444
486
  'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, # {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"}
487
+ 'The amount increment is invalid.': BadRequest,
488
+ 'The quantity is below the minimum requirement.': InvalidOrder, # {"msg":"The quantity is below the minimum requirement.","code":"400100"}
445
489
  '400': BadRequest,
446
490
  '401': AuthenticationError,
447
491
  '403': NotSupported,
@@ -465,6 +509,56 @@ class kucoin(Exchange, ImplicitAPI):
465
509
  '130202': ExchangeError, # The system is renewing the loan automatically. Please try again later
466
510
  '130203': InsufficientFunds, # Insufficient account balance
467
511
  '130204': BadRequest, # As the total lending amount for platform leverage reaches the platform's maximum position limit, the system suspends the borrowing function of leverage
512
+ '130301': InsufficientFunds, # Insufficient account balance
513
+ '130302': PermissionDenied, # Your relevant permission rights have been restricted, you can contact customer service for processing
514
+ '130303': NotSupported, # The current trading pair does not support isolated positions
515
+ '130304': NotSupported, # The trading function of the current trading pair is not enabled
516
+ '130305': NotSupported, # The current trading pair does not support cross position
517
+ '130306': NotSupported, # The account has not opened leveraged trading
518
+ '130307': NotSupported, # Please reopen the leverage agreement
519
+ '130308': InvalidOrder, # Position renewal freeze
520
+ '130309': InvalidOrder, # Position forced liquidation freeze
521
+ '130310': ExchangeError, # Abnormal leverage account status
522
+ '130311': InvalidOrder, # Failed to place an order, triggering buy limit
523
+ '130312': InvalidOrder, # Trigger global position limit, suspend buying
524
+ '130313': InvalidOrder, # Trigger global position limit, suspend selling
525
+ '130314': InvalidOrder, # Trigger the global position limit and prompt the remaining quantity available for purchase
526
+ '130315': NotSupported, # This feature has been suspended due to country restrictions
527
+ '126000': ExchangeError, # Abnormal margin trading
528
+ '126001': NotSupported, # Users currently do not support high frequency
529
+ '126002': ExchangeError, # There is a risk problem in your account and transactions are temporarily not allowed!
530
+ '126003': InvalidOrder, # The commission amount is less than the minimum transaction amount for a single commission
531
+ '126004': ExchangeError, # Trading pair does not exist or is prohibited
532
+ '126005': PermissionDenied, # This trading pair requires advanced KYC certification before trading
533
+ '126006': ExchangeError, # Trading pair is not available
534
+ '126007': ExchangeError, # Trading pair suspended
535
+ '126009': ExchangeError, # Trading pair is suspended from creating orders
536
+ '126010': ExchangeError, # Trading pair suspended order cancellation
537
+ '126011': ExchangeError, # There are too many orders in the order
538
+ '126013': InsufficientFunds, # Insufficient account balance
539
+ '126015': ExchangeError, # It is prohibited to place orders on self trading pair
540
+ '126021': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
541
+ '126022': InvalidOrder, # The final transaction price of your order will trigger the price protection strategy. To protect the price from deviating too much, please place an order again.
542
+ '126027': InvalidOrder, # Only limit orders are supported
543
+ '126028': InvalidOrder, # Only limit orders are supported before the specified time
544
+ '126029': InvalidOrder, # The maximum order price is: xxx
545
+ '126030': InvalidOrder, # The minimum order price is: xxx
546
+ '126033': InvalidOrder, # Duplicate order
547
+ '126034': InvalidOrder, # Failed to create take profit and stop loss order
548
+ '126036': InvalidOrder, # Failed to create margin order
549
+ '126037': ExchangeError, # Due to country and region restrictions, self function has been suspended!
550
+ '126038': ExchangeError, # Third-party service call failed(internal exception)
551
+ '126039': ExchangeError, # Third-party service call failed, reason: xxx
552
+ '126041': ExchangeError, # clientTimestamp parameter error
553
+ '126042': ExchangeError, # Exceeded maximum position limit
554
+ '126043': OrderNotFound, # Order does not exist
555
+ '126044': InvalidOrder, # clientOid duplicate
556
+ '126045': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
557
+ '126046': NotSupported, # This digital asset does not support your IP region, thank you for your understanding!
558
+ '126047': PermissionDenied, # Please complete identity verification
559
+ '126048': PermissionDenied, # Please complete authentication for the master account
560
+ '135005': ExchangeError, # Margin order query business abnormality
561
+ '135018': ExchangeError, # Margin order query service abnormality
468
562
  '200004': InsufficientFunds,
469
563
  '210014': InvalidOrder, # {"code":"210014","msg":"Exceeds the max. borrowing amount, the remaining amount you can borrow: 0USDT"}
470
564
  '210021': InsufficientFunds, # {"code":"210021","msg":"Balance not enough"}
@@ -481,20 +575,25 @@ class kucoin(Exchange, ImplicitAPI):
481
575
  '400006': AuthenticationError,
482
576
  '400007': AuthenticationError,
483
577
  '400008': NotSupported,
484
- '400100': InsufficientFunds, # {"msg":"account.available.amount","code":"400100"}
578
+ '400100': InsufficientFunds, # {"msg":"account.available.amount","code":"400100"} or {"msg":"Withdrawal amount is below the minimum requirement.","code":"400100"}
485
579
  '400200': InvalidOrder, # {"code":"400200","msg":"Forbidden to place an order"}
580
+ '400330': InvalidOrder, # {"msg":"Order price can't deviate from NAV by 50%","code":"400330"}
486
581
  '400350': InvalidOrder, # {"code":"400350","msg":"Upper limit for holding: 10,000USDT, you can still buy 10,000USDT worth of coin."}
487
582
  '400370': InvalidOrder, # {"code":"400370","msg":"Max. price: 0.02500000000000000000"}
488
583
  '400400': BadRequest, # Parameter error
584
+ '400401': AuthenticationError, # User is not logged in
489
585
  '400500': InvalidOrder, # {"code":"400500","msg":"Your located country/region is currently not supported for the trading of self token"}
490
586
  '400600': BadSymbol, # {"code":"400600","msg":"validation.createOrder.symbolNotAvailable"}
491
587
  '400760': InvalidOrder, # {"code":"400760","msg":"order price should be more than XX"}
492
588
  '401000': BadRequest, # {"code":"401000","msg":"The interface has been deprecated"}
589
+ '408000': BadRequest, # Network timeout, please try again later
493
590
  '411100': AccountSuspended,
494
591
  '415000': BadRequest, # {"code":"415000","msg":"Unsupported Media Type"}
495
592
  '400303': PermissionDenied, # {"msg":"To enjoy the full range of our products and services, we kindly request you complete the identity verification process.","code":"400303"}
496
593
  '500000': ExchangeNotAvailable, # {"code":"500000","msg":"Internal Server Error"}
497
594
  '260220': InvalidAddress, # {"code": "260220", "msg": "deposit.address.not.exists"}
595
+ '600100': InsufficientFunds, # {"msg":"Funds below the minimum requirement.","code":"600100"}
596
+ '600101': InvalidOrder, # {"msg":"The order funds should more then 0.1 USDT.","code":"600101"}
498
597
  '900014': BadRequest, # {"code":"900014","msg":"Invalid chainId"}
499
598
  },
500
599
  'broad': {
@@ -552,11 +651,17 @@ class kucoin(Exchange, ImplicitAPI):
552
651
  'BIFI': 'BIFIF',
553
652
  'VAI': 'VAIOT',
554
653
  'WAX': 'WAXP',
654
+ 'ALT': 'APTOSLAUNCHTOKEN',
655
+ 'KALT': 'ALT', # ALTLAYER
656
+ 'FUD': 'FTX Users\' Debt',
555
657
  },
556
658
  'options': {
659
+ 'hf': None, # would be auto set to `true/false` after first load
557
660
  'version': 'v1',
558
661
  'symbolSeparator': '-',
559
662
  'fetchMyTradesMethod': 'private_get_fills',
663
+ 'timeDifference': 0, # the difference between system clock and Binance clock
664
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
560
665
  'fetchCurrencies': {
561
666
  'webApiEnable': True, # fetches from WEB
562
667
  'webApiRetries': 1,
@@ -576,6 +681,8 @@ class kucoin(Exchange, ImplicitAPI):
576
681
  'currencies': 'v3',
577
682
  'currencies/{currency}': 'v3',
578
683
  'symbols': 'v2',
684
+ 'mark-price/all-symbols': 'v3',
685
+ 'announcements': 'v3',
579
686
  },
580
687
  },
581
688
  'private': {
@@ -600,6 +707,7 @@ class kucoin(Exchange, ImplicitAPI):
600
707
  'oco/orders': 'v3',
601
708
  # margin trading
602
709
  'hf/margin/orders/active': 'v3',
710
+ 'hf/margin/order/active/symbols': 'v3',
603
711
  'hf/margin/orders/done': 'v3',
604
712
  'hf/margin/orders/{orderId}': 'v3',
605
713
  'hf/margin/orders/client-order/{clientOid}': 'v3',
@@ -613,6 +721,10 @@ class kucoin(Exchange, ImplicitAPI):
613
721
  'project/marketInterestRate': 'v3',
614
722
  'redeem/orders': 'v3',
615
723
  'purchase/orders': 'v3',
724
+ 'migrate/user/account/status': 'v3',
725
+ 'margin/symbols': 'v3',
726
+ 'affiliate/inviter/statistics': 'v2',
727
+ 'asset/ndbroker/deposit/list': 'v1',
616
728
  },
617
729
  'POST': {
618
730
  # account
@@ -622,6 +734,7 @@ class kucoin(Exchange, ImplicitAPI):
622
734
  'accounts/sub-transfer': 'v2',
623
735
  'accounts/inner-transfer': 'v2',
624
736
  'transfer-out': 'v3',
737
+ 'deposit-address/create': 'v3',
625
738
  # spot trading
626
739
  'oco/order': 'v3',
627
740
  # margin trading
@@ -632,6 +745,8 @@ class kucoin(Exchange, ImplicitAPI):
632
745
  'purchase': 'v3',
633
746
  'redeem': 'v3',
634
747
  'lend/purchase/update': 'v3',
748
+ 'position/update-user-leverage': 'v3',
749
+ 'withdrawals': 'v3',
635
750
  },
636
751
  'DELETE': {
637
752
  # account
@@ -679,7 +794,7 @@ class kucoin(Exchange, ImplicitAPI):
679
794
  'hf': 'trade_hf',
680
795
  },
681
796
  'networks': {
682
- 'BTC': 'btc',
797
+ 'BRC20': 'btc',
683
798
  'BTCNATIVESEGWIT': 'bech32',
684
799
  'ERC20': 'eth',
685
800
  'TRC20': 'trx',
@@ -697,7 +812,7 @@ class kucoin(Exchange, ImplicitAPI):
697
812
  'TLOS': 'tlos', # tlosevm is different
698
813
  'CFX': 'cfx',
699
814
  'ACA': 'aca',
700
- 'OPTIMISM': 'optimism',
815
+ 'OP': 'optimism',
701
816
  'ONT': 'ont',
702
817
  'GLMR': 'glmr',
703
818
  'CSPR': 'cspr',
@@ -816,6 +931,7 @@ class kucoin(Exchange, ImplicitAPI):
816
931
  'TRUE': 'true',
817
932
  'CS': 'cs',
818
933
  'ORAI': 'orai',
934
+ 'BASE': 'base',
819
935
  # below will be uncommented after consensus
820
936
  # 'BITCOINDIAMON': 'bcd',
821
937
  # 'BITCOINGOLD': 'btg',
@@ -891,15 +1007,85 @@ class kucoin(Exchange, ImplicitAPI):
891
1007
  'spot': 'TRADE',
892
1008
  },
893
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
+ },
1044
+ 'fetchOrder': {
1045
+ 'marginMode': False,
1046
+ 'trigger': True,
1047
+ 'trailing': False,
1048
+ },
1049
+ 'fetchOpenOrders': {
1050
+ 'marginMode': True,
1051
+ 'limit': 500,
1052
+ 'trigger': True,
1053
+ 'trailing': False,
1054
+ },
1055
+ 'fetchOrders': None,
1056
+ 'fetchClosedOrders': {
1057
+ 'marginMode': True,
1058
+ 'limit': 500,
1059
+ 'daysBack': None,
1060
+ 'daysBackCanceled': None,
1061
+ 'untilDays': 7,
1062
+ 'trigger': True,
1063
+ 'trailing': False,
1064
+ },
1065
+ 'fetchOHLCV': {
1066
+ 'limit': 1500,
1067
+ },
1068
+ },
1069
+ 'swap': {
1070
+ 'linear': None,
1071
+ 'inverse': None,
1072
+ },
1073
+ 'future': {
1074
+ 'linear': None,
1075
+ 'inverse': None,
1076
+ },
1077
+ },
894
1078
  })
895
1079
 
896
1080
  def nonce(self):
897
- return self.milliseconds()
1081
+ return self.milliseconds() - self.options['timeDifference']
898
1082
 
899
1083
  async def fetch_time(self, params={}):
900
1084
  """
901
1085
  fetches the current integer timestamp in milliseconds from the exchange server
902
- :see: https://docs.kucoin.com/#server-time
1086
+
1087
+ https://docs.kucoin.com/#server-time
1088
+
903
1089
  :param dict [params]: extra parameters specific to the exchange API endpoint
904
1090
  :returns int: the current integer timestamp in milliseconds from the exchange server
905
1091
  """
@@ -916,7 +1102,9 @@ class kucoin(Exchange, ImplicitAPI):
916
1102
  async def fetch_status(self, params={}):
917
1103
  """
918
1104
  the latest known information on the availability of the exchange API
919
- :see: https://docs.kucoin.com/#service-status
1105
+
1106
+ https://docs.kucoin.com/#service-status
1107
+
920
1108
  :param dict [params]: extra parameters specific to the exchange API endpoint
921
1109
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
922
1110
  """
@@ -940,15 +1128,20 @@ class kucoin(Exchange, ImplicitAPI):
940
1128
  'info': response,
941
1129
  }
942
1130
 
943
- async def fetch_markets(self, params={}):
1131
+ async def fetch_markets(self, params={}) -> List[Market]:
944
1132
  """
945
1133
  retrieves data on all markets for kucoin
946
- :see: https://docs.kucoin.com/#get-symbols-list-deprecated
947
- :see: https://docs.kucoin.com/#get-all-tickers
1134
+
1135
+ https://docs.kucoin.com/#get-symbols-list-deprecated
1136
+ https://docs.kucoin.com/#get-all-tickers
1137
+
948
1138
  :param dict [params]: extra parameters specific to the exchange API endpoint
949
1139
  :returns dict[]: an array of objects representing market data
950
1140
  """
951
- response = await self.publicGetSymbols(params)
1141
+ fetchTickersFees = None
1142
+ fetchTickersFees, params = self.handle_option_and_params(params, 'fetchMarkets', 'fetchTickersFees', True)
1143
+ promises = []
1144
+ promises.append(self.publicGetSymbols(params))
952
1145
  #
953
1146
  # {
954
1147
  # "code": "200000",
@@ -971,59 +1164,102 @@ class kucoin(Exchange, ImplicitAPI):
971
1164
  # "isMarginEnabled": True,
972
1165
  # "enableTrading": True
973
1166
  # },
974
- # ]
975
- # }
976
1167
  #
977
- data = self.safe_list(response, 'data')
978
- options = self.safe_dict(self.options, 'fetchMarkets', {})
979
- fetchTickersFees = self.safe_bool(options, 'fetchTickersFees', True)
980
- tickersResponse = {}
1168
+ credentialsSet = self.check_required_credentials(False)
1169
+ requestMarginables = credentialsSet and self.safe_bool(params, 'marginables', True)
1170
+ if requestMarginables:
1171
+ promises.append(self.privateGetMarginSymbols(params)) # cross margin symbols
1172
+ #
1173
+ # {
1174
+ # "code": "200000",
1175
+ # "data": {
1176
+ # "timestamp": 1719393213421,
1177
+ # "items": [
1178
+ # {
1179
+ # # same object market, with one additional field:
1180
+ # "minFunds": "0.1"
1181
+ # },
1182
+ #
1183
+ promises.append(self.privateGetIsolatedSymbols(params)) # isolated margin symbols
1184
+ #
1185
+ # {
1186
+ # "code": "200000",
1187
+ # "data": [
1188
+ # {
1189
+ # "symbol": "NKN-USDT",
1190
+ # "symbolName": "NKN-USDT",
1191
+ # "baseCurrency": "NKN",
1192
+ # "quoteCurrency": "USDT",
1193
+ # "maxLeverage": 5,
1194
+ # "flDebtRatio": "0.97",
1195
+ # "tradeEnable": True,
1196
+ # "autoRenewMaxDebtRatio": "0.96",
1197
+ # "baseBorrowEnable": True,
1198
+ # "quoteBorrowEnable": True,
1199
+ # "baseTransferInEnable": True,
1200
+ # "quoteTransferInEnable": True,
1201
+ # "baseBorrowCoefficient": "1",
1202
+ # "quoteBorrowCoefficient": "1"
1203
+ # },
1204
+ #
981
1205
  if fetchTickersFees:
982
- tickersResponse = await self.publicGetMarketAllTickers(params)
983
- #
984
- # {
985
- # "code": "200000",
986
- # "data": {
987
- # "time":1602832092060,
988
- # "ticker":[
989
- # {
990
- # "symbol": "BTC-USDT", # symbol
991
- # "symbolName":"BTC-USDT", # Name of trading pairs, it would change after renaming
992
- # "buy": "11328.9", # bestAsk
993
- # "sell": "11329", # bestBid
994
- # "changeRate": "-0.0055", # 24h change rate
995
- # "changePrice": "-63.6", # 24h change price
996
- # "high": "11610", # 24h highest price
997
- # "low": "11200", # 24h lowest price
998
- # "vol": "2282.70993217", # 24h volume,the aggregated trading volume in BTC
999
- # "volValue": "25984946.157790431", # 24h total, the trading volume in quote currency of last 24 hours
1000
- # "last": "11328.9", # last price
1001
- # "averagePrice": "11360.66065903", # 24h average transaction price yesterday
1002
- # "takerFeeRate": "0.001", # Basic Taker Fee
1003
- # "makerFeeRate": "0.001", # Basic Maker Fee
1004
- # "takerCoefficient": "1", # Taker Fee Coefficient
1005
- # "makerCoefficient": "1" # Maker Fee Coefficient
1006
- # }
1007
- # ]
1008
- # }
1009
- # }
1010
- #
1011
- tickersData = self.safe_dict(tickersResponse, 'data', {})
1012
- tickers = self.safe_list(tickersData, 'ticker', [])
1013
- tickersByMarketId = self.index_by(tickers, 'symbol')
1206
+ promises.append(self.publicGetMarketAllTickers(params))
1207
+ #
1208
+ # {
1209
+ # "code": "200000",
1210
+ # "data": {
1211
+ # "time":1602832092060,
1212
+ # "ticker":[
1213
+ # {
1214
+ # "symbol": "BTC-USDT", # symbol
1215
+ # "symbolName":"BTC-USDT", # Name of trading pairs, it would change after renaming
1216
+ # "buy": "11328.9", # bestAsk
1217
+ # "sell": "11329", # bestBid
1218
+ # "changeRate": "-0.0055", # 24h change rate
1219
+ # "changePrice": "-63.6", # 24h change price
1220
+ # "high": "11610", # 24h highest price
1221
+ # "low": "11200", # 24h lowest price
1222
+ # "vol": "2282.70993217", # 24h volume,the aggregated trading volume in BTC
1223
+ # "volValue": "25984946.157790431", # 24h total, the trading volume in quote currency of last 24 hours
1224
+ # "last": "11328.9", # last price
1225
+ # "averagePrice": "11360.66065903", # 24h average transaction price yesterday
1226
+ # "takerFeeRate": "0.001", # Basic Taker Fee
1227
+ # "makerFeeRate": "0.001", # Basic Maker Fee
1228
+ # "takerCoefficient": "1", # Taker Fee Coefficient
1229
+ # "makerCoefficient": "1" # Maker Fee Coefficient
1230
+ # }
1231
+ #
1232
+ if credentialsSet:
1233
+ # load migration status for account
1234
+ promises.append(self.load_migration_status())
1235
+ responses = await asyncio.gather(*promises)
1236
+ symbolsData = self.safe_list(responses[0], 'data')
1237
+ crossData = self.safe_dict(responses[1], 'data', {}) if requestMarginables else {}
1238
+ crossItems = self.safe_list(crossData, 'items', [])
1239
+ crossById = self.index_by(crossItems, 'symbol')
1240
+ isolatedData = responses[2] if requestMarginables else {}
1241
+ isolatedItems = self.safe_list(isolatedData, 'data', [])
1242
+ isolatedById = self.index_by(isolatedItems, 'symbol')
1243
+ tickersIdx = 3 if requestMarginables else 1
1244
+ tickersResponse = self.safe_dict(responses, tickersIdx, {})
1245
+ tickerItems = self.safe_list(self.safe_dict(tickersResponse, 'data', {}), 'ticker', [])
1246
+ tickersById = self.index_by(tickerItems, 'symbol')
1014
1247
  result = []
1015
- for i in range(0, len(data)):
1016
- market = data[i]
1248
+ for i in range(0, len(symbolsData)):
1249
+ market = symbolsData[i]
1017
1250
  id = self.safe_string(market, 'symbol')
1018
1251
  baseId, quoteId = id.split('-')
1019
1252
  base = self.safe_currency_code(baseId)
1020
1253
  quote = self.safe_currency_code(quoteId)
1021
1254
  # quoteIncrement = self.safe_number(market, 'quoteIncrement')
1022
- ticker = self.safe_dict(tickersByMarketId, id, {})
1255
+ ticker = self.safe_dict(tickersById, id, {})
1023
1256
  makerFeeRate = self.safe_string(ticker, 'makerFeeRate')
1024
1257
  takerFeeRate = self.safe_string(ticker, 'takerFeeRate')
1025
1258
  makerCoefficient = self.safe_string(ticker, 'makerCoefficient')
1026
1259
  takerCoefficient = self.safe_string(ticker, 'takerCoefficient')
1260
+ hasCrossMargin = (id in crossById)
1261
+ hasIsolatedMargin = (id in isolatedById)
1262
+ isMarginable = self.safe_bool(market, 'isMarginEnabled', False) or hasCrossMargin or hasIsolatedMargin
1027
1263
  result.append({
1028
1264
  'id': id,
1029
1265
  'symbol': base + '/' + quote,
@@ -1035,7 +1271,11 @@ class kucoin(Exchange, ImplicitAPI):
1035
1271
  'settleId': None,
1036
1272
  'type': 'spot',
1037
1273
  'spot': True,
1038
- 'margin': self.safe_bool(market, 'isMarginEnabled'),
1274
+ 'margin': isMarginable,
1275
+ 'marginModes': {
1276
+ 'cross': hasCrossMargin,
1277
+ 'isolated': hasIsolatedMargin,
1278
+ },
1039
1279
  'swap': False,
1040
1280
  'future': False,
1041
1281
  'option': False,
@@ -1075,12 +1315,40 @@ class kucoin(Exchange, ImplicitAPI):
1075
1315
  'created': None,
1076
1316
  'info': market,
1077
1317
  })
1318
+ if self.options['adjustForTimeDifference']:
1319
+ await self.load_time_difference()
1078
1320
  return result
1079
1321
 
1080
- async def fetch_currencies(self, params={}):
1322
+ async def load_migration_status(self, force: bool = False):
1323
+ """
1324
+ :param boolean force: load account state for non hf
1325
+ loads the migration status for the account(hf or not)
1326
+
1327
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/get-user-type
1328
+
1329
+ """
1330
+ if not ('hf' in self.options) or (self.options['hf'] is None) or force:
1331
+ result: dict = await self.privateGetHfAccountsOpened()
1332
+ self.options['hf'] = self.safe_bool(result, 'data')
1333
+
1334
+ def handle_hf_and_params(self, params={}):
1335
+ migrated: Bool = self.safe_bool(self.options, 'hf', False)
1336
+ loadedHf: Bool = None
1337
+ if migrated is not None:
1338
+ if migrated:
1339
+ loadedHf = True
1340
+ else:
1341
+ loadedHf = False
1342
+ hf: Bool = self.safe_bool(params, 'hf', loadedHf)
1343
+ params = self.omit(params, 'hf')
1344
+ return [hf, params]
1345
+
1346
+ async def fetch_currencies(self, params={}) -> Currencies:
1081
1347
  """
1082
1348
  fetches all available currencies on an exchange
1083
- :see: https://docs.kucoin.com/#get-currencies
1349
+
1350
+ https://docs.kucoin.com/#get-currencies
1351
+
1084
1352
  :param dict params: extra parameters specific to the exchange API endpoint
1085
1353
  :returns dict: an associative dictionary of currencies
1086
1354
  """
@@ -1102,8 +1370,10 @@ class kucoin(Exchange, ImplicitAPI):
1102
1370
  # "chains":[
1103
1371
  # {
1104
1372
  # "chainName":"ERC20",
1105
- # "chain":"eth",
1373
+ # "chainId": "eth"
1106
1374
  # "withdrawalMinSize":"2999",
1375
+ # "depositMinSize":null,
1376
+ # "withdrawFeeRate":"0",
1107
1377
  # "withdrawalMinFee":"2999",
1108
1378
  # "isWithdrawEnabled":false,
1109
1379
  # "isDepositEnabled":false,
@@ -1152,12 +1422,12 @@ class kucoin(Exchange, ImplicitAPI):
1152
1422
  # }
1153
1423
  #
1154
1424
  responses = await asyncio.gather(*promises)
1155
- currenciesResponse = self.safe_value(responses, 0, {})
1156
- currenciesData = self.safe_value(currenciesResponse, 'data', [])
1157
- additionalResponse = self.safe_value(responses, 1, {})
1158
- additionalData = self.safe_value(additionalResponse, 'data', [])
1425
+ currenciesResponse = self.safe_dict(responses, 0, {})
1426
+ currenciesData = self.safe_list(currenciesResponse, 'data', [])
1427
+ additionalResponse = self.safe_dict(responses, 1, {})
1428
+ additionalData = self.safe_list(additionalResponse, 'data', [])
1159
1429
  additionalDataGrouped = self.group_by(additionalData, 'currency')
1160
- result = {}
1430
+ result: dict = {}
1161
1431
  for i in range(0, len(currenciesData)):
1162
1432
  entry = currenciesData[i]
1163
1433
  id = self.safe_string(entry, 'currency')
@@ -1165,9 +1435,9 @@ class kucoin(Exchange, ImplicitAPI):
1165
1435
  code = self.safe_currency_code(id)
1166
1436
  isWithdrawEnabled = None
1167
1437
  isDepositEnabled = None
1168
- networks = {}
1438
+ networks: dict = {}
1169
1439
  chains = self.safe_list(entry, 'chains', [])
1170
- extraChainsData = self.index_by(self.safe_value(additionalDataGrouped, id, []), 'chain')
1440
+ extraChainsData = self.index_by(self.safe_list(additionalDataGrouped, id, []), 'chain')
1171
1441
  rawPrecision = self.safe_string(entry, 'precision')
1172
1442
  precision = self.parse_number(self.parse_precision(rawPrecision))
1173
1443
  chainsLength = len(chains)
@@ -1178,7 +1448,7 @@ class kucoin(Exchange, ImplicitAPI):
1178
1448
  for j in range(0, chainsLength):
1179
1449
  chain = chains[j]
1180
1450
  chainId = self.safe_string(chain, 'chainId')
1181
- networkCode = self.network_id_to_code(chainId)
1451
+ networkCode = self.network_id_to_code(chainId, code)
1182
1452
  chainWithdrawEnabled = self.safe_bool(chain, 'isWithdrawEnabled', False)
1183
1453
  if isWithdrawEnabled is None:
1184
1454
  isWithdrawEnabled = chainWithdrawEnabled
@@ -1206,7 +1476,7 @@ class kucoin(Exchange, ImplicitAPI):
1206
1476
  'max': None,
1207
1477
  },
1208
1478
  'deposit': {
1209
- 'min': self.safe_number(chainExtraData, 'depositMinSize'),
1479
+ 'min': self.safe_number(chain, 'depositMinSize'),
1210
1480
  'max': None,
1211
1481
  },
1212
1482
  },
@@ -1232,7 +1502,9 @@ class kucoin(Exchange, ImplicitAPI):
1232
1502
  async def fetch_accounts(self, params={}) -> List[Account]:
1233
1503
  """
1234
1504
  fetch all the accounts associated with a profile
1235
- :see: https://docs.kucoin.com/#list-accounts
1505
+
1506
+ https://docs.kucoin.com/#list-accounts
1507
+
1236
1508
  :param dict [params]: extra parameters specific to the exchange API endpoint
1237
1509
  :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
1238
1510
  """
@@ -1280,14 +1552,16 @@ class kucoin(Exchange, ImplicitAPI):
1280
1552
  async def fetch_transaction_fee(self, code: str, params={}):
1281
1553
  """
1282
1554
  *DEPRECATED* please use fetchDepositWithdrawFee instead
1283
- :see: https://docs.kucoin.com/#get-withdrawal-quotas
1555
+
1556
+ https://docs.kucoin.com/#get-withdrawal-quotas
1557
+
1284
1558
  :param str code: unified currency code
1285
1559
  :param dict params: extra parameters specific to the exchange API endpoint
1286
1560
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
1287
1561
  """
1288
1562
  await self.load_markets()
1289
1563
  currency = self.currency(code)
1290
- request = {
1564
+ request: dict = {
1291
1565
  'currency': currency['id'],
1292
1566
  }
1293
1567
  networkCode = None
@@ -1295,8 +1569,8 @@ class kucoin(Exchange, ImplicitAPI):
1295
1569
  if networkCode is not None:
1296
1570
  request['chain'] = self.network_code_to_id(networkCode).lower()
1297
1571
  response = await self.privateGetWithdrawalsQuotas(self.extend(request, params))
1298
- data = self.safe_value(response, 'data')
1299
- withdrawFees = {}
1572
+ data = self.safe_dict(response, 'data', {})
1573
+ withdrawFees: dict = {}
1300
1574
  withdrawFees[code] = self.safe_number(data, 'withdrawMinFee')
1301
1575
  return {
1302
1576
  'info': response,
@@ -1307,7 +1581,9 @@ class kucoin(Exchange, ImplicitAPI):
1307
1581
  async def fetch_deposit_withdraw_fee(self, code: str, params={}):
1308
1582
  """
1309
1583
  fetch the fee for deposits and withdrawals
1310
- :see: https://docs.kucoin.com/#get-withdrawal-quotas
1584
+
1585
+ https://docs.kucoin.com/#get-withdrawal-quotas
1586
+
1311
1587
  :param str code: unified currency code
1312
1588
  :param dict [params]: extra parameters specific to the exchange API endpoint
1313
1589
  :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
@@ -1315,7 +1591,7 @@ class kucoin(Exchange, ImplicitAPI):
1315
1591
  """
1316
1592
  await self.load_markets()
1317
1593
  currency = self.currency(code)
1318
- request = {
1594
+ request: dict = {
1319
1595
  'currency': currency['id'],
1320
1596
  }
1321
1597
  networkCode = None
@@ -1360,32 +1636,28 @@ class kucoin(Exchange, ImplicitAPI):
1360
1636
  # "chain": "ERC20"
1361
1637
  # }
1362
1638
  #
1363
- result = {
1639
+ minWithdrawFee = self.safe_number(fee, 'withdrawMinFee')
1640
+ result: dict = {
1364
1641
  'info': fee,
1365
1642
  'withdraw': {
1643
+ 'fee': minWithdrawFee,
1644
+ 'percentage': False,
1645
+ },
1646
+ 'deposit': {
1366
1647
  'fee': None,
1367
1648
  'percentage': None,
1368
1649
  },
1650
+ 'networks': {},
1651
+ }
1652
+ networkId = self.safe_string(fee, 'chain')
1653
+ networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
1654
+ result['networks'][networkCode] = {
1655
+ 'withdraw': minWithdrawFee,
1369
1656
  'deposit': {
1370
1657
  'fee': None,
1371
1658
  'percentage': None,
1372
1659
  },
1373
- 'networks': {},
1374
1660
  }
1375
- isWithdrawEnabled = self.safe_bool(fee, 'isWithdrawEnabled')
1376
- if isWithdrawEnabled:
1377
- result['withdraw']['fee'] = self.safe_number_2(fee, 'withdrawalMinFee', 'withdrawMinFee')
1378
- result['withdraw']['percentage'] = False
1379
- networkId = self.safe_string(fee, 'chain')
1380
- if networkId:
1381
- networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
1382
- result['networks'][networkCode] = {
1383
- 'withdraw': result['withdraw'],
1384
- 'deposit': {
1385
- 'fee': None,
1386
- 'percentage': None,
1387
- },
1388
- }
1389
1661
  return result
1390
1662
 
1391
1663
  def is_futures_method(self, methodName, params):
@@ -1405,7 +1677,7 @@ class kucoin(Exchange, ImplicitAPI):
1405
1677
  params = self.omit(params, 'type')
1406
1678
  return(type == 'contract') or (type == 'future') or (type == 'futures') # * (type == 'futures') deprecated, use(type == 'future')
1407
1679
 
1408
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1680
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1409
1681
  #
1410
1682
  # {
1411
1683
  # "symbol": "BTC-USDT", # symbol
@@ -1471,7 +1743,7 @@ class kucoin(Exchange, ImplicitAPI):
1471
1743
  symbol = market['symbol']
1472
1744
  baseVolume = self.safe_string(ticker, 'vol')
1473
1745
  quoteVolume = self.safe_string(ticker, 'volValue')
1474
- timestamp = self.safe_integer_2(ticker, 'time', 'datetime')
1746
+ timestamp = self.safe_integer_n(ticker, ['time', 'datetime', 'timePoint'])
1475
1747
  return self.safe_ticker({
1476
1748
  'symbol': symbol,
1477
1749
  'timestamp': timestamp,
@@ -1492,13 +1764,16 @@ class kucoin(Exchange, ImplicitAPI):
1492
1764
  'average': self.safe_string(ticker, 'averagePrice'),
1493
1765
  'baseVolume': baseVolume,
1494
1766
  'quoteVolume': quoteVolume,
1767
+ 'markPrice': self.safe_string(ticker, 'value'),
1495
1768
  'info': ticker,
1496
1769
  }, market)
1497
1770
 
1498
1771
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1499
1772
  """
1500
1773
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1501
- :see: https://docs.kucoin.com/#get-all-tickers
1774
+
1775
+ https://docs.kucoin.com/#get-all-tickers
1776
+
1502
1777
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1503
1778
  :param dict [params]: extra parameters specific to the exchange API endpoint
1504
1779
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1537,7 +1812,7 @@ class kucoin(Exchange, ImplicitAPI):
1537
1812
  data = self.safe_dict(response, 'data', {})
1538
1813
  tickers = self.safe_list(data, 'ticker', [])
1539
1814
  time = self.safe_integer(data, 'time')
1540
- result = {}
1815
+ result: dict = {}
1541
1816
  for i in range(0, len(tickers)):
1542
1817
  tickers[i]['time'] = time
1543
1818
  ticker = self.parse_ticker(tickers[i])
@@ -1546,17 +1821,35 @@ class kucoin(Exchange, ImplicitAPI):
1546
1821
  result[symbol] = ticker
1547
1822
  return self.filter_by_array_tickers(result, 'symbol', symbols)
1548
1823
 
1824
+ async def fetch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1825
+ """
1826
+ fetches the mark price for multiple markets
1827
+
1828
+ https://www.kucoin.com/docs/rest/margin-trading/margin-info/get-all-margin-trading-pairs-mark-prices
1829
+
1830
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1831
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1832
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1833
+ """
1834
+ await self.load_markets()
1835
+ symbols = self.market_symbols(symbols)
1836
+ response = await self.publicGetMarkPriceAllSymbols(params)
1837
+ data = self.safe_list(response, 'data', [])
1838
+ return self.parse_tickers(data)
1839
+
1549
1840
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1550
1841
  """
1551
1842
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1552
- :see: https://docs.kucoin.com/#get-24hr-stats
1843
+
1844
+ https://docs.kucoin.com/#get-24hr-stats
1845
+
1553
1846
  :param str symbol: unified symbol of the market to fetch the ticker for
1554
1847
  :param dict [params]: extra parameters specific to the exchange API endpoint
1555
1848
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1556
1849
  """
1557
1850
  await self.load_markets()
1558
1851
  market = self.market(symbol)
1559
- request = {
1852
+ request: dict = {
1560
1853
  'symbol': market['id'],
1561
1854
  }
1562
1855
  response = await self.publicGetMarketStats(self.extend(request, params))
@@ -1583,7 +1876,28 @@ class kucoin(Exchange, ImplicitAPI):
1583
1876
  # }
1584
1877
  # }
1585
1878
  #
1586
- return self.parse_ticker(response['data'], market)
1879
+ data = self.safe_dict(response, 'data', {})
1880
+ return self.parse_ticker(data, market)
1881
+
1882
+ async def fetch_mark_price(self, symbol: str, params={}) -> Ticker:
1883
+ """
1884
+ fetches the mark price for a specific market
1885
+
1886
+ https://www.kucoin.com/docs/rest/margin-trading/margin-info/get-mark-price
1887
+
1888
+ :param str symbol: unified symbol of the market to fetch the ticker for
1889
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1890
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1891
+ """
1892
+ await self.load_markets()
1893
+ market = self.market(symbol)
1894
+ request: dict = {
1895
+ 'symbol': market['id'],
1896
+ }
1897
+ response = await self.publicGetMarkPriceSymbolCurrent(self.extend(request, params))
1898
+ #
1899
+ data = self.safe_dict(response, 'data', {})
1900
+ return self.parse_ticker(data, market)
1587
1901
 
1588
1902
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1589
1903
  #
@@ -1609,7 +1923,9 @@ class kucoin(Exchange, ImplicitAPI):
1609
1923
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1610
1924
  """
1611
1925
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1612
- :see: https://docs.kucoin.com/#get-klines
1926
+
1927
+ https://docs.kucoin.com/#get-klines
1928
+
1613
1929
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1614
1930
  :param str timeframe: the length of time each candle represents
1615
1931
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -1625,7 +1941,7 @@ class kucoin(Exchange, ImplicitAPI):
1625
1941
  return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1500)
1626
1942
  market = self.market(symbol)
1627
1943
  marketId = market['id']
1628
- request = {
1944
+ request: dict = {
1629
1945
  'symbol': marketId,
1630
1946
  'type': self.safe_string(self.timeframes, timeframe, timeframe),
1631
1947
  }
@@ -1660,7 +1976,9 @@ class kucoin(Exchange, ImplicitAPI):
1660
1976
 
1661
1977
  async def create_deposit_address(self, code: str, params={}):
1662
1978
  """
1663
- :see: https://docs.kucoin.com/#create-deposit-address
1979
+
1980
+ https://www.kucoin.com/docs/rest/funding/deposit/create-deposit-address-v3-
1981
+
1664
1982
  create a currency deposit address
1665
1983
  :param str code: unified currency code of the currency for the deposit address
1666
1984
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1669,24 +1987,38 @@ class kucoin(Exchange, ImplicitAPI):
1669
1987
  """
1670
1988
  await self.load_markets()
1671
1989
  currency = self.currency(code)
1672
- request = {
1990
+ request: dict = {
1673
1991
  'currency': currency['id'],
1674
1992
  }
1675
1993
  networkCode = None
1676
1994
  networkCode, params = self.handle_network_code_and_params(params)
1677
1995
  if networkCode is not None:
1678
- request['chain'] = self.network_code_to_id(networkCode).lower()
1679
- response = await self.privatePostDepositAddresses(self.extend(request, params))
1996
+ request['chain'] = self.network_code_to_id(networkCode) # docs mention "chain-name", but seems "chain-id" is used, like in "fetchDepositAddress"
1997
+ response = await self.privatePostDepositAddressCreate(self.extend(request, params))
1680
1998
  # {"code":"260000","msg":"Deposit address already exists."}
1681
- # BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
1682
- # BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
1999
+ #
2000
+ # {
2001
+ # "code": "200000",
2002
+ # "data": {
2003
+ # "address": "0x2336d1834faab10b2dac44e468f2627138417431",
2004
+ # "memo": null,
2005
+ # "chainId": "bsc",
2006
+ # "to": "MAIN",
2007
+ # "expirationDate": 0,
2008
+ # "currency": "BNB",
2009
+ # "chainName": "BEP20"
2010
+ # }
2011
+ # }
2012
+ #
1683
2013
  data = self.safe_dict(response, 'data', {})
1684
2014
  return self.parse_deposit_address(data, currency)
1685
2015
 
1686
- async def fetch_deposit_address(self, code: str, params={}):
2016
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1687
2017
  """
1688
2018
  fetch the deposit address for a currency associated with self account
1689
- :see: https://docs.kucoin.com/#get-deposit-addresses-v2
2019
+
2020
+ https://docs.kucoin.com/#get-deposit-addresses-v2
2021
+
1690
2022
  :param str code: unified currency code
1691
2023
  :param dict [params]: extra parameters specific to the exchange API endpoint
1692
2024
  :param str [params.network]: the blockchain network name
@@ -1694,7 +2026,7 @@ class kucoin(Exchange, ImplicitAPI):
1694
2026
  """
1695
2027
  await self.load_markets()
1696
2028
  currency = self.currency(code)
1697
- request = {
2029
+ request: dict = {
1698
2030
  'currency': currency['id'],
1699
2031
  # for USDT - OMNI, ERC20, TRC20, default is ERC20
1700
2032
  # for BTC - Native, Segwit, TRC20, the parameters are bech32, btc, trx, default is Native
@@ -1715,28 +2047,30 @@ class kucoin(Exchange, ImplicitAPI):
1715
2047
  raise ExchangeError(self.id + ' fetchDepositAddress() returned an empty response, you might try to run createDepositAddress() first and try again')
1716
2048
  return self.parse_deposit_address(data, currency)
1717
2049
 
1718
- def parse_deposit_address(self, depositAddress, currency: Currency = None):
2050
+ def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
1719
2051
  address = self.safe_string(depositAddress, 'address')
1720
2052
  # BCH/BSV is returned with a "bitcoincash:" prefix, which we cut off here and only keep the address
1721
2053
  if address is not None:
1722
2054
  address = address.replace('bitcoincash:', '')
1723
2055
  code = None
1724
2056
  if currency is not None:
1725
- code = currency['id']
2057
+ code = self.safe_currency_code(currency['id'])
1726
2058
  if code != 'NIM':
1727
2059
  # contains spaces
1728
2060
  self.check_address(address)
1729
2061
  return {
1730
2062
  'info': depositAddress,
1731
2063
  'currency': code,
2064
+ 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chainId')),
1732
2065
  'address': address,
1733
2066
  'tag': self.safe_string(depositAddress, 'memo'),
1734
- 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chain')),
1735
2067
  }
1736
2068
 
1737
- async def fetch_deposit_addresses_by_network(self, code: str, params={}):
2069
+ async def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
1738
2070
  """
1739
- :see: https://docs.kucoin.com/#get-deposit-addresses-v2
2071
+
2072
+ https://docs.kucoin.com/#get-deposit-addresses-v2
2073
+
1740
2074
  fetch the deposit address for a currency associated with self account
1741
2075
  :param str code: unified currency code
1742
2076
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1744,7 +2078,7 @@ class kucoin(Exchange, ImplicitAPI):
1744
2078
  """
1745
2079
  await self.load_markets()
1746
2080
  currency = self.currency(code)
1747
- request = {
2081
+ request: dict = {
1748
2082
  'currency': currency['id'],
1749
2083
  }
1750
2084
  version = self.options['versions']['private']['GET']['deposit-addresses']
@@ -1768,15 +2102,17 @@ class kucoin(Exchange, ImplicitAPI):
1768
2102
  self.options['versions']['private']['GET']['deposit-addresses'] = version
1769
2103
  chains = self.safe_list(response, 'data', [])
1770
2104
  parsed = self.parse_deposit_addresses(chains, [currency['code']], False, {
1771
- 'currency': currency['id'],
2105
+ 'currency': currency['code'],
1772
2106
  })
1773
2107
  return self.index_by(parsed, 'network')
1774
2108
 
1775
2109
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1776
2110
  """
1777
2111
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1778
- :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-part-order-book-aggregated-
1779
- :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-full-order-book-aggregated-
2112
+
2113
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-part-order-book-aggregated-
2114
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-full-order-book-aggregated-
2115
+
1780
2116
  :param str symbol: unified symbol of the market to fetch the order book for
1781
2117
  :param int [limit]: the maximum amount of order book entries to return
1782
2118
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1785,7 +2121,7 @@ class kucoin(Exchange, ImplicitAPI):
1785
2121
  await self.load_markets()
1786
2122
  market = self.market(symbol)
1787
2123
  level = self.safe_integer(params, 'level', 2)
1788
- request = {'symbol': market['id']}
2124
+ request: dict = {'symbol': market['id']}
1789
2125
  isAuthenticated = self.check_required_credentials(False)
1790
2126
  response = None
1791
2127
  if not isAuthenticated or limit is not None:
@@ -1850,49 +2186,56 @@ class kucoin(Exchange, ImplicitAPI):
1850
2186
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1851
2187
  """
1852
2188
  Create an order on the exchange
1853
- :see: https://docs.kucoin.com/spot#place-a-new-order
1854
- :see: https://docs.kucoin.com/spot#place-a-new-order-2
1855
- :see: https://docs.kucoin.com/spot#place-a-margin-order
1856
- :see: https://docs.kucoin.com/spot-hf/#place-hf-order
1857
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order-test
1858
- :see: https://www.kucoin.com/docs/rest/margin-trading/orders/place-margin-order-test
2189
+
2190
+ https://docs.kucoin.com/spot#place-a-new-order
2191
+ https://docs.kucoin.com/spot#place-a-new-order-2
2192
+ https://docs.kucoin.com/spot#place-a-margin-order
2193
+ https://docs.kucoin.com/spot-hf/#place-hf-order
2194
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order-test
2195
+ https://www.kucoin.com/docs/rest/margin-trading/orders/place-margin-order-test
2196
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-place-hf-order
2197
+
1859
2198
  :param str symbol: Unified CCXT market symbol
1860
2199
  :param str type: 'limit' or 'market'
1861
2200
  :param str side: 'buy' or 'sell'
1862
2201
  :param float amount: the amount of currency to trade
1863
- :param float [price]: *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
2202
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1864
2203
  :param dict [params]: extra parameters specific to the exchange API endpoint
1865
2204
  :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1866
2205
  :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
1867
2206
  :param str [params.timeInForce]: GTC, GTT, IOC, or FOK, default is GTC, limit orders only
1868
2207
  :param str [params.postOnly]: Post only flag, invalid when timeInForce is IOC or FOK
1869
- *
1870
- * EXCHANGE SPECIFIC PARAMETERS
2208
+
2209
+ EXCHANGE SPECIFIC PARAMETERS
1871
2210
  :param str [params.clientOid]: client order id, defaults to uuid if not passed
1872
2211
  :param str [params.remark]: remark for the order, length cannot exceed 100 utf8 characters
1873
2212
  :param str [params.tradeType]: 'TRADE', # TRADE, MARGIN_TRADE # not used with margin orders
1874
- * limit orders ---------------------------------------------------
2213
+ limit orders ---------------------------------------------------
1875
2214
  :param float [params.cancelAfter]: long, # cancel after n seconds, requires timeInForce to be GTT
1876
2215
  :param bool [params.hidden]: False, # Order will not be displayed in the order book
1877
2216
  :param bool [params.iceberg]: False, # Only a portion of the order is displayed in the order book
1878
2217
  :param str [params.visibleSize]: self.amount_to_precision(symbol, visibleSize), # The maximum visible size of an iceberg order
1879
- * market orders --------------------------------------------------
2218
+ market orders --------------------------------------------------
1880
2219
  :param str [params.funds]: # Amount of quote currency to use
1881
- * stop orders ----------------------------------------------------
1882
- :param str [params.stop]: Either loss or entry, the default is loss. Requires stopPrice to be defined
1883
- * margin orders --------------------------------------------------
2220
+ stop orders ----------------------------------------------------
2221
+ :param str [params.stop]: Either loss or entry, the default is loss. Requires triggerPrice to be defined
2222
+ margin orders --------------------------------------------------
1884
2223
  :param float [params.leverage]: Leverage size of the order
1885
2224
  :param str [params.stp]: '', # self trade prevention, CN, CO, CB or DC
1886
2225
  :param bool [params.autoBorrow]: False, # The system will first borrow you funds at the optimal interest rate and then place an order for you
1887
2226
  :param bool [params.hf]: False, # True for hf order
1888
2227
  :param bool [params.test]: set to True to test an order, no order will be created but the request will be validated
2228
+ :param bool [params.sync]: set to True to use the hf sync call
1889
2229
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1890
2230
  """
1891
2231
  await self.load_markets()
1892
2232
  market = self.market(symbol)
1893
2233
  testOrder = self.safe_bool(params, 'test', False)
1894
2234
  params = self.omit(params, 'test')
1895
- isHf = self.safe_bool(params, 'hf', False)
2235
+ hf = None
2236
+ hf, params = self.handle_hf_and_params(params)
2237
+ useSync = False
2238
+ useSync, params = self.handle_option_and_params(params, 'createOrder', 'sync', False)
1896
2239
  triggerPrice, stopLossPrice, takeProfitPrice = self.handle_trigger_prices(params)
1897
2240
  tradeType = self.safe_string(params, 'tradeType') # keep it for backward compatibility
1898
2241
  isTriggerOrder = (triggerPrice or stopLossPrice or takeProfitPrice)
@@ -1905,14 +2248,18 @@ class kucoin(Exchange, ImplicitAPI):
1905
2248
  if testOrder:
1906
2249
  if isMarginOrder:
1907
2250
  response = await self.privatePostMarginOrderTest(orderRequest)
2251
+ elif hf:
2252
+ response = await self.privatePostHfOrdersTest(orderRequest)
1908
2253
  else:
1909
2254
  response = await self.privatePostOrdersTest(orderRequest)
1910
- elif isHf:
1911
- response = await self.privatePostHfOrders(orderRequest)
1912
2255
  elif isTriggerOrder:
1913
2256
  response = await self.privatePostStopOrder(orderRequest)
1914
2257
  elif isMarginOrder:
1915
2258
  response = await self.privatePostMarginOrder(orderRequest)
2259
+ elif useSync:
2260
+ response = await self.privatePostHfOrdersSync(orderRequest)
2261
+ elif hf:
2262
+ response = await self.privatePostHfOrders(orderRequest)
1916
2263
  else:
1917
2264
  response = await self.privatePostOrders(orderRequest)
1918
2265
  #
@@ -1929,7 +2276,9 @@ class kucoin(Exchange, ImplicitAPI):
1929
2276
  async def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
1930
2277
  """
1931
2278
  create a market order by providing the symbol, side and cost
1932
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2279
+
2280
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2281
+
1933
2282
  :param str symbol: unified symbol of the market to create an order in
1934
2283
  :param str side: 'buy' or 'sell'
1935
2284
  :param float cost: how much you want to trade in units of the quote currency
@@ -1937,13 +2286,17 @@ class kucoin(Exchange, ImplicitAPI):
1937
2286
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1938
2287
  """
1939
2288
  await self.load_markets()
1940
- params['cost'] = cost
1941
- return await self.create_order(symbol, 'market', side, cost, None, params)
2289
+ req = {
2290
+ 'cost': cost,
2291
+ }
2292
+ return await self.create_order(symbol, 'market', side, 0, None, self.extend(req, params))
1942
2293
 
1943
2294
  async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
1944
2295
  """
1945
2296
  create a market buy order by providing the symbol and cost
1946
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2297
+
2298
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2299
+
1947
2300
  :param str symbol: unified symbol of the market to create an order in
1948
2301
  :param float cost: how much you want to trade in units of the quote currency
1949
2302
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1955,7 +2308,9 @@ class kucoin(Exchange, ImplicitAPI):
1955
2308
  async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
1956
2309
  """
1957
2310
  create a market sell order by providing the symbol and cost
1958
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2311
+
2312
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
2313
+
1959
2314
  :param str symbol: unified symbol of the market to create an order in
1960
2315
  :param float cost: how much you want to trade in units of the quote currency
1961
2316
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1967,11 +2322,15 @@ class kucoin(Exchange, ImplicitAPI):
1967
2322
  async def create_orders(self, orders: List[OrderRequest], params={}):
1968
2323
  """
1969
2324
  create a list of trade orders
1970
- :see: https://www.kucoin.com/docs/rest/spot-trading/orders/place-multiple-orders
1971
- :see: https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-multiple-hf-orders
2325
+
2326
+ https://www.kucoin.com/docs/rest/spot-trading/orders/place-multiple-orders
2327
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-multiple-hf-orders
2328
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-place-multiple-hf-orders
2329
+
1972
2330
  :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
1973
2331
  :param dict [params]: extra parameters specific to the exchange API endpoint
1974
2332
  :param bool [params.hf]: False, # True for hf orders
2333
+ :param bool [params.sync]: False, # True to use the hf sync call
1975
2334
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1976
2335
  """
1977
2336
  await self.load_markets()
@@ -1995,14 +2354,18 @@ class kucoin(Exchange, ImplicitAPI):
1995
2354
  orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
1996
2355
  ordersRequests.append(orderRequest)
1997
2356
  market = self.market(symbol)
1998
- request = {
2357
+ request: dict = {
1999
2358
  'symbol': market['id'],
2000
2359
  'orderList': ordersRequests,
2001
2360
  }
2002
- hf = self.safe_bool(params, 'hf', False)
2003
- params = self.omit(params, 'hf')
2361
+ hf = None
2362
+ hf, params = self.handle_hf_and_params(params)
2363
+ useSync = False
2364
+ useSync, params = self.handle_option_and_params(params, 'createOrders', 'sync', False)
2004
2365
  response = None
2005
- if hf:
2366
+ if useSync:
2367
+ response = await self.privatePostHfOrdersMultiSync(self.extend(request, params))
2368
+ elif hf:
2006
2369
  response = await self.privatePostHfOrdersMulti(self.extend(request, params))
2007
2370
  else:
2008
2371
  response = await self.privatePostOrdersMulti(self.extend(request, params))
@@ -2040,12 +2403,19 @@ class kucoin(Exchange, ImplicitAPI):
2040
2403
  data = self.safe_list(data, 'data', [])
2041
2404
  return self.parse_orders(data)
2042
2405
 
2406
+ def market_order_amount_to_precision(self, symbol: str, amount):
2407
+ market = self.market(symbol)
2408
+ result = self.decimal_to_precision(amount, TRUNCATE, market['info']['quoteIncrement'], self.precisionMode, self.paddingMode)
2409
+ if result == '0':
2410
+ raise InvalidOrder(self.id + ' amount of ' + market['symbol'] + ' must be greater than minimum amount precision of ' + self.number_to_string(market['precision']['amount']))
2411
+ return result
2412
+
2043
2413
  def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2044
2414
  market = self.market(symbol)
2045
2415
  # required param, cannot be used twice
2046
2416
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId', self.uuid())
2047
2417
  params = self.omit(params, ['clientOid', 'clientOrderId'])
2048
- request = {
2418
+ request: dict = {
2049
2419
  'clientOid': clientOrderId,
2050
2420
  'side': side,
2051
2421
  'symbol': market['id'],
@@ -2060,7 +2430,7 @@ class kucoin(Exchange, ImplicitAPI):
2060
2430
  if quoteAmount is not None:
2061
2431
  params = self.omit(params, ['cost', 'funds'])
2062
2432
  # kucoin uses base precision even for quote values
2063
- costString = self.amount_to_precision(symbol, quoteAmount)
2433
+ costString = self.market_order_amount_to_precision(symbol, quoteAmount)
2064
2434
  request['funds'] = costString
2065
2435
  else:
2066
2436
  amountString = self.amount_to_precision(symbol, amount)
@@ -2100,20 +2470,22 @@ class kucoin(Exchange, ImplicitAPI):
2100
2470
  async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
2101
2471
  """
2102
2472
  edit an order, kucoin currently only supports the modification of HF orders
2103
- :see: https://docs.kucoin.com/spot-hf/#modify-order
2473
+
2474
+ https://docs.kucoin.com/spot-hf/#modify-order
2475
+
2104
2476
  :param str id: order id
2105
2477
  :param str symbol: unified symbol of the market to create an order in
2106
2478
  :param str type: not used
2107
2479
  :param str side: not used
2108
2480
  :param float amount: how much of the currency you want to trade in units of the base currency
2109
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2481
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2110
2482
  :param dict [params]: extra parameters specific to the exchange API endpoint
2111
2483
  :param str [params.clientOrderId]: client order id, defaults to id if not passed
2112
2484
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2113
2485
  """
2114
2486
  await self.load_markets()
2115
2487
  market = self.market(symbol)
2116
- request = {
2488
+ request: dict = {
2117
2489
  'symbol': market['id'],
2118
2490
  }
2119
2491
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
@@ -2140,78 +2512,149 @@ class kucoin(Exchange, ImplicitAPI):
2140
2512
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
2141
2513
  """
2142
2514
  cancels an open order
2143
- :see: https://docs.kucoin.com/spot#cancel-an-order
2144
- :see: https://docs.kucoin.com/spot#cancel-an-order-2
2145
- :see: https://docs.kucoin.com/spot#cancel-single-order-by-clientoid
2146
- :see: https://docs.kucoin.com/spot#cancel-single-order-by-clientoid-2
2147
- :see: https://docs.kucoin.com/spot-hf/#cancel-orders-by-orderid
2148
- :see: https://docs.kucoin.com/spot-hf/#cancel-order-by-clientoid
2515
+
2516
+ https://docs.kucoin.com/spot#cancel-an-order
2517
+ https://docs.kucoin.com/spot#cancel-an-order-2
2518
+ https://docs.kucoin.com/spot#cancel-single-order-by-clientoid
2519
+ https://docs.kucoin.com/spot#cancel-single-order-by-clientoid-2
2520
+ https://docs.kucoin.com/spot-hf/#cancel-orders-by-orderid
2521
+ https://docs.kucoin.com/spot-hf/#cancel-order-by-clientoid
2522
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-cancel-hf-order-by-orderid
2523
+ https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/sync-cancel-hf-order-by-clientoid
2524
+
2149
2525
  :param str id: order id
2150
2526
  :param str symbol: unified symbol of the market the order was made in
2151
2527
  :param dict [params]: extra parameters specific to the exchange API endpoint
2152
- :param bool [params.stop]: True if cancelling a stop order
2528
+ :param bool [params.trigger]: True if cancelling a stop order
2153
2529
  :param bool [params.hf]: False, # True for hf order
2530
+ :param bool [params.sync]: False, # True to use the hf sync call
2154
2531
  :returns: Response from the exchange
2155
2532
  """
2156
2533
  await self.load_markets()
2157
- request = {}
2534
+ request: dict = {}
2158
2535
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
2159
- stop = self.safe_bool_2(params, 'stop', 'trigger', False)
2160
- hf = self.safe_bool(params, 'hf', False)
2161
- if hf:
2536
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2537
+ hf = None
2538
+ hf, params = self.handle_hf_and_params(params)
2539
+ useSync = False
2540
+ useSync, params = self.handle_option_and_params(params, 'cancelOrder', 'sync', False)
2541
+ if hf or useSync:
2162
2542
  if symbol is None:
2163
2543
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol parameter for hf orders')
2164
2544
  market = self.market(symbol)
2165
2545
  request['symbol'] = market['id']
2166
2546
  response = None
2167
- params = self.omit(params, ['clientOid', 'clientOrderId', 'stop', 'hf', 'trigger'])
2547
+ params = self.omit(params, ['clientOid', 'clientOrderId', 'stop', 'trigger'])
2168
2548
  if clientOrderId is not None:
2169
2549
  request['clientOid'] = clientOrderId
2170
- if stop:
2550
+ if trigger:
2171
2551
  response = await self.privateDeleteStopOrderCancelOrderByClientOid(self.extend(request, params))
2552
+ #
2553
+ # {
2554
+ # code: '200000',
2555
+ # data: {
2556
+ # cancelledOrderId: 'vs8lgpiuao41iaft003khbbk',
2557
+ # clientOid: '123456'
2558
+ # }
2559
+ # }
2560
+ #
2561
+ elif useSync:
2562
+ response = await self.privateDeleteHfOrdersSyncClientOrderClientOid(self.extend(request, params))
2172
2563
  elif hf:
2173
2564
  response = await self.privateDeleteHfOrdersClientOrderClientOid(self.extend(request, params))
2565
+ #
2566
+ # {
2567
+ # "code": "200000",
2568
+ # "data": {
2569
+ # "clientOid": "6d539dc614db3"
2570
+ # }
2571
+ # }
2572
+ #
2174
2573
  else:
2175
2574
  response = await self.privateDeleteOrderClientOrderClientOid(self.extend(request, params))
2575
+ #
2576
+ # {
2577
+ # code: '200000',
2578
+ # data: {
2579
+ # cancelledOrderId: '665e580f6660500007aba341',
2580
+ # clientOid: '1234567',
2581
+ # cancelledOcoOrderIds: null
2582
+ # }
2583
+ # }
2584
+ #
2585
+ response = self.safe_dict(response, 'data')
2586
+ return self.parse_order(response)
2176
2587
  else:
2177
2588
  request['orderId'] = id
2178
- if stop:
2589
+ if trigger:
2179
2590
  response = await self.privateDeleteStopOrderOrderId(self.extend(request, params))
2591
+ #
2592
+ # {
2593
+ # code: '200000',
2594
+ # data: {cancelledOrderIds: ['vs8lgpiuaco91qk8003vebu9']}
2595
+ # }
2596
+ #
2597
+ elif useSync:
2598
+ response = await self.privateDeleteHfOrdersSyncOrderId(self.extend(request, params))
2180
2599
  elif hf:
2181
2600
  response = await self.privateDeleteHfOrdersOrderId(self.extend(request, params))
2601
+ #
2602
+ # {
2603
+ # "code": "200000",
2604
+ # "data": {
2605
+ # "orderId": "630625dbd9180300014c8d52"
2606
+ # }
2607
+ # }
2608
+ #
2609
+ response = self.safe_dict(response, 'data')
2610
+ return self.parse_order(response)
2182
2611
  else:
2183
2612
  response = await self.privateDeleteOrdersOrderId(self.extend(request, params))
2184
- return response
2613
+ #
2614
+ # {
2615
+ # code: '200000',
2616
+ # data: {cancelledOrderIds: ['665e4fbe28051a0007245c41']}
2617
+ # }
2618
+ #
2619
+ data = self.safe_dict(response, 'data')
2620
+ orderIds = self.safe_list(data, 'cancelledOrderIds', [])
2621
+ orderId = self.safe_string(orderIds, 0)
2622
+ return self.safe_order({
2623
+ 'info': data,
2624
+ 'id': orderId,
2625
+ })
2185
2626
 
2186
2627
  async def cancel_all_orders(self, symbol: Str = None, params={}):
2187
2628
  """
2188
2629
  cancel all open orders
2189
- :see: https://docs.kucoin.com/spot#cancel-all-orders
2190
- :see: https://docs.kucoin.com/spot#cancel-orders
2191
- :see: https://docs.kucoin.com/spot-hf/#cancel-all-hf-orders-by-symbol
2630
+
2631
+ https://docs.kucoin.com/spot#cancel-all-orders
2632
+ https://docs.kucoin.com/spot#cancel-orders
2633
+ https://docs.kucoin.com/spot-hf/#cancel-all-hf-orders-by-symbol
2634
+
2192
2635
  :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
2193
2636
  :param dict [params]: extra parameters specific to the exchange API endpoint
2194
- :param bool [params.stop]: *invalid for isolated margin* True if cancelling all stop orders
2637
+ :param bool [params.trigger]: *invalid for isolated margin* True if cancelling all stop orders
2195
2638
  :param str [params.marginMode]: 'cross' or 'isolated'
2196
2639
  :param str [params.orderIds]: *stop orders only* Comma seperated order IDs
2197
- :param bool [params.stop]: True if cancelling a stop order
2198
2640
  :param bool [params.hf]: False, # True for hf order
2199
2641
  :returns: Response from the exchange
2200
2642
  """
2201
2643
  await self.load_markets()
2202
- request = {}
2203
- stop = self.safe_bool(params, 'stop', False)
2204
- hf = self.safe_bool(params, 'hf', False)
2205
- params = self.omit(params, ['stop', 'hf'])
2644
+ request: dict = {}
2645
+ trigger = self.safe_bool(params, 'stop', False)
2646
+ hf = None
2647
+ hf, params = self.handle_hf_and_params(params)
2648
+ params = self.omit(params, 'stop')
2206
2649
  marginMode, query = self.handle_margin_mode_and_params('cancelAllOrders', params)
2207
2650
  if symbol is not None:
2208
2651
  request['symbol'] = self.market_id(symbol)
2209
2652
  if marginMode is not None:
2210
2653
  request['tradeType'] = self.options['marginModes'][marginMode]
2211
- if marginMode == 'isolated' and stop:
2654
+ if marginMode == 'isolated' and trigger:
2212
2655
  raise BadRequest(self.id + ' cancelAllOrders does not support isolated margin for stop orders')
2213
2656
  response = None
2214
- if stop:
2657
+ if trigger:
2215
2658
  response = await self.privateDeleteStopOrderCancel(self.extend(request, query))
2216
2659
  elif hf:
2217
2660
  if symbol is None:
@@ -2225,38 +2668,42 @@ class kucoin(Exchange, ImplicitAPI):
2225
2668
  async def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2226
2669
  """
2227
2670
  fetch a list of orders
2228
- :see: https://docs.kucoin.com/spot#list-orders
2229
- :see: https://docs.kucoin.com/spot#list-stop-orders
2230
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2231
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2671
+
2672
+ https://docs.kucoin.com/spot#list-orders
2673
+ https://docs.kucoin.com/spot#list-stop-orders
2674
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2675
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2676
+
2232
2677
  :param str status: *not used for stop orders* 'open' or 'closed'
2233
2678
  :param str symbol: unified market symbol
2234
2679
  :param int [since]: timestamp in ms of the earliest order
2235
2680
  :param int [limit]: max number of orders to return
2236
2681
  :param dict [params]: exchange specific params
2237
2682
  :param int [params.until]: end time in ms
2238
- :param bool [params.stop]: True if fetching stop orders
2239
2683
  :param str [params.side]: buy or sell
2240
2684
  :param str [params.type]: limit, market, limit_stop or market_stop
2241
2685
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2242
- :param int [params.currentPage]: *stop orders only* current page
2243
- :param str [params.orderIds]: *stop orders only* comma seperated order ID list
2244
- :param bool [params.stop]: True if fetching a stop order
2686
+ :param int [params.currentPage]: *trigger orders only* current page
2687
+ :param str [params.orderIds]: *trigger orders only* comma seperated order ID list
2688
+ :param bool [params.trigger]: True if fetching a trigger order
2245
2689
  :param bool [params.hf]: False, # True for hf order
2246
2690
  :returns: An `array of order structures <https://docs.ccxt.com/#/?id=order-structure>`
2247
2691
  """
2248
2692
  await self.load_markets()
2249
2693
  lowercaseStatus = status.lower()
2250
- until = self.safe_integer_2(params, 'until', 'till')
2251
- stop = self.safe_bool(params, 'stop', False)
2252
- hf = self.safe_bool(params, 'hf', False)
2253
- params = self.omit(params, ['stop', 'hf', 'till', 'until'])
2694
+ until = self.safe_integer(params, 'until')
2695
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2696
+ hf = None
2697
+ hf, params = self.handle_hf_and_params(params)
2698
+ if hf and (symbol is None):
2699
+ raise ArgumentsRequired(self.id + ' fetchOrdersByStatus() requires a symbol parameter for hf orders')
2700
+ params = self.omit(params, ['stop', 'trigger', 'till', 'until'])
2254
2701
  marginMode, query = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
2255
2702
  if lowercaseStatus == 'open':
2256
2703
  lowercaseStatus = 'active'
2257
2704
  elif lowercaseStatus == 'closed':
2258
2705
  lowercaseStatus = 'done'
2259
- request = {
2706
+ request: dict = {
2260
2707
  'status': lowercaseStatus,
2261
2708
  }
2262
2709
  market = None
@@ -2271,7 +2718,7 @@ class kucoin(Exchange, ImplicitAPI):
2271
2718
  request['endAt'] = until
2272
2719
  request['tradeType'] = self.safe_string(self.options['marginModes'], marginMode, 'TRADE')
2273
2720
  response = None
2274
- if stop:
2721
+ if trigger:
2275
2722
  response = await self.privateGetStopOrder(self.extend(request, query))
2276
2723
  elif hf:
2277
2724
  if lowercaseStatus == 'active':
@@ -2323,26 +2770,31 @@ class kucoin(Exchange, ImplicitAPI):
2323
2770
  # ]
2324
2771
  # }
2325
2772
  # }
2773
+ listData = self.safe_list(response, 'data')
2774
+ if listData is not None:
2775
+ return self.parse_orders(listData, market, since, limit)
2326
2776
  responseData = self.safe_dict(response, 'data', {})
2327
- orders = self.safe_value(responseData, 'items', responseData)
2777
+ orders = self.safe_list(responseData, 'items', [])
2328
2778
  return self.parse_orders(orders, market, since, limit)
2329
2779
 
2330
2780
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2331
2781
  """
2332
2782
  fetches information on multiple closed orders made by the user
2333
- :see: https://docs.kucoin.com/spot#list-orders
2334
- :see: https://docs.kucoin.com/spot#list-stop-orders
2335
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2336
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2783
+
2784
+ https://docs.kucoin.com/spot#list-orders
2785
+ https://docs.kucoin.com/spot#list-stop-orders
2786
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2787
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2788
+
2337
2789
  :param str symbol: unified market symbol of the market orders were made in
2338
2790
  :param int [since]: the earliest time in ms to fetch orders for
2339
2791
  :param int [limit]: the maximum number of order structures to retrieve
2340
2792
  :param dict [params]: extra parameters specific to the exchange API endpoint
2341
- :param int [params.till]: end time in ms
2793
+ :param int [params.until]: end time in ms
2342
2794
  :param str [params.side]: buy or sell
2343
2795
  :param str [params.type]: limit, market, limit_stop or market_stop
2344
2796
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2345
- :param bool [params.stop]: True if fetching a stop order
2797
+ :param bool [params.trigger]: True if fetching a trigger order
2346
2798
  :param bool [params.hf]: False, # True for hf order
2347
2799
  :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)
2348
2800
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2357,22 +2809,23 @@ class kucoin(Exchange, ImplicitAPI):
2357
2809
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2358
2810
  """
2359
2811
  fetch all unfilled currently open orders
2360
- :see: https://docs.kucoin.com/spot#list-orders
2361
- :see: https://docs.kucoin.com/spot#list-stop-orders
2362
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2363
- :see: https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2812
+
2813
+ https://docs.kucoin.com/spot#list-orders
2814
+ https://docs.kucoin.com/spot#list-stop-orders
2815
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2816
+ https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2817
+
2364
2818
  :param str symbol: unified market symbol
2365
2819
  :param int [since]: the earliest time in ms to fetch open orders for
2366
2820
  :param int [limit]: the maximum number of open orders structures to retrieve
2367
2821
  :param dict [params]: extra parameters specific to the exchange API endpoint
2368
- :param int [params.till]: end time in ms
2369
- :param bool [params.stop]: True if fetching stop orders
2822
+ :param int [params.until]: end time in ms
2823
+ :param bool [params.trigger]: True if fetching trigger orders
2370
2824
  :param str [params.side]: buy or sell
2371
2825
  :param str [params.type]: limit, market, limit_stop or market_stop
2372
2826
  :param str [params.tradeType]: TRADE for spot trading, MARGIN_TRADE for Margin Trading
2373
- :param int [params.currentPage]: *stop orders only* current page
2374
- :param str [params.orderIds]: *stop orders only* comma seperated order ID list
2375
- :param bool [params.stop]: True if fetching a stop order
2827
+ :param int [params.currentPage]: *trigger orders only* current page
2828
+ :param str [params.orderIds]: *trigger orders only* comma seperated order ID list
2376
2829
  :param bool [params.hf]: False, # True for hf order
2377
2830
  :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)
2378
2831
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2387,25 +2840,28 @@ class kucoin(Exchange, ImplicitAPI):
2387
2840
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
2388
2841
  """
2389
2842
  fetch an order
2390
- :see: https://docs.kucoin.com/spot#get-an-order
2391
- :see: https://docs.kucoin.com/spot#get-single-active-order-by-clientoid
2392
- :see: https://docs.kucoin.com/spot#get-single-order-info
2393
- :see: https://docs.kucoin.com/spot#get-single-order-by-clientoid
2394
- :see: https://docs.kucoin.com/spot-hf/#details-of-a-single-hf-order
2395
- :see: https://docs.kucoin.com/spot-hf/#obtain-details-of-a-single-hf-order-using-clientoid
2843
+
2844
+ https://docs.kucoin.com/spot#get-an-order
2845
+ https://docs.kucoin.com/spot#get-single-active-order-by-clientoid
2846
+ https://docs.kucoin.com/spot#get-single-order-info
2847
+ https://docs.kucoin.com/spot#get-single-order-by-clientoid
2848
+ https://docs.kucoin.com/spot-hf/#details-of-a-single-hf-order
2849
+ https://docs.kucoin.com/spot-hf/#obtain-details-of-a-single-hf-order-using-clientoid
2850
+
2396
2851
  :param str id: Order id
2397
- :param str symbol: not sent to exchange except for stop orders with clientOid, but used internally by CCXT to filter
2852
+ :param str symbol: not sent to exchange except for trigger orders with clientOid, but used internally by CCXT to filter
2398
2853
  :param dict [params]: exchange specific parameters
2399
- :param bool [params.stop]: True if fetching a stop order
2854
+ :param bool [params.trigger]: True if fetching a trigger order
2400
2855
  :param bool [params.hf]: False, # True for hf order
2401
2856
  :param bool [params.clientOid]: unique order id created by users to identify their orders
2402
2857
  :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2403
2858
  """
2404
2859
  await self.load_markets()
2405
- request = {}
2860
+ request: dict = {}
2406
2861
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
2407
- stop = self.safe_bool(params, 'stop', False)
2408
- hf = self.safe_bool(params, 'hf', False)
2862
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2863
+ hf = None
2864
+ hf, params = self.handle_hf_and_params(params)
2409
2865
  market = None
2410
2866
  if symbol is not None:
2411
2867
  market = self.market(symbol)
@@ -2413,11 +2869,11 @@ class kucoin(Exchange, ImplicitAPI):
2413
2869
  if symbol is None:
2414
2870
  raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol parameter for hf orders')
2415
2871
  request['symbol'] = market['id']
2416
- params = self.omit(params, ['stop', 'hf', 'clientOid', 'clientOrderId'])
2872
+ params = self.omit(params, ['stop', 'clientOid', 'clientOrderId', 'trigger'])
2417
2873
  response = None
2418
2874
  if clientOrderId is not None:
2419
2875
  request['clientOid'] = clientOrderId
2420
- if stop:
2876
+ if trigger:
2421
2877
  if symbol is not None:
2422
2878
  request['symbol'] = market['id']
2423
2879
  response = await self.privateGetStopOrderQueryOrderByClientOid(self.extend(request, params))
@@ -2432,7 +2888,7 @@ class kucoin(Exchange, ImplicitAPI):
2432
2888
  if id is None:
2433
2889
  raise InvalidOrder(self.id + ' fetchOrder() requires an order id')
2434
2890
  request['orderId'] = id
2435
- if stop:
2891
+ if trigger:
2436
2892
  response = await self.privateGetStopOrderOrderId(self.extend(request, params))
2437
2893
  elif hf:
2438
2894
  response = await self.privateGetHfOrdersOrderId(self.extend(request, params))
@@ -2443,7 +2899,7 @@ class kucoin(Exchange, ImplicitAPI):
2443
2899
  responseData = self.safe_value(responseData, 0)
2444
2900
  return self.parse_order(responseData, market)
2445
2901
 
2446
- def parse_order(self, order, market: Market = None) -> Order:
2902
+ def parse_order(self, order: dict, market: Market = None) -> Order:
2447
2903
  #
2448
2904
  # createOrder
2449
2905
  #
@@ -2570,7 +3026,7 @@ class kucoin(Exchange, ImplicitAPI):
2570
3026
  feeCurrencyId = self.safe_string(order, 'feeCurrency')
2571
3027
  cancelExist = self.safe_bool(order, 'cancelExist', False)
2572
3028
  responseStop = self.safe_string(order, 'stop')
2573
- stop = responseStop is not None
3029
+ trigger = responseStop is not None
2574
3030
  stopTriggered = self.safe_bool(order, 'stopTriggered', False)
2575
3031
  isActive = self.safe_bool_2(order, 'isActive', 'active')
2576
3032
  responseStatus = self.safe_string(order, 'status')
@@ -2580,7 +3036,7 @@ class kucoin(Exchange, ImplicitAPI):
2580
3036
  status = 'open'
2581
3037
  else:
2582
3038
  status = 'closed'
2583
- if stop:
3039
+ if trigger:
2584
3040
  if responseStatus == 'NEW':
2585
3041
  status = 'open'
2586
3042
  elif not isActive and not stopTriggered:
@@ -2589,10 +3045,9 @@ class kucoin(Exchange, ImplicitAPI):
2589
3045
  status = 'canceled'
2590
3046
  if responseStatus == 'fail':
2591
3047
  status = 'rejected'
2592
- stopPrice = self.safe_number(order, 'stopPrice')
2593
3048
  return self.safe_order({
2594
3049
  'info': order,
2595
- 'id': self.safe_string_n(order, ['id', 'orderId', 'newOrderId']),
3050
+ 'id': self.safe_string_n(order, ['id', 'orderId', 'newOrderId', 'cancelledOrderId']),
2596
3051
  'clientOrderId': self.safe_string(order, 'clientOid'),
2597
3052
  'symbol': self.safe_symbol(marketId, market, '-'),
2598
3053
  'type': self.safe_string(order, 'type'),
@@ -2601,8 +3056,7 @@ class kucoin(Exchange, ImplicitAPI):
2601
3056
  'side': self.safe_string(order, 'side'),
2602
3057
  'amount': self.safe_string(order, 'size'),
2603
3058
  'price': self.safe_string(order, 'price'), # price is zero for market order, omitZero is called in safeOrder2
2604
- 'stopPrice': stopPrice,
2605
- 'triggerPrice': stopPrice,
3059
+ 'triggerPrice': self.safe_number(order, 'stopPrice'),
2606
3060
  'cost': self.safe_string(order, 'dealFunds'),
2607
3061
  'filled': self.safe_string(order, 'dealSize'),
2608
3062
  'remaining': None,
@@ -2614,15 +3068,17 @@ class kucoin(Exchange, ImplicitAPI):
2614
3068
  },
2615
3069
  'status': status,
2616
3070
  'lastTradeTimestamp': None,
2617
- 'average': None,
3071
+ 'average': self.safe_string(order, 'avgDealPrice'),
2618
3072
  'trades': None,
2619
3073
  }, market)
2620
3074
 
2621
3075
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2622
3076
  """
2623
3077
  fetch all the trades made from a single order
2624
- :see: https://docs.kucoin.com/#list-fills
2625
- :see: https://docs.kucoin.com/spot-hf/#transaction-details
3078
+
3079
+ https://docs.kucoin.com/#list-fills
3080
+ https://docs.kucoin.com/spot-hf/#transaction-details
3081
+
2626
3082
  :param str id: order id
2627
3083
  :param str symbol: unified market symbol
2628
3084
  :param int [since]: the earliest time in ms to fetch trades for
@@ -2630,15 +3086,17 @@ class kucoin(Exchange, ImplicitAPI):
2630
3086
  :param dict [params]: extra parameters specific to the exchange API endpoint
2631
3087
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2632
3088
  """
2633
- request = {
3089
+ request: dict = {
2634
3090
  'orderId': id,
2635
3091
  }
2636
3092
  return await self.fetch_my_trades(symbol, since, limit, self.extend(request, params))
2637
3093
 
2638
3094
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2639
3095
  """
2640
- :see: https://docs.kucoin.com/#list-fills
2641
- :see: https://docs.kucoin.com/spot-hf/#transaction-details
3096
+
3097
+ https://docs.kucoin.com/#list-fills
3098
+ https://docs.kucoin.com/spot-hf/#transaction-details
3099
+
2642
3100
  fetch all trades made by the user
2643
3101
  :param str symbol: unified market symbol
2644
3102
  :param int [since]: the earliest time in ms to fetch trades for
@@ -2654,8 +3112,9 @@ class kucoin(Exchange, ImplicitAPI):
2654
3112
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
2655
3113
  if paginate:
2656
3114
  return await self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
2657
- request = {}
2658
- hf = self.safe_bool(params, 'hf', False)
3115
+ request: dict = {}
3116
+ hf = None
3117
+ hf, params = self.handle_hf_and_params(params)
2659
3118
  if hf and symbol is None:
2660
3119
  raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol parameter for hf orders')
2661
3120
  market = None
@@ -2669,6 +3128,10 @@ class kucoin(Exchange, ImplicitAPI):
2669
3128
  response = None
2670
3129
  request, params = self.handle_until_option('endAt', request, params)
2671
3130
  if hf:
3131
+ # does not return trades earlier than 2019-02-18T00:00:00Z
3132
+ if since is not None:
3133
+ # only returns trades up to one week after the since param
3134
+ request['startAt'] = since
2672
3135
  response = await self.privateGetHfFills(self.extend(request, params))
2673
3136
  elif method == 'private_get_fills':
2674
3137
  # does not return trades earlier than 2019-02-18T00:00:00Z
@@ -2735,7 +3198,9 @@ class kucoin(Exchange, ImplicitAPI):
2735
3198
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
2736
3199
  """
2737
3200
  get the list of most recent trades for a particular symbol
2738
- :see: https://docs.kucoin.com/#get-trade-histories
3201
+
3202
+ https://www.kucoin.com/docs/rest/spot-trading/market-data/get-trade-histories
3203
+
2739
3204
  :param str symbol: unified symbol of the market to fetch trades for
2740
3205
  :param int [since]: timestamp in ms of the earliest trade to fetch
2741
3206
  :param int [limit]: the maximum amount of trades to fetch
@@ -2744,7 +3209,7 @@ class kucoin(Exchange, ImplicitAPI):
2744
3209
  """
2745
3210
  await self.load_markets()
2746
3211
  market = self.market(symbol)
2747
- request = {
3212
+ request: dict = {
2748
3213
  'symbol': market['id'],
2749
3214
  }
2750
3215
  # pagination is not supported on the exchange side anymore
@@ -2772,7 +3237,7 @@ class kucoin(Exchange, ImplicitAPI):
2772
3237
  trades = self.safe_list(response, 'data', [])
2773
3238
  return self.parse_trades(trades, market, since, limit)
2774
3239
 
2775
- def parse_trade(self, trade, market: Market = None) -> Trade:
3240
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
2776
3241
  #
2777
3242
  # fetchTrades(public)
2778
3243
  #
@@ -2897,17 +3362,19 @@ class kucoin(Exchange, ImplicitAPI):
2897
3362
  'fee': fee,
2898
3363
  }, market)
2899
3364
 
2900
- async def fetch_trading_fee(self, symbol: str, params={}):
3365
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2901
3366
  """
2902
3367
  fetch the trading fees for a market
2903
- :see: https://docs.kucoin.com/#actual-fee-rate-of-the-trading-pair
3368
+
3369
+ https://www.kucoin.com/docs/rest/funding/trade-fee/trading-pair-actual-fee-spot-margin-trade_hf
3370
+
2904
3371
  :param str symbol: unified market symbol
2905
3372
  :param dict [params]: extra parameters specific to the exchange API endpoint
2906
3373
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
2907
3374
  """
2908
3375
  await self.load_markets()
2909
3376
  market = self.market(symbol)
2910
- request = {
3377
+ request: dict = {
2911
3378
  'symbols': market['id'],
2912
3379
  }
2913
3380
  response = await self.privateGetTradeFees(self.extend(request, params))
@@ -2935,10 +3402,12 @@ class kucoin(Exchange, ImplicitAPI):
2935
3402
  'tierBased': True,
2936
3403
  }
2937
3404
 
2938
- async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
3405
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
2939
3406
  """
2940
3407
  make a withdrawal
2941
- :see: https://docs.kucoin.com/#apply-withdraw-2
3408
+
3409
+ https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw-v3-
3410
+
2942
3411
  :param str code: unified currency code
2943
3412
  :param float amount: the amount to withdraw
2944
3413
  :param str address: the address to withdraw to
@@ -2950,10 +3419,10 @@ class kucoin(Exchange, ImplicitAPI):
2950
3419
  await self.load_markets()
2951
3420
  self.check_address(address)
2952
3421
  currency = self.currency(code)
2953
- request = {
3422
+ request: dict = {
2954
3423
  'currency': currency['id'],
2955
- 'address': address,
2956
- 'amount': amount,
3424
+ 'toAddress': address,
3425
+ 'withdrawType': 'ADDRESS',
2957
3426
  # 'memo': tag,
2958
3427
  # 'isInner': False, # internal transfer or external withdrawal
2959
3428
  # 'remark': 'optional',
@@ -2965,13 +3434,14 @@ class kucoin(Exchange, ImplicitAPI):
2965
3434
  networkCode, params = self.handle_network_code_and_params(params)
2966
3435
  if networkCode is not None:
2967
3436
  request['chain'] = self.network_code_to_id(networkCode).lower()
3437
+ request['amount'] = float(self.currency_to_precision(code, amount, networkCode))
2968
3438
  includeFee = None
2969
3439
  includeFee, params = self.handle_option_and_params(params, 'withdraw', 'includeFee', False)
2970
3440
  if includeFee:
2971
3441
  request['feeDeductType'] = 'INTERNAL'
2972
3442
  response = await self.privatePostWithdrawals(self.extend(request, params))
2973
3443
  #
2974
- # https://github.com/ccxt/ccxt/issues/5558
3444
+ # the id is inside "data"
2975
3445
  #
2976
3446
  # {
2977
3447
  # "code": 200000,
@@ -2983,8 +3453,8 @@ class kucoin(Exchange, ImplicitAPI):
2983
3453
  data = self.safe_dict(response, 'data', {})
2984
3454
  return self.parse_transaction(data, currency)
2985
3455
 
2986
- def parse_transaction_status(self, status):
2987
- statuses = {
3456
+ def parse_transaction_status(self, status: Str):
3457
+ statuses: dict = {
2988
3458
  'SUCCESS': 'ok',
2989
3459
  'PROCESSING': 'pending',
2990
3460
  'WALLET_PROCESSING': 'pending',
@@ -2992,7 +3462,7 @@ class kucoin(Exchange, ImplicitAPI):
2992
3462
  }
2993
3463
  return self.safe_string(statuses, status, status)
2994
3464
 
2995
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
3465
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2996
3466
  #
2997
3467
  # fetchDeposits
2998
3468
  #
@@ -3099,8 +3569,10 @@ class kucoin(Exchange, ImplicitAPI):
3099
3569
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3100
3570
  """
3101
3571
  fetch all deposits made to an account
3102
- :see: https://docs.kucoin.com/#get-deposit-list
3103
- :see: https://docs.kucoin.com/#get-v1-historical-deposits-list
3572
+
3573
+ https://www.kucoin.com/docs/rest/funding/deposit/get-deposit-list
3574
+ https://www.kucoin.com/docs/rest/funding/deposit/get-v1-historical-deposits-list
3575
+
3104
3576
  :param str code: unified currency code
3105
3577
  :param int [since]: the earliest time in ms to fetch deposits for
3106
3578
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -3114,7 +3586,7 @@ class kucoin(Exchange, ImplicitAPI):
3114
3586
  paginate, params = self.handle_option_and_params(params, 'fetchDeposits', 'paginate')
3115
3587
  if paginate:
3116
3588
  return await self.fetch_paginated_call_dynamic('fetchDeposits', code, since, limit, params)
3117
- request = {}
3589
+ request: dict = {}
3118
3590
  currency = None
3119
3591
  if code is not None:
3120
3592
  currency = self.currency(code)
@@ -3169,14 +3641,17 @@ class kucoin(Exchange, ImplicitAPI):
3169
3641
  # }
3170
3642
  # }
3171
3643
  #
3172
- responseData = response['data']['items']
3173
- return self.parse_transactions(responseData, currency, since, limit, {'type': 'deposit'})
3644
+ data = self.safe_dict(response, 'data', {})
3645
+ items = self.safe_list(data, 'items', [])
3646
+ return self.parse_transactions(items, currency, since, limit, {'type': 'deposit'})
3174
3647
 
3175
3648
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3176
3649
  """
3177
3650
  fetch all withdrawals made from an account
3178
- :see: https://docs.kucoin.com/#get-withdrawals-list
3179
- :see: https://docs.kucoin.com/#get-v1-historical-withdrawals-list
3651
+
3652
+ https://www.kucoin.com/docs/rest/funding/withdrawals/get-withdrawals-list
3653
+ https://www.kucoin.com/docs/rest/funding/withdrawals/get-v1-historical-withdrawals-list
3654
+
3180
3655
  :param str code: unified currency code
3181
3656
  :param int [since]: the earliest time in ms to fetch withdrawals for
3182
3657
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -3190,7 +3665,7 @@ class kucoin(Exchange, ImplicitAPI):
3190
3665
  paginate, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'paginate')
3191
3666
  if paginate:
3192
3667
  return await self.fetch_paginated_call_dynamic('fetchWithdrawals', code, since, limit, params)
3193
- request = {}
3668
+ request: dict = {}
3194
3669
  currency = None
3195
3670
  if code is not None:
3196
3671
  currency = self.currency(code)
@@ -3246,14 +3721,15 @@ class kucoin(Exchange, ImplicitAPI):
3246
3721
  # }
3247
3722
  # }
3248
3723
  #
3249
- responseData = response['data']['items']
3250
- return self.parse_transactions(responseData, currency, since, limit, {'type': 'withdrawal'})
3724
+ data = self.safe_dict(response, 'data', {})
3725
+ items = self.safe_list(data, 'items', [])
3726
+ return self.parse_transactions(items, currency, since, limit, {'type': 'withdrawal'})
3251
3727
 
3252
3728
  def parse_balance_helper(self, entry):
3253
3729
  account = self.account()
3254
- account['used'] = self.safe_string(entry, 'holdBalance')
3255
- account['free'] = self.safe_string(entry, 'availableBalance')
3256
- account['total'] = self.safe_string(entry, 'totalBalance')
3730
+ account['used'] = self.safe_string_2(entry, 'holdBalance', 'hold')
3731
+ account['free'] = self.safe_string_2(entry, 'availableBalance', 'available')
3732
+ account['total'] = self.safe_string_2(entry, 'totalBalance', 'total')
3257
3733
  debt = self.safe_string(entry, 'liability')
3258
3734
  interest = self.safe_string(entry, 'interest')
3259
3735
  account['debt'] = Precise.string_add(debt, interest)
@@ -3262,9 +3738,11 @@ class kucoin(Exchange, ImplicitAPI):
3262
3738
  async def fetch_balance(self, params={}) -> Balances:
3263
3739
  """
3264
3740
  query for balance and get the amount of funds available for trading or funds locked in orders
3265
- :see: https://docs.kucoin.com/#list-accounts
3266
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3267
- :see: https://docs.kucoin.com/#query-isolated-margin-account-info
3741
+
3742
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3743
+ https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-margin
3744
+ https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-isolated-margin
3745
+
3268
3746
  :param dict [params]: extra parameters specific to the exchange API endpoint
3269
3747
  :param dict [params.marginMode]: 'cross' or 'isolated', margin type for fetching margin balance
3270
3748
  :param dict [params.type]: extra parameters specific to the exchange API endpoint
@@ -3281,15 +3759,15 @@ class kucoin(Exchange, ImplicitAPI):
3281
3759
  accountsByType = self.safe_dict(self.options, 'accountsByType')
3282
3760
  type = self.safe_string(accountsByType, requestedType, requestedType)
3283
3761
  params = self.omit(params, 'type')
3284
- isHf = self.safe_bool(params, 'hf', False)
3285
- if isHf:
3762
+ hf = None
3763
+ hf, params = self.handle_hf_and_params(params)
3764
+ if hf and (type != 'main'):
3286
3765
  type = 'trade_hf'
3287
- params = self.omit(params, 'hf')
3288
3766
  marginMode, query = self.handle_margin_mode_and_params('fetchBalance', params)
3289
3767
  response = None
3290
- request = {}
3768
+ request: dict = {}
3291
3769
  isolated = (marginMode == 'isolated') or (type == 'isolated')
3292
- cross = (marginMode == 'cross') or (type == 'cross')
3770
+ cross = (marginMode == 'cross') or (type == 'margin')
3293
3771
  if isolated:
3294
3772
  if currency is not None:
3295
3773
  request['balanceCurrency'] = currency['id']
@@ -3302,7 +3780,7 @@ class kucoin(Exchange, ImplicitAPI):
3302
3780
  request['type'] = type
3303
3781
  response = await self.privateGetAccounts(self.extend(request, query))
3304
3782
  #
3305
- # Spot and Cross
3783
+ # Spot
3306
3784
  #
3307
3785
  # {
3308
3786
  # "code": "200000",
@@ -3318,35 +3796,59 @@ class kucoin(Exchange, ImplicitAPI):
3318
3796
  # ]
3319
3797
  # }
3320
3798
  #
3799
+ # Cross
3800
+ #
3801
+ # {
3802
+ # "code": "200000",
3803
+ # "data": {
3804
+ # "debtRatio": "0",
3805
+ # "accounts": [
3806
+ # {
3807
+ # "currency": "USDT",
3808
+ # "totalBalance": "5",
3809
+ # "availableBalance": "5",
3810
+ # "holdBalance": "0",
3811
+ # "liability": "0",
3812
+ # "maxBorrowSize": "20"
3813
+ # },
3814
+ # ]
3815
+ # }
3816
+ # }
3817
+ #
3321
3818
  # Isolated
3322
3819
  #
3323
3820
  # {
3324
3821
  # "code": "200000",
3325
3822
  # "data": {
3326
- # "totalConversionBalance": "0",
3327
- # "liabilityConversionBalance": "0",
3823
+ # "totalAssetOfQuoteCurrency": "0",
3824
+ # "totalLiabilityOfQuoteCurrency": "0",
3825
+ # "timestamp": 1712085661155,
3328
3826
  # "assets": [
3329
3827
  # {
3330
3828
  # "symbol": "MANA-USDT",
3331
- # "status": "CLEAR",
3829
+ # "status": "EFFECTIVE",
3332
3830
  # "debtRatio": "0",
3333
3831
  # "baseAsset": {
3334
3832
  # "currency": "MANA",
3335
- # "totalBalance": "0",
3336
- # "holdBalance": "0",
3337
- # "availableBalance": "0",
3833
+ # "borrowEnabled": True,
3834
+ # "transferInEnabled": True,
3835
+ # "total": "0",
3836
+ # "hold": "0",
3837
+ # "available": "0",
3338
3838
  # "liability": "0",
3339
3839
  # "interest": "0",
3340
- # "borrowableAmount": "0"
3840
+ # "maxBorrowSize": "0"
3341
3841
  # },
3342
3842
  # "quoteAsset": {
3343
3843
  # "currency": "USDT",
3344
- # "totalBalance": "0",
3345
- # "holdBalance": "0",
3346
- # "availableBalance": "0",
3844
+ # "borrowEnabled": True,
3845
+ # "transferInEnabled": True,
3846
+ # "total": "0",
3847
+ # "hold": "0",
3848
+ # "available": "0",
3347
3849
  # "liability": "0",
3348
3850
  # "interest": "0",
3349
- # "borrowableAmount": "0"
3851
+ # "maxBorrowSize": "0"
3350
3852
  # }
3351
3853
  # },
3352
3854
  # ...
@@ -3354,13 +3856,14 @@ class kucoin(Exchange, ImplicitAPI):
3354
3856
  # }
3355
3857
  # }
3356
3858
  #
3357
- data = self.safe_list(response, 'data', [])
3358
- result = {
3859
+ data = None
3860
+ result: dict = {
3359
3861
  'info': response,
3360
3862
  'timestamp': None,
3361
3863
  'datetime': None,
3362
3864
  }
3363
3865
  if isolated:
3866
+ data = self.safe_dict(response, 'data', {})
3364
3867
  assets = self.safe_value(data, 'assets', data)
3365
3868
  for i in range(0, len(assets)):
3366
3869
  entry = assets[i]
@@ -3370,11 +3873,12 @@ class kucoin(Exchange, ImplicitAPI):
3370
3873
  quote = self.safe_dict(entry, 'quoteAsset', {})
3371
3874
  baseCode = self.safe_currency_code(self.safe_string(base, 'currency'))
3372
3875
  quoteCode = self.safe_currency_code(self.safe_string(quote, 'currency'))
3373
- subResult = {}
3876
+ subResult: dict = {}
3374
3877
  subResult[baseCode] = self.parse_balance_helper(base)
3375
3878
  subResult[quoteCode] = self.parse_balance_helper(quote)
3376
3879
  result[symbol] = self.safe_balance(subResult)
3377
3880
  elif cross:
3881
+ data = self.safe_dict(response, 'data', {})
3378
3882
  accounts = self.safe_list(data, 'accounts', [])
3379
3883
  for i in range(0, len(accounts)):
3380
3884
  balance = accounts[i]
@@ -3382,6 +3886,7 @@ class kucoin(Exchange, ImplicitAPI):
3382
3886
  codeInner = self.safe_currency_code(currencyId)
3383
3887
  result[codeInner] = self.parse_balance_helper(balance)
3384
3888
  else:
3889
+ data = self.safe_list(response, 'data', [])
3385
3890
  for i in range(0, len(data)):
3386
3891
  balance = data[i]
3387
3892
  balanceType = self.safe_string(balance, 'type')
@@ -3399,9 +3904,11 @@ class kucoin(Exchange, ImplicitAPI):
3399
3904
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
3400
3905
  """
3401
3906
  transfer currency internally between wallets on the same account
3402
- :see: https://docs.kucoin.com/#inner-transfer
3403
- :see: https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3404
- :see: https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3907
+
3908
+ https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
3909
+ https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3910
+ https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3911
+
3405
3912
  :param str code: unified currency code
3406
3913
  :param float amount: amount to transfer
3407
3914
  :param str fromAccount: account to transfer from
@@ -3419,7 +3926,7 @@ class kucoin(Exchange, ImplicitAPI):
3419
3926
  if fromId == 'contract':
3420
3927
  if toId != 'main':
3421
3928
  raise ExchangeError(self.id + ' transfer() only supports transferring from futures account to main account')
3422
- request = {
3929
+ request: dict = {
3423
3930
  'currency': currency['id'],
3424
3931
  'amount': requestedAmount,
3425
3932
  }
@@ -3454,7 +3961,7 @@ class kucoin(Exchange, ImplicitAPI):
3454
3961
  data = self.safe_dict(response, 'data')
3455
3962
  return self.parse_transfer(data, currency)
3456
3963
  else:
3457
- request = {
3964
+ request: dict = {
3458
3965
  'currency': currency['id'],
3459
3966
  'amount': requestedAmount,
3460
3967
  }
@@ -3481,7 +3988,7 @@ class kucoin(Exchange, ImplicitAPI):
3481
3988
  data = self.safe_dict(response, 'data')
3482
3989
  return self.parse_transfer(data, currency)
3483
3990
 
3484
- def parse_transfer(self, transfer, currency: Currency = None):
3991
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
3485
3992
  #
3486
3993
  # transfer(spot)
3487
3994
  #
@@ -3536,14 +4043,14 @@ class kucoin(Exchange, ImplicitAPI):
3536
4043
  'info': transfer,
3537
4044
  }
3538
4045
 
3539
- def parse_transfer_status(self, status):
3540
- statuses = {
4046
+ def parse_transfer_status(self, status: Str) -> Str:
4047
+ statuses: dict = {
3541
4048
  'PROCESSING': 'pending',
3542
4049
  }
3543
4050
  return self.safe_string(statuses, status, status)
3544
4051
 
3545
4052
  def parse_ledger_entry_type(self, type):
3546
- types = {
4053
+ types: dict = {
3547
4054
  'Assets Transferred in After Upgrading': 'transfer', # Assets Transferred in After V1 to V2 Upgrading
3548
4055
  'Deposit': 'transaction', # Deposit
3549
4056
  'Withdrawal': 'transaction', # Withdrawal
@@ -3586,7 +4093,7 @@ class kucoin(Exchange, ImplicitAPI):
3586
4093
  }
3587
4094
  return self.safe_string(types, type, type)
3588
4095
 
3589
- def parse_ledger_entry(self, item, currency: Currency = None):
4096
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
3590
4097
  #
3591
4098
  # {
3592
4099
  # "id": "611a1e7c6a053300067a88d9", #unique key for each ledger entry
@@ -3604,6 +4111,7 @@ class kucoin(Exchange, ImplicitAPI):
3604
4111
  id = self.safe_string(item, 'id')
3605
4112
  currencyId = self.safe_string(item, 'currency')
3606
4113
  code = self.safe_currency_code(currencyId, currency)
4114
+ currency = self.safe_currency(currencyId, currency)
3607
4115
  amount = self.safe_number(item, 'amount')
3608
4116
  balanceAfter = None
3609
4117
  # balanceAfter = self.safe_number(item, 'balance'); only returns zero string
@@ -3646,7 +4154,8 @@ class kucoin(Exchange, ImplicitAPI):
3646
4154
  if feeCost != '0':
3647
4155
  feeCurrency = code
3648
4156
  fee = {'cost': self.parse_number(feeCost), 'currency': feeCurrency}
3649
- return {
4157
+ return self.safe_ledger_entry({
4158
+ 'info': item,
3650
4159
  'id': id,
3651
4160
  'direction': direction,
3652
4161
  'account': account,
@@ -3661,33 +4170,34 @@ class kucoin(Exchange, ImplicitAPI):
3661
4170
  'after': balanceAfter, # None
3662
4171
  'status': None,
3663
4172
  'fee': fee,
3664
- 'info': item,
3665
- }
4173
+ }, currency)
3666
4174
 
3667
- async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4175
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
3668
4176
  """
3669
- :see: https://docs.kucoin.com/#get-account-ledgers
3670
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
3671
- :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
3672
- fetch the history of changes, actions done by the user or operations that altered balance of the user
3673
- :param str code: unified currency code, default is None
4177
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
4178
+
4179
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-spot-margin
4180
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
4181
+ https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
4182
+
4183
+ :param str [code]: unified currency code, default is None
3674
4184
  :param int [since]: timestamp in ms of the earliest ledger entry, default is None
3675
- :param int [limit]: max number of ledger entrys to return, default is None
4185
+ :param int [limit]: max number of ledger entries to return, default is None
3676
4186
  :param dict [params]: extra parameters specific to the exchange API endpoint
3677
4187
  :param boolean [params.hf]: default False, when True will fetch ledger entries for the high frequency trading account
3678
4188
  :param int [params.until]: the latest time in ms to fetch entries for
3679
- :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)
3680
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
4189
+ :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)
4190
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
3681
4191
  """
3682
4192
  await self.load_markets()
3683
4193
  await self.load_accounts()
3684
4194
  paginate = False
3685
4195
  paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
3686
- isHf = self.safe_bool(params, 'hf')
3687
- params = self.omit(params, 'hf')
4196
+ hf = None
4197
+ hf, params = self.handle_hf_and_params(params)
3688
4198
  if paginate:
3689
4199
  return await self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params)
3690
- request = {
4200
+ request: dict = {
3691
4201
  # 'currency': currency['id'], # can choose up to 10, if not provided returns for all currencies by default
3692
4202
  # 'direction': 'in', # 'out'
3693
4203
  # 'bizType': 'DEPOSIT', # DEPOSIT, WITHDRAW, TRANSFER, SUB_TRANSFER,TRADE_EXCHANGE, MARGIN_EXCHANGE, KUCOIN_BONUS(optional)
@@ -3705,7 +4215,7 @@ class kucoin(Exchange, ImplicitAPI):
3705
4215
  marginMode = None
3706
4216
  marginMode, params = self.handle_margin_mode_and_params('fetchLedger', params)
3707
4217
  response = None
3708
- if isHf:
4218
+ if hf:
3709
4219
  if marginMode is not None:
3710
4220
  response = await self.privateGetHfMarginAccountLedgers(self.extend(request, params))
3711
4221
  else:
@@ -3770,15 +4280,6 @@ class kucoin(Exchange, ImplicitAPI):
3770
4280
  return config['v1']
3771
4281
  return self.safe_value(config, 'cost', 1)
3772
4282
 
3773
- def parse_borrow_rate_history(self, response, code, since, limit):
3774
- result = []
3775
- for i in range(0, len(response)):
3776
- item = response[i]
3777
- borrowRate = self.parse_borrow_rate(item)
3778
- result.append(borrowRate)
3779
- sorted = self.sort_by(result, 'timestamp')
3780
- return self.filter_by_currency_since_limit(sorted, code, since, limit)
3781
-
3782
4283
  def parse_borrow_rate(self, info, currency: Currency = None):
3783
4284
  #
3784
4285
  # {
@@ -3809,13 +4310,15 @@ class kucoin(Exchange, ImplicitAPI):
3809
4310
  'info': info,
3810
4311
  }
3811
4312
 
3812
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4313
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
3813
4314
  """
3814
4315
  fetch the interest owed by the user for borrowing currency for margin trading
3815
- :see: https://docs.kucoin.com/#get-repay-record
3816
- :see: https://docs.kucoin.com/#query-isolated-margin-account-info
3817
- :param str code: unified currency code
3818
- :param str symbol: unified market symbol, required for isolated margin
4316
+
4317
+ https://docs.kucoin.com/#get-repay-record
4318
+ https://docs.kucoin.com/#query-isolated-margin-account-info
4319
+
4320
+ :param str [code]: unified currency code
4321
+ :param str [symbol]: unified market symbol, required for isolated margin
3819
4322
  :param int [since]: the earliest time in ms to fetch borrrow interest for
3820
4323
  :param int [limit]: the maximum number of structures to retrieve
3821
4324
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3824,14 +4327,19 @@ class kucoin(Exchange, ImplicitAPI):
3824
4327
  """
3825
4328
  await self.load_markets()
3826
4329
  marginMode = None
3827
- marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params)
3828
- if marginMode is None:
3829
- marginMode = 'cross' # cross marginMode
3830
- request = {}
3831
- response = None
4330
+ marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params, 'cross')
4331
+ request: dict = {}
4332
+ currency = None
3832
4333
  if code is not None:
3833
4334
  currency = self.currency(code)
3834
- request['quoteCurrency'] = currency['id']
4335
+ if marginMode == 'isolated':
4336
+ request['balanceCurrency'] = currency['id']
4337
+ else:
4338
+ request['quoteCurrency'] = currency['id']
4339
+ market = None
4340
+ if symbol is not None:
4341
+ market = self.market(symbol)
4342
+ response = None
3835
4343
  if marginMode == 'isolated':
3836
4344
  response = await self.privateGetIsolatedAccounts(self.extend(request, params))
3837
4345
  else:
@@ -3902,9 +4410,11 @@ class kucoin(Exchange, ImplicitAPI):
3902
4410
  #
3903
4411
  data = self.safe_dict(response, 'data', {})
3904
4412
  assets = self.safe_list(data, 'assets', []) if (marginMode == 'isolated') else self.safe_list(data, 'accounts', [])
3905
- return self.parse_borrow_interests(assets, None)
4413
+ interest = self.parse_borrow_interests(assets, market)
4414
+ filteredByCurrency = self.filter_by_currency_since_limit(interest, code, since, limit)
4415
+ return self.filter_by_symbol_since_limit(filteredByCurrency, symbol, since, limit)
3906
4416
 
3907
- def parse_borrow_interest(self, info, market: Market = None):
4417
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
3908
4418
  #
3909
4419
  # Cross
3910
4420
  #
@@ -3967,21 +4477,23 @@ class kucoin(Exchange, ImplicitAPI):
3967
4477
  interest = self.safe_number(info, 'accruedInterest')
3968
4478
  currencyId = self.safe_string(info, 'currency')
3969
4479
  return {
4480
+ 'info': info,
3970
4481
  'symbol': symbol,
3971
- 'marginMode': marginMode,
3972
4482
  'currency': self.safe_currency_code(currencyId),
3973
4483
  'interest': interest,
3974
4484
  'interestRate': self.safe_number(info, 'dailyIntRate'),
3975
4485
  'amountBorrowed': amountBorrowed,
4486
+ 'marginMode': marginMode,
3976
4487
  'timestamp': timestamp, # create time
3977
4488
  'datetime': self.iso8601(timestamp),
3978
- 'info': info,
3979
4489
  }
3980
4490
 
3981
4491
  async def fetch_borrow_rate_histories(self, codes=None, since: Int = None, limit: Int = None, params={}):
3982
4492
  """
3983
4493
  retrieves a history of a multiple currencies borrow interest rate at specific time slots, returns all currencies if no symbols passed, default is None
3984
- :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4494
+
4495
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4496
+
3985
4497
  :param str[]|None codes: list of unified currency codes, default is None
3986
4498
  :param int [since]: timestamp in ms of the earliest borrowRate, default is None
3987
4499
  :param int [limit]: max number of borrow rate prices to return, default is None
@@ -3994,7 +4506,7 @@ class kucoin(Exchange, ImplicitAPI):
3994
4506
  marginResult = self.handle_margin_mode_and_params('fetchBorrowRateHistories', params)
3995
4507
  marginMode = self.safe_string(marginResult, 0, 'cross')
3996
4508
  isIsolated = (marginMode == 'isolated') # True-isolated, False-cross
3997
- request = {
4509
+ request: dict = {
3998
4510
  'isIsolated': isIsolated,
3999
4511
  }
4000
4512
  if since is not None:
@@ -4024,13 +4536,15 @@ class kucoin(Exchange, ImplicitAPI):
4024
4536
  # }
4025
4537
  #
4026
4538
  data = self.safe_dict(response, 'data')
4027
- rows = self.safe_list(data, 'items')
4539
+ rows = self.safe_list(data, 'items', [])
4028
4540
  return self.parse_borrow_rate_histories(rows, codes, since, limit)
4029
4541
 
4030
4542
  async def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
4031
4543
  """
4032
4544
  retrieves a history of a currencies borrow interest rate at specific time slots
4033
- :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4545
+
4546
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4547
+
4034
4548
  :param str code: unified currency code
4035
4549
  :param int [since]: timestamp for the earliest borrow rate
4036
4550
  :param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
@@ -4044,7 +4558,7 @@ class kucoin(Exchange, ImplicitAPI):
4044
4558
  marginMode = self.safe_string(marginResult, 0, 'cross')
4045
4559
  isIsolated = (marginMode == 'isolated') # True-isolated, False-cross
4046
4560
  currency = self.currency(code)
4047
- request = {
4561
+ request: dict = {
4048
4562
  'isIsolated': isIsolated,
4049
4563
  'currency': currency['id'],
4050
4564
  }
@@ -4075,7 +4589,7 @@ class kucoin(Exchange, ImplicitAPI):
4075
4589
  # }
4076
4590
  #
4077
4591
  data = self.safe_dict(response, 'data')
4078
- rows = self.safe_list(data, 'items')
4592
+ rows = self.safe_list(data, 'items', [])
4079
4593
  return self.parse_borrow_rate_history(rows, code, since, limit)
4080
4594
 
4081
4595
  def parse_borrow_rate_histories(self, response, codes, since, limit):
@@ -4089,7 +4603,7 @@ class kucoin(Exchange, ImplicitAPI):
4089
4603
  # }
4090
4604
  # ]
4091
4605
  #
4092
- borrowRateHistories = {}
4606
+ borrowRateHistories: dict = {}
4093
4607
  for i in range(0, len(response)):
4094
4608
  item = response[i]
4095
4609
  code = self.safe_currency_code(self.safe_string(item, 'currency'))
@@ -4107,7 +4621,9 @@ class kucoin(Exchange, ImplicitAPI):
4107
4621
  async def borrow_cross_margin(self, code: str, amount: float, params={}):
4108
4622
  """
4109
4623
  create a loan to borrow margin
4110
- :see: https://docs.kucoin.com/#1-margin-borrowing
4624
+
4625
+ https://docs.kucoin.com/#1-margin-borrowing
4626
+
4111
4627
  :param str code: unified currency code of the currency to borrow
4112
4628
  :param float amount: the amount to borrow
4113
4629
  :param dict [params]: extra parameters specific to the exchange API endpoints
@@ -4116,7 +4632,7 @@ class kucoin(Exchange, ImplicitAPI):
4116
4632
  """
4117
4633
  await self.load_markets()
4118
4634
  currency = self.currency(code)
4119
- request = {
4635
+ request: dict = {
4120
4636
  'currency': currency['id'],
4121
4637
  'size': self.currency_to_precision(code, amount),
4122
4638
  'timeInForce': 'FOK',
@@ -4140,7 +4656,9 @@ class kucoin(Exchange, ImplicitAPI):
4140
4656
  async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
4141
4657
  """
4142
4658
  create a loan to borrow margin
4143
- :see: https://docs.kucoin.com/#1-margin-borrowing
4659
+
4660
+ https://docs.kucoin.com/#1-margin-borrowing
4661
+
4144
4662
  :param str symbol: unified market symbol, required for isolated margin
4145
4663
  :param str code: unified currency code of the currency to borrow
4146
4664
  :param float amount: the amount to borrow
@@ -4151,7 +4669,7 @@ class kucoin(Exchange, ImplicitAPI):
4151
4669
  await self.load_markets()
4152
4670
  market = self.market(symbol)
4153
4671
  currency = self.currency(code)
4154
- request = {
4672
+ request: dict = {
4155
4673
  'currency': currency['id'],
4156
4674
  'size': self.currency_to_precision(code, amount),
4157
4675
  'symbol': market['id'],
@@ -4177,7 +4695,9 @@ class kucoin(Exchange, ImplicitAPI):
4177
4695
  async def repay_cross_margin(self, code: str, amount, params={}):
4178
4696
  """
4179
4697
  repay borrowed margin and interest
4180
- :see: https://docs.kucoin.com/#2-repayment
4698
+
4699
+ https://docs.kucoin.com/#2-repayment
4700
+
4181
4701
  :param str code: unified currency code of the currency to repay
4182
4702
  :param float amount: the amount to repay
4183
4703
  :param dict [params]: extra parameters specific to the exchange API endpoints
@@ -4185,7 +4705,7 @@ class kucoin(Exchange, ImplicitAPI):
4185
4705
  """
4186
4706
  await self.load_markets()
4187
4707
  currency = self.currency(code)
4188
- request = {
4708
+ request: dict = {
4189
4709
  'currency': currency['id'],
4190
4710
  'size': self.currency_to_precision(code, amount),
4191
4711
  }
@@ -4208,7 +4728,9 @@ class kucoin(Exchange, ImplicitAPI):
4208
4728
  async def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
4209
4729
  """
4210
4730
  repay borrowed margin and interest
4211
- :see: https://docs.kucoin.com/#2-repayment
4731
+
4732
+ https://docs.kucoin.com/#2-repayment
4733
+
4212
4734
  :param str symbol: unified market symbol
4213
4735
  :param str code: unified currency code of the currency to repay
4214
4736
  :param float amount: the amount to repay
@@ -4218,7 +4740,7 @@ class kucoin(Exchange, ImplicitAPI):
4218
4740
  await self.load_markets()
4219
4741
  market = self.market(symbol)
4220
4742
  currency = self.currency(code)
4221
- request = {
4743
+ request: dict = {
4222
4744
  'currency': currency['id'],
4223
4745
  'size': self.currency_to_precision(code, amount),
4224
4746
  'symbol': market['id'],
@@ -4262,7 +4784,9 @@ class kucoin(Exchange, ImplicitAPI):
4262
4784
  async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
4263
4785
  """
4264
4786
  fetch deposit and withdraw fees - *IMPORTANT* use fetchDepositWithdrawFee to get more in-depth info
4265
- :see: https://docs.kucoin.com/#get-currencies
4787
+
4788
+ https://docs.kucoin.com/#get-currencies
4789
+
4266
4790
  :param str[]|None codes: list of unified currency codes
4267
4791
  :param dict [params]: extra parameters specific to the exchange API endpoint
4268
4792
  :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -4290,6 +4814,38 @@ class kucoin(Exchange, ImplicitAPI):
4290
4814
  data = self.safe_list(response, 'data', [])
4291
4815
  return self.parse_deposit_withdraw_fees(data, codes, 'currency')
4292
4816
 
4817
+ async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
4818
+ """
4819
+ set the level of leverage for a market
4820
+
4821
+ https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/modify-leverage-multiplier
4822
+
4823
+ :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
4824
+ :param str [symbol]: unified market symbol
4825
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4826
+ :returns dict: response from the exchange
4827
+ """
4828
+ await self.load_markets()
4829
+ market = None
4830
+ marketType: Str = None
4831
+ marketType, params = self.handle_market_type_and_params('setLeverage', None, params)
4832
+ if (symbol is not None) or marketType != 'spot':
4833
+ market = self.market(symbol)
4834
+ if market['contract']:
4835
+ raise NotSupported(self.id + ' setLeverage currently supports only spot margin')
4836
+ marginMode: Str = None
4837
+ marginMode, params = self.handle_margin_mode_and_params('setLeverage', params)
4838
+ if marginMode is None:
4839
+ raise ArgumentsRequired(self.id + ' setLeverage requires a marginMode parameter')
4840
+ request: dict = {}
4841
+ if marginMode == 'isolated' and symbol is None:
4842
+ raise ArgumentsRequired(self.id + ' setLeverage requires a symbol parameter for isolated margin')
4843
+ if symbol is not None:
4844
+ request['symbol'] = market['id']
4845
+ request['leverage'] = str(leverage)
4846
+ request['isIsolated'] = (marginMode == 'isolated')
4847
+ return await self.privatePostPositionUpdateUserLeverage(self.extend(request, params))
4848
+
4293
4849
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4294
4850
  #
4295
4851
  # the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint
@@ -4305,12 +4861,14 @@ class kucoin(Exchange, ImplicitAPI):
4305
4861
  endpoint = '/api/' + version + '/' + self.implode_params(path, params)
4306
4862
  if api == 'webExchange':
4307
4863
  endpoint = '/' + self.implode_params(path, params)
4864
+ if api == 'earn':
4865
+ endpoint = '/api/v1/' + self.implode_params(path, params)
4308
4866
  query = self.omit(params, self.extract_params(path))
4309
4867
  endpart = ''
4310
4868
  headers = headers if (headers is not None) else {}
4311
4869
  url = self.urls['api'][api]
4312
4870
  if not self.is_empty(query):
4313
- if (method == 'GET') or (method == 'DELETE'):
4871
+ if ((method == 'GET') or (method == 'DELETE')) and (path != 'orders/multi-cancel'):
4314
4872
  endpoint += '?' + self.rawencode(query)
4315
4873
  else:
4316
4874
  body = self.json(query)
@@ -4320,7 +4878,8 @@ class kucoin(Exchange, ImplicitAPI):
4320
4878
  isFuturePrivate = (api == 'futuresPrivate')
4321
4879
  isPrivate = (api == 'private')
4322
4880
  isBroker = (api == 'broker')
4323
- if isPrivate or isFuturePrivate or isBroker:
4881
+ isEarn = (api == 'earn')
4882
+ if isPrivate or isFuturePrivate or isBroker or isEarn:
4324
4883
  self.check_required_credentials()
4325
4884
  timestamp = str(self.nonce())
4326
4885
  headers = self.extend({
@@ -4346,13 +4905,14 @@ class kucoin(Exchange, ImplicitAPI):
4346
4905
  partnerSignature = self.hmac(self.encode(partnerPayload), self.encode(partnerSecret), hashlib.sha256, 'base64')
4347
4906
  headers['KC-API-PARTNER-SIGN'] = partnerSignature
4348
4907
  headers['KC-API-PARTNER'] = partnerId
4908
+ headers['KC-API-PARTNER-VERIFY'] = 'true'
4349
4909
  if isBroker:
4350
4910
  brokerName = self.safe_string(partner, 'name')
4351
4911
  if brokerName is not None:
4352
4912
  headers['KC-BROKER-NAME'] = brokerName
4353
4913
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
4354
4914
 
4355
- def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
4915
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
4356
4916
  if not response:
4357
4917
  self.throw_broadly_matched_exception(self.exceptions['broad'], body, body)
4358
4918
  return None
@@ -4364,7 +4924,7 @@ class kucoin(Exchange, ImplicitAPI):
4364
4924
  #
4365
4925
  errorCode = self.safe_string(response, 'code')
4366
4926
  message = self.safe_string_2(response, 'msg', 'data', '')
4367
- feedback = self.id + ' ' + message
4927
+ feedback = self.id + ' ' + body
4368
4928
  self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
4369
4929
  self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
4370
4930
  self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)