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