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